all bms comunicating with nucleo board and balancing
Dependencies: CANnucleo LTC68041 mbed
Fork of BMS_2 by
Diff: main.cpp
- Revision:
- 21:988413f53fbe
- Parent:
- 20:eb1a8042605e
- Child:
- 23:bde0179eee92
diff -r eb1a8042605e -r 988413f53fbe main.cpp --- a/main.cpp Tue Aug 16 21:13:47 2016 +0000 +++ b/main.cpp Sat Oct 22 16:34:06 2016 +0000 @@ -1,131 +1,324 @@ -/* - * An example showing how to use the CANnucleo library: - * - * Two affordable (less than $3 on ebay) STM32F103C8T6 boards (20kB SRAM, 64kB Flash), - * (see [https://developer.mbed.org/users/hudakz/code/STM32F103C8T6_Hello/] for more details) - * are connected to the same CAN bus via transceivers (MCP2551 or TJA1040, or etc.). - * CAN transceivers are not part of NUCLEO boards, therefore must be added by you. - * Remember also that CAN bus (even a short one) must be terminated with 120 Ohm resitors at both ends. - * - * For more details see the wiki page <https://developer.mbed.org/users/hudakz/code/CANnucleo_Hello/> - * - * NOTE: If you'd like to use the official NUCLEO boards comment out line 22 - * - * The same code is used for both NUCLEO boards, but: - * For board #1 compile the example without any change. - * For board #2 comment out line 23 before compiling - * - * Once the binaries have been downloaded to the boards reset board #1. - * - */ - -//#define TARGET_STM32F103C8T6 1 // uncomment this line when using STM32F103C8T6 boards! -#define BOARD1 1 // comment out this line when compiling for board #2 - -#if defined(TARGET_STM32F103C8T6) - #define LED_PIN PC_13 - const int OFF = 1; - const int ON = 0; -#else - #define LED_PIN LED1 - const int OFF = 0; - const int ON = 1; -#endif - -#if defined(BOARD1) - const unsigned int RX_ID = 0x100; - const unsigned int TX_ID = 0x101; -#else - const unsigned int RX_ID = 0x101; - const unsigned int TX_ID = 0x100; -#endif - #include "CANnucleo.h" #include "mbed.h" +#include "LTC68041.h" -/* - * To avaoid name collision with the CAN and CANMessage classes built into the mbed library - * the CANnucleo's CAN and CANMessage classes have been moved into the CANnucleo namespace. - * Remember to qualify them with the CANnucleo namespace. - */ + + +uint8_t const TOTAL_IC = 1;//!<number of ICs in the daisy chain + +uint8_t rx_cfg[TOTAL_IC][8]; +uint8_t tx_cfg[TOTAL_IC][6]; +uint16_t aux_codes[TOTAL_IC][6]; +uint16_t cell_codes[TOTAL_IC][12]; +volatile bool msgAvailable = false; +volatile bool to_send = false; CANnucleo::CAN can(PA_11, PA_12); // CAN Rx pin name, CAN Tx pin name CANnucleo::CANMessage rxMsg; CANnucleo::CANMessage txMsg; -DigitalOut led(LED_PIN); -int ledState; -Timer timer; -int counter = 0; -volatile bool msgAvailable = false; +DigitalOut led(PA_5); +/*!*********************************** +\brief Initializes the configuration array +**************************************/ +void init_cfg() +{ + for (int i = 0; i<TOTAL_IC; i++) { + tx_cfg[i][0] = 0xFE; + tx_cfg[i][1] = 0x00 ; + tx_cfg[i][2] = 0x00 ; + tx_cfg[i][3] = 0x00 ; + tx_cfg[i][4] = 0x00 ; + tx_cfg[i][5] = 0x00 ; + } +} +void serial_print_hex(uint8_t data) +{ + if (data< 16) { + printf("0"); + printf("%x",(uint8_t)data); + } else + printf("%x",(uint8_t)data); +} +void print_config() +{ + int cfg_pec; + printf("Written Configuration:\n\r "); + for (int current_ic = 0; current_ic<TOTAL_IC; current_ic++) { + printf(" IC "); + printf("%d", current_ic+1); + printf(": "); + printf("0x"); + serial_print_hex(tx_cfg[current_ic][0]); + printf(", 0x"); + serial_print_hex(tx_cfg[current_ic][1]); + printf(", 0x"); + serial_print_hex(tx_cfg[current_ic][2]); + printf(", 0x"); + serial_print_hex(tx_cfg[current_ic][3]); + printf(", 0x"); + serial_print_hex(tx_cfg[current_ic][4]); + printf(", 0x"); + serial_print_hex(tx_cfg[current_ic][5]); + printf(", Calculated PEC: 0x"); + cfg_pec = pec15_calc(6,&tx_cfg[current_ic][0]); + serial_print_hex((uint8_t)(cfg_pec>>8)); + printf(", 0x"); + serial_print_hex((uint8_t)(cfg_pec)); + } + printf("\n\r"); +} + +void print_rxconfig() +{ + printf("Received Configuration "); + for (int current_ic=0; current_ic<TOTAL_IC; current_ic++) { + printf(" IC "); + printf("%d " ,current_ic+1); + printf(": 0x"); + serial_print_hex(rx_cfg[current_ic][0]); + printf(", 0x"); + serial_print_hex(rx_cfg[current_ic][1]); + printf(", 0x"); + serial_print_hex(rx_cfg[current_ic][2]); + printf(", 0x"); + serial_print_hex(rx_cfg[current_ic][3]); + printf(", 0x"); + serial_print_hex(rx_cfg[current_ic][4]); + printf(", 0x"); + serial_print_hex(rx_cfg[current_ic][5]); + printf(", Received PEC: 0x"); + serial_print_hex(rx_cfg[current_ic][6]); + printf(", 0x"); + serial_print_hex(rx_cfg[current_ic][7]); + } +} +int err; +void print_cells2() +{ + + for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) { + + for (int i=0; i<12; i++) { + printf(" C"); + printf("%d",i+1); + printf(":"); + printf("%f", cell_codes[current_ic][i]*0.0001); + printf(","); + } -/** - * @brief 'CAN receive-complete' interrup handler. - * @note Called on arrival of new CAN message. - * Keep it as short as possible. - * @param - * @retval - */ -void onMsgReceived() { + } +} +void pec_error() +{ + for(int i = 0; i<5; i++) { + led = 1; + wait(0.2); + led=0; + wait(0.2); + } +} +char cells_left=0; +Ticker ticker; +Ticker sender; + +typedef union can_union { + int i[2]; + char bytes[8]; + float f[2]; +} data; + +void message_trigger() +{ + if(cells_left < 1) { + sender.detach(); + } else { + + + to_send = 1; + } + +} + +void check_charging_voltage() +{ + wakeup_idle(); + __disable_irq(); + LTC6804_adcv(); + __enable_irq(); + wait_ms(10); + wakeup_idle(); + __enable_irq(); + err = LTC6804_rdcv(0, TOTAL_IC,cell_codes); + __disable_irq(); + if (err == -1) { + pec_error(); + } + for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) { + for (int i=0; i<12; i++) { + if(cell_codes[current_ic][i]*0.0001 > 3.85) { + switch (i) { + case 0: + tx_cfg[0][4] = tx_cfg[0][4] | 0x01 ; + case 1: + tx_cfg[0][4] = tx_cfg[0][4] | 0x02 ; + case 2: + tx_cfg[0][4] = tx_cfg[0][4] | 0x04 ; + case 3: + tx_cfg[0][4] = tx_cfg[0][4] | 0x08 ; + case 4: + tx_cfg[0][4] = tx_cfg[0][4] | 0x10 ; + case 5: + tx_cfg[0][4] = tx_cfg[0][4] | 0x20 ; + case 6: + tx_cfg[0][4] = tx_cfg[0][4] | 0x40 ; + case 7: + tx_cfg[0][4] = tx_cfg[0][4] | 0x80; + case 8: + tx_cfg[0][5] = tx_cfg[0][5] | 0x01; + case 9: + tx_cfg[0][5] = tx_cfg[0][5] | 0x10; + } + } + } + } + //print_cells2(); + __disable_irq(); + LTC6804_wrcfg(TOTAL_IC,tx_cfg); + __enable_irq(); +} + + + +void check_discharging_voltage() +{ + wakeup_idle(); + LTC6804_adcv(); + + wait_ms(10); + wakeup_idle(); + err = LTC6804_rdcv(0, TOTAL_IC,cell_codes); + if (err == -1) { + pec_error(); + }/* + for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) { + for (int i=0; i<11; i++) { + //printf("%f\t", cell_codes[current_ic][i]*0.0001); + if(cell_codes[current_ic][i]*0.0001 < 2.7) { + txMsg.clear(); + txMsg.id = 1; + printf("%f\t", cell_codes[current_ic][i]*0.0001); + + txMsg << cell_codes[current_ic][i]*0.0001; + can.write(txMsg); + wait(0.1); + } + } + }*/ + //print_cells2(); + cells_left = 12; + +//print_cells2(); + LTC6804_wrcfg(TOTAL_IC,tx_cfg); +} + +void onMsgReceived() +{ msgAvailable = true; } -/** - * @brief Main - * @note - * @param - * @retval - */ -int main() { - can.frequency(1000000); // set bit rate to 1Mbps - can.attach(&onMsgReceived); // attach 'CAN receive-complete' interrupt handler - -#if defined(BOARD1) - led = ON; // turn LED on - timer.start(); // start timer - printf("CANnucleo_Hello board #1\r\n"); -#else - led = OFF; // turn LED off - printf("CANnucleo_Hello board #2\r\n"); -#endif + - while(1) { - if(timer.read() >= 1.0) { // check for timeout - timer.stop(); // stop timer - timer.reset(); // reset timer - counter++; // increment counter - ledState = led.read(); // get led state - txMsg.clear(); // clear Tx message storage - txMsg.id = TX_ID; // set ID - txMsg << counter; // append first data item - txMsg << ledState; // append second data item (total data lenght must be <= 8 bytes!) - led = OFF; // turn LED off - if(can.write(txMsg)) // transmit message - printf("CAN message sent\r\n"); - else - printf("Transmission error\r\n"); - } - if(msgAvailable) { - msgAvailable = false; // reset flag for next use - can.read(rxMsg); // read message into Rx message storage - printf("CAN message received\r\n"); - printf(" ID = 0x%.3x\r\n", rxMsg.id); - printf(" Type = %d\r\n", rxMsg.type); - printf(" Format = %d\r\n", rxMsg.format); - printf(" Length = %d\r\n", rxMsg.len); - printf(" Data ="); - for(int i = 0; i < rxMsg.len; i++) - printf(" %.2x", rxMsg.data[i]); - printf("\r\n"); - // Filtering performed by software: - if(rxMsg.id == RX_ID) { // See comments in CAN.cpp for filtering performed by hardware - rxMsg >> counter; // extract first data item - rxMsg >> ledState; // extract second data item - printf(" counter = %d\r\n", counter); - led = ON; // turn LED on - timer.start(); // transmission lag - } - } +bool to_charge_or_not_to_charge=false; // false = discharge +bool charging = false; +bool discharging = false; +void monitor() +{ + led = !led; + if(to_charge_or_not_to_charge) { + charging = 1; + discharging = 0; + } else { + discharging = 1; + charging = 0; } } +int main() +{ + data data; + //printf("starting\n\r"); + led =1; + wait(1); + pec_error(); + discharging = 1; + + ticker.attach(&monitor, 5); + LTC6804_initialize(); + init_cfg(); +//write configuration + wakeup_sleep(); + __disable_irq(); // Disable Interrupts + LTC6804_wrcfg(TOTAL_IC,tx_cfg); + __enable_irq(); + wait(1); +//read configuration: may differ from written config + wakeup_sleep(); + __disable_irq(); + err = LTC6804_rdcfg(TOTAL_IC,rx_cfg); + __enable_irq(); + if (err == -1) { + pec_error(); + } + wait(0.5); + + wakeup_idle(); + __disable_irq(); + LTC6804_adcv(); + __enable_irq(); + wait_ms(10); + wakeup_idle(); + __disable_irq(); + err = LTC6804_rdcv(0, TOTAL_IC,cell_codes); + __enable_irq(); + if (err == -1) { + pec_error(); + } + can.frequency(1000000); // set bit rate to 1Mbps + can.attach(&onMsgReceived); + //print_cells2(); + while(1) { + if(charging) { + charging = 0; + check_charging_voltage(); + + } + if(discharging) { + discharging = 0; + check_discharging_voltage(); + sender.attach(&message_trigger,0.1); + } + if(to_send) { + + + to_send=0; + txMsg.clear(); + txMsg.id = 10; + txMsg.len = 5; + data.f[0] = cell_codes[0][cells_left-1]*0.0001; + txMsg.data[0] = data.bytes[0]; + txMsg.data[1] = data.bytes[1]; + txMsg.data[2] = data.bytes[2]; + txMsg.data[3] = data.bytes[3]; + txMsg.data[4] = cells_left; + cells_left--; + if(!(can.write(txMsg))) { + pec_error(); + cells_left++; + //to_send=1; + } + + } + } + +}