Mosfet Driver

Dependencies:   mbed

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;}
   
    }
 
}