CUER
/
charger_code
Code to run on the charger board (used to charge the car from the mains).
charger.cpp@0:6d930d0d13a1, 2017-05-06 (annotated)
- 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?
User | Revision | Line number | New 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 | } |