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
Voltage.c
Go to the documentation of this file.
1 /*
2  Linear Technology DC2100A Demonstration Board.
3  Reference Application File for Monitoring Voltages from the LTC6804-2 Battery Monitor on the DC2100A PCB.
4 
5  @verbatim
6  This file contains a task to read the voltages in the DC2100A System at a rate set by VOLTAGE_TASK_RATE.
7 
8  The task measures all cell voltages in the system, and calculates the sum-of-cells voltages for each LTC6804 in the system.
9  Each cell is monitored for under-voltage (UV) and over-voltage (OV), and balancing is automatically stopped if these conditions occur.
10 
11  @endverbatim
12 
13  http://www.linear.com/solutions/5126
14 
15  REVISION HISTORY
16  $Revision: 699 $
17  $Date: 2014-09-09 16:02:09 -0400 (Tue, 09 Sep 2014) $
18 
19  Copyright (c) 2013, Linear Technology Corp.(LTC)
20  All rights reserved.
21 
22  Redistribution and use in source and binary forms, with or without
23  modification, are permitted provided that the following conditions are met:
24 
25  1. Redistributions of source code must retain the above copyright notice, this
26  list of conditions and the following disclaimer.
27  2. Redistributions in binary form must reproduce the above copyright notice,
28  this list of conditions and the following disclaimer in the documentation
29  and/or other materials provided with the distribution.
30 
31  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
35  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 
42  The views and conclusions contained in the software and documentation are those
43  of the authors and should not be interpreted as representing official policies,
44  either expressed or implied, of Linear Technology Corp.
45 
46 */
47 
48 //! @defgroup Voltage Reference Application File for Monitoring Voltages from the LTC6804-2 Battery Monitor on the DC2100A PCB.
49 
50 /*! @file
51  @ingroup Voltage
52  Reference Application File for Monitoring Voltages from the LTC6804-2 Battery Monitor on the DC2100A PCB.
53 */
54 
55 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
56 // Includes
57 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
58 #include "Typedefs.h"
59 #include "DC2100A.h"
60 #include "Voltage.h"
61 #include "System.h"
62 #include "LTC6804-2.h"
63 #include "Balancer.h"
64 #include "USB_Parser.h"
65 #include <string.h>
66 
67 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
68 // Definitions
69 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
70 
71 #define VOLTAGE_VUV_DEFAULT (2.50 * UV_PER_V/LTC6804_VOLTAGE_RESOLUTION)
72 #define VOLTAGE_VOV_DEFAULT (4.50 * UV_PER_V/LTC6804_VOLTAGE_RESOLUTION)
73 #define VOLTAGE_UVOV_CONVERSION (LTC6804_UVOV_RESOLUTION/LTC6804_VOLTAGE_RESOLUTION)
74 #define VOLTAGE_UVOV_ROUND_MASK (VOLTAGE_UVOV_CONVERSION - 1)
75 
76 #define VOLTAGE_PROCESSING_DURING_DELAY 50 // Estimated number of microseconds that we can avoid waiting, due to processing done during ADC conversion
77 
78 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
79 // Global Data
80 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
81 unsigned int16 voltage_cell[DC2100A_MAX_BOARDS][DC2100A_NUM_CELLS]; // Measured cell voltages for each board in LTC6804_VOLTAGE_RESOLUTION.
82 unsigned int16 voltage_sum[DC2100A_MAX_BOARDS]; // Measured sum of the cell voltages for this board in LTC6804_SOC_RESOLUTION.
83 unsigned int32 voltage_timestamp; // Timestamp taken when voltage measurements were started.
84 unsigned int8 voltage_balancestamp; // 1 if balancers were on when these measurements were taken, otherwise 0
85 
86 unsigned int16 voltage_vov_threshold; // over-voltage threshold in LTC6804_VOLTAGE_RESOLUTION.
87 unsigned int16 voltage_vuv_threshold; // under-voltage threshold in LTC6804_VOLTAGE_RESOLUTION.
88 unsigned int16 voltage_ov_flags[DC2100A_MAX_BOARDS]; // Bitmap indicating if a cell input on the LTC6804 is over-voltage (1) or not (0).
89 unsigned int16 voltage_uv_flags[DC2100A_MAX_BOARDS]; // Bitmap indicating if a cell input on the LTC6804 is under-voltage (1) or not (0).
90 VOLTAGE_CELL_PRESENT_TYPE voltage_cell_present_flags[DC2100A_MAX_BOARDS];// Bitmap indicating if a cell input on the LTC6804 is unpopulated (0), such that UV conditions should be ignored.
91 
92 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
93 // Local Data
94 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
95 
96 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
97 // Local Prototypes
98 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
99 void voltage_error_adc_clear(int8 board_num);
100 
101 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
102 // Global Functions
103 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
104 
105 // Initializes the parts of the Voltage Module, that need to be initialized upon power-up of the PIC.
106 void Voltage_Init(void)
107 {
108  // Init all measurements to be clear.
109  memset(voltage_cell, 0, sizeof(voltage_cell));
110  memset(voltage_sum, 0, sizeof(voltage_sum));
111  voltage_timestamp = PIC18FXXJ_Timer_Update();
113 
114  // Assume all cells to be present
115  memset(voltage_cell_present_flags, 0xFF, sizeof(voltage_uv_flags));
116 
117  // Init all cells to be UV until we've seen an LTC6804 communicate and reply back with voltages.
118  memset(voltage_ov_flags, 0, sizeof(voltage_ov_flags));
119  memset(voltage_uv_flags, 0xFF, sizeof(voltage_uv_flags));
120 
121  // Init thresholds to defaults.
122  voltage_vov_threshold = VOLTAGE_VOV_DEFAULT;
123  voltage_vuv_threshold = VOLTAGE_VUV_DEFAULT;
124 
125 }
126 
127 // Initializes the parts of the Voltage Module, that need to be initialized upon wakeup of the LTC6804.
128 BOOLEAN Voltage_Wakeup_Init(void)
129 {
130  // Initialize the UV and OV threshold registers in the LTC6804.
132 }
133 
134 // Executes the Voltage monitor task.
135 // - Measures all cell voltages in the system. Note that all DC2100A voltages are started simultaneously and read sequentially.
136 // - A timestamp is attached to each voltage for mathematical operations to be performed on the samples.
137 // - The state of the balancers is saved, as the cell voltage measurements are affected by the large DC2100A balance currents.
138 // - Calculates the sum-of-cells voltages for each LTC6804 in the system.
139 // - Monitors each cell for UV and OV. Balancing is stopped if UV or OV occurs, and in USB message is sent to the GUI
141 {
142  int8 board_num, cell_num; // loop variables.
143  unsigned int16 voltage_temp[DC2100A_NUM_CELLS]; // temp storage for reading voltages, so that last results are not overwritten if ADC fails to start.
144  int16 vov_flags, vuv_flags; // temp storage so changes can be detected in flags.
145  BOOLEAN suspend_sent; // flag so that only one suspend command is sent if any cell voltages are vov or vuv.
146  BOOLEAN results_clear; // flag that results were not received for this board.
147  int32 cell_sum; // temp storage for summing cell voltages before scaling.
148 
149  // Clear ADC results, so that it can be detected if LTC6804_Cell_ADC_Start() command is not successful.
151 
152  // Start converting all of the cell ADC values
153  // Broadcast Start Cell Voltage ADC Start in Normal Mode (7KHz)
155 
156  // Update Timer and store timestamp for these samples.
157  voltage_timestamp = PIC18FXXJ_Timer_Update();
158 
159  // Add stamp for whether balancing was active during these voltage samples.
160  voltage_balancestamp = (Balancer_Is_Balancing() == TRUE) ? 0x1 : 0x0;
161 
162  // If under-voltage or over-voltage condition found, suspend balancing but only send once for all boards.
163  suspend_sent = FALSE;
164 
165  // Wait for conversion to be complete.
166  // Note - It is worthwhile to perform some other action while waiting for the ADC conversion to be complete.
167 #if (LTC6804_CONVERSIONS_ALL_7KHZ_DELAY > VOLTAGE_PROCESSING_DURING_DELAY)
168  delay_us(LTC6804_CONVERSIONS_ALL_7KHZ_DELAY - VOLTAGE_PROCESSING_DURING_DELAY);
169 #endif
170 
171  // Read cell voltage ADC values.
172  // Note that broadcast read commands can not be performed by the LTC6804-2, so a loop must be used.
173  for (board_num = 0; board_num < System_Num_Boards; board_num++)
174  {
175  // Start with sum cleared, and flag indicating ADC results were received.
176  results_clear = FALSE;
177  cell_sum = 0;
178 
179  // Read the ADC results
180  LTC6804_Cell_ADC_Read(board_num, LTC6804_CH_ALL, voltage_temp);
181 
182  // Sum to get the voltage for the full board and copy to global variables.
183  // If any results are clear, log an error but do not update the sum of cells.
184  for(cell_num = 0; cell_num < DC2100A_NUM_CELLS; cell_num++)
185  {
186  if(voltage_temp[cell_num] != LTC6804_ADC_CLEAR)
187  {
188  voltage_cell[board_num][cell_num] = voltage_temp[cell_num];
189  cell_sum += voltage_cell[board_num][cell_num];
190  }
191  else
192  {
193  results_clear = TRUE;
194  }
195  }
196 
197  // Scale sum and save.
198  // If any results were clear, send an error.
199  if(results_clear == FALSE)
200  {
201  voltage_sum[board_num] = UNSIGNED_DIVIDE_BY_UNSIGNED_WITH_ROUND(cell_sum, LTC6804_SOC_RESOLUTION/LTC6804_VOLTAGE_RESOLUTION);
202  }
203  else
204  {
205  voltage_error_adc_clear(board_num);
206  }
207 
208  // Check UV and OV flags after system has initialized the thresholds and the ADC results are not clear.
209  if((System_Powered_Up() == TRUE) && (results_clear == FALSE))
210  {
211  // Init temporary storage to current flag values, so that failed reads to not appear as changes
212  vuv_flags = voltage_uv_flags[board_num];
213  vov_flags = voltage_ov_flags[board_num];
214 
215  // Read the under-voltage and over-voltage conditions, which are only updated after the ADC conversion is complete.
216  if(LTC6804_UVOV_Flags_Get(board_num, &vuv_flags, &vov_flags) == TRUE)
217  {
218 
219  // Ignore UV and OV if the cells are not present
220  vov_flags &= voltage_cell_present_flags[board_num];
221  vuv_flags &= voltage_cell_present_flags[board_num];
222 
223  if(vov_flags || vuv_flags)
224  {
225  // todo - Using the balancers to correct and overvoltage or undervoltage condition would be better than suspending,
226  // but requires more knowledge of how the cells are connected.
227  if(suspend_sent == FALSE)
228  {
230  suspend_sent = TRUE;
231  }
232  }
233 
234  // Send Async USB response if UV or OV condition changed.
235  if((vuv_flags != voltage_uv_flags[board_num]) || (vov_flags != voltage_ov_flags[board_num]))
236  {
237  voltage_uv_flags[board_num] = vuv_flags;
238  voltage_ov_flags[board_num] = vov_flags;
239  USB_Parser_Board_Vov_Vuv_Async(board_num);
240  }
241  }
242  }
243  }
244  return;
245 }
246 
247 // Sets the under-voltage and over-voltage thresholds in all DC2100A in the system.
248 BOOLEAN Voltage_UVOV_Thresholds_Set(unsigned int16 vuv_value, unsigned int16 vov_value)
249 {
250  int8 board_num;
251  BOOLEAN write_successful;
252  unsigned int16 vuv_value_temp, vov_value_temp;
253 
254  // Convert from resolution used by voltage module to the resolution used by the LTC6804 to store VUV and VOV thresholds.
255  // LTC6804_UVOV_RESOLUTION doesn't allow for nice round decimal numbers, so select "closest value lower than or equal to" for vov,
256  // and "closest value greater than or equal to" for vuv.
257  vov_value = (vov_value / VOLTAGE_UVOV_CONVERSION) - (vov_value & VOLTAGE_UVOV_ROUND_MASK ? 1 : 0);
258  vuv_value = (vuv_value / VOLTAGE_UVOV_CONVERSION) + (vuv_value & VOLTAGE_UVOV_ROUND_MASK ? 1 : 0);
259 
260  // Write the new values to the LTC6804s
261  LTC6804_UVOV_Thresholds_Set(LTC6804_BROADCAST, vuv_value, vov_value);
262 
263  // Verify that the values were changed for all boards
264  write_successful = TRUE;
265  for (board_num = 0; board_num < System_Num_Boards; board_num++)
266  {
267  LTC6804_UVOV_Thresholds_Get(board_num, &vuv_value_temp, &vov_value_temp);
268  if((vuv_value_temp != vuv_value) || (vov_value_temp != vov_value))
269  {
270  write_successful = FALSE;
271  }
272  }
273 
274  // Convert back to resolution that can be used by FW for comparison against cell voltage measurements.
275  voltage_vov_threshold = vov_value * VOLTAGE_UVOV_CONVERSION;
276  voltage_vuv_threshold = vuv_value * VOLTAGE_UVOV_CONVERSION;
277 
278  return write_successful;
279 }
280 
281 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
282 // Local Functions
283 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
284 
285 // Reports that the adc results were clear when we attempted to read, indicating the LTC6804 did not receive the Start command.
286 void voltage_error_adc_clear(int8 board_num)
287 {
288  int8 temp_data[ERROR_DATA_SIZE];
289  temp_data[0] = board_num;
290  temp_data[1] = UPPER_BYTE(UPPER_WORD(voltage_timestamp));
291  temp_data[2] = LOWER_BYTE(UPPER_WORD(voltage_timestamp));
292  temp_data[3] = UPPER_BYTE(LOWER_WORD(voltage_timestamp));
293  temp_data[4] = LOWER_BYTE(LOWER_WORD(voltage_timestamp));
294  Error_Data_Set(ERROR_CODE_LTC6804_ADC_CLEAR, temp_data, 5);
295 }
BOOLEAN LTC6804_UVOV_Flags_Get(int8 board_num, int16 *vuv_flags, int16 *vov_flags)
Gets the LTC6804 flags indicating under-voltage and over-voltage conditions are present.
Definition: LTC6804-2.c:316
All Cells.
Definition: LTC6804-2.h:100
BOOLEAN Voltage_Wakeup_Init(void)
Initializes the parts of the Voltage Module, that need to be initialized upon wakeup of the LTC6804...
Definition: Voltage.c:128
BOOLEAN LTC6804_UVOV_Thresholds_Get(int8 board_num, unsigned int16 *vuv_value, unsigned int16 *vov_value)
Gets the LTC6804 under-voltage and over-voltage thresholds in LTC6804_UVOV_RESOLUTION units...
Definition: LTC6804-2.c:282
unsigned int16 voltage_ov_flags[DC2100A_MAX_BOARDS]
Bitmap indicating if a cell input on the LTC6804 is over-voltage (1) or not (0).
Definition: Voltage.c:88
void LTC6804_UVOV_Thresholds_Set(int8 board_num, int16 vuv_value, int16 vov_value)
Sets the LTC6804 under-voltage and over-voltage thresholds in LTC6804_UVOV_RESOLUTION units...
Definition: LTC6804-2.c:230
void Balancer_Suspend(void)
Places Balancer Control Task in the BALANCER_CONTROL_SUSPEND state immediately as it's possible there...
Definition: Balancer.c:562
#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 LTC6804_Cell_ADC_Read(int8 board_num, LTC6804_CH_CELL_TYPE cell_select, unsigned int16 *adc_value_ptr)
Reads the LTC6804 Cell Voltage ADC conversion results.
Definition: LTC6804-2.c:502
unsigned int8 voltage_balancestamp
1 if balancers were on when these measurements were taken, otherwise 0
Definition: Voltage.c:84
void LTC6804_Cell_ADC_Start(int8 board_num, LTC6804_CONVERSION_MODE_T mode, LTC6804_CH_CELL_TYPE cell_select, BOOLEAN discharge_permitted)
Starts the LTC6804 Cell Voltage ADC conversion at the specified conversion mode.
Definition: LTC6804-2.c:468
void LTC6804_Cell_ADC_Clear(int8 board_num)
Clears the LTC6804 Cell Voltage ADC registers.
Definition: LTC6804-2.c:447
#define LTC6804_SOC_RESOLUTION
uV per bit (SOC), sum-of-cells resolution.
Definition: LTC6804-2.h:178
API Header File for LTC6804-2 Multicell Battery Monitors.
7kHz conversion mode
Definition: LTC6804-2.h:145
Reference Application File for Monitoring Voltages from the LTC6804-2 Battery Monitor on the DC2100A ...
unsigned int16 voltage_uv_flags[DC2100A_MAX_BOARDS]
Bitmap indicating if a cell input on the LTC6804 is under-voltage (1) or not (0). ...
Definition: Voltage.c:89
unsigned int32 voltage_timestamp
Timestamp taken when voltage measurements were started.
Definition: Voltage.c:83
BOOLEAN Voltage_UVOV_Thresholds_Set(unsigned int16 vuv_value, unsigned int16 vov_value)
Sets the under-voltage and over-voltage thresholds in all DC2100A in the system.
Definition: Voltage.c:248
void Voltage_Init(void)
Initializes the parts of the Voltage Module, that need to be initialized upon power-up of the PIC...
Definition: Voltage.c:106
#define LTC6804_CONVERSIONS_ALL_7KHZ_DELAY
in us, delay between sampling and reading ADC in 7kHz conversion mode
Definition: LTC6804-2.h:167
void Voltage_Monitor_Task(void)
Executes the Voltage Monitor task.
Definition: Voltage.c:140
#define LTC6804_VOLTAGE_RESOLUTION
uV per bit (CxV), cell voltage resolution.
Definition: LTC6804-2.h:176
unsigned int16 voltage_cell[DC2100A_MAX_BOARDS][DC2100A_NUM_CELLS]
Measured cell voltages for each board in LTC6804_VOLTAGE_RESOLUTION.
Definition: Voltage.c:81
unsigned int16 voltage_vov_threshold
over-voltage threshold in LTC6804_VOLTAGE_RESOLUTION.
Definition: Voltage.c:86
unsigned int16 voltage_sum[DC2100A_MAX_BOARDS]
Measured sum of the cell voltages for this board in LTC6804_SOC_RESOLUTION.
Definition: Voltage.c:82
VOLTAGE_CELL_PRESENT_TYPE voltage_cell_present_flags[DC2100A_MAX_BOARDS]
Bitmap indicating if a cell input on the LTC6804 is unpopulated (0), such that UV conditions should b...
Definition: Voltage.c:90
unsigned int16 voltage_vuv_threshold
under-voltage threshold in LTC6804_VOLTAGE_RESOLUTION.
Definition: Voltage.c:87
Reference Application File for Controlling the LTC3300-1 Battery Balancers through the LTC6804-2 Batt...
unsigned int16 VOLTAGE_CELL_PRESENT_TYPE
Bitmap indicating if a cell input on the LTC6804 is populated or shorted.
Definition: Voltage.h:72