Hochschule München
/
H2M_2014_race
Shell Eco Fuelcell controller
main.cpp
- Committer:
- HMFK03LST1
- Date:
- 2014-01-07
- Revision:
- 0:adf68d4b873f
File content as of revision 0:adf68d4b873f:
#include "mbed.h" #include "math.h" #include <string> #include "FastPWM.h" #include "components.cpp" const char I2C_IN = 4; const char I2C_OUT = 8; const int PWM_Frequenz = 10000; DigitalOut led_1(LED1); DigitalOut led_2(LED2); DigitalOut led_3(LED3); DigitalOut led_4(LED4); DigitalOut i2c_cs(p29); DigitalOut xb_rst(p11); DigitalOut mp_A(p15); DigitalOut mp_B(p16); AnalogIn current(p19); AnalogIn mp1yA(p20); AnalogIn mp2yA(p18); AnalogIn mp2xA(p17); DigitalIn mp2xD(p12); FastPWM pwm_6(p21,-1); //Mosfet DigitalOut h2_purge(p22); FastPWM pwm_4(p23,-1); //H2O Fan FastPWM pwm_3(p24,-1); //H20 Pump FastPWM pwm_2(p25,-1); //Air Pump 2 FastPWM pwm_1(p26,-1); //Air Pump 2 Serial xbee(p9,p10); Serial gps(p13,p14); Serial pc(USBTX,USBRX); SPI ext_spi(p5, p6, p7); I2C i2c(p28, p27); LocalFileSystem local("local"); //init Flashdrive for reading config file FILE *fp; struct_cap cap; struct_fuelcell fc; struct_h2o h2o; struct_mosfet mosfet; struct_o2 o2; struct_switch switches; struct_system sys; struct_error error; //Standard Funktions //---------------------------------------------------------------------------------------------- void read_val(const char* name,const char* value); double clamp(double value, double val_min, double val_max, bool* has_clamped) { *has_clamped = true; if(value < val_min) return val_min; if(value > val_max) return val_max; *has_clamped = false; return value; } void load_cfg() { char name_val[2][20]; char i = 0; char name = 1; int c = 50; fp = fopen("/local/power.cfg", "r"); if ( fp != NULL ) { while(c != EOF) { c = fgetc(fp); if (c == 10){ name_val[name][i+1] = '\0'; name = 1; i = 0; read_val(&name_val[1][0], &name_val[0][0]); } else { if (c == '='){ name_val[name][i+1] = '\0'; name = 0; i = 0; } else { name_val[name][i] = c; i++; } } } fclose(fp); } } void read_val(const char* name,const char* value) { float temp; sscanf(value, "%f", &temp ); pc.printf("Input : %-18s Value : %6d ", name, int(temp)); if (string(&name[0]) == "O2_air_current" ){ o2.air_current = temp; pc.printf("Value read: %6d \n\r", o2.air_current );} if (string(&name[0]) == "O2_water_created" ){ o2.water_created = temp; pc.printf("Value read: %6d \n\r", o2.water_created);} if (string(&name[0]) == "O2_lambda_max" ) o2.lambda_max = temp; if (string(&name[0]) == "O2_lambda_min" ) o2.lambda_min = temp; if (string(&name[0]) == "O2_pump_over_load") o2.pump_over_load = temp; if (string(&name[0]) == "O2_pump_up" ) o2.pump_up = temp; if (string(&name[0]) == "O2_pump_dual_on" ) o2.pump_dual_on = temp; if (string(&name[0]) == "O2_pump_dual_off" ) o2.pump_dual_off = temp; if (string(&name[0]) == "CAP_voltage_low" ) cap.voltage_low = temp; if (string(&name[0]) == "CAP_voltage_mid" ) cap.voltage_mid = temp; if (string(&name[0]) == "CAP_voltage_high" ) cap.voltage_high = temp; if (string(&name[0]) == "CAP_voltage_max" ) cap.voltage_max = temp; if (string(&name[0]) == "CAP_voltage_down" ) cap.voltage_down = temp; if (string(&name[0]) == "CAP_current_low" ) cap.current_low = temp; if (string(&name[0]) == "CAP_current_mid" ) cap.current_mid = temp; if (string(&name[0]) == "CAP_current_high" ) cap.current_high = temp; if (string(&name[0]) == "FC_temp_max" ) fc.temp_max = temp; if (string(&name[0]) == "FC_voltage_max" ) fc.voltage_max = temp; if (string(&name[0]) == "H2O_fan_over_pwm" ) h2o.fan_over_pwm = temp; if (string(&name[0]) == "H2O_fan_p" ) h2o.fan_p = temp; if (string(&name[0]) == "H2O_fan_i" ) h2o.fan_i = temp; if (string(&name[0]) == "H2O_fan_thr" ) h2o.fan_thr = temp; if (string(&name[0]) == "H2O_fan_up" ) h2o.fan_up = temp; if (string(&name[0]) == "H2O_pump_over_pwm") h2o.pump_over_pwm = temp; if (string(&name[0]) == "H2O_pump_p" ) h2o.pump_p = temp; if (string(&name[0]) == "H2O_pump_i" ) h2o.pump_i = temp; if (string(&name[0]) == "H2O_pump_min" ) h2o.pump_min = temp; if (string(&name[0]) == "H2O_pump_up" ) h2o.pump_up = temp; if (string(&name[0]) == "MOSFET_temp_max" ) mosfet.temp_max = temp; } // T - Funktions //---------------------------------------------------------------------------------------------- void T_1() { o2.water_in = 13235 * o2.rh_in / (o2.temp_in + 2731) * pow(10.0,(7.5 * o2.temp_in)/((2373 + o2.temp_in))-1); o2.water_in = clamp(o2.water_in,0,4000,&error.t_1); } void T_2() { if (o2.pump_load_act > 0) { o2.delta_t = o2.temp_out - h2o.temp_out; o2.temp_calc = o2.temp_out; } else { o2.temp_calc = o2.delta_t + h2o.temp_out; } o2.temp_calc = clamp(o2.temp_calc,0,800,&error.t_2); } void T_3() { o2.water_out = 13235000 / (o2.temp_calc + 2731) * pow(10.0,(7.5 * o2.temp_calc)/((2373 + o2.temp_calc))-1); o2.water_out = clamp(o2.water_out,0,30000,&error.t_3); } void T_4() { o2.water_extracted = o2.water_out - o2.water_in; o2.air_needed = o2.water_created * 10000 / o2.water_extracted; o2.lambda = o2.air_needed * 100 / o2.air_current; o2.lambda = clamp(o2.lambda,100,500,&error.t_4); } void T_5() { o2.lambda_delta = ((o2.lambda_max + o2.lambda_min) / 2) - o2.lambda; o2.lambda_delta_sum = o2.lambda_delta_sum + (o2.lambda_delta * 0.1); o2.lambda_delta_sum = clamp(o2.lambda_delta_sum,-2000,7000,&error.t_5); h2o.fan_pwm = ((h2o.fan_p * o2.lambda_delta) ) + ((h2o.fan_i * o2.lambda_delta_sum / 10) ); h2o.fan_pwm = clamp( h2o.fan_pwm,0,1000,&error.t_5); } void T_6() { h2o.pump_pwm = ((h2o.pump_p * o2.lambda_delta) ) + ((h2o.pump_i * o2.lambda_delta_sum / 10) + h2o.pump_min ); h2o.pump_pwm = clamp( h2o.pump_pwm,h2o.pump_min,1000,&error.t_6); } void T_7() { if(h2o.fan_override) { h2o.fan_pwm_act = h2o.fan_over_pwm; } else { if ((h2o.fan_pwm_act == 0) && (h2o.fan_pwm >= h2o.fan_thr)) { h2o.fan_up_count = h2o.fan_up; } else { h2o.fan_pwm_act = h2o.fan_pwm; } } if (h2o.fan_up_count > 0) {h2o.fan_up_count--; h2o.fan_pwm_act = 1000;} if (!((h2o.fan_pwm_act >= h2o.fan_thr) & sys.run)){h2o.fan_pwm_act = 0;} h2o.fan_pwm_act = clamp( h2o.fan_pwm_act,0,1000,&error.t_7); pwm_4.write(h2o.fan_pwm_act * 0.001); } void T_8() { if(h2o.pump_override){ h2o.pump_pwm_act = h2o.pump_over_pwm; } else { if ((h2o.pump_pwm_act == 0) && (h2o.pump_pwm > 0)) { h2o.pump_up_count = h2o.pump_up; } else { h2o.pump_pwm_act = h2o.pump_pwm; } } if (h2o.pump_up_count > 0) {h2o.pump_up_count--; h2o.pump_pwm_act = 1000;} if (!(sys.run)){ h2o.pump_pwm_act = 0;} h2o.pump_pwm_act = clamp( h2o.pump_pwm_act,0,1000,&error.t_8); pwm_3.write(h2o.fan_pwm_act * 0.001); } void T_ALL(){ T_1(); T_2(); T_3(); T_4(); T_5(); T_6(); T_7(); T_8(); } // O - Funktions //---------------------------------------------------------------------------------------------- void O_1() { o2.rh_out_delta = ((o2.rh_out_soll) - o2.rh_out; o2.rh_out_delta = clamp( o2.rh_out_delta,-100,100,&error.o_1); o2.rh_pump_load = 02.rh_p * o2.rh_out_delta; o2.rh_pump_load = clamp( o2.rh_pump_load,o2.rh_pump_min,o2.rh_pump_max,&error.o_2); } void O_2() { if(cap.voltage_act < cap.voltage_mid) { if(cap.voltage_act < cap.voltage_low) fc.current_load = cap.current_low; else fc.current_load = cap.current_mid; } else fc.current_load = cap.current_high; return 0; } bool O_3() { o2.lambda_min = 150; fc.air_needed = fc.current_load * o2.lambda_min * 0.007; return 0; } bool O_4() { if(o2.pump_on == false) o2.pump_load = 0; return 0; } bool O_5() { if(o2.pump_override) o2.pump_load_act = o2.pump_over_load; else o2.pump_load_act = o2.pump_load; return 0; } bool O_6() { if(o2.pump_load_act < o2.pump_dual_off){o2.pump_dual = false;} if(o2.pump_load_act > o2.pump_dual_on ){o2.pump_dual = true;} if (o2.pump_dual) { o2.pump_pwm_1 = o2.pump_load_act * 0.5; o2.pump_pwm_2 = o2.pump_load_act * 0.5; } else { o2.pump_pwm_1 = o2.pump_load_act; o2.pump_pwm_2 = 0; } return 0; } void O_ALL() { O_1(); O_2(); O_3(); O_4(); O_5(); O_6(); } // M - Funktions //---------------------------------------------------------------------------------------------- bool M_1() { if(o2.pump_on) mosfet.pwm = 0; mosfet.pwm = mosfet.pwm + ( ((fc.current_load - fc.current_act) * mosfet.i) / 100000); if(sys.load_act == false) mosfet.pwm = 0; return 0; } bool M_2() { sys.mos_overtemp = (mosfet.temp_act < mosfet.temp_max); return 0; } bool M_3() { if(sys.mosfet && sys.run) mosfet.pwm_act = mosfet.pwm; else mosfet.pwm_act = 0; return 0; } // S - Funktions //---------------------------------------------------------------------------------------------- bool S_1() { sys.run = (switches.master && switches.safety); return 0; } bool S_2() { sys.fc_overtemp = (fc.temp_act > fc.temp_max); return 0; } bool S_3() { sys.fc_overvoltage = (fc.voltage_act > fc.voltage_max); return 0; } bool S_4() { sys.fuelcell = (sys.temp && sys.voltage); return 0; } // C - Funktions //---------------------------------------------------------------------------------------------- bool C_1() { sys.cap_load = (cap.voltage_act < cap.voltage_max); return 0; } bool C_2() { sys.cap_down_load = (cap.voltage_act < cap.voltage_down); return 0; } bool C_3() { sys.cap_voltage_reset = (cap.voltage_act > cap.voltage_max); return 0; } bool C_4() { sys.cap_down_reset = (cap.voltage_act > cap.voltage_down); return 0; } bool C_5() { sys.load = ((switches.drive) || (sys.cap_load && (!switches.capdown)) || (switches.capdown && sys.cap_down_load)); return 0; } bool C_6() { sys.load_reset = (sys.cap_voltage_reset || (sys.cap_down_reset && switches.capdown)); return 0; } bool C_7() { if(sys.load) sys.load_act = true; if(sys.load_reset) sys.load_act = false; return 0; } bool C_8() { o2.pump_on = (sys.mosfet && sys.run && sys.fuelcell && sys.load_act); return 0; } void read_inputs() { char channel = sys.count%4; switch (channel) { case 0 : switches.drive = mp2xD; sys.h2_analog = mp2yA.read_u16() /2; fc.voltage_act = mp1yA.read_u16() /1.638; fc.current_act = current.read_u16()/4; break; case 1 : sys.safety_V = mp2xA.read_u16() /4; switches.safety = (sys.safety_V > 8000); sys.current_out = mp2yA.read_u16() /5; cap.voltage_act = mp1yA.read_u16() /1.638; fc.current_act = current.read_u16()/4; break; case 2 : switches.capdown = !mp2xD; mosfet.temp_act = mosfet.temp_act + ((((59000-mp2yA.read_u16())/90) - mosfet.temp_act ) >> 3); fc.voltage_act = mp1yA.read_u16() /1.638; fc.current_act = current.read_u16()/4; break; case 3 : switches.master = mp2xD; fc.temp_act = fc.temp_act + ((((61800-mp2yA.read_u16())/90) - fc.temp_act) >> 3); h2o.temp_out = fc.temp_act; cap.voltage_act = mp1yA.read_u16() /1.638; fc.current_act = current.read_u16()/4; break; } mp_A = ( (channel + 1) & 0x01); // A setzen mp_B = (((channel + 1) >> 1) & 0x01); // B setzen } void read_i2c_RHTMP(char ad) { char input[4]; short RH = 0; short TMP = 0; i2c.write(ad<<1, 0x00 , 1); //wake up i2c.read (ad<<1, input , 4); //read out RH = (( 1000 * (((input[0]<<8) | (input[1] )) & 0x3FFF ))>> 14) ; //transform into 0 - 1000 as Integer represents 0.0 - 100.0 % TMP = (( 1650 * (((input[2]<<6) | (input[3]>>2)) & 0x3FFF ))>> 14) -400; //transform into -400 - 1250 as Integer represents -40.0 - 125.0 °C if (TMP > -50 && TMP < 800) { if (ad == I2C_IN ){o2.temp_in = TMP; o2.rh_in = RH;error.o2_in = false;}; if (ad == I2C_OUT){o2.temp_out = TMP; o2.rh_out = RH;error.o2_out = false;}; } else { if (ad == I2C_IN ){error.o2_in = true;}; if (ad == I2C_OUT){error.o2_out = true;}; } } void timetable() { switch (sys.count) { case 0: read_i2c_RHTMP(I2C_IN) ; break; case 125: T_ALL() ; break; case 250: read_i2c_RHTMP(I2C_OUT) ; break; case 375: O_ALL() ; break; case 500: read_i2c_RHTMP(I2C_IN) ; break; case 625: T_ALL() ; break; case 750: read_i2c_RHTMP(I2C_OUT) ; break; case 875: O_ALL() ; break; } read_inputs(); sys.count ++; if (sys.count >= 1000){sys.count=0; led_1 = !led_1;}; } int main() { pc.baud(115200); i2c.frequency(400000); pwm_6.pulsewidth(1.0/PWM_Frequenz); //Mosfet //pwm_5.pulsewidth(1.0/PWM_Frequenz); //H2 Purge pwm_4.pulsewidth(1.0/PWM_Frequenz); //H2O Fan pwm_3.pulsewidth(1.0/PWM_Frequenz); //H20 Pump pwm_2.pulsewidth(1.0/PWM_Frequenz); //Air Pump 2 pwm_1.pulsewidth(1.0/PWM_Frequenz); //Air Pump 2 load_cfg(); while(1) { timetable(); } }