Hochschule München
/
PowerDriverforH2m
Mosfet Driver
main.cpp
- Committer:
- HMFK03LST1
- Date:
- 2013-07-21
- Revision:
- 6:4af29761b1f0
- Parent:
- 5:d814001b8aae
File content as of revision 6:4af29761b1f0:
#include "mbed.h" LocalFileSystem local("local"); //init Flashdrive for reading config file FILE *fp; //Pointer to local Config File FILE *lp; #define USR_POWERDOWN (0x104) //Power Down Mbed Interface (save 50% or 45 mA) float version = 1.1; //Program Version bool mosfet_open = false; //Mosfet1 geschlossen bool mosfet_close = true; //Mosfet1 offen DigitalOut myled (LED1); DigitalOut myled1 (LED2); DigitalOut myled2 (LED3); DigitalOut myled3 (LED4); DigitalOut pump (p36); DigitalOut purge (p35); DigitalOut h2_blow(p34); DigitalOut out4 (p33); DigitalOut mosfet (p21); DigitalOut xbee_rst(p11); DigitalIn In1 (p22); // Caps Down DigitalIn In2 (p23); // Power UP DigitalIn In3 (p24); DigitalIn In4 (p25); DigitalIn In5 (p29); DigitalIn In6 (p30); AnalogIn cap_in (p15); // AI 1 Faktor /14.8 AnalogIn bz_in (p16); // AI 2 Faktor /14.8 AnalogIn mos_in (p17); // AI 3 Faktor /1.5 AnalogIn temp_in(p18); // AI 4 Faktor /1.5 AnalogIn AI_5 (p19); // AI 5 Faktor * 2 AnalogIn cur_in (p20); // AI 6 Faktor * 2 zum Strommesser // Serial pc(USBTX, USBRX); Serial pc(p9, p10); // XBee Ticker PC_OUT_timer; // Output Monitoring to Serial Timer t; // Brennstoffzellen Parameter float bz_max = 30.5; //Brennstoffzelle Spannung Abs. max. float bz_p_oben = 15.0; //Brennstoffzelle Prozent Load bei bz_max float bz_on = 29.0; //Brennstoffzelle Spannung für Ladefreigabe) float bz_min = 26.0; //Brennstoffzelle Spannung min. Laden beenden float bz_p_unten = -20.0; //Brennstoffzelle Prozent Load bei bz_min float bz_current = 1.5; //Brennstoffzellen Strom nominal float bz_cur_add = 2.0; //Brennstoffzellen Strom max float bz_c_i_max = 20.0; //Strom Integrale Reglung Max % float bz_c_i_min = -10.0; //Strom Integrale Reglung Min % float bz_temp_max = 55.0; //Maximale Wassertemperatur °C float bz_faktor = 0; //Temp Variable // SuperCap Parameter float cap_max = 35.0; //CAP Spannung max. (Abschaltung) float cap_p_max = 90.0; //CAP Prozent Load bei 0V float cap_min = 30.0; //CAP Spannung min. (Zelle an) float cap_p_min = 15.0; //CAP Prozent Load bei 0V float cap_delta = 1.5; //Absenkung der Spannung mit Din float cap_low = 26.0; //Grenze zur Volleinkopplung *** float cap_up = 29.5; //Grenze high current *** // Pump & Purge Parameter float purge_start = 3.0; //s before starting purch float purge_end = 3.2; //s after finishing purch float boost_time = 0.2; //s Pump runup with 100% Duty Cycle float pump_red = 30.0; //% Pumpen PWM red. zwischen BZ_on und BZ_max linear float pwm_cycle = 20.0; //ms für PWM Period float pwm_on = 12.0; //ms für PWM high float pwm_pro = 0; //PWM Taktung float pow_up_on = 28.5; //Einschalten Boostpumpe V unter Cap_min *** float pow_up_off = 29.5; //Ausschalten Boostpumpe V unter Cap_min *** // Monitoring Parameter int debug = 1; //Serial Output on (1) float sample = 5; //Serial Output Samples per Second char com_in[8] ; //Serial input float mos_t_max = 85; // Mosfet Parameter int Cel_Level = 0; //% Load aus Bz Spannung int Cap_Level = 0; //% Load aus Cap Spannung float Cur_Level = 0; //% Load aus BZ Strom float Load_Level = 0; //% Load aus Bz und Cap float mos_temp = 0; //°C Mosfet // Temp Variable bool pwm_mode = false; bool Load = false; //Laderegler aktiv bool pump_on = false; //Pumpenzustand int boost = 0; //Number of PWM-Cycles for Pump runup boost calc in load_cfg char input_c = 0; //Serial comand input float bz = 0; //Spannung Brennstoffzelle float cap = 0; //Spannung SuperCap float current = 0; //Strom in den Mosfet float bz_temp = 0; //BZ Temperatur bool temp_1_2 = false; //Auswahl Temperaturkanal int pump_block = 2; int mos_block = 1000; int purge_h2_on = 0; bool power_up = 0; int h2purge = 100; int h2purge_count = 0; int msg_cnt = 0; bool mos_over = false; bool pump_2 = true; unsigned int counter_cycle = 0; //Counter PWM-Cycles for Pump-Purge unsigned int counter_takt = 0; //Counter for PWM Pump unsigned int counter_send = 0; unsigned int temp_takt = 0; float pwm_cycle_count = 0; float zahler = 0; float Regler_Hz = 1000.0; void load_cfg(); void LED(); void led_beep(); void do_command(); void get_input(); int semihost_powerdown(); int port(int); void SEND(); void TEMP(); void PUMPE(); void control_block(); bool LOAD_STATE(); void mos_pwm() { int temp = 0; temp = int((Load_Level * pwm_cycle_count) / 100.0); while(t.read_us() <= temp){ mosfet = mosfet_close;}; // %Load PWM zu Timer vergleich {} if (Load_Level < 100.0) { mosfet = mosfet_open ;}; // %Load PWM erreicht Mosfet aus oder dauer an } int main() { mosfet = mosfet_open; //Mosfet auf pc.baud(115200); //config Serial Port load_cfg(); //init config File t.start(); //Timer für PWM starten while(1) { while (t.read_us() <= pwm_cycle_count){}; // Time Sync SEND(); // Send MSG get_input(); // Serial Command input t.reset(); // Timer reset if (LOAD_STATE() == true) { if (Load_Level > 50) { mosfet = mosfet_close; // Mosfet close control_block(); // PID Block mos_pwm(); // Mosfet PWM } else { mos_pwm(); // Mosfet PWM control_block(); // PID Block }; } else { control_block(); // PID Block } } } void xbee_rs() { xbee_rst = 0; wait_ms(1); xbee_rst = 1; } void load_cfg() { char read[27][5]; char i = 0; char j = 0; int c = 0; float temp; for (j = 0; j<28; j++) { for (i = 0; i<6; i++) { read[j][i] = '\0'; } } i=0; j=0; fp = fopen("/local/power.cfg", "r"); if ( fp != NULL ) { while((c != EOF) && (c !=10)) { c = fgetc(fp); if (c == ';'){read[j][0] = i; i = 0; j++;} else {i++; read[j][i] = c;} } fclose(fp); sscanf(&read[ 0][1], "%f", &temp); bz_max = temp; sscanf(&read[ 1][1], "%f", &temp); bz_p_oben = temp; sscanf(&read[ 2][1], "%f", &temp); bz_on = temp; sscanf(&read[ 3][1], "%f", &temp); bz_min = temp; sscanf(&read[ 4][1], "%f", &temp); bz_p_unten = temp; sscanf(&read[ 5][1], "%f", &temp); bz_current = temp; sscanf(&read[ 6][1], "%f", &temp); bz_cur_add = temp; sscanf(&read[ 7][1], "%f", &temp); bz_c_i_max = temp; sscanf(&read[ 8][1], "%f", &temp); bz_c_i_min = temp; sscanf(&read[ 9][1], "%f", &temp); bz_temp_max = temp; sscanf(&read[10][1], "%f", &temp); cap_max = temp; sscanf(&read[11][1], "%f", &temp); cap_p_max = temp; sscanf(&read[12][1], "%f", &temp); cap_min = temp; sscanf(&read[13][1], "%f", &temp); cap_p_min = temp; sscanf(&read[14][1], "%f", &temp); cap_delta = temp; sscanf(&read[15][1], "%f", &temp); purge_start = temp; sscanf(&read[16][1], "%f", &temp); purge_end = temp; sscanf(&read[17][1], "%f", &temp); boost_time = temp; sscanf(&read[18][1], "%f", &temp); pump_red = temp; sscanf(&read[19][1], "%f", &temp); pwm_cycle = temp; sscanf(&read[20][1], "%f", &temp); pwm_on = temp; sscanf(&read[21][1], "%f", &temp); Regler_Hz = temp; sscanf(&read[22][1], "%f", &temp); debug = temp; sscanf(&read[23][1], "%f", &temp); sample = temp; sscanf(&read[24][1], "%f", &temp); mos_t_max = temp; boost = boost_time * 1000 / pwm_cycle; //boost in Pumpen PWM-Cycle pump_block = 5 / purge_end; //5s Pumpen aus mos_block = 2000000.0/Regler_Hz ; //2s Mosfet aus pwm_cycle_count = 1000000.0/Regler_Hz ; //ns pro Mosfet PWM-Cycle bz_faktor = (bz_p_oben - bz_p_unten)/(bz_max - bz_min); // h2purge = 600 / purge_end; xbee_rs(); } pc.printf("\n\r" ); pc.printf("******************************** \n\r" ); pc.printf("* Brennstoffzellenregler V%03.1f * \n\r",version); pc.printf("******************************** \n\r" ); pc.printf("--------------BZ---------------- \n\r" ); pc.printf(" BZ max [V] : %5.1f \n\r",bz_max ); pc.printf(" BZ max [%c] : %5.1f \n\r",37,bz_p_oben ); pc.printf(" BZ Laden on [V] : %5.1f \n\r",bz_on ); pc.printf(" BZ Laden off [V] : %5.1f \n\r",bz_min ); pc.printf(" BZ Laden off [%c] : %5.1f \n\r",37,bz_p_unten ); pc.printf(" BZ Strom norm [A] : %5.1f \n\r",bz_current ); pc.printf(" BZ Strom max. [A] : %5.1f \n\r",bz_cur_add ); pc.printf(" BZ Strom I max.[%c] : %5.1f \n\r",37,bz_c_i_max ); pc.printf(" BZ Strom I min.[%c] : %5.1f \n\r",37,bz_c_i_min ); pc.printf(" BZ Temp max. [%cC]: %5.1f \n\r",176,bz_temp_max); pc.printf("-------------CAP---------------- \n\r" ); pc.printf(" CAP max [V] : %5.1f \n\r",cap_max ); pc.printf(" CAP max [%c] : %5.1f \n\r",37,cap_p_max ); pc.printf(" CAP min [V] : %5.1f \n\r",cap_min ); pc.printf(" CAP min [%c] : %5.1f \n\r",37,cap_p_min ); pc.printf(" CAP up add A [V] : %5.1f \n\r",cap_up ); pc.printf(" CAP low Mos on [V] : %5.1f \n\r",cap_low ); pc.printf(" CAP lo on Din [-V]: %5.1f \n\r",cap_delta ); pc.printf("----------Pump & Purge---------- \n\r" ); pc.printf(" Purge on [s] : %5.1f \n\r",purge_start ); pc.printf(" Purge off [s] : %5.1f \n\r",purge_end ); pc.printf(" Boost [s] : %5.1f \n\r",boost_time ); pc.printf(" Pumpe abregeln [%c] : %5.1f \n\r",37,pump_red ); pc.printf(" PWM cycle [ms]: %5.0f \n\r" ,pwm_cycle ); pc.printf(" PWM on [ms]: %5.0f \n\r" ,pwm_on ); pc.printf(" All Pumps on [V] : %5.1f \n\r" ,pow_up_on ); pc.printf(" All Pumps off [V] : %5.1f \n\r" ,pow_up_off ); pc.printf("------------Monitor------------- \n\r" ); pc.printf(" Mosfet Temp max[%cC] :%4.0f \n\r",176,mos_t_max); pc.printf(" Regler Frequenz[Hz] :%4.0f \n\r" ,Regler_Hz ); pc.printf(" Serial output [bool]: %3d \n\r" ,debug ); pc.printf(" Samplerate [Hz] : %3.0f \n\r",sample ); pc.printf("******************************** \n\r" ); pc.printf("\n\r" ); } void LED() { if (bz < bz_min ) myled = 1; else myled = 0; //LED = Spannung an der BZ IO if (cap > cap_min) myled1 = 1; else myled1 = 0; //LED = Spannung an den Cap´s IO if (Load == true ) myled2 = 1; else myled2 = 0; //LED = Gate Zustand Mosfet 1 if (pump_on == 1 ) myled3 = 1; else myled3 = 0; //LED = Pumpe an } void led_beep() { myled = 0; myled1 = 0; myled2 = 0; myled3 = 0; wait(0.05); myled = 1; wait(0.05); myled1 = 1; wait(0.05); myled2 = 1; wait(0.05); myled3 = 1; wait(0.05); } void do_command() { switch(com_in[0]) { case 'r': mosfet = mosfet_open; load_cfg(); led_beep(); break; case 'm': mosfet = mosfet_open; debug = 5; break; case 'n': mosfet = mosfet_open; debug = 0; break; case 'l': debug = 6; break; case 'u': pump_on = true; break; case '0': mos_over = false; break; case '1': mos_over = true; break; case '2': pump_2 = true; break; case '3': pump_2 = false; break; } } void get_input() { char wert; while (pc.readable() == true) { wert = pc.getc(); //Char lesen if ((wert == 'c') && ((input_c == 0))) {input_c = 1;} //Command Char 1 prüfen if ( wert == 10) {input_c = 0; do_command(); com_in[0] =' ';} //Command End prüfen if (input_c == 2) { com_in[0] = wert; } if ((input_c == 1) && (wert == '_')){input_c = 2;} //Command Char 2 prüfen } } int semihost_powerdown() { uint32_t arg; return __semihost(USR_POWERDOWN, &arg); } int port(int number) { if (number == 1) {if (In1 == 1) return 1; else return 0;} if (number == 2) {if (In2 == 1) return 1; else return 0;} if (number == 3) {if (In3 == 1) return 1; else return 0;} if (number == 4) {if (In4 == 1) return 1; else return 0;} if (number == 5) {if (In5 == 1) return 1; else return 0;} if (number == 6) {if (In6 == 1) return 1; else return 0;} return -1; } void SEND() { float temp1 = 0; float temp2 = 0; float temp3 = 0; float temp4 = 0; float temp5 = 0; char temp6 = 0; if (counter_send >= int(Regler_Hz / sample)) { LED(); counter_send = 0; switch (debug) { case 1: mosfet = mosfet_open; pc.printf("BZ: %4.1f/%4.1f-%4.1f+%4.1f CAP: %4.1f/%4.1f-%4.1f Pump : %2d Purge: %3.1f/%3.1f-%3.1f Load: %02d/%02d-%02d Current: %4.2f Temp BZ: %3.1f Temp Mos: %3.1f H2purge: %03d\n\r" ,bz,bz_min,bz_on,bz_max,cap,cap_min,cap_max,int(pwm_pro*100),float(counter_cycle * pwm_cycle/1000), purge_start,purge_end,int(Load_Level),int((Cap_Level + Cel_Level) + bz_c_i_min), int((Cap_Level + Cel_Level) + bz_c_i_max), current, bz_temp, mos_temp, h2purge_count); break; case 2: mosfet = mosfet_open; pc.printf("In1: %2d In2: %2d In3: %2d In4: %2d In5: %2d In6: %2d \n\r",port(1),port(2),port(3),port(4),port(5),port(6)); break; case 3: mosfet = mosfet_open; pc.printf("AI1: %3.2f AI2: %3.2f AI3: %3.2f AI4: %3.2f AI5: %3.2f AI6: %3.2f \n\r",cap_in.read(),bz_in.read(),mos_in.read(),temp_in.read(),AI_5.read(),cur_in.read()); break; case 4: pc.printf("Change \n\r"); pump = !pump ; purge = !purge; h2_blow = !h2_blow; out4 = !out4; mosfet = !mosfet; break; case 5: mosfet = mosfet_open; if (msg_cnt > 1000) {xbee_rs(); msg_cnt = 0;} else {msg_cnt++; xbee_rst = 1;}; if (((Cap_Level + Cel_Level) + bz_c_i_min) > 0) {temp1 = ((Cap_Level + Cel_Level) + bz_c_i_min);} else temp1 = 0; if (temp1 > 100) temp1 = 100; if (((Cap_Level + Cel_Level) + bz_c_i_max) > 0) {temp2 = ((Cap_Level + Cel_Level) + bz_c_i_max);} else temp2 = 0; if (temp2 > 100) temp2 = 100; if (current > 0) {temp3 = current;} else temp3 = 0; if (current > 10){temp3 = 10;}; if (bz_temp > 0) {temp4 = bz_temp;} else temp4 = 0; if (mos_temp > 0) {temp5 = mos_temp;} else temp5 = 0; temp6 = (purge<<7)+(pump_on<<6)+(In1<<5) + (In2<<4) + (In3<<3) + (In4<<2) + (In5<<1) + In6; pc.printf("%c%c%c%c%c%c%c%c%c%c%c%c%c", 255,128, //0,1 char(int(bz*6)), //0-42 zu 0-250 2 0 char(int(cap*7)), //0-38 zu 0-250 3 1 char(int(Load_Level * 2.5)), //0-100 zu 0-250 4 2 char(int(temp1 * 2.5)), //0-100 zu 0-250 5 3 char(int(temp2 * 2.5)), //0-100 zu 0-250 6 4 char(int(temp3 * 25 )), //0-10 zu 0-250 7 5 char(int(temp4 * 2.5)), //0-100 zu 0-250 8 6 char(int(temp5 * 2.5)), //0-100 zu 0-250 9 7 char(int(pwm_pro * 250)), //0-100 zu 0-250 10 8 char(h2purge_count ), //counter 0 - 11 9 temp6 //Statusbits 12 10 ); break; case 6: mosfet = mosfet_open; break; } } } void TEMP() { if (temp_1_2 == true) bz_temp = (temp_in.read()/0.00407)- 53.6; else mos_temp = ( mos_in.read()/0.00407)- 54.1; temp_1_2 = !temp_1_2; if ( (mos_temp > mos_t_max ) ||(bz_temp > bz_temp_max)){power_up = 0; pump_block = (10 / purge_end);} ; } void PUMPE() { temp_takt++; //Aufrufzähler if (temp_takt >= 500){TEMP();temp_takt = 0;} //alle 500ms //*** Autopurge if ( (h2purge == 0) // Purge Sperre aus && (Cur_Level == bz_c_i_max) // Current Integral auf maximum && (pump_on == 1) // Pumpe an && (cap < (0.95 * cap_low)) // Capspannung niedrig ) {mosfet = mosfet_open; h2_blow = 1; wait_ms(40); h2_blow = 0; h2purge = 495 * Regler_Hz/pwm_cycle; h2purge_count++;} else {h2_blow = 0;} //*** Abschalten if ( (cap >= (cap_max - (In1 * cap_delta))) // Abschalten wenn CAP max erreicht ||(bz > (bz_max)) // Abschalten wenn BZ max überrschritten ) { pump_on = false; pwm_pro = 0; } //*** Einschalten if ( ((cap <= (cap_min - (In1 * cap_delta))) // Einschalten wenn Cap min erreicht ||(pump_on == true)) // Einschalten wenn Pumpe in Betrieb - Abschaltbedingung nicht erreicht && (In2 == false) // Serviceschalter nicht betätigt ) { pump_on = true; pwm_pro = ((float(pwm_on)) / pwm_cycle ); // PWM Prozent für Monitoring if ((pump_block == 0) && (counter_takt > (pwm_cycle - pwm_on))) {pump = 1 ;} //Set PWM from low to high if (counter_takt > pwm_cycle) //End PWM cycle 40ms * 7500/1000=7.5/ms { counter_takt = 0; counter_cycle++; if (h2purge > 0){h2purge--;}; if ((boost > 0) && (pump_block == 0)) {boost--; pump = 1;} else {pump = 0;} //PWM Betrieb if ( ( (counter_cycle == int((purge_start - boost_time) * (1000 / pwm_cycle))) //Vorgezogener Anlauf Purgepumpe || (power_up == 1)) ) { if (pump_2 == true) purge = 1; else purge = 0; } if (counter_cycle == int((purge_start) * (1000 / pwm_cycle))) //Purge Start { } if (counter_cycle >= int(purge_end * (1000 / pwm_cycle ))) //Purge Ende counter_cycle = 1 pro Mosfet (PWM 1000/Regler_Hz in [ms]) { counter_cycle = 0; if ((power_up == 0))purge = 0; if (pump_block > 0) pump_block--; } } } else { pump_on = 0; pump = 0; purge = 0; //Pumpe aus boost = (boost_time * 1000 / pwm_cycle); //Boost für nächsten Start setzen } } void control_block() { float cur_t; float bz_t; float cap_t; float bz_cur_t; counter_takt++; counter_send++; if (counter_takt%(int(Regler_Hz/1000)) == 0) PUMPE(); //Pumpen PWM aufrufen cur_t = (cur_in - 0.270); current = ( (cur_t * cur_t * 24.975) + (cur_t * 4.701) + (current) ) / 2; //Current RAW in Spannung umrechnen (immer) -0.28 if (current > 10.1) current = 10.1; if (counter_takt%2 == 0){cap_t = cap_in; cap = (((24.54 * cap_t * cap_t)+(31.812 * cap_t) + 0.04) + cap * 2)/3;} //CAP RAW in Spannung umrechnen (1*neu zu 2*alt Glättung) (jedes 2.mal) else {bz_t = bz_in ; bz = (((24.54 * bz_t * bz_t )+(31.812 * bz_t ) + 0.04) + bz * 2)/3;} //BZ RAW in Spannung umrechnen (1*neu zu 2*alt Glättung)(jedes 2.mal) //***Regulate Cell Level*** Cel_Level = (bz_faktor * (bz - bz_min) + bz_p_unten); //%Load aus Zellenspannung berechnen //***Regulate Cap´s Level*** Cap_Level = (((cap / cap_max) * (cap_p_max - cap_p_min)) + cap_p_min); //%Load aus Cap Level //***Regulate Current Level*** if ((cap < pow_up_on ) && (cap > 10)) {power_up = 1;}; if ((cap > pow_up_off) ) {power_up = 0;}; if ( (cap > cap_up) || (cap < 14) ) {bz_cur_t = bz_current;} else {bz_cur_t = bz_current + bz_cur_add;}; if ( (current - bz_cur_t) > 0 ) {if ((Cur_Level > bz_c_i_min)) {Cur_Level = Cur_Level - 0.2;}} //to much Amp-Load else {if ((Cur_Level < bz_c_i_max) && (bz > bz_min)) {Cur_Level = Cur_Level + 0.2;}} //less Amp-Load //*** Sum and limit all Regulators Load_Level = Cur_Level + Cap_Level + Cel_Level; if ( (Load_Level > 100) ||(mos_over == true) ) Load_Level = 100.1; if ( (cap > (bz_max - 3.5)) ||(cap < cap_low) ) Load_Level = 100.1; if (Load_Level < 0) Load_Level = 0; } bool LOAD_STATE() { if ( ( bz > bz_on ) // BZ über Einschaltspannung && ( Load == false ) // Laden noch nicht ausgelöst ) { Load = true; Cur_Level = bz_c_i_min; // mit I min einkoppeln } if ( ( Load == true ) // Laden aktiv &&( (bz - cap) > 0.0 ) &&( bz > bz_min ) ) {return true;} else {Load = false; mosfet = mosfet_open; return false;}; }