| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

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