| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

support_functions_LTC2983.cpp
Go to the documentation of this file.
1 /*!
2 LTC2983: Multi-Sensor High Accuracy Digital Temperature Measurement System.
3
4 @verbatim
5
6 support_functions_LTC2983.cpp:
7 This file contains all the support functions used in the main program.
8 @endverbatim
9
10 http://www.linear.com/product/LTC2983
11
12 http://www.linear.com/product/LTC2983#demoboards
13
14
15 Copyright 2018(c) Analog Devices, Inc.
16
17 All rights reserved.
18
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21 - Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 - Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in
25 the documentation and/or other materials provided with the
26 distribution.
27 - Neither the name of Analog Devices, Inc. nor the names of its
28 contributors may be used to endorse or promote products derived
29 from this software without specific prior written permission.
30 - The use of this software may or may not infringe the patent rights
31 of one or more patent holders. This license does not release you
32 from the requirement that you obtain separate licenses from these
33 patent holders to use this software.
34 - Use of the software either in source or binary form, must be run
35 on or directly connected to an Analog Devices Inc. component.
36
37 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
38 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
39 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
41 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
43 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
44 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 */
48
49
50 //! @ingroup Temperature_Monitors
51 //! @{
52 //! @defgroup LTC2983 LTC2983: Multi-Sensor High Accuracy Digital Temperature Measurement System
53 //! @}
54
55 /*! @file
56 @ingroup LTC2983
57 Library for LTC2983: Multi-Sensor High Accuracy Digital Temperature Measurement System
58 */
59
60
61
62 #include <Arduino.h>
63 #include <stdint.h>
64 #include "Linduino.h"
65 #include "LT_SPI.h"
66 #include <SPI.h>
67 #include "UserInterface.h"
68 #include "LT_I2C.h"
69 #include "QuikEval_EEPROM.h"
70 #include "configuration_constants_LTC2983.h"
71 #include "table_coeffs_LTC2983.h"
72 #include "support_functions_LTC2983.h"
73
74 //! Prints the title block when program first starts.
75 void print_title()
76 {
77 Serial.print(F("\n******************************************************************\n"));
78 Serial.print(F(" LTC2983 Demonstration Program \n"));
79 Serial.print(F(" \n"));
80 Serial.print(F(" This program demonstrates how to read the multi-sensor \n"));
81 Serial.print(F(" temperature measurement system. \n"));
82 Serial.print(F(" \n"));
83 Serial.print(F(" Set the baud rate to 115200 and select the newline terminator. \n"));
84 Serial.print(F("******************************************************************\n"));
85 }
86
87 // ***********************
88 // Program the part
89 // ***********************
90 void assign_channel(uint8_t chip_select, uint8_t channel_number, uint32_t channel_assignment_data)
91 {
92 uint16_t start_address = get_start_address(CH_ADDRESS_BASE, channel_number);
93 transfer_four_bytes(chip_select, WRITE_TO_RAM, start_address, channel_assignment_data);
94 }
95
96
97 void write_custom_table(uint8_t chip_select, struct table_coeffs coefficients[64], uint16_t start_address, uint8_t table_length)
98 {
99 int8_t i;
100 uint32_t coeff;
101
102 output_low(chip_select);
103
104 SPI.transfer(WRITE_TO_RAM);
105 SPI.transfer(highByte(start_address));
106 SPI.transfer(lowByte(start_address));
107
108 for (i=0; i< table_length; i++)
109 {
110 coeff = coefficients[i].measurement;
111 SPI.transfer((uint8_t)(coeff >> 16));
112 SPI.transfer((uint8_t)(coeff >> 8));
113 SPI.transfer((uint8_t)coeff);
114
115 coeff = coefficients[i].temperature;
116 SPI.transfer((uint8_t)(coeff >> 16));
117 SPI.transfer((uint8_t)(coeff >> 8));
118 SPI.transfer((uint8_t)coeff);
119 }
120 output_high(chip_select);
121 }
122
123
124 void write_custom_steinhart_hart(uint8_t chip_select, uint32_t steinhart_hart_coeffs[6], uint16_t start_address)
125 {
126 int8_t i;
127 uint32_t coeff;
128
129 output_low(chip_select);
130
131 SPI.transfer(WRITE_TO_RAM);
132 SPI.transfer(highByte(start_address));
133 SPI.transfer(lowByte(start_address));
134
135 for (i = 0; i < 6; i++)
136 {
137 coeff = steinhart_hart_coeffs[i];
138 SPI.transfer((uint8_t)(coeff >> 24));
139 SPI.transfer((uint8_t)(coeff >> 16));
140 SPI.transfer((uint8_t)(coeff >> 8));
141 SPI.transfer((uint8_t)coeff);
142 }
143 output_high(chip_select);
144 }
145
146
147
148
149 // *****************
150 // Measure channel
151 // *****************
152 void measure_channel(uint8_t chip_select, uint8_t channel_number, uint8_t channel_output)
153 {
154 convert_channel(chip_select, channel_number);
155 get_result(chip_select, channel_number, channel_output);
156 }
157
158
159 void convert_channel(uint8_t chip_select, uint8_t channel_number)
160 {
161 // Start conversion
162 transfer_byte(chip_select, WRITE_TO_RAM, COMMAND_STATUS_REGISTER, CONVERSION_CONTROL_BYTE | channel_number);
163
164 wait_for_process_to_finish(chip_select);
165 }
166
167
168 void wait_for_process_to_finish(uint8_t chip_select)
169 {
170 uint8_t process_finished = 0;
171 uint8_t data;
172 while (process_finished == 0)
173 {
174 data = transfer_byte(chip_select, READ_FROM_RAM, COMMAND_STATUS_REGISTER, 0);
175 process_finished = data & 0x40;
176 }
177 }
178
179
180 // *********************************
181 // Get results
182 // *********************************
183 void get_result(uint8_t chip_select, uint8_t channel_number, uint8_t channel_output)
184 {
185 uint32_t raw_data;
186 uint8_t fault_data;
187 uint16_t start_address = get_start_address(CONVERSION_RESULT_MEMORY_BASE, channel_number);
188 uint32_t raw_conversion_result;
189
190 raw_data = transfer_four_bytes(chip_select, READ_FROM_RAM, start_address, 0);
191
192 Serial.print(F("\nChannel "));
193 Serial.println(channel_number);
194
195 // 24 LSB's are conversion result
196 raw_conversion_result = raw_data & 0xFFFFFF;
197 print_conversion_result(raw_conversion_result, channel_output);
198
199 // If you're interested in the raw voltage or resistance, use the following
200 if (channel_output != VOLTAGE)
201 {
202 read_voltage_or_resistance_results(chip_select, channel_number);
203 }
204
205 // 8 MSB's show the fault data
206 fault_data = raw_data >> 24;
207 print_fault_data(fault_data);
208 }
209
210
211 void print_conversion_result(uint32_t raw_conversion_result, uint8_t channel_output)
212 {
213 int32_t signed_data = raw_conversion_result;
214 float scaled_result;
215
216 // Convert the 24 LSB's into a signed 32-bit integer
217 if (signed_data & 0x800000)
218 signed_data = signed_data | 0xFF000000;
219
220 // Translate and print result
221 if (channel_output == TEMPERATURE)
222 {
223 scaled_result = float(signed_data) / 1024;
224 Serial.print(F(" Temperature = "));
225 Serial.println(scaled_result);
226 }
227 else if (channel_output == VOLTAGE)
228 {
229 scaled_result = float(signed_data) / 2097152;
230 Serial.print(F(" Direct ADC reading in V = "));
231 Serial.println(scaled_result);
232 }
233
234 }
235
236
237 void read_voltage_or_resistance_results(uint8_t chip_select, uint8_t channel_number)
238 {
239 int32_t raw_data;
240 float voltage_or_resistance_result;
241 uint16_t start_address = get_start_address(VOUT_CH_BASE, channel_number);
242
243 raw_data = transfer_four_bytes(chip_select, READ_FROM_RAM, start_address, 0);
244 voltage_or_resistance_result = (float)raw_data/1024;
245 Serial.print(F(" Voltage or resistance = "));
246 Serial.println(voltage_or_resistance_result);
247 }
248
249
250 // Translate the fault byte into usable fault data and print it out
251 void print_fault_data(uint8_t fault_byte)
252 {
253 //
254 Serial.print(F(" FAULT DATA = "));
255 Serial.println(fault_byte, BIN);
256
257 if (fault_byte & SENSOR_HARD_FAILURE)
258 Serial.println(F(" - SENSOR HARD FALURE"));
259 if (fault_byte & ADC_HARD_FAILURE)
260 Serial.println(F(" - ADC_HARD_FAILURE"));
261 if (fault_byte & CJ_HARD_FAILURE)
262 Serial.println(F(" - CJ_HARD_FAILURE"));
263 if (fault_byte & CJ_SOFT_FAILURE)
264 Serial.println(F(" - CJ_SOFT_FAILURE"));
265 if (fault_byte & SENSOR_ABOVE)
266 Serial.println(F(" - SENSOR_ABOVE"));
267 if (fault_byte & SENSOR_BELOW)
268 Serial.println(F(" - SENSOR_BELOW"));
269 if (fault_byte & ADC_RANGE_ERROR)
270 Serial.println(F(" - ADC_RANGE_ERROR"));
271 if (!(fault_byte & VALID))
272 Serial.println(F("INVALID READING !!!!!!"));
273 if (fault_byte == 0b11111111)
274 Serial.println(F("CONFIGURATION ERROR !!!!!!"));
275 }
276
277 // *********************
278 // SPI RAM data transfer
279 // *********************
280 // To write to the RAM, set ram_read_or_write = WRITE_TO_RAM.
281 // To read from the RAM, set ram_read_or_write = READ_FROM_RAM.
282 // input_data is the data to send into the RAM. If you are reading from the part, set input_data = 0.
283
284 uint32_t transfer_four_bytes(uint8_t chip_select, uint8_t ram_read_or_write, uint16_t start_address, uint32_t input_data)
285 {
286 uint32_t output_data;
287 uint8_t tx[7], rx[7];
288
289 tx[6] = ram_read_or_write;
290 tx[5] = highByte(start_address);
291 tx[4] = lowByte(start_address);
292 tx[3] = (uint8_t)(input_data >> 24);
293 tx[2] = (uint8_t)(input_data >> 16);
294 tx[1] = (uint8_t)(input_data >> 8);
295 tx[0] = (uint8_t) input_data;
296
297 spi_transfer_block(chip_select, tx, rx, 7);
298
299 output_data = (uint32_t) rx[3] << 24 |
300 (uint32_t) rx[2] << 16 |
301 (uint32_t) rx[1] << 8 |
302 (uint32_t) rx[0];
303
304 return output_data;
305 }
306
307
308 uint8_t transfer_byte(uint8_t chip_select, uint8_t ram_read_or_write, uint16_t start_address, uint8_t input_data)
309 {
310 uint8_t tx[4], rx[4];
311
312 tx[3] = ram_read_or_write;
313 tx[2] = (uint8_t)(start_address >> 8);
314 tx[1] = (uint8_t)start_address;
315 tx[0] = input_data;
316 spi_transfer_block(chip_select, tx, rx, 4);
317 return rx[0];
318 }
319
320
321 // ******************************
322 // Misc support functions
323 // ******************************
324 uint16_t get_start_address(uint16_t base_address, uint8_t channel_number)
325 {
326 return base_address + 4 * (channel_number-1);
327 }
328
329
330 bool is_number_in_array(uint8_t number, uint8_t *array, uint8_t array_length)
331 // Find out if a number is an element in an array
332 {
333 bool found = false;
334 for (uint8_t i=0; i< array_length; i++)
335 {
336 if (number == array[i])
337 {
338 found = true;
339 }
340 }
341 return found;
342 }
343
344
345
346
347
348
349
350
351
352
WRITE_TO_RAM
#define WRITE_TO_RAM
Definition: configuration_constants_LTC2983.h:326
CONVERSION_RESULT_MEMORY_BASE
#define CONVERSION_RESULT_MEMORY_BASE
Definition: configuration_constants_LTC2983.h:322
read_voltage_or_resistance_results
void read_voltage_or_resistance_results(uint8_t chip_select, uint8_t channel_number)
Definition: support_functions_LTC2983.cpp:237
SENSOR_HARD_FAILURE
#define SENSOR_HARD_FAILURE
Definition: configuration_constants_LTC2983.h:307
TEMPERATURE
#define TEMPERATURE
is_number_in_array
bool is_number_in_array(uint8_t number, uint8_t *array, uint8_t array_length)
Definition: support_functions_LTC2983.cpp:330
assign_channel
void assign_channel(uint8_t chip_select, uint8_t channel_number, uint32_t channel_assignment_data)
Definition: support_functions_LTC2983.cpp:90
output_high
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
wait_for_process_to_finish
void wait_for_process_to_finish(uint8_t chip_select)
Definition: support_functions_LTC2983.cpp:168
Linduino.h
Header File for Linduino Libraries and Demo Code.
VOUT_CH_BASE
#define VOUT_CH_BASE
Definition: configuration_constants_LTC2983.h:320
get_result
void get_result(uint8_t chip_select, uint8_t channel_number, uint8_t channel_output)
Definition: support_functions_LTC2983.cpp:183
CONVERSION_CONTROL_BYTE
#define CONVERSION_CONTROL_BYTE
Definition: configuration_constants_LTC2983.h:328
READ_FROM_RAM
#define READ_FROM_RAM
Definition: configuration_constants_LTC2983.h:327
COMMAND_STATUS_REGISTER
#define COMMAND_STATUS_REGISTER
Definition: configuration_constants_LTC2983.h:318
write_custom_steinhart_hart
void write_custom_steinhart_hart(uint8_t chip_select, uint32_t steinhart_hart_coeffs[6], uint16_t start_address)
Definition: support_functions_LTC2983.cpp:124
table_coeffs
LTC2983: Multi-Sensor High Accuracy Digital Temperature Measurement System.
Definition: table_coeffs_LTC2983.h:51
CJ_SOFT_FAILURE
#define CJ_SOFT_FAILURE
Definition: configuration_constants_LTC2983.h:310
ADC_RANGE_ERROR
#define ADC_RANGE_ERROR
Definition: configuration_constants_LTC2983.h:313
data
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
configuration_constants_LTC2983.h
LTC2983: Multi-Sensor High Accuracy Digital Temperature Measurement System.
table_coeffs_LTC2983.h
print_fault_data
void print_fault_data(uint8_t fault_byte)
Definition: support_functions_LTC2983.cpp:251
output_low
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
QuikEval_EEPROM.h
QuikEval EEPROM Library.
support_functions_LTC2983.h
LTC2983: Multi-Sensor High Accuracy Digital Temperature Measurement System.
table_coeffs::measurement
uint32_t measurement
Definition: table_coeffs_LTC2983.h:53
SENSOR_BELOW
#define SENSOR_BELOW
Definition: configuration_constants_LTC2983.h:312
get_start_address
uint16_t get_start_address(uint16_t base_address, uint8_t channel_number)
Definition: support_functions_LTC2983.cpp:324
write_custom_table
void write_custom_table(uint8_t chip_select, struct table_coeffs coefficients[64], uint16_t start_address, uint8_t table_length)
Definition: support_functions_LTC2983.cpp:97
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
measure_channel
void measure_channel(uint8_t chip_select, uint8_t channel_number, uint8_t channel_output)
Definition: support_functions_LTC2983.cpp:152
ADC_HARD_FAILURE
#define ADC_HARD_FAILURE
Definition: configuration_constants_LTC2983.h:308
LT_I2C.h
LT_I2C: Routines to communicate with ATmega328P&#39;s hardware I2C port.
CJ_HARD_FAILURE
#define CJ_HARD_FAILURE
Definition: configuration_constants_LTC2983.h:309
print_title
void print_title()
Prints the title block when program first starts.
Definition: support_functions_LTC2983.cpp:75
UserInterface.h
VOLTAGE
#define VOLTAGE
Definition: configuration_constants_LTC2983.h:330
CH_ADDRESS_BASE
#define CH_ADDRESS_BASE
Definition: configuration_constants_LTC2983.h:319
transfer_four_bytes
uint32_t transfer_four_bytes(uint8_t chip_select, uint8_t ram_read_or_write, uint16_t start_address, uint32_t input_data)
Definition: support_functions_LTC2983.cpp:284
SENSOR_ABOVE
#define SENSOR_ABOVE
Definition: configuration_constants_LTC2983.h:311
print_conversion_result
void print_conversion_result(uint32_t raw_conversion_result, uint8_t channel_output)
Definition: support_functions_LTC2983.cpp:211
i
static int i
Definition: DC2430A.ino:184
spi_transfer_block
void spi_transfer_block(uint8_t cs_pin, uint8_t *tx, uint8_t *rx, uint8_t length)
Reads and sends a byte array.
Definition: LT_SPI.cpp:125
table_coeffs::temperature
uint32_t temperature
Definition: table_coeffs_LTC2983.h:54
convert_channel
void convert_channel(uint8_t chip_select, uint8_t channel_number)
Definition: support_functions_LTC2983.cpp:159
transfer_byte
uint8_t transfer_byte(uint8_t chip_select, uint8_t ram_read_or_write, uint16_t start_address, uint8_t input_data)
Definition: support_functions_LTC2983.cpp:308
VALID
#define VALID
Definition: configuration_constants_LTC2983.h:314