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