DC2100A  1.2.0
Bi-Directional Cell Balancer Using the LTC3300-1 and the LTC6804-2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Temperature.c
Go to the documentation of this file.
1 /*
2  Linear Technology DC2100A Demonstration Board.
3  Reference Application File for Monitoring Temperature Sensors through the LTC6804-2 Battery Monitor on the DC2100A PCB.
4  All datasheet references in this file refer to Vishay document number: 33011.
5 
6  @verbatim
7 
8  This code contains a task to read the temperature sensors in the DC2100A System at a rate set by TEMPERATURE_TASK_RATE.
9 
10  J17 of the DC2100A board has connections for DC2100A_NUM_TEMPS thermistors. The DC2100A hardware can only connect to one thermistor
11  at a time, as it is connected to the LTC6804 GPIO channel through one of two LTC1380 analog muxes. The task reads one thermistor each
12  execution, and allows the large time constants that result when switching mux channels to settle in between task executions. Therefore,
13  it takes TEMPERATURE_TASK_RATE * DC2100A_NUM_TEMPS time for all of the thermistor inputs to be read.
14 
15  This code module assumes the resistors are of the 100kOhm Curve Type 1 from Vishay document number 33011. The voltages are sampled,
16  accounting for the large time constants when performing the ADC conversion, with the results stored as to minimize RAM usage. The temperatures for
17  each DC2100A board can be retrieved with a function that converts them to °C. See "Temperature" worksheet on DC2100A_Design.xlsm for details of
18  conversion from ADC counts to °C.
19 
20  The raw ADC values for one DC2100A board can be stored for retrieval by the DC2100A GUI.
21 
22  @endverbatim
23 
24  http://www.linear.com/solutions/5126
25 
26  REVISION HISTORY
27  $Revision: 697 $
28  $Date: 2014-09-09 15:15:44 -0400 (Tue, 09 Sep 2014) $
29 
30  Copyright (c) 2013, Linear Technology Corp.(LTC)
31  All rights reserved.
32 
33  Redistribution and use in source and binary forms, with or without
34  modification, are permitted provided that the following conditions are met:
35 
36  1. Redistributions of source code must retain the above copyright notice, this
37  list of conditions and the following disclaimer.
38  2. Redistributions in binary form must reproduce the above copyright notice,
39  this list of conditions and the following disclaimer in the documentation
40  and/or other materials provided with the distribution.
41 
42  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
43  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
46  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
51  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 
53  The views and conclusions contained in the software and documentation are those
54  of the authors and should not be interpreted as representing official policies,
55  either expressed or implied, of Linear Technology Corp.
56 
57 */
58 
59 //! @defgroup Temperature Reference Application File for Monitoring Temperature Sensors through the LTC6804-2 Battery Monitor on the DC2100A PCB.
60 
61 /*! @file
62  @ingroup Temperature
63  Reference Application File for Monitoring Temperature Sensors through the LTC6804-2 Battery Monitor on the DC2100A PCB.
64 */
65 
66 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
67 // Includes
68 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
69 #include "Typedefs.h"
70 #include "DC2100A.h"
71 #include "Temperature.h"
72 #include "System.h"
73 #include "LTC6804-2.h"
74 #include "LTC1380.h"
75 #include <string.h>
76 
77 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
78 // Definitions
79 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
80 
81 #define TEMPERATURE_TABLE_OFFSET -56 // in °C, offset used to store temperatures in 8 bit number even though range exceeds 8 bits.
82 #define TEMPERATURE_TABLE_RESOLUTION 8 // temperatures are stored in 1/8°C
83 
84 #define TEMPERATURE_TABLE_IDX_MAX (sizeof(Temperature_Table)/sizeof(int16) - 1)
85 
86 #define TEMPERATURE_ADC_VALUE_INVALID 0xFFFF // Code used to indicate that temperature adc value has not been read yet.
87 
88 // properties needed to relate a temperature number to an LTC1380 mux and channel
89 typedef struct {
90  int8 mux_num;
91  int8 channel_num;
93 
94 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
95 // Global Data
96 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
97 unsigned int32 temperature_timestamp; // Timestamp taken when last temperature measurement was started.
98 unsigned int8 temperature_balancestamp; // 1 if balancers were on when these measurements were taken, otherwise 0
99 
100 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
101 // Local Data
102 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
103 // Temperatures measured by the thermistor switched by the LTC1380 on the DC2100A board
104 unsigned int8 temperatures[DC2100A_MAX_BOARDS][DC2100A_NUM_TEMPS];
105 
106 
107 // Relationship between 10kOhm NTHS01N1002JE thermistor and temperature from Curve 1 of datasheet, assuming 35Ohm RON in series due to LTC1380 Multiplexer
108 const unsigned int16 Temperature_Table[] = { 29715, // -56°C
109  29495, // -48°C
110  29136, // -40°C
111  28578, // -32°C
112  27745, // -24°C
113  26563, // -16°C
114  24978, // -8°C
115  22979, // 0°C
116  20622, // 8°C
117  18034, // 16°C
118  15380, // 24°C
119  12830, // 32°C
120  10513, // 40°C
121  8507, // 48°C
122  6830, // 56°C
123  5466, // 64°C
124  4376, // 72°C
125  3515, // 80°C
126  2841, // 88°C
127  2312, // 96°C
128  1898, // 104°C
129  1573, // 112°C
130  1318, // 120°C
131  1116, // 128°C
132  955, // 136°C
133  826, // 144°C
134  723, // 152°C
135  639 } ; // 160°C
136 
137 // Relationship between thermistor number, and LTC1380 mux/channel
138 const TEMPERATURE_CHANNEL_TYPE Temperature_Channel_Table[DC2100A_NUM_TEMPS] = { 0, 0, // RT1
139  0, 1, // RT2
140  0, 2, // RT3
141  0, 3, // RT4
142  0, 4, // RT5
143  0, 5, // RT6
144  0, 6, // RT7
145  0, 7, // RT8
146  1, 0, // RT9
147  1, 1, // RT10
148  1, 2, // RT11
149  1, 3}; // RT12
150 
151 int8 temperature_in_process; // The temperature channel currently being monitored.
152 BOOLEAN temperature_skip; // Flag to skip the first thermistor reading after wakeup of the LTCH6804, as it is likely junk.
153 unsigned int16 temperature_adc_values[DC2100A_NUM_TEMPS]; // For debug and manufacturing mostly, tracks the adc values for one board.
154 int8 temperature_board_for_adc_values; // The board currently having its temperature adc values being tracked
155 
156 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
157 // Local Prototypes
158 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
159 void temperature_channel_setup(void);
160 unsigned int8 temperature_lookup(unsigned int16 adc_value);
161 
162 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
163 // Global Functions
164 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
165 
166 // Initializes the parts of the Temperature Module, that need to be initialized upon power-up of the PIC.
168 {
169  // Init temperatures to room temperature
170  memset(temperatures, (25 - TEMPERATURE_TABLE_OFFSET), sizeof(temperatures));
171 
172  // Init to start monitoring first channel
173  temperature_in_process = 0;
174 
175  temperature_board_for_adc_values = 0;
176 
177  temperature_timestamp = PIC18FXXJ_Timer_Update();;
178  temperature_balancestamp = 0;
179 
180  return;
181 }
182 
183 // Initializes the parts of the Temperature Module, that need to be initialized upon wakeup of the LTC6804.
185 {
186  BOOLEAN success = TRUE;
187  int8 refon_temp;
188  int8 board_num;
189 
190  // Turn on the Reference.
192  // Check to see if reference was turned on for each board.
193  for (board_num = 0; board_num < System_Num_Boards; board_num++)
194  {
195  refon_temp = FALSE;
196  success &= LTC6804_Refon_Get(board_num, &refon_temp);
197  If(refon_temp == 0)
198  {
199  success = FALSE;
200  }
201  }
202 
203  // Set Up GPIO2 for Analog Input
204  // No way to check if these bits are actually set in the 6804 as read value and write value have different meanings.
206 
207  temperature_skip = TRUE;
208 
209  return success;
210 }
211 
212 // Executes the Temperature monitor task.
213 // - Measures one thermistor value on each DC2100 board in the system.
214 // - Calculates the temperature from the thermistor ADC value..
215 // - Sets up LTC1380 analog mux channel for the next thermistor measurement.
216 // - This task must be executed at a maximum of TEMPERATURE_THERMISTOR_DELAY, to allow circuit to settled after analog mux is switched.
218 {
219  int8 board_num;
220  int16 adc_value;
221 
222  // Clear ADC results, so that it can be detected if LTC6804_Cell_ADC_Start() command is not successful.
224 
225  // Convert and read adc value of temperature measurement started at the end of last task
227 
228  // Update Timer and store timestamp for these samples.
229  temperature_timestamp = PIC18FXXJ_Timer_Update();
230 
231  // Add stamp for whether balancing was active during these temperature samples.
232  temperature_balancestamp = (Balancer_Is_Balancing() == TRUE) ? 0x1 : 0x0;
233 
234  // Due to the massive time constants involved with switching to the temperature channel the first reading
235  // is likely to be junk upon wakeup of the LTC6804.
236  if(temperature_skip == TRUE)
237  {
238  temperature_skip = FALSE;
239  }
240  else
241  {
242  // Wait for conversion to be complete.
243  // Note - It is worthwhile to perform some other action while waiting for the ADC conversion to be complete.
244  delay_us(LTC6804_CONVERSION_2KHZ_DELAY); // Wait for conversion to complete
245 
246  // Read adc values and convert to temperatures.
247  // Note that broadcast read commands can not be performed by the LTC6804-2, so a loop must be used.
248  for (board_num = 0; board_num < System_Num_Boards; board_num++)
249  {
250  // Read the adc result
251  LTC6804_GPIO_ADC_Read(board_num, LTC6804_CHG_GPIO2, &adc_value);
252 
253  if(adc_value != LTC6804_ADC_CLEAR)
254  {
255  if(board_num == temperature_board_for_adc_values)
256  {
257  temperature_adc_values[temperature_in_process] = adc_value;
258  }
259 
260  // Convert adc value to a temperature
261  temperatures[board_num][temperature_in_process] = temperature_lookup(adc_value);
262  }
263  }
264 
265  // Switch to the next temperature
266  if(temperature_in_process < (DC2100A_NUM_TEMPS - 1))
267  {
268  temperature_in_process++;
269  }
270  else
271  {
272  temperature_in_process = 0;
273  }
274  }
275 
276  // Setup LTC1380s to connect next thermistor to be read to the adc
277  temperature_channel_setup();
278 
279  // This delay is massive. Do not wait here, but time task such that delay will be done the next time the task is entered.
280  // delay_ms(TEMPERATURE_THERMISTOR_DELAY);
281 
282  return;
283 }
284 
285 // Gets one temperature from one DC2100A PCB in °C
286 int16 Temperature_Get(int8 board_num, int8 temperature_num)
287 {
288  int16 temp_int16;
289 
290  temp_int16 = (int16)temperatures[board_num][temperature_num];
291  temp_int16 += TEMPERATURE_TABLE_OFFSET;
292 
293  return temp_int16;
294 }
295 
296 // Gets the raw ADC values for all of the thermistors on one DC2100A board.
297 // Returns a pointer to the thermistor ADC values for this board. Returns NULL if all ADC values have not yet been taken.
298 int16* Temperature_Adc_Value_Get(int8 board_num)
299 {
300  int8 temp_num;
301 
302  // If this is the board that was previously selected, then check to see if all adc values have been stored yet.
303  if(board_num == temperature_board_for_adc_values)
304  {
305  for (temp_num = 0; temp_num < DC2100A_NUM_TEMPS; temp_num++)
306  {
307  if(temperature_adc_values[temp_num] == TEMPERATURE_ADC_VALUE_INVALID)
308  {
309  // All adc values have not been stored yet. Return NULL
310  return NULL;
311  }
312  }
313  }
314  // A new board is having its adc values requested. Prepare to store the adc values.
315  else
316  {
317  temperature_board_for_adc_values = board_num;
318  for (temp_num = 0; temp_num < DC2100A_NUM_TEMPS; temp_num++)
319  {
320  temperature_adc_values[temp_num] = TEMPERATURE_ADC_VALUE_INVALID;
321  }
322  // No adc values have not been stored yet. Return NULL
323  return NULL;
324  }
325 
326  return temperature_adc_values;
327 }
328 
329 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
330 // Local Functions
331 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
332 
333 // Sets up a channel to be converted.
334 void temperature_channel_setup(void)
335 {
336  int8 mux_num = Temperature_Channel_Table[temperature_in_process].mux_num;
337  int8 channel_num = Temperature_Channel_Table[temperature_in_process].channel_num;
338 
339  // Turn off channels on mux that is not being used
340  LTC1380_All_Off(LTC6804_BROADCAST, (DC2100A_NUM_MUXES - 1) - mux_num);
341 
342  // Turn on the channel on the mux for temperature to be measured
343  LTC1380_Set_Channel(LTC6804_BROADCAST, mux_num, channel_num);
344 }
345 
346 // Converts a 16 bit adc value value to a temperature by performing a binary search of Temperature_Table[]
347 // Note that Temperature_Table[] is reverse ordered due to the inverse relationship between temperature and resistance.
348 unsigned int8 temperature_lookup(unsigned int16 adc_value)
349 {
350  unsigned int8 idx, idx_min, idx_max;
351  unsigned int16 temp_uint16, temp_uint16b;
352 
353  if(Temperature_Table[0] <= adc_value)
354  {
355  // Temperature is too low for the table, return min value
356  idx = 0;
357  }
358  else if(Temperature_Table[TEMPERATURE_TABLE_IDX_MAX] >= adc_value)
359  {
360  // Temperature is too high for the table, return max value
361  idx = TEMPERATURE_TABLE_IDX_MAX*TEMPERATURE_TABLE_RESOLUTION;
362  }
363  else
364  {
365  idx_min = 0;
366  idx_max = TEMPERATURE_TABLE_IDX_MAX;
367  idx = TEMPERATURE_TABLE_IDX_MAX/2;
368 
369  // Temperature is in the table. Find the closest values and interpolate
370  while (idx_min < idx_max)
371  {
372  temp_uint16 = Temperature_Table[idx];
373 
374  if(temp_uint16 == adc_value)
375  {
376  // If temperature is exactly value in the table, stop searching
377  break;
378  }
379  else if(temp_uint16 < adc_value)
380  {
381  // If temperature is lower than tested table value, adjust the max
382  idx_max = idx;
383  }
384  else
385  {
386  // If temperature is higher than tested table value, adjust the min
387  idx_min = idx + 1;
388  }
389 
390  idx = (idx_max + idx_min) >> 1;
391  }
392 
393  // idx is the value in the table that's higher than the measured temperature. Interpolate to nearest degree.
394  temp_uint16 = (Temperature_Table[idx - 1] - Temperature_Table[idx]);
395  temp_uint16b = (Temperature_Table[idx - 1] - adc_value);
396  idx = ((idx - 1) * TEMPERATURE_TABLE_RESOLUTION) + (temp_uint16b * TEMPERATURE_TABLE_RESOLUTION + temp_uint16/2) / temp_uint16;
397  }
398 
399  return idx;
400 }
void LTC6804_Refon_Set(int8 board_num, BOOLEAN refon)
Turns the LTC6804 ADC Reference on and off.
Definition: LTC6804-2.c:206
Reference Application File for Monitoring Temperature Sensors through the LTC6804-2 Battery Monitor o...
#define LTC6804_BROADCAST
Code for application code to indicate an LTC6804 command is to be broadcast to all boards...
Definition: LTC6804-2.h:89
BOOLEAN Balancer_Is_Balancing(void)
Returns if any balancer is actively balancing.
Definition: Balancer.c:576
#define LTC6804_ADC_CLEAR
ADC Value returned when results are cleared, but not retaken.
Definition: LTC6804-2.h:93
BOOLEAN Temperature_Wakeup_Init(void)
Initializes the parts of the Temperature Module, that need to be initialized upon wakeup of the LTC68...
Definition: Temperature.c:184
int16 Temperature_Get(int8 board_num, int8 temperature_num)
Gets one temperature from one DC2100A PCB.
Definition: Temperature.c:286
API Header File for LTC6804-2 Multicell Battery Monitors.
void LTC6804_GPIO_Set(int8 board_num, int8 gpio_bitmap)
Sets the LTC6804 GPIO Pull Downs.
Definition: LTC6804-2.c:185
void LTC6804_GPIO_ADC_Start(int8 board_num, LTC6804_CONVERSION_MODE_T mode, LTC6804_CHG_GPIO_TYPE gpio_select)
Starts the specified LTC6804 GPIO ADC conversion at the specified conversion mode.
Definition: LTC6804-2.c:599
2kHz conversion mode
Definition: LTC6804-2.h:147
int16 * Temperature_Adc_Value_Get(int8 board_num)
Gets the raw ADC values for all of the thermistors on one DC2100A board.
Definition: Temperature.c:298
BOOLEAN LTC6804_GPIO_ADC_Read(int8 board_num, LTC6804_CHG_GPIO_TYPE gpio_select, int16 *adc_value_ptr)
Reads the specified LTC6804 GPIO ADC conversion results.
Definition: LTC6804-2.c:633
API Header File for LTC1380 Single-Ended 8-Channel/Differential 4-Channel Analog Multiplexer with SMB...
void Temperature_Monitor_Task(void)
Executes the Temperature Monitor task.
Definition: Temperature.c:217
void LTC6804_GPIO_ADC_Clear(int8 board_num)
Clears the LTC6804 GPIO ADC registers.
Definition: LTC6804-2.c:578
#define LTC6804_CONVERSION_2KHZ_DELAY
in us, delay between sampling and reading ADC in 2kHz conversion mode
Definition: LTC6804-2.h:163
void LTC1380_All_Off(int8 board_num, int8 mux_num)
Commands an LTC1380 mux to disconnect all channels from its output.
Definition: LTC1380.c:138
BOOLEAN LTC6804_Refon_Get(int8 board_num, int8 *refon)
Gets the LTC6804 ADC Reference status, where 1 = ON and 0 = OFF.
Definition: LTC6804-2.c:406
void LTC1380_Set_Channel(int8 board_num, int8 mux_num, int8 channel_num)
Commands an LTC1380 mux to connect one channel to its output.
Definition: LTC1380.c:114
void Temperature_Init(void)
Initializes the parts of the Temperature Module, that need to be initialized upon power-up of the PIC...
Definition: Temperature.c:167
unsigned int32 temperature_timestamp
Timestamp taken when last temperature measurement was started.
Definition: Temperature.c:97