Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
DC2515.ino
Go to the documentation of this file.
1 /*! Analog Devices DC2515 Demonstration Board.
2 * LTC6810: 6-Channel Battery Stack Monitors
3 *
4 *@verbatim
5 *NOTES
6 * Setup:
7 * Set the terminal baud rate to 115200 and select the newline terminator.
8 * Ensure all jumpers on the demo board are installed in their default positions from the factory.
9 * Refer to Demo Manual.
10 *
11 *USER INPUT DATA FORMAT:
12 * decimal : 1024
13 * hex : 0x400
14 * octal : 02000 (leading 0)
15 * binary : B10000000000
16 * float : 1024.0
17 *@endverbatim
18 *
19 * https://www.analog.com/en/products/ltc6810-1.html
20 *
21 *********************************************************************************
22 * Copyright 2019(c) Analog Devices, Inc.
23 *
24 * All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions are met:
28 * - Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 * - Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in
32 * the documentation and/or other materials provided with the
33 * distribution.
34 * - Neither the name of Analog Devices, Inc. nor the names of its
35 * contributors may be used to endorse or promote products derived
36 * from this software without specific prior written permission.
37 * - The use of this software may or may not infringe the patent rights
38 * of one or more patent holders. This license does not release you
39 * from the requirement that you obtain separate licenses from these
40 * patent holders to use this software.
41 * - Use of the software either in source or binary form, must be run
42 * on or directly connected to an Analog Devices Inc. component.
43 *
44 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
46 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
48 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
50 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
51 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 ********************************************************************************/
55 
56 /*! @file
57  @ingroup LTC6810-1
58 */
59 
60 /************************************* Read me *******************************************
61 In this sketch book:
62  -All Global Variables are in Upper casing
63  -All Local Variables are in lower casing
64  -The Function wakeup_sleep(TOTAL_IC) : is used to wake the LTC681x from sleep state.
65  It is defined in LTC681x.cpp
66  -The Function wakeup_idle(TOTAL_IC) : is used to wake the ICs connected in daisy chain
67  via the LTC6820 by initiating a dummy SPI communication. It is defined in LTC681x.cpp
68 *******************************************************************************************/
69 
70 /************************* Includes ***************************/
71 #include <Arduino.h>
72 #include <stdint.h>
73 #include <SPI.h>
74 #include "Linduino.h"
75 #include "LT_SPI.h"
76 #include "UserInterface.h"
77 #include "LTC681x.h"
78 #include "LTC6810.h"
79 
80 /************************* Defines *****************************/
81 #define ENABLED 1
82 #define DISABLED 0
83 #define DATALOG_ENABLED 1
84 #define DATALOG_DISABLED 0
85 
86 /**************** Local Function Declaration *******************/
87 void measurement_loop(uint8_t datalog_en);
88 void print_menu(void);
89 void print_wrconfig(void);
90 void print_rxconfig(void);
91 void print_cells(uint8_t datalog_en);
92 void print_aux(uint8_t datalog_en);
93 void print_stat(void);
94 void print_sumofcells(void);
95 void print_svolt(uint8_t datalog_en);
96 void check_mux_fail(void);
97 void print_selftest_errors(uint8_t adc_reg ,int8_t error);
98 void print_digital_redundancy_errors(uint8_t adc_reg ,int8_t error);
99 void print_open_wires(void);
100 void print_pec_error_count(void);
101 int8_t select_s_pin(void);
102 void print_wrpwm(void);
103 void print_rxpwm(void);
104 void print_wrcomm(void);
105 void print_rxcomm(void);
106 void print_sid(void);
107 void reverse_isospi_direction(void);
108 void check_mute_bit(void);
109 void print_conv_time(uint32_t conv_time);
110 void check_error(int error);
111 void serial_print_text(char data[]);
112 void serial_print_hex(uint8_t data);
113 char read_hex(void);
114 char get_char(void);
115 
116 /********************************************************************
117  Setup Variables
118  The following variables can be modified to configure the software.
119 *********************************************************************/
120 const uint8_t TOTAL_IC = 2;//!< Number of ICs in the daisy chain
121 
122 //ADC Command Configurations. See LTC681x.h for options.
123 const uint8_t ADC_OPT = ADC_OPT_DISABLED; //!< ADC Mode option bit
124 const uint8_t ADC_CONVERSION_MODE = MD_7KHZ_3KHZ; //!< ADC Mode
125 const uint8_t ADC_DCP = DCP_DISABLED; //!< Discharge Permitted
126 const uint8_t CELL_CH_TO_CONVERT = CELL_CH_ALL; //!< Channel Selection for ADC conversion
127 const uint8_t AUX_CH_TO_CONVERT = AUX_CH_ALL; //!< Channel Selection for ADC conversion
128 const uint8_t STAT_CH_TO_CONVERT = STAT_CH_ALL; //!< Channel Selection for ADC conversion
129 const uint8_t SEL_ALL_REG = REG_ALL; //!< Register Selection
130 const uint8_t SEL_REG_A = REG_1; //!< Register Selection
131 const uint8_t SEL_REG_B = REG_2; //!< Register Selection
132 
133 //Under Voltage and Over Voltage Thresholds
134 const uint16_t OV_THRESHOLD = 41000; //!< Over voltage threshold ADC Code. LSB = 0.0001 ---(4.1V)
135 const uint16_t UV_THRESHOLD = 30000; //!< Under voltage threshold ADC Code. LSB = 0.0001 ---(1V)
136 
137 const uint16_t MEASUREMENT_LOOP_TIME = 500; //!< Loop Time in milliseconds(ms)
138 
139 //Loop Measurement Setup. These Variables are ENABLED or DISABLED Remember ALL CAPS
140 const uint8_t WRITE_CONFIG = DISABLED; //!< This is to ENABLED or DISABLED writing into to configuration registers in a continuous loop
141 const uint8_t READ_CONFIG = DISABLED; //!< This is to ENABLED or DISABLED reading the configuration registers in a continuous loop
142 const uint8_t MEASURE_CELL = ENABLED; //!< This is to ENABLED or DISABLED measuring the cell voltages in a continuous loop
143 const uint8_t MEASURE_AUX = DISABLED; //!< This is to ENABLED or DISABLED reading the auxiliary registers in a continuous loop
144 const uint8_t MEASURE_STAT = DISABLED; //!< This is to ENABLED or DISABLED reading the status registers in a continuous loop
145 const uint8_t PRINT_PEC = DISABLED; //!< This is to ENABLED or DISABLED printing the PEC Error Count in a continuous loop
146 /************************************
147  END SETUP
148 *************************************/
149 
150 /******************************************************
151  Global Battery Variables received from 681x commands
152  These variables store the results from the LTC6810
153  register reads and the array lengths must be based
154  on the number of ICs on the stack
155  ******************************************************/
156 cell_asic BMS_IC[TOTAL_IC];//!< Global Battery Variable
157 
158 bool ISOSPI_DIR=BMS_IC[0].isospi_reverse;
159 
160 /*************************************************************************
161  Set configuration register. Refer to the data sheet
162 **************************************************************************/
163 bool ADCOPT = false; //!< ADC Mode option bit
164 bool REFON = true; //!< Reference Powered Up Bit
165 bool GPIOBITS[4] = {false,true,true,true}; //!< GPIO Pin Control // Gpio 1,2,3,4
166 uint16_t UV=UV_THRESHOLD; //!< Under voltage Comparison Voltage
167 uint16_t OV=OV_THRESHOLD; //!< Over voltage Comparison Voltage
168 bool DCCBITS[6] = {false,false,false,false,false,false}; //!< Discharge cell switch //Dcc 1,2,3,4,5,6
169 bool DCCBIT_0= false; //!< Discharge cell switch //Dcc 0 // For discharging optional 7th cell
170 bool MCAL = false; //!< Enable Multi-Calibration
171 bool EN_DTMEN = true; //!< Enable Discharge timer monitor
172 bool DIS_RED = false; //!< Disable Digital Redundancy Check
173 bool FDRF = false; //!< Force digital Redundancy Failure
174 bool SCONV = true; //!< Enable Cell Measurement Redundancy using S Pin
175 bool DCTOBITS[4] = {true,false,true,false}; //!< Discharge Time Out Value //Dcto 0,1,2,3 // Programed for 4 min
176 /*Ensure that Dcto bits are set according to the required discharge time. Refer to the data sheet */
177 
178 /*!**********************************************************************
179  \brief Initializes hardware and variables
180  @return void
181  ***********************************************************************/
182 void setup()
183 {
184  Serial.begin(115200);
186  spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock
187  LTC6810_init_cfg(TOTAL_IC, BMS_IC);
188  for (uint8_t current_ic = 0; current_ic<TOTAL_IC; current_ic++)
189  {
191  }
192  LTC6810_reset_crc_count(TOTAL_IC,BMS_IC);
193  LTC6810_init_reg_limits(TOTAL_IC,BMS_IC);
194  print_menu();
195 }
196 
197 /*!*********************************************************************
198  \brief main loop
199  @return void
200 ***********************************************************************/
201 void loop()
202 {
203  if (Serial.available()) // Check for user input
204  {
205  uint32_t user_command;
206  user_command = read_int(); // Read the user command
207  Serial.println(user_command);
208  run_command(user_command);
209  }
210 }
211 
212 /*!*****************************************
213  \brief executes the user command
214  @return void
215 *******************************************/
216 void run_command(uint32_t cmd)
217 {
218  int8_t error = 0;
219  uint32_t conv_time = 0;
220  int8_t s_pin_read=0;
221 
222  switch (cmd)
223  {
224  case 1: // Write and Read Configuration Register
226  LTC6810_wrcfg(TOTAL_IC,BMS_IC); // Write into Configuration Register
227  print_wrconfig();
229  error = LTC6810_rdcfg(TOTAL_IC,BMS_IC); // Read Configuration Register
230  check_error(error);
231  print_rxconfig();
232  break;
233 
234  case 2: // Read Configuration Register
236  error = LTC6810_rdcfg(TOTAL_IC,BMS_IC);
237  check_error(error);
238  print_rxconfig();
239  break;
240 
241  case 3: // Start Cell ADC Measurement
244  conv_time = LTC6810_pollAdc();
245  print_conv_time(conv_time);
246  break;
247 
248  case 4: // Read Cell Voltage Registers
250  error = LTC6810_rdcv(SEL_ALL_REG,TOTAL_IC,BMS_IC); // Set to read back all cell voltage registers
251  check_error(error);
253  break;
254 
255  case 5: // Start GPIO ADC Measurement
258  conv_time = LTC6810_pollAdc();
259  print_conv_time(conv_time);
260  break;
261 
262  case 6: // Read AUX Voltage Registers
264  error = LTC6810_rdaux(SEL_ALL_REG, TOTAL_IC,BMS_IC); // Set to read back all aux registers
265  check_error(error);
267  break;
268 
269  case 7: // Start Status ADC Measurement
272  conv_time=LTC6810_pollAdc();
273  print_conv_time(conv_time);
274  break;
275 
276  case 8: // Read Status registers
278  error = LTC6810_rdstat(SEL_ALL_REG,TOTAL_IC,BMS_IC); // Set to read back all Status registers
279  check_error(error);
280  print_stat();
281  break;
282 
283  case 9:// Start Combined Cell Voltage and Cell 0, GPIO1 Conversion and Poll Status
286  conv_time = LTC6810_pollAdc();
287  print_conv_time(conv_time);
289  error =LTC6810_rdcv(SEL_ALL_REG, TOTAL_IC,BMS_IC); // Set to read back all cell voltage registers
290  check_error(error);
293  error = LTC6810_rdaux(SEL_REG_A,TOTAL_IC,BMS_IC); // Set to read back aux register A
294  check_error(error);
296  break;
297 
298  case 10: //Start Combined Cell Voltage and Sum of cells
301  conv_time = LTC6810_pollAdc();
302  print_conv_time(conv_time);
304  error = LTC6810_rdcv(SEL_ALL_REG,TOTAL_IC,BMS_IC); // Set to read back all cell voltage registers
305  check_error(error);
308  error = LTC6810_rdstat(SEL_REG_A,TOTAL_IC,BMS_IC); // Set to read back stat register A
309  check_error(error);
311  break;
312 
313  case 11: // Read S Voltage Registers
314  /****************************************************************
315  Ensure that the SCONV bit in the configuration register is set.
316  ****************************************************************/
318  LTC6810_wrcfg(TOTAL_IC,BMS_IC); // Write into Configuration Register
320  conv_time = LTC6810_pollAdc();
321  print_conv_time(conv_time);
323  error = LTC6810_rds(SEL_ALL_REG, TOTAL_IC,BMS_IC); // Set to read back all S voltage registers
324  check_error(error);
326  break;
327 
328  case 12: // Loop Measurements of configuration register or cell voltages or auxiliary register or status register without data-log output
330  LTC6810_wrcfg(TOTAL_IC,BMS_IC);
332  print_menu();
333  break;
334 
335  case 13: // Data-log print option Loop Measurements of configuration register or cell voltages or auxiliary register or status register
337  LTC6810_wrcfg(TOTAL_IC,BMS_IC);
339  print_menu();
340  break;
341 
342  case 14: // Clear all ADC measurement registers
344  LTC6810_clrcell();
345  LTC6810_clraux();
346  LTC6810_clrstat();
348  LTC6810_rdcv(SEL_ALL_REG, TOTAL_IC,BMS_IC); // Set to read back all cell voltage registers
350 
352  LTC6810_rdaux(SEL_ALL_REG,TOTAL_IC,BMS_IC); // Set to read back all aux registers
354 
356  LTC6810_rdstat(SEL_ALL_REG,TOTAL_IC,BMS_IC); // Set to read back all status registers
357  print_stat();
358  break;
359 
360  case 15: // Run the Mux Decoder Self Test
362  LTC6810_diagn();
363  conv_time = LTC6810_pollAdc();
364  print_conv_time(conv_time);
365  error = LTC6810_rdstat(SEL_REG_B,TOTAL_IC,BMS_IC); // Set to read back Status registers B
366  check_error(error);
367  check_mux_fail();
368  break;
369 
370  case 16: // Run the ADC/Memory Self Test
371  error =0;
374  print_selftest_errors(CELL, error);
375 
376  error =0;
379  print_selftest_errors(AUX, error);
380 
381  error =0;
384  print_selftest_errors(STAT, error);
385  print_menu();
386  break;
387 
388  case 17: // Run ADC Digital Redundancy test
389  error =0;
393 
394  error =0;
398  break;
399 
400  case 18: // Open Wire test for single cell detection
404  break;
405 
406  case 19: // Open Wire test for multiple cell and two consecutive cells detection
409  break;
410 
411  case 20: // Open wire Diagnostic for Auxiliary Measurements
415  break;
416 
417  case 21: // PEC Errors Detected
419  break;
420 
421  case 22: //Reset PEC Counter
424  break;
425 
426  case 23: // Enable a discharge transistor
427  s_pin_read = select_s_pin();
428  LTC6810_set_discharge(s_pin_read,TOTAL_IC,BMS_IC);
430  LTC6810_wrcfg(TOTAL_IC,BMS_IC);
431  print_wrconfig();
433  error = LTC6810_rdcfg(TOTAL_IC,BMS_IC);
434  check_error(error);
435  print_rxconfig();
436  break;
437 
438  case 24: // Clear all discharge transistors
441  LTC6810_wrcfg(TOTAL_IC,BMS_IC);
442  print_wrconfig();
444  error = LTC6810_rdcfg(TOTAL_IC,BMS_IC);
445  check_error(error);
446  print_rxconfig();
447  break;
448 
449  case 25://Write and read pwm configuration
450  /*****************************************************
451  Choose the value to be configured depending on the
452  required duty cycle. Refer to the data sheet.
453  Ensure that the DCTO value in the Configuration
454  Register Group is set to a non-zero value.
455  *******************************************************/
457 
458  for (uint8_t current_ic = 0; current_ic<TOTAL_IC;current_ic++)
459  {
460  BMS_IC[current_ic].pwm.tx_data[0]= 0x88; // PWM Duty cycle for cell 2 and 1
461  BMS_IC[current_ic].pwm.tx_data[1]= 0x88; // PWM Duty cycle for cell 4 and 3
462  BMS_IC[current_ic].pwm.tx_data[2]= 0x88; // PWM Duty cycle for cell 6 and 5
463  }
464  LTC6810_wrpwm(TOTAL_IC,0,BMS_IC);
465  print_wrpwm();
466 
467  wakeup_idle(TOTAL_IC);
468  error=LTC6810_rdpwm(TOTAL_IC,0,BMS_IC);
469  check_error(error);
470  print_rxpwm();
471  break;
472 
473  case 26://SPI Communication
474  /**************************************************************
475  Ensure to set the GPIO bits to 1 in the CFG register group.
476  ****************************************************************/
477  for (uint8_t current_ic = 0; current_ic<TOTAL_IC;current_ic++)
478  {
479  //Communication control bits and communication data bytes. Refer to the data sheet.
480  BMS_IC[current_ic].com.tx_data[0]= 0x81; // Icom CSBM Low(8) + data D0 (0x11)
481  BMS_IC[current_ic].com.tx_data[1]= 0x10; // Fcom CSBM Low(0)
482  BMS_IC[current_ic].com.tx_data[2]= 0xA2; // Icom CSBM Falling Edge (A) + D1 (0x25)
483  BMS_IC[current_ic].com.tx_data[3]= 0x50; // Fcom CSBM Low(0)
484  BMS_IC[current_ic].com.tx_data[4]= 0xA1; // Icom CSBM Falling Edge (A) + D2 (0x17)
485  BMS_IC[current_ic].com.tx_data[5]= 0x79; // Fcom CSBM High(9)
486  }
487  wakeup_sleep(TOTAL_IC);
488  LTC6810_wrcomm(TOTAL_IC,BMS_IC); // write to comm register
489  print_wrcomm(); // print data in the comm register
490 
491  wakeup_idle(TOTAL_IC);
492  LTC6810_stcomm(3); // data length=3 // initiates communication between master and the I2C slave
493 
494  wakeup_idle(TOTAL_IC);
495  error = LTC6810_rdcomm(TOTAL_IC,BMS_IC); // read from comm register
496  check_error(error);
497  print_rxcomm(); // print received data into the comm register
498  break;
499 
500  case 27: // Write byte I2C Communication on the GPIO Ports(using I2C eeprom 24LC025)
501  /************************************************************
502  Ensure to set the GPIO bits to 1 in the CFG register group.
503  *************************************************************/
504  for (uint8_t current_ic = 0; current_ic<TOTAL_IC;current_ic++)
505  {
506  //Communication control bits and communication data bytes. Refer to the data sheet.
507  BMS_IC[current_ic].com.tx_data[0]= 0x6A; // Icom Start(6) + I2C_address D0 (0xA0)
508  BMS_IC[current_ic].com.tx_data[1]= 0x08; // Fcom master NACK(8)
509  BMS_IC[current_ic].com.tx_data[2]= 0x00; // Icom Blank (0) + eeprom address D1 (0x00)
510  BMS_IC[current_ic].com.tx_data[3]= 0x08; // Fcom master NACK(8)
511  BMS_IC[current_ic].com.tx_data[4]= 0x01; // Icom Blank (0) + data D2 (0x10)
512  BMS_IC[current_ic].com.tx_data[5]= 0x09; // Fcom master NACK + Stop(9)
513  }
514  wakeup_sleep(TOTAL_IC);
515  LTC6810_wrcomm(TOTAL_IC,BMS_IC);// write to comm register
516  print_wrcomm(); // print data from the comm register
517 
518  wakeup_idle(TOTAL_IC);
519  LTC6810_stcomm(3); // data length=3 // initiates communication between master and the I2C slave
520 
521  wakeup_idle(TOTAL_IC);
522  error = LTC6810_rdcomm(TOTAL_IC,BMS_IC); // read from comm register
523  check_error(error);
524  print_rxcomm(); // print received data into the comm register
525  break;
526 
527  case 28: // Read byte data I2C Communication on the GPIO Ports(using I2C eeprom 24LC025 )
528  /************************************************************
529  Ensure to set the GPIO bits to 1 in the CFG register group.
530  *************************************************************/
531  for (uint8_t current_ic = 0; current_ic<TOTAL_IC;current_ic++)
532  {
533  //Communication control bits and communication data bytes. Refer to the data sheet.
534  BMS_IC[current_ic].com.tx_data[0]= 0x6A; // Icom Start (6) + I2C_address D0 (A0) (Write operation to set the word address)
535  BMS_IC[current_ic].com.tx_data[1]= 0x08; // Fcom master NACK(8)
536  BMS_IC[current_ic].com.tx_data[2]= 0x00; // Icom Blank (0) + eeprom address(word address) D1 (0x00)
537  BMS_IC[current_ic].com.tx_data[3]= 0x08; // Fcom master NACK(8)
538  BMS_IC[current_ic].com.tx_data[4]= 0x6A; // Icom Start (6) + I2C_address D2 (0xA1)(Read operation)
539  BMS_IC[current_ic].com.tx_data[5]= 0x18; // Fcom master NACK(8)
540  }
541  wakeup_sleep(TOTAL_IC);
542  LTC6810_wrcomm(TOTAL_IC,BMS_IC); // write to comm register
543 
544  wakeup_idle(TOTAL_IC);
545  LTC6810_stcomm(3); // data length=3 // initiates communication between master and the I2C slave
546 
547  for (uint8_t current_ic = 0; current_ic<TOTAL_IC;current_ic++)
548  {
549  //Communication control bits and communication data bytes. Refer to the data sheet.
550  BMS_IC[current_ic].com.tx_data[0]= 0x0F; // Icom Blank (0) + data D0 (FF)
551  BMS_IC[current_ic].com.tx_data[1]= 0xF9; // Fcom master NACK + Stop(9)
552  BMS_IC[current_ic].com.tx_data[2]= 0x7F; // Icom No Transmit (7) + data D1 (FF)
553  BMS_IC[current_ic].com.tx_data[3]= 0xF9; // Fcom master NACK + Stop(9)
554  BMS_IC[current_ic].com.tx_data[4]= 0x7F; // Icom No Transmit (7) + data D2 (FF)
555  BMS_IC[current_ic].com.tx_data[5]= 0xF9; // Fcom master NACK + Stop(9)
556  }
557  wakeup_idle(TOTAL_IC);
558  LTC6810_wrcomm(TOTAL_IC,BMS_IC); // write to comm register
559 
560  wakeup_idle(TOTAL_IC);
561  LTC6810_stcomm(1); // data length=1 // initiates communication between master and the I2C slave
562 
563  wakeup_idle(TOTAL_IC);
564  error = LTC6810_rdcomm(TOTAL_IC,BMS_IC); // read from comm register
565  check_error(error);
566  print_rxcomm(); // print received data from the comm register
567  break;
568 
569  case 29: // To Reverse the direction of ISOSPI communication in a daisy chain connection
571  break;
572 
573  case 30: // Read SID Register Group
574  wakeup_sleep(TOTAL_IC);
575  error = LTC6810_rdsid(TOTAL_IC,BMS_IC);
576  check_error(error);
577  print_sid();
578  break;
579 
580  case 31: // To Mute discharging
581  wakeup_sleep(TOTAL_IC);
582  LTC6810_mute();
583  wakeup_idle(TOTAL_IC);
584  error = LTC6810_rdstat(SEL_REG_B,TOTAL_IC,BMS_IC); // Set to read back Status registers B
585  check_error(error);
586  check_mute_bit();
587  break;
588 
589  case 32: // To Unmute discharging
590  wakeup_sleep(TOTAL_IC);
591  LTC6810_unmute();
592  wakeup_idle(TOTAL_IC);
593  error = LTC6810_rdstat(SEL_REG_B,TOTAL_IC,BMS_IC); // Set to read back Status registers B
594  check_error(error);
595  check_mute_bit();
596  break;
597 
598  case 33: // Set or reset the gpio pins(to drive output on gpio pins)
599  /***********************************************************************
600  Please ensure you have set the GPIO bits according to your requirement
601  in the configuration register.( check the global variable GPIOBITS )
602  ************************************************************************/
603  wakeup_sleep(TOTAL_IC);
604  for (uint8_t current_ic = 0; current_ic<TOTAL_IC;current_ic++)
605  {
607  }
608  wakeup_idle(TOTAL_IC);
609  LTC6810_wrcfg(TOTAL_IC,BMS_IC);
610  print_wrconfig();
611  break;
612 
613  case 'm': //prints menu
614  print_menu();
615  break;
616 
617  default:
618  char str_error[]="Incorrect Option \n";
619  serial_print_text(str_error);
620  break;
621  }
622 }
623 
624 /*!**********************************************************************************************************************************************
625  \brief For writing/reading configuration data or measuring cell voltages or reading aux register or reading status register in a continuous loop
626  @return void
627 *************************************************************************************************************************************************/
628 void measurement_loop(uint8_t datalog_en)
629 {
630  int8_t error = 0;
631  char input = 0;
632 
633  Serial.println(F("Transmit 'm' to quit"));
634 
635  while (input != 'm')
636  {
637  if (Serial.available() > 0)
638  {
639  input = read_char();
640  }
641 
642  if (WRITE_CONFIG == ENABLED)
643  {
645  LTC6810_wrcfg(TOTAL_IC,BMS_IC);
646  print_wrconfig();
647  }
648 
649  if (READ_CONFIG == ENABLED)
650  {
652  error = LTC6810_rdcfg(TOTAL_IC,BMS_IC);
653  check_error(error);
654  print_rxconfig();
655  }
656 
657  if (MEASURE_CELL == ENABLED)
658  {
661  LTC6810_pollAdc();
663  error = LTC6810_rdcv(SEL_ALL_REG, TOTAL_IC,BMS_IC);
664  check_error(error);
665  print_cells(datalog_en);
666  }
667 
668  if (MEASURE_AUX == ENABLED)
669  {
672  LTC6810_pollAdc();
674  error = LTC6810_rdaux(SEL_ALL_REG,TOTAL_IC,BMS_IC); // Set to read back all aux registers
675  check_error(error);
676  print_aux(datalog_en);
677  }
678 
679  if (MEASURE_STAT == ENABLED)
680  {
683  LTC6810_pollAdc();
685  error = LTC6810_rdstat(SEL_ALL_REG,TOTAL_IC,BMS_IC); // Set to read back all stat registers
686  check_error(error);
687  print_stat();
688  }
689 
690  if(PRINT_PEC == ENABLED)
691  {
693  }
694  delay(MEASUREMENT_LOOP_TIME);
695  }
696 }
697 
698 /*!*********************************
699  \brief Prints the main menu
700  @return void
701 ***********************************/
702 void print_menu(void)
703 {
704  Serial.println(F("Please enter LTC6810 Command"));
705  Serial.println(F("Write and Read Configuration: 1 |Loop Measurements: 12 |Set Discharge: 23"));
706  Serial.println(F("Read Configuration: 2 |Loop Measurements with Data Log output : 13 |Clear Discharge: 24"));
707  Serial.println(F("Start Cell Voltage Conversion: 3 |Clear all ADC Measurement Registers: 14 |Write and Read of PWM : 25"));
708  Serial.println(F("Read Cell Voltages: 4 |Run Mux Self Test: 15 |SPI Communication : 26"));
709  Serial.println(F("Start Aux Voltage Conversion: 5 |Run ADC Self Test: 16 |I2C Communication Write to Slave :27"));
710  Serial.println(F("Read Aux Voltages: 6 |Run Digital Redundancy Test: 17 |I2C Communication Read from Slave :28"));
711  Serial.println(F("Start Stat Voltage Conversion: 7 |Open Wire Test for single cell detection: 18 |Reverse ISOSPI : 29"));
712  Serial.println(F("Read Stat Voltages: 8 |Open Wire Test for multiple cell or two consecutive cells detection: 19|Read Serial ID : 30"));
713  Serial.println(F("Start Combined Cell Voltage and Cell 0, GPIO2 Conversion: 9|Open wire for Auxiliary Measurement: 20 |Enable MUTE : 31"));
714  Serial.println(F("Start Cell Voltage and Sum of cells: 10 |Print PEC Counter: 21 |Disable MUTE : 32"));
715  Serial.println(F("Read S Voltage Registers: 11 |Reset PEC Counter: 22 |Set or reset the gpio pins: 33 \n"));
716  Serial.println(F("Print 'm' for menu"));
717  Serial.println(F("Please enter command: \n"));
718 }
719 
720 /*!******************************************************************************
721  \brief Prints the configuration data that is going to be written to the LTC6810
722  to the serial port.
723  @return void
724  ********************************************************************************/
725 void print_wrconfig(void)
726 {
727  int cfg_pec;
728 
729  Serial.println(F("Written Configuration: "));
730  for (int current_ic = 0; current_ic<TOTAL_IC; current_ic++)
731  {
732  Serial.print(F("CFGA IC "));
733  Serial.print(current_ic+1,DEC);
734  for(int i = 0;i<6;i++)
735  {
736  Serial.print(F(", 0x"));
737  serial_print_hex(BMS_IC[current_ic].config.tx_data[i]);
738  }
739  Serial.print(F(", Calculated PEC: 0x"));
740  cfg_pec = pec15_calc(6,&BMS_IC[current_ic].config.tx_data[0]);
741  serial_print_hex((uint8_t)(cfg_pec>>8));
742  Serial.print(F(", 0x"));
743  serial_print_hex((uint8_t)(cfg_pec));
744  Serial.println("\n");
745  }
746 }
747 
748 /*!*****************************************************************
749  \brief Prints the configuration data that was read back from the
750  LTC6810 to the serial port.
751  @return void
752  *******************************************************************/
753 void print_rxconfig(void)
754 {
755  Serial.println(F("Received Configuration "));
756  for (int current_ic=0; current_ic<TOTAL_IC; current_ic++)
757  {
758  Serial.print(F("CFGA IC "));
759  Serial.print(current_ic+1,DEC);
760  for(int i = 0; i < 6; i++)
761  {
762  Serial.print(F(", 0x"));
763  serial_print_hex(BMS_IC[current_ic].config.rx_data[i]);
764  }
765  Serial.print(F(", Received PEC: 0x"));
766  serial_print_hex(BMS_IC[current_ic].config.rx_data[6]);
767  Serial.print(F(", 0x"));
768  serial_print_hex(BMS_IC[current_ic].config.rx_data[7]);
769  Serial.println("\n");
770  }
771 }
772 
773 /*!************************************************************
774  \brief Prints cell voltage codes to the serial port
775  @return void
776  *************************************************************/
777 void print_cells(uint8_t datalog_en)
778 {
779  for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++)
780  {
781  if (datalog_en == 0)
782  {
783  Serial.print(" IC ");
784  Serial.print(current_ic+1,DEC);
785  Serial.print(": "); for (int i=0; i< BMS_IC[0].ic_reg.cell_channels; i++)
786  {
787  Serial.print(" C");
788  Serial.print(i+1,DEC);
789  Serial.print(":");
790  Serial.print(BMS_IC[current_ic].cells.c_codes[i]*0.0001,4);
791  Serial.print(",");
792  }
793  Serial.println();
794  }
795  else
796  {
797  Serial.print(" Cells :");
798  for (int i=0; i<BMS_IC[0].ic_reg.cell_channels; i++)
799  {
800  Serial.print(BMS_IC[current_ic].cells.c_codes[i]*0.0001,4);
801  Serial.print(",");
802  }
803  }
804  }
805  Serial.println("\n");
806 }
807 
808 /*!****************************************************************************
809  \brief Prints GPIO voltage codes and Vref2 voltage code onto the serial port
810  @return void
811  *****************************************************************************/
812 void print_aux(uint8_t datalog_en)
813 {
814  for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++)
815  {
816  if (datalog_en == 0)
817  {
818  Serial.print(" IC ");
819  Serial.print(current_ic+1,DEC);
820  Serial.print(F(": S0_V :"));
821  Serial.print(BMS_IC[current_ic].aux.a_codes[0]*0.0001,4);
822  Serial.print(",");
823  for (int i = 1; i < 5; i++)
824  {
825  Serial.print(F(" GPIO-"));
826  Serial.print(i,DEC);
827  Serial.print(":");
828  Serial.print(BMS_IC[current_ic].aux.a_codes[i]*0.0001,4);
829  Serial.print(",");
830  }
831  Serial.print(F(" Vref2 :"));
832  Serial.print(BMS_IC[current_ic].aux.a_codes[5]*0.0001,4);
833  Serial.println();
834  }
835  else
836  {
837  Serial.print("AUX :");
838 
839  for (int i=0; i < 6; i++)
840  {
841  Serial.print(BMS_IC[current_ic].aux.a_codes[i]*0.0001,4);
842  Serial.print(",");
843  }
844  }
845  }
846  Serial.println("\n");
847 }
848 
849 /*!*****************************************************************************
850  \brief Prints Status voltage codes and Vref2 voltage code onto the serial port
851  @return void
852  ******************************************************************************/
853 void print_stat(void)
854 {
855  double itmp;
856  for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++)
857  {
858  Serial.print(F(" IC "));
859  Serial.print(current_ic+1,DEC);
860  Serial.print(F(" SOC:"));
861  Serial.print(BMS_IC[current_ic].stat.stat_codes[0]*0.0001*10,4);
862  Serial.print(F(", Itemp:"));
863  itmp = (double)((BMS_IC[current_ic].stat.stat_codes[1] * (0.0001 / 0.0075)) - 273); //Internal Die Temperature(°C) = ITMP • (100 µV / 7.5mV)°C - 273°C
864  Serial.print(itmp,4);
865  Serial.print(F(", VregA:"));
866  Serial.print(BMS_IC[current_ic].stat.stat_codes[2]*0.0001,4);
867  Serial.print(F(", VregD:"));
868  Serial.println(BMS_IC[current_ic].stat.stat_codes[3]*0.0001,4);
869  Serial.print(F(" Flag bits: 0x"));
870  serial_print_hex(BMS_IC[current_ic].stat.flags[0]);
871  Serial.print(F(",\t Flag bits and Mute bit:"));
872  Serial.print(F(" 0x"));
873  serial_print_hex((BMS_IC[current_ic].stat.flags[1])&(0x1F));
874  Serial.print(F(",\t Mux fail flag:"));
875  Serial.print(F(" 0x"));
876  serial_print_hex(BMS_IC[current_ic].stat.mux_fail[0]);
877  Serial.print(F(",\t THSD:"));
878  Serial.print(F(" 0x"));
879  serial_print_hex(BMS_IC[current_ic].stat.thsd[0]);
880  Serial.println("\n");
881  }
882 }
883 
884 /*!****************************************************************************
885  \brief Prints Status voltage codes for SOC onto the serial port
886  @return void
887  *****************************************************************************/
889 {
890  for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++)
891  {
892  Serial.print(F(" IC "));
893  Serial.print(current_ic+1,DEC);
894  Serial.print(F(": SOC:"));
895  Serial.print(BMS_IC[current_ic].stat.stat_codes[0]*0.0001*10,4);
896  Serial.print(F(","));
897  }
898  Serial.println("\n");
899 }
900 
901 /*!************************************************************
902  \brief Prints S voltage codes to the serial port
903  @return void
904 *************************************************************/
905 void print_svolt(uint8_t datalog_en)
906 {
907  for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++)
908  {
909  if (datalog_en == 0)
910  {
911  Serial.print(" IC ");
912  Serial.print(current_ic+1,DEC);
913  Serial.print(": ");
914  int j=1;
915  for (int i=6; i<12; i++)
916  {
917  Serial.print(" S");
918  Serial.print(j,DEC);
919  Serial.print(":");
920  Serial.print(BMS_IC[current_ic].cells.c_codes[i]*0.0001,4);
921  Serial.print(",");
922  j++;
923  }
924  Serial.println();
925  }
926  else
927  {
928  Serial.print("S pin:, ");
929  for (int i=6; i<12; i++)
930  {
931  Serial.print(BMS_IC[current_ic].cells.c_codes[i]*0.0001,4);
932  Serial.print(",");
933  }
934  }
935  }
936  Serial.println("\n");
937 }
938 
939 /*!****************************************************************
940  \brief Function to check the MUX fail bit in the Status Register
941  @return void
942 *******************************************************************/
943 void check_mux_fail(void)
944 {
945  int8_t error = 0;
946  for (int ic = 0; ic<TOTAL_IC; ic++)
947  {
948  Serial.print(" IC ");
949  Serial.println(ic+1,DEC);
950  if (BMS_IC[ic].stat.mux_fail[0] != 0) error++;
951 
952  if (error==0) Serial.println(F("Mux Test: PASS \n"));
953  else Serial.println(F("Mux Test: FAIL \n"));
954  }
955 }
956 
957 /*!************************************************************
958  \brief Prints Errors Detected during self test
959  @return void
960 *************************************************************/
961 void print_selftest_errors(uint8_t adc_reg ,int8_t error)
962 {
963  if(adc_reg==1)
964  {
965  Serial.println("Cell ");
966  }
967  else if(adc_reg==2)
968  {
969  Serial.println("Aux ");
970  }
971  else if(adc_reg==3)
972  {
973  Serial.println("Stat ");
974  }
975  Serial.print(error, DEC);
976  Serial.println(F(" : errors detected in Digital Filter and Memory \n"));
977 }
978 
979 /*!************************************************************
980  \brief Prints Errors Detected during Digital Redundancy test
981  @return void
982 *************************************************************/
983 void print_digital_redundancy_errors(uint8_t adc_reg ,int8_t error)
984 {
985  if(adc_reg==2)
986  {
987  Serial.println("Aux ");
988  }
989  else if(adc_reg==3)
990  {
991  Serial.println("Stat ");
992  }
993 
994  Serial.print(error, DEC);
995  Serial.println(F(" : errors detected in Measurement \n"));
996  }
997 
998 /*!****************************************************************************
999  \brief Prints Open wire test results to the serial port
1000  @return void
1001  *****************************************************************************/
1003 {
1004  for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++)
1005  {
1006  if (BMS_IC[current_ic].system_open_wire == 65535)
1007  {
1008  Serial.print("No Opens Detected on IC ");
1009  Serial.print(current_ic+1, DEC);
1010  }
1011  else
1012  {
1013  Serial.print(F("There is an open wire on IC "));
1014  Serial.print(current_ic + 1,DEC);
1015  Serial.print(F(" Channel: "));
1016  Serial.println(BMS_IC[current_ic].system_open_wire);
1017  }
1018  Serial.println("\n");
1019  }
1020 }
1021 
1022 /*!****************************************************************************
1023  \brief Function to print the number of PEC Errors
1024  @return void
1025  *****************************************************************************/
1027 {
1028  for (int current_ic=0; current_ic<TOTAL_IC; current_ic++)
1029  {
1030  Serial.println("");
1031  Serial.print(BMS_IC[current_ic].crc_count.pec_count,DEC);
1032  Serial.print(F(" : PEC Errors Detected on IC"));
1033  Serial.println(current_ic+1,DEC);
1034  }
1035  Serial.println("\n");
1036 }
1037 
1038 /*!****************************************************
1039  \brief Function to select the S pin for discharge
1040  @return void
1041  ******************************************************/
1042 int8_t select_s_pin(void)
1043 {
1044  int8_t read_s_pin=0;
1045 
1046  Serial.print(F("Please enter the Spin number: "));
1047  read_s_pin = (int8_t)read_int();
1048  Serial.println(read_s_pin);
1049  return(read_s_pin);
1050 }
1051 
1052 /*!***********************************************************************************
1053  \brief Prints PWM the configuration data that is going to be written to the LTC6810
1054  to the serial port.
1055  @return void
1056  ************************************************************************************/
1057 void print_wrpwm(void)
1058 {
1059  int pwm_pec;
1060 
1061  Serial.println(F("Written PWM Configuration: "));
1062  for (uint8_t current_ic = 0; current_ic<TOTAL_IC; current_ic++)
1063  {
1064  Serial.print(F("IC "));
1065  Serial.print(current_ic+1,DEC);
1066  for(int i = 0; i < 6; i++)
1067  {
1068  Serial.print(F(", 0x"));
1069  serial_print_hex(BMS_IC[current_ic].pwm.tx_data[i]);
1070  }
1071  Serial.print(F(", Calculated PEC: 0x"));
1072  pwm_pec = pec15_calc(6,&BMS_IC[current_ic].pwm.tx_data[0]);
1073  serial_print_hex((uint8_t)(pwm_pec>>8));
1074  Serial.print(F(", 0x"));
1075  serial_print_hex((uint8_t)(pwm_pec));
1076  Serial.println("\n");
1077  }
1078 }
1079 
1080 /*!*****************************************************************
1081  \brief Prints the PWM configuration data that was read back from the
1082  LTC6810 to the serial port.
1083  @return void
1084  *******************************************************************/
1085 void print_rxpwm(void)
1086 {
1087  Serial.println(F("Received pwm Configuration:"));
1088  for (uint8_t current_ic=0; current_ic<TOTAL_IC; current_ic++)
1089  {
1090  Serial.print(F("IC "));
1091  Serial.print(current_ic+1,DEC);
1092  for(int i = 0; i < 6; i++)
1093  {
1094  Serial.print(F(", 0x"));
1095  serial_print_hex(BMS_IC[current_ic].pwm.rx_data[i]);
1096  }
1097  Serial.print(F(", Received PEC: 0x"));
1098  serial_print_hex(BMS_IC[current_ic].pwm.rx_data[6]);
1099  Serial.print(F(", 0x"));
1100  serial_print_hex(BMS_IC[current_ic].pwm.rx_data[7]);
1101  Serial.println("\n");
1102  }
1103 }
1104 
1105 /*!****************************************************************************
1106  /prints data which is written on COMM register onto the serial port
1107  @return void
1108  *****************************************************************************/
1109 void print_wrcomm(void)
1110 {
1111  int comm_pec;
1112 
1113  Serial.println(F("Written Data in COMM Register: "));
1114  for (int current_ic = 0; current_ic<TOTAL_IC; current_ic++)
1115  {
1116  Serial.print(F(" IC- "));
1117  Serial.print(current_ic+1,DEC);
1118 
1119  for(int i = 0; i < 6; i++)
1120  {
1121  Serial.print(F(", 0x"));
1122  serial_print_hex(BMS_IC[current_ic].com.tx_data[i]);
1123  }
1124  Serial.print(F(", Calculated PEC: 0x"));
1125  comm_pec = pec15_calc(6,&BMS_IC[current_ic].com.tx_data[0]);
1126  serial_print_hex((uint8_t)(comm_pec>>8));
1127  Serial.print(F(", 0x"));
1128  serial_print_hex((uint8_t)(comm_pec));
1129  Serial.println("\n");
1130  }
1131 }
1132 
1133 /*!****************************************************************************
1134  \brief Prints received data from COMM register onto the serial port
1135  @return void
1136  *****************************************************************************/
1137 void print_rxcomm(void)
1138 {
1139  Serial.println(F("Received Data in COMM register:"));
1140  for (int current_ic=0; current_ic<TOTAL_IC; current_ic++)
1141  {
1142  Serial.print(F(" IC- "));
1143  Serial.print(current_ic+1,DEC);
1144 
1145  for(int i = 0; i < 6; i++)
1146  {
1147  Serial.print(F(", 0x"));
1148  serial_print_hex(BMS_IC[current_ic].com.rx_data[i]);
1149  }
1150  Serial.print(F(", Received PEC: 0x"));
1151  serial_print_hex(BMS_IC[current_ic].com.rx_data[6]);
1152  Serial.print(F(", 0x"));
1153  serial_print_hex(BMS_IC[current_ic].com.rx_data[7]);
1154  Serial.println("\n");
1155  }
1156 }
1157 
1158 /*!******************************************************************************
1159  \brief Prints Serial ID to the serial port.
1160  @return void
1161  ********************************************************************************/
1162 void print_sid(void)
1163 {
1164  int sid_pec;
1165 
1166  Serial.println(F("Serial ID: "));
1167  for (uint8_t current_ic = 0; current_ic<TOTAL_IC; current_ic++)
1168  {
1169  Serial.print(F("IC "));
1170  Serial.print(current_ic+1,DEC);
1171 
1172  for(int i = 0; i < 6; i++)
1173  {
1174  Serial.print(F(", 0x"));
1175  serial_print_hex(BMS_IC[current_ic].sid[i]);
1176  }
1177  Serial.print(F(", Calculated PEC: 0x"));
1178  sid_pec = pec15_calc(6,&BMS_IC[current_ic].sid[0]);
1179  serial_print_hex((uint8_t)(sid_pec>>8));
1180  Serial.print(F(", 0x"));
1181  serial_print_hex((uint8_t)(sid_pec));
1182  Serial.println("\n");
1183  }
1184 }
1185 
1186 /*!****************************************************************
1187  \brief Function to reverse the direction of ISOSPI communication
1188  when the ICs are connected in daisy chain
1189  @return void
1190 *******************************************************************/
1192 {
1193  Serial.print(F("ISOSPI: "));
1194  Serial.println(ISOSPI_DIR);
1195  BMS_IC[0].isospi_reverse =(bool)(!( ISOSPI_DIR));
1196  ISOSPI_DIR=BMS_IC[0].isospi_reverse;
1197  Serial.print(F("Current ISOSPI Direction: "));
1198  Serial.println(BMS_IC[0].isospi_reverse);
1199  Serial.println("\n");
1200 }
1201 
1202 /*!****************************************************************
1203  \brief Function to check the Mute bit in the Status Register
1204  @return void
1205 *******************************************************************/
1206 void check_mute_bit(void)
1207 {
1208  for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++)
1209  {
1210  Serial.print(F(" Mute bit in Status Register B: 0x"));
1211  serial_print_hex((BMS_IC[current_ic].stat.flags[1])&(0x10));
1212  Serial.println("\n");
1213  }
1214 }
1215 
1216 /*!****************************************************************************
1217  \brief Function to print the Conversion Time
1218  @return void
1219  *****************************************************************************/
1220 void print_conv_time(uint32_t conv_time)
1221 {
1222  uint16_t m_factor=1000; // to print in ms
1223 
1224  Serial.print(F("Conversion completed in:"));
1225  Serial.print(((float)conv_time/m_factor), 1);
1226  Serial.println(F("ms \n"));
1227 }
1228 
1229 /*!****************************************************************************
1230  \brief Function to check error flag and print PEC error message
1231  @return void
1232  *****************************************************************************/
1234 {
1235  if (error == -1)
1236  {
1237  Serial.println(F("A PEC error was detected in the received data"));
1238  }
1239 }
1240 
1241 /*!************************************************************
1242  \brief Function to print text on serial monitor
1243  @return void
1244 *************************************************************/
1246 {
1247  Serial.println(data);
1248 }
1249 
1250 /*!************************************************************
1251  \brief Function to print in HEX form
1252  @return void
1253 *************************************************************/
1254 void serial_print_hex(uint8_t data)
1255 {
1256  if (data< 16)
1257  {
1258  Serial.print("0");
1259  Serial.print((byte)data,HEX);
1260  }
1261  else
1262  Serial.print((byte)data,HEX);
1263 }
1264 
1265 /*!************************************************************
1266  \brief Hex conversion constants
1267  *************************************************************/
1268 char hex_digits[16]=
1269 {
1270  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
1271 };
1272 
1273 /*!************************************************************
1274  \brief Global Variables
1275  *************************************************************/
1277 {
1278  '0', 'x', '0', '0', '\0'
1279 };
1280 
1281 /*!************************************************************
1282  \brief Buffer for ASCII hex to byte conversion
1283  *************************************************************/
1285 {
1286  '\0','\0','\0'
1287 };
1288 
1289 /*!****************************************************************************
1290  \brief Read 2 hex characters from the serial buffer and convert them to a byte
1291  @return char data Read Data
1292  *****************************************************************************/
1293 char read_hex(void)
1294 {
1295  byte data;
1298  get_char();
1299  get_char();
1300  data = strtol(hex_to_byte_buffer, NULL, 0);
1301  return(data);
1302 }
1303 
1304 /*!************************************************************
1305  \brief Read a command from the serial port
1306  @return char
1307  *************************************************************/
1308 char get_char(void)
1309 {
1310  // read a command from the serial port
1311  while (Serial.available() <= 0);
1312  return(Serial.read());
1313 }
bool DCCBITS[6]
Discharge cell switch //Dcc 1,2,3,4,5,6.
Definition: DC2515.ino:168
static void print_open_wires(void)
Definition: DC2515.ino:1002
const uint8_t MEASURE_AUX
This is to ENABLED or DISABLED reading the auxiliary registers in a continuous loop.
Definition: DC2515.ino:143
int16_t LTC6810_run_cell_adc_st(uint8_t adc_reg, uint8_t total_ic, cell_asic *ic, uint8_t md, bool adcopt)
Helper function that runs the ADC Self Tests.
Definition: LTC6810.cpp:368
static void print_conv_time(uint32_t conv_time)
Definition: DC2515.ino:1220
uint8_t LTC6810_rdcv(uint8_t reg, uint8_t total_ic, cell_asic *ic)
Reads and parses the LTC6810 cell voltage registers.
Definition: LTC6810.cpp:150
void LTC6810_set_cfgr(uint8_t nIC, cell_asic *ic, bool refon, bool adcopt, bool gpio[4], bool dcc[6], bool dcc_0, bool mcal, bool en_dtmen, bool dis_red, bool fdrf, bool sconv, bool dcto[4], uint16_t uv, uint16_t ov)
Helper function to set appropriate bits in CFGR register based on bit function.
Definition: LTC6810.cpp:666
General BMS Library.
void wakeup_sleep()
Definition: LTC68041.cpp:969
unsigned char user_command
uint8_t tx_data[6]
Stores data to be transmitted.
Definition: LTC681x.h:143
const uint8_t TOTAL_IC
Number of ICs in the daisy chain.
Definition: DC2515.ino:120
#define CELL_CH_ALL
CH Dec Channels to convert 0000 All Cells 0011 Cell 1 and Cell 7 0102 Cell 2 and Cell 8 0113 Cell 3 ...
Definition: LTC68041.h:142
static void setup()
Definition: DC2515.ino:182
static void print_aux(uint8_t datalog_en)
Definition: DC2515.ino:812
static void print_selftest_errors(uint8_t adc_reg, int8_t error)
Definition: DC2515.ino:961
#define DATALOG_ENABLED
Definition: DC2515.ino:83
const uint8_t READ_CONFIG
This is to ENABLED or DISABLED reading the configuration registers in a continuous loop...
Definition: DC2515.ino:141
int8_t LTC6810_rdcomm(uint8_t total_ic, cell_asic *ic)
Reads comm registers of a LTC6810 in daisy chain.
Definition: LTC6810.cpp:569
LTC6810: 6-Channel Battery Stack Monitors.
#define DISABLED
Definition: DC2515.ino:82
static void print_sumofcells(void)
Definition: DC2515.ino:888
#define AUX
Definition: LTC6810.h:63
const uint16_t MEASUREMENT_LOOP_TIME
Loop Time in milliseconds(ms)
Definition: DC2515.ino:137
const uint8_t ADC_DCP
Discharge Permitted.
Definition: DC2515.ino:125
const uint8_t SEL_ALL_REG
Register Selection.
Definition: DC2515.ino:129
Header File for Linduino Libraries and Demo Code.
Cell variable structure.
Definition: LTC681x.h:170
cell_asic BMS_IC[TOTAL_IC]
Global Battery Variable.
Definition: DC2515.ino:156
static int8_t select_s_pin(void)
Definition: DC2515.ino:1042
#define STAT_CH_ALL
Definition: LTC681x.h:88
#define AUX_CH_ALL
CHG Dec Channels to convert 000 0 All GPIOS and 2nd Ref 001 1 GPIO 1 010 2 GPIO 2 011 3 GPIO 3 100 4...
Definition: LTC68041.h:164
char get_char(void)
Definition: DC2515.ino:1308
bool ISOSPI_DIR
Definition: DC2515.ino:158
int8_t LTC6810_rdcfg(uint8_t total_ic, cell_asic *ic)
Reads configuration registers of a LTC6810 daisy chain.
Definition: LTC6810.cpp:94
static void print_rxcomm(void)
Definition: DC2515.ino:1137
#define CELL
Definition: LTC6810.h:62
const uint8_t SEL_REG_B
Register Selection.
Definition: DC2515.ino:131
static void print_menu(void)
Definition: DC2515.ino:702
register_cfg ic_reg
Definition: LTC681x.h:185
void spi_enable(uint8_t spi_clock_divider)
Setup the processor for hardware SPI communication.
Definition: LT_SPI.cpp:160
static void print_cells(uint8_t datalog_en)
Definition: DC2515.ino:777
ic_register com
Definition: LTC681x.h:177
static uint16_t OV
Over voltage Comparison Voltage.
Definition: DC2515.ino:167
void LTC6810_clrstat()
Clears the LTC6810 Stat registers.
Definition: LTC6810.cpp:316
bool ADCOPT
ADC Mode option bit.
Definition: DC2515.ino:163
bool GPIOBITS[4]
GPIO Pin Control // Gpio 1,2,3,4.
Definition: DC2515.ino:165
char read_hex(void)
Definition: DC2515.ino:1293
int8_t LTC6810_rdpwm(uint8_t total_ic, uint8_t pwmReg, cell_asic *ic)
Reads pwm registers of the LTC6810 in daisy chain.
Definition: LTC6810.cpp:549
static void print_stat(void)
Definition: DC2515.ino:853
void LTC6810_mute()
Mutes the LTC6810 discharge transistors.
Definition: LTC6810.cpp:622
static void print_wrconfig(void)
Definition: DC2515.ino:725
#define DATALOG_DISABLED
Definition: DC2515.ino:84
bool SCONV
Enable Cell Measurement Redundancy using S Pin.
Definition: DC2515.ino:174
bool EN_DTMEN
Enable Discharge timer monitor.
Definition: DC2515.ino:171
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
void LTC6810_adcvsc(uint8_t MD, uint8_t DCP)
Starts cell voltage and SOC conversion.
Definition: LTC6810.cpp:129
char byte_to_hex_buffer[3]
Definition: DC2515.ino:1284
static void measurement_loop(uint8_t datalog_en)
Definition: DC2515.ino:628
#define STAT
Definition: LTC6810.h:64
const uint16_t UV_THRESHOLD
Under voltage threshold ADC Code.
Definition: DC2515.ino:135
static void print_rxconfig(void)
Definition: DC2515.ino:753
static void print_pec_error_count(void)
Definition: DC2515.ino:1026
char hex_digits[16]
Definition: DC2515.ino:1268
static void reverse_isospi_direction(void)
Definition: DC2515.ino:1191
#define ADC_OPT_DISABLED
Definition: LTC681x.h:67
const uint16_t OV_THRESHOLD
Over voltage threshold ADC Code.
Definition: DC2515.ino:134
bool DCTOBITS[4]
Discharge Time Out Value //Dcto 0,1,2,3 // Programed for 4 min.
Definition: DC2515.ino:175
void LTC6810_stcomm(uint8_t len)
Issues a stcomm command and clocks data out of the COMM register.
Definition: LTC6810.cpp:579
ic_register pwm
Definition: LTC681x.h:178
void LTC6810_adcv(uint8_t MD, uint8_t DCP, uint8_t CH)
Starts cell voltage conversion.
Definition: LTC6810.cpp:104
void LTC6810_clear_discharge(uint8_t total_ic, cell_asic *ic)
Clears all of the DCC bits in the configuration registers.
Definition: LTC6810.cpp:529
static uint16_t UV
Under voltage Comparison Voltage.
Definition: DC2515.ino:166
void wakeup_idle()
Definition: LTC68041.cpp:957
const uint8_t SEL_REG_A
Register Selection.
Definition: DC2515.ino:130
#define REG_ALL
Definition: LTC681x.h:94
static void serial_print_text(char data[])
Definition: DC2515.ino:1245
#define REG_2
Definition: LTC681x.h:96
static void check_error(int error)
Definition: DC2515.ino:1233
#define input(pin)
Return the state of pin "pin".
Definition: Linduino.h:79
void LTC6810_clraux()
Clears the LTC6810 Auxiliary registers.
Definition: LTC6810.cpp:306
uint8_t cell_channels
Number of Cell channels.
Definition: LTC681x.h:161
void LTC6810_unmute()
Clears the LTC6810 Mute Discharge.
Definition: LTC6810.cpp:633
static void run_command(uint32_t cmd)
Definition: DC2515.ino:216
static int error
void LTC6810_reset_crc_count(uint8_t total_ic, cell_asic *ic)
Helper Function that resets the PEC error counters.
Definition: LTC6810.cpp:652
static void print_wrcomm(void)
/prints data which is written on COMM register onto the serial port
Definition: DC2515.ino:1109
int8_t LTC6810_rdstat(uint8_t reg, uint8_t total_ic, cell_asic *ic)
Reads and parses the LTC6810 stat registers.
Definition: LTC6810.cpp:182
void LTC6810_init_cfg(uint8_t total_ic, cell_asic *ic)
Helper Function to initialize the CFGR data structures.
Definition: LTC6810.cpp:660
const uint8_t MEASURE_CELL
This is to ENABLED or DISABLED measuring the cell voltages in a continuous loop.
Definition: DC2515.ino:142
uint8_t LTC6810_rds(uint8_t reg, uint8_t total_ic, cell_asic *ic)
Reads and parses the LTC6810 S voltage registers.
Definition: LTC6810.cpp:198
bool REFON
Reference Powered Up Bit.
Definition: DC2515.ino:164
void LTC6810_clrcell()
Clears the LTC6810 cell voltage registers.
Definition: LTC6810.cpp:296
const uint8_t AUX_CH_TO_CONVERT
Channel Selection for ADC conversion.
Definition: DC2515.ino:127
uint16_t pec15_calc(uint8_t len, uint8_t *data)
Definition: LTC68041.cpp:985
static void check_mux_fail(void)
Definition: DC2515.ino:943
bool MCAL
Enable Multi-Calibration.
Definition: DC2515.ino:170
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
const uint8_t MEASURE_STAT
This is to ENABLED or DISABLED reading the status registers in a continuous loop. ...
Definition: DC2515.ino:144
void LTC6810_wrcomm(uint8_t total_ic, cell_asic *ic)
Write the LTC6810 COMM register.
Definition: LTC6810.cpp:561
#define MD_7KHZ_3KHZ
Definition: LTC681x.h:63
#define ENABLED
Definition: DC2515.ino:81
void LTC6810_run_gpio_openwire(uint8_t total_ic, cell_asic ic[])
Definition: LTC6810.cpp:427
void LTC6810_adax(uint8_t MD, uint8_t CHG)
Start a GPIO, cell 0 and Vref2 Conversion.
Definition: LTC6810.cpp:113
void LTC6810_adstat(uint8_t MD, uint8_t CHST)
Start a Status ADC Conversion.
Definition: LTC6810.cpp:121
const uint8_t WRITE_CONFIG
This is to ENABLED or DISABLED writing into to configuration registers in a continuous loop...
Definition: DC2515.ino:140
void LTC6810_adcvax(uint8_t MD, uint8_t DCP)
Starts cell voltage, Cell 0 and GPIO 1 conversion.
Definition: LTC6810.cpp:137
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
#define REG_1
Definition: LTC681x.h:95
int32_t read_int()
void LTC6810_wrcfg(uint8_t total_ic, cell_asic *ic)
Write the LTC6810 configuration register.
Definition: LTC6810.cpp:86
static void loop()
Definition: DC2515.ino:201
int8_t LTC6810_rdaux(uint8_t reg, uint8_t total_ic, cell_asic *ic)
Reads and parses the LTC6810 auxiliary registers.
Definition: LTC6810.cpp:166
const uint8_t ADC_CONVERSION_MODE
ADC Mode.
Definition: DC2515.ino:124
#define DCP_DISABLED
Definition: LTC68041.h:183
const uint8_t STAT_CH_TO_CONVERT
Channel Selection for ADC conversion.
Definition: DC2515.ino:128
void LTC6810_diagn()
Starts the Mux Decoder diagnostic self test.
Definition: LTC6810.cpp:322
static void print_wrpwm(void)
Definition: DC2515.ino:1057
static void print_sid(void)
Definition: DC2515.ino:1162
uint8_t LTC6810_rdsid(uint8_t total_ic, cell_asic *ic)
Reads Serial ID registers group.
Definition: LTC6810.cpp:585
bool DCCBIT_0
Discharge cell switch //Dcc 0 // For discharging optional 7th cell.
Definition: DC2515.ino:169
int16_t LTC6810_run_adc_redundancy_st(uint8_t adc_mode, uint8_t adc_reg, uint8_t total_ic, cell_asic *ic)
Helper function that runs the ADC Digital Redundancy commands and checks output for errors...
Definition: LTC6810.cpp:381
const uint8_t ADC_OPT
ADC Mode option bit.
Definition: DC2515.ino:123
void LTC6810_run_openwire_single(uint8_t total_ic, cell_asic *ic)
Helper function that runs the data sheet open wire algorithm for single cell detection.
Definition: LTC6810.cpp:411
char hex_to_byte_buffer[5]
Definition: DC2515.ino:1276
static int i
Definition: DC2430A.ino:184
static void print_rxpwm(void)
Definition: DC2515.ino:1085
const uint8_t PRINT_PEC
This is to ENABLED or DISABLED printing the PEC Error Count in a continuous loop. ...
Definition: DC2515.ino:145
bool FDRF
Force digital Redundancy Failure.
Definition: DC2515.ino:173
void LTC6810_init_reg_limits(uint8_t total_ic, cell_asic *ic)
Initialize the Register limits.
Definition: LTC6810.cpp:66
static void check_mute_bit(void)
Definition: DC2515.ino:1206
static void serial_print_hex(uint8_t data)
Definition: DC2515.ino:1254
int8_t read_char()
static void print_svolt(uint8_t datalog_en)
Definition: DC2515.ino:905
bool isospi_reverse
Definition: LTC681x.h:183
const uint8_t CELL_CH_TO_CONVERT
Channel Selection for ADC conversion.
Definition: DC2515.ino:126
void LTC6810_run_openwire_multi(uint8_t total_ic, cell_asic *ic)
Runs the data sheet algorithm for open wire for multiple cell and two consecutive cells detection...
Definition: LTC6810.cpp:419
void LTC6810_wrpwm(uint8_t total_ic, uint8_t pwmReg, cell_asic *ic)
Writes to the LTC6810 PWM register of LTC6810.
Definition: LTC6810.cpp:540
uint32_t LTC6810_pollAdc()
This function will block operation until the ADC has finished it&#39;s conversion.
Definition: LTC6810.cpp:286
static void print_digital_redundancy_errors(uint8_t adc_reg, int8_t error)
Definition: DC2515.ino:983
bool DIS_RED
Disable Digital Redundancy Check.
Definition: DC2515.ino:172
void LTC6810_set_discharge(int Cell, uint8_t total_ic, cell_asic *ic)
Helper function to set discharge bit in CFG register.
Definition: LTC6810.cpp:510