Hochschule München
/
PowerDriverforH2m
Mosfet Driver
main.cpp
- Committer:
- HMFK03LST1
- Date:
- 2013-05-14
- Revision:
- 5:d814001b8aae
- Parent:
- 4:8c89e422bed7
- Child:
- 6:4af29761b1f0
File content as of revision 5:d814001b8aae:
#include "mbed.h" LocalFileSystem local("local"); //init Flashdrive for reading config file FILE *fp; //Pointer to local Config File #define USR_POWERDOWN (0x104) //Power Down Mbed Interface (save 50% or 45 mA) float version = 0.9; //Program Version bool mosfet_open = true ; //Mosfet1 geschlossen bool mosfet_close = false; //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 waterp (p33); DigitalOut mosfet (p21); 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); Ticker PC_OUT_timer; // Output Monitoring to Serial Ticker LED_timer; // Set Status LED´s 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 int load_fail = 0; //Kein Strom trotz Imax // SuperCap Parameter float cap_max = 25.0; //CAP Spannung max. (Abschaltung) float cap_p_max = 90.0; //CAP Prozent Load bei 0V float cap_min = 20.0; //CAP Spannung min. (Zelle an) float cap_p_min = 5.0; //CAP Prozent Load bei 0V float cap_delta = 1.5; //Absenkung der Spannung mit Din // 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 // Monitoring Parameter int debug = 1; //Serial Output on (1) float sample = 5; //Serial Output Samples per Second char com_in[8] ; //Serial input // Mosfet Parameter int Cel_Level = 0; //% Load aus Bz Spannung int Cap_Level = 0; //% Load aus Cap Spannung int Cur_Level = 0; int Load_Level = 0; //% Load aus Bz und Cap float mos_temp = 0; //°C Mosfet // Temp Variable 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; unsigned int counter_cycle = 0; //Counter PWM-Cycles for Pump-Purge unsigned int counter_takt = 0; //Counter for PWM Pump float Regler_Hz = 1000.0; void load_cfg() { char read[25][5]; char i = 0; char j = 0; int c = 0; float temp; for (j = 0; j<26; 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; boost = boost_time * 1000 / pwm_cycle; pump_block = 5 / purge_end; } 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 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("------------Monitor------------- \n\r" ); 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 ((mosfet == mosfet_close) &&(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() { LED_timer.detach(); mosfet = mosfet_open; myled = 0; myled1 = 0; myled2 = 0; myled3 = 0; wait(0.1); myled = 1; wait(0.1); myled1 = 1; wait(0.1); myled2 = 1; wait(0.1); myled3 = 1; wait(0.1); LED_timer.attach (&LED , 0.200); myled3 = 1; } void do_command() { switch(com_in[0]) { case 'r': load_cfg(); led_beep(); 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 2; } void SEND() { float temp1 = 0; float temp2 = 0; float temp3 = 0; float temp4 = 0; float temp5 = 0; char temp6 = 0; bool status= false; switch (debug) { case 1: if (mosfet == mosfet_close) status = true; if (Load == true) 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\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); if (status == true) mosfet = mosfet_close; break; case 2: if (mosfet == mosfet_close) status = true; if (Load == true) 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)); if (status == true) mosfet = mosfet_close; break; case 3: if (mosfet == mosfet_close) status = true; if (Load == true) 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()); if (status == true) mosfet = mosfet_close; break; case 4: pc.printf("Change \n\r"); pump = !pump ; purge = !purge; h2_blow = !h2_blow; waterp = !waterp; mosfet = !mosfet; break; case 5: if (((Cap_Level + Cel_Level) + bz_c_i_min) > 0) {temp1 = ((Cap_Level + Cel_Level) + bz_c_i_min);} else temp1 = 0; if (((Cap_Level + Cel_Level) + bz_c_i_max) > 0) {temp2 = ((Cap_Level + Cel_Level) + bz_c_i_max);} else temp2 = 0; if (current > 0) {temp3 = current;} else temp3 = 0; 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",255,128, //0,1 char(int(bz*6)), //0-35 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 temp6 //Statusbits Din/Pump/Purge ); break; } } void TEMP() { if (temp_1_2 == true) bz_temp = (temp_in.read()/0.00407)- 48.3; else mos_temp = ( mos_in.read()/0.00407)- 50.3; temp_1_2 = !temp_1_2; } void PUMPE() { float regler = 1; counter_takt++; //Aufrufzähler if (cap > (cap_max - (!In1 * cap_delta))) { pump_on = false; pwm_pro = 0; } if ((cap <= cap_min) || (pump_on == true)) //Pumpe Einschaltbedingung { pump_on = true; if (bz > bz_on) {1 - ((pump_red / ((bz_max-(!In1 * cap_delta)) - bz_on) * (bz - bz_on)) / 1000);} //Luftreduzierung wenn Spannung über BZ_on (lineare Reduzierung bis BZ_max um pump_red(%)) pwm_pro = ((float(pwm_on) * regler) / pwm_cycle ); //PWM Prozent für Monitoring if ((pump_block == 0) && (counter_takt > (pwm_cycle - pwm_on) * Regler_Hz / 1000.0)) {pump = 1 ;} //Set PWM from low to high if (counter_takt > (pwm_cycle * Regler_Hz / 1000)) //End PWM cycle { if (counter_cycle == (50)) TEMP(); //Temperatur messen counter_takt = 0; counter_cycle++; if ((boost > 0) && (pump_block == 0)) {boost--;} if (counter_cycle >= ((purge_start - boost_time) * 1000 / pwm_cycle)) //Vorgezogener Anlauf Purgepumpe { if (pump = 1) purge = 1; } if (counter_cycle < ((purge_start - boost_time) * 1000 / pwm_cycle)) { if (boost == 0) pump = 0; //PWM Betrieb purge = 0; } else { pump = 0; } if (counter_cycle >= (purge_end * (1000 / pwm_cycle ))) //Purge Ende counter_cycle = 1 pro Mosfet (PWM 1000/Regler_Hz in [ms]) { counter_cycle = 0; purge = 0; pump = 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 } } int main() { mosfet = mosfet_open; //Mosfet schließen pc.baud(115200); //config Serial Port load_cfg(); //init config File //semihost_powerdown(); //Mbed Interface powerdown PC_OUT_timer.attach(&SEND , (1/sample)); //Serial output Timer LED_timer.attach (&LED , 0.200 ); //LED Status Timer t.start(); //Timer für PWM starten float bz_faktor; //Temp Variable unsigned int pwm_cycle_count; bool power_up = 0; pwm_cycle_count = ((1000000/Regler_Hz)); bz_faktor = ((bz_p_oben - bz_p_unten)/(bz_max - bz_min)); //Prozent Umrechnung BZ while(1) { while (t.read_us() <= pwm_cycle_count){}; get_input(); //µs Timer für Mosfet PWM starten PUMPE(); //Pumpen PWM aufrufen bz = (((24.54 * bz_in * bz_in)+(31.812 * bz_in)+0.04)*2 + bz )/3; //BZ RAW in Spannung umrechnen (2*neu zu 1*alt Glättung) (immer) if (counter_takt%2 == 0){cap = (((24.54 * cap_in * cap_in)+(31.812 * cap_in + 0.04))*2 + cap_in )/3;} //CAP RAW in Spannung umrechnen (2*neu zu 1*alt Glättung) (jedes 2.mal) else {current = (cur_in - 0.32) * 12.568;} //Current RAW in Spannung umrechnen (ohne 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 < cap_min) {power_up = 1;}; if (cap > 0.9*cap_max){power_up = 0;}; if ((current-(bz_current + (power_up * bz_cur_add))) > 0) {if (Cur_Level > (bz_c_i_min)) Cur_Level--;} //to much Load else {if (Cur_Level < (bz_c_i_max)) Cur_Level++;} //less Load //*** Sum all Regulators Load_Level = Cur_Level; Load_Level = Load_Level + Cap_Level; Load_Level = Load_Level + Cel_Level; if (Load_Level > 100) Load_Level = 100; if (Load_Level < 0) Load_Level = 0; t.reset(); if (Load == true) // Laden aktiv { if (bz > bz_min || bz > bz_max) // Zelle über min. Spannung oder über max Spannung zum Entladen { while (t.read_us() <= pwm_cycle_count) // während der PWM (1khz Periode) { if (t.read_us() < Load_Level * 10000 / Regler_Hz) // %Load PWM zu Timer vergleich {mosfet = mosfet_close;} // %Load PWM nicht erreicht Mosfet an else {mosfet = mosfet_open;} // %Load PWM erreicht Mosfet aus } } else { mosfet = mosfet_open ; // Mosfet wegen Unterspannung BZ auskoppeln Load = false; // Laden beenden bis BZ > BZ on (Sicherungsschaltung) } } else { if (bz > cap + 0.5){mosfet = mosfet_open ;} // Mosfet im nicht Ladebetrieb auskoppeln else {mosfet = mosfet_close;} // Mosfet im nicht Ladebetrieb einkoppeln (Treiber stromfrei = Stromsparen) } if ((current < 0.2) && (Cur_Level > (0.9 * bz_c_i_max)) && (Load == true)){Load = false; load_fail = 100;} if (( cap < cap_min) && (bz > bz_on) && (Load == false)) { Load = true; if (bz_c_i_min < 0) {Cur_Level = 2 * bz_c_i_min;}else {Cur_Level = -100;} // Cap unter Minimum oder BZ über Maximum = Laden beginnen / PWM vom Minimum Starten } if ( bz > bz_max && load_fail == 0) Load = true; // Überladung abführen if (load_fail > 0){load_fail--;pump_on = false;} } }