Code to run on the charger board (used to charge the car from the mains).

Dependencies:   mbed CUER_CAN

Committer:
drajan
Date:
Sat May 06 20:28:22 2017 +0000
Revision:
0:6d930d0d13a1
Child:
1:0c77e20b4d4c
CAN stuff still needs to be implemented.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
drajan 0:6d930d0d13a1 1 #include "charger.h"
drajan 0:6d930d0d13a1 2
drajan 0:6d930d0d13a1 3
drajan 0:6d930d0d13a1 4 void get_charger_data(void) {
drajan 0:6d930d0d13a1 5 //Updates charger data
drajan 0:6d930d0d13a1 6
drajan 0:6d930d0d13a1 7 //for now, before the CAN communication is set up, arbitrary values are set.
drajan 0:6d930d0d13a1 8 voltage_error = 0.1; //received function is in mV. Must be divided by 1000 so that this value is in V.
drajan 0:6d930d0d13a1 9 temp_margin = 5; //multiply received temp_margin by 10 to get answer in Celcius.
drajan 0:6d930d0d13a1 10 discharge_error = 0.1; //divide received value by 1000 to get value in V
drajan 0:6d930d0d13a1 11 chrg_status_recv_time = chargerboard_timer.read_ms();
drajan 0:6d930d0d13a1 12 charger_current;
drajan 0:6d930d0d13a1 13 charger_voltage;
drajan 0:6d930d0d13a1 14
drajan 0:6d930d0d13a1 15 }
drajan 0:6d930d0d13a1 16
drajan 0:6d930d0d13a1 17 void get_voltage_data(void){
drajan 0:6d930d0d13a1 18
drajan 0:6d930d0d13a1 19 //Updates Voltage Data
drajan 0:6d930d0d13a1 20 min_cell_voltage = 1; //divide received value by 1000 to get value in V
drajan 0:6d930d0d13a1 21 max_cell_voltage = 5;//divide received value by 1000 to get value in V
drajan 0:6d930d0d13a1 22
drajan 0:6d930d0d13a1 23 bms_minmax_cell_volts_recv_time = chargerboard_timer.read_ms();
drajan 0:6d930d0d13a1 24
drajan 0:6d930d0d13a1 25 }
drajan 0:6d930d0d13a1 26
drajan 0:6d930d0d13a1 27 void get_bms_data(void){
drajan 0:6d930d0d13a1 28 //Updates BMS data
drajan 0:6d930d0d13a1 29 rising_voltage_threshold; //(V)
drajan 0:6d930d0d13a1 30 falling_voltage_threshold; //(V)
drajan 0:6d930d0d13a1 31 bms_status;
drajan 0:6d930d0d13a1 32
drajan 0:6d930d0d13a1 33 bms_pack_status_recv_time = chargerboard_timer.read_ms();
drajan 0:6d930d0d13a1 34
drajan 0:6d930d0d13a1 35 }
drajan 0:6d930d0d13a1 36
drajan 0:6d930d0d13a1 37 void calculate_current(float voltage_error, float temp_margin, float *current, float *voltage){
drajan 0:6d930d0d13a1 38
drajan 0:6d930d0d13a1 39 float Idot, I;
drajan 0:6d930d0d13a1 40 static bool balancing = false;
drajan 0:6d930d0d13a1 41 I = *current;
drajan 0:6d930d0d13a1 42 if (I < 0.8 && voltage_error < 0.1 || balancing) {
drajan 0:6d930d0d13a1 43 balancing = true;
drajan 0:6d930d0d13a1 44 printf("balancing\r\n");
drajan 0:6d930d0d13a1 45 Idot = voltage_error*KI_BALANCE;
drajan 0:6d930d0d13a1 46 } else {
drajan 0:6d930d0d13a1 47 Idot = voltage_error*KI_CHARGE;
drajan 0:6d930d0d13a1 48 }
drajan 0:6d930d0d13a1 49 I += Idot*TIME_STEP/1000.0;
drajan 0:6d930d0d13a1 50
drajan 0:6d930d0d13a1 51 if(I > MAX_CURRENT) {
drajan 0:6d930d0d13a1 52 I = MAX_CURRENT;
drajan 0:6d930d0d13a1 53 }
drajan 0:6d930d0d13a1 54 if(I < 0) {
drajan 0:6d930d0d13a1 55 I = 0;
drajan 0:6d930d0d13a1 56 }
drajan 0:6d930d0d13a1 57
drajan 0:6d930d0d13a1 58 //Reduce current if temperature is too high
drajan 0:6d930d0d13a1 59 if (temp_margin > TEMP_RAMP_START) {
drajan 0:6d930d0d13a1 60 I = 1 - ((temp_margin - TEMP_RAMP_START) / (TEMP_RAMP_FINISH - TEMP_RAMP_START));
drajan 0:6d930d0d13a1 61 }
drajan 0:6d930d0d13a1 62 if (temp_margin > TEMP_RAMP_FINISH) {
drajan 0:6d930d0d13a1 63 I *= 0;
drajan 0:6d930d0d13a1 64 }
drajan 0:6d930d0d13a1 65
drajan 0:6d930d0d13a1 66 *current = I;
drajan 0:6d930d0d13a1 67 *voltage = MAX_VOLTAGE;
drajan 0:6d930d0d13a1 68 }
drajan 0:6d930d0d13a1 69
drajan 0:6d930d0d13a1 70
drajan 0:6d930d0d13a1 71 int main() {
drajan 0:6d930d0d13a1 72
drajan 0:6d930d0d13a1 73 chargerboard_timer.start();
drajan 0:6d930d0d13a1 74
drajan 0:6d930d0d13a1 75 while(1) {
drajan 0:6d930d0d13a1 76
drajan 0:6d930d0d13a1 77 get_voltage_data();
drajan 0:6d930d0d13a1 78 get_charger_data();
drajan 0:6d930d0d13a1 79 get_bms_data();
drajan 0:6d930d0d13a1 80
drajan 0:6d930d0d13a1 81 int current_time = chargerboard_timer.read_ms();
drajan 0:6d930d0d13a1 82
drajan 0:6d930d0d13a1 83 bool timeout = false;
drajan 0:6d930d0d13a1 84 bool failure = false;
drajan 0:6d930d0d13a1 85
drajan 0:6d930d0d13a1 86
drajan 0:6d930d0d13a1 87 //check for timeouts
drajan 0:6d930d0d13a1 88 if (current_time < CHARGER_MSG_TIMEOUT + BMS_MSG_TIMEOUT) {
drajan 0:6d930d0d13a1 89 printf("Waiting for messages\r\n");
drajan 0:6d930d0d13a1 90 timeout = false;
drajan 0:6d930d0d13a1 91
drajan 0:6d930d0d13a1 92 }
drajan 0:6d930d0d13a1 93
drajan 0:6d930d0d13a1 94 if (current_time - chrg_status_recv_time > BMS_MSG_TIMEOUT ||
drajan 0:6d930d0d13a1 95 current_time - bms_minmax_cell_volts_recv_time > BMS_MSG_TIMEOUT ||
drajan 0:6d930d0d13a1 96 current_time - bms_pack_status_recv_time > BMS_MSG_TIMEOUT) {
drajan 0:6d930d0d13a1 97
drajan 0:6d930d0d13a1 98 printf("BMS timeout\r\n");
drajan 0:6d930d0d13a1 99 timeout = true;
drajan 0:6d930d0d13a1 100 bms_timeout = true;
drajan 0:6d930d0d13a1 101
drajan 0:6d930d0d13a1 102 }
drajan 0:6d930d0d13a1 103
drajan 0:6d930d0d13a1 104 if (current_time - chrg_status_recv_time > CHARGER_MSG_TIMEOUT) {
drajan 0:6d930d0d13a1 105
drajan 0:6d930d0d13a1 106 printf("charger timeout\r\n");
drajan 0:6d930d0d13a1 107 timeout = true;
drajan 0:6d930d0d13a1 108 charger_timeout = true;
drajan 0:6d930d0d13a1 109 }
drajan 0:6d930d0d13a1 110
drajan 0:6d930d0d13a1 111 if (charger_timeout) {
drajan 0:6d930d0d13a1 112 printf("charger has timed out\r\n");
drajan 0:6d930d0d13a1 113 }
drajan 0:6d930d0d13a1 114
drajan 0:6d930d0d13a1 115
drajan 0:6d930d0d13a1 116 //Check for Failure: Values set according to ELON-CAN-specification.pdf STATUS register
drajan 0:6d930d0d13a1 117 if(bms_status bitand 1 == 1) {
drajan 0:6d930d0d13a1 118
drajan 0:6d930d0d13a1 119 printf("Hardware Failure\r\n");
drajan 0:6d930d0d13a1 120 failure = true;
drajan 0:6d930d0d13a1 121
drajan 0:6d930d0d13a1 122 }
drajan 0:6d930d0d13a1 123
drajan 0:6d930d0d13a1 124 if(bms_status bitand 2 == 2) {
drajan 0:6d930d0d13a1 125
drajan 0:6d930d0d13a1 126 printf("Error: Over Temperature\r\n");
drajan 0:6d930d0d13a1 127 failure = true;
drajan 0:6d930d0d13a1 128
drajan 0:6d930d0d13a1 129 }
drajan 0:6d930d0d13a1 130
drajan 0:6d930d0d13a1 131 if(bms_status bitand 4 == 4) {
drajan 0:6d930d0d13a1 132
drajan 0:6d930d0d13a1 133 printf("Input Voltage Wrong\r\n");
drajan 0:6d930d0d13a1 134 failure = true;
drajan 0:6d930d0d13a1 135
drajan 0:6d930d0d13a1 136 }
drajan 0:6d930d0d13a1 137
drajan 0:6d930d0d13a1 138
drajan 0:6d930d0d13a1 139
drajan 0:6d930d0d13a1 140
drajan 0:6d930d0d13a1 141 //Update LEDs
drajan 0:6d930d0d13a1 142 if (failure == true) {
drajan 0:6d930d0d13a1 143 desired_current = 0;
drajan 0:6d930d0d13a1 144 red_led = 1;
drajan 0:6d930d0d13a1 145
drajan 0:6d930d0d13a1 146 } else if (timeout == true) {
drajan 0:6d930d0d13a1 147 desired_current = 0;
drajan 0:6d930d0d13a1 148 yellow_led = 1;
drajan 0:6d930d0d13a1 149 } else if (charge_finished == false) {
drajan 0:6d930d0d13a1 150 green_led = 1;
drajan 0:6d930d0d13a1 151 } else {
drajan 0:6d930d0d13a1 152 red_led = 0;
drajan 0:6d930d0d13a1 153 yellow_led = 0;
drajan 0:6d930d0d13a1 154 green_led = 0;
drajan 0:6d930d0d13a1 155 }
drajan 0:6d930d0d13a1 156
drajan 0:6d930d0d13a1 157
drajan 0:6d930d0d13a1 158
drajan 0:6d930d0d13a1 159 if (min_cell_voltage > rising_voltage_threshold) {
drajan 0:6d930d0d13a1 160 charge_finished = true;
drajan 0:6d930d0d13a1 161 printf("Charge Finished\r\n");
drajan 0:6d930d0d13a1 162 //set charger control bit to finished charging
drajan 0:6d930d0d13a1 163 } else {
drajan 0:6d930d0d13a1 164 calculate_current(voltage_error, temp_margin, &desired_current, &desired_voltage);
drajan 0:6d930d0d13a1 165 charge_finished = false;
drajan 0:6d930d0d13a1 166
drajan 0:6d930d0d13a1 167 }
drajan 0:6d930d0d13a1 168
drajan 0:6d930d0d13a1 169 //voltage error, temp margin, desired voltage, desired current, voltage, current, min cell voltage, max cell voltage.
drajan 0:6d930d0d13a1 170
drajan 0:6d930d0d13a1 171 printf("Voltage Error = %f\n", voltage_error);
drajan 0:6d930d0d13a1 172 printf("Temperature Margin = %f\n", temp_margin);
drajan 0:6d930d0d13a1 173 printf("Desired Voltage = %f\n", desired_voltage);
drajan 0:6d930d0d13a1 174 printf("Desired Current = %f\n", desired_current);
drajan 0:6d930d0d13a1 175 printf("Voltage = %f\n", charger_voltage);
drajan 0:6d930d0d13a1 176 printf("Current = %f\n", charger_current);
drajan 0:6d930d0d13a1 177 printf("Min cell voltage = %f\n", min_cell_voltage);
drajan 0:6d930d0d13a1 178 printf("Max cell voltage = %f\n", max_cell_voltage);
drajan 0:6d930d0d13a1 179
drajan 0:6d930d0d13a1 180 //send CAN data
drajan 0:6d930d0d13a1 181 //send charger control max voltage MAX_VOLTAGE
drajan 0:6d930d0d13a1 182 //send charger control max current desired_current
drajan 0:6d930d0d13a1 183 //send charge_finished value to control bit.
drajan 0:6d930d0d13a1 184
drajan 0:6d930d0d13a1 185
drajan 0:6d930d0d13a1 186
drajan 0:6d930d0d13a1 187 }
drajan 0:6d930d0d13a1 188 }