Solarbox Powerbank Firmware V0.24

Aus Open Source Ecology - Germany
Version vom 15. September 2014, 19:52 Uhr von Case (Diskussion | Beiträge) (Created page with "/* created on 08/04/2014 by Debasish Dutta/deba168 extended on 04.09.2014 by OS/case This code is in the public domain. If you modify please inform me ...")
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

/* created on 08/04/2014

  by Debasish Dutta/deba168
  
  extended on 04.09.2014 by OS/case
     
  This code is in the public domain.
  If you modify please inform me
  send a modified copy which will be helpfull for me
*/
  1. include <LiquidCrystal.h>

/*

The LCD-Display circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
*/

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


// LEDs int RED=8; // To indicate discharged condition of battery int GREEN=7; // Solar or Grid-Power on int redflag = 0; // make red LED blink int greenflag = 0; // make green LED blink


// Sampling float solar_volt =0; // variable for solar panel voltage float bat_volt=0; // variable for battery voltage float bat_amp=0; // variable for battery voltage float old_bat_amp; float sample1=0; // reading from Arduino pin A0 float sample2=0; // reading from Arduino pin A1 float sample3=0; // reading from Arduino pin A2 int fenster = 100; // Fensterbreite f. gleitenden Durchschnitt float gleiwin[100]; // gleitender Durchschnitt //gleiwin = new float[fenster];


// Kalibrierwerte float vsys = 0.0; // gemessene Systemspannung float r1 = 0.0; // gemessener 1. Widerstand von Spannungsteiler VBat float r2 = 0.0; // gemessener 2. Widerstand von Spannungsteiuler VBat float rel = 0.0; float onebit; float rfaktor = 0; // Realitätsfaktor zum Abgleich mit meinem Multimeter


// Charging Values //float vladeschluss = 6.4; // Max-Voltage per cell 3.2 //float vladeschluss = 6.6; // Max-Voltage per cell 3.3 //float vladeschluss = 7.2; // Max-Voltage per cell 3.6 ==> this defines the upper level if 100% use of cell capacity is wanted float vladeschluss = 7.1; // Max-Voltage per cell 3.55 ==> this defines the upper level if about 95% use of cell capacity is wanted - its healthier

// float vladeschluss = 7.2; // Max-Voltage per cell 3.55 ==> this defines the upper level if about 95% use of cell capacity is wanted - its healthier

//float cc = 0.5; // constant current , current clamp for CC/CV-charging

float cc = 0.9; // constant current , current clamp for CC/CV-charging


int pwm=6; // pwm out put to mosfet // float duty = 0.0; // duty cycle prozente int duty = 0; // duty cycle prozente int chargingflag = 0;


// Discharging Values float ventladeschluss = 5.6; // Min-Voltage per cell 2.8 ==> Depth of Discharge (DOD) about 80% int load=9; //load is connected to pin-9

// Floating Values // float vfloating_min = 6.8; // In floating-mode discharge until 3.45V per cell then start charging again ==> Hysteresis float vfloating_min = 6.9; // In floating-mode discharge until 3.45V per cell then start charging again ==> Hysteresis float cv = vladeschluss; // default value for charging, choose a smaller value for more battery-health int floatingflag = 0;



// Evaluation unsigned long timestamp; int charged_percent =0; int i = 0;


void setup() {

 TCCR0B = TCCR0B & 0b11111000 | 0x05; // setting prescaar for 61.03Hz pwm
 Serial.begin(9600);
 pinMode(pwm,OUTPUT);
 //pinMode(load,OUTPUT);
 pinMode(RED,OUTPUT);
 pinMode(GREEN,OUTPUT);
 digitalWrite(pwm,LOW);
 //digitalWrite(load,LOW);
 digitalWrite(RED,LOW);
 digitalWrite(GREEN,LOW);
 
 lcd.begin(16, 2);                     // columns, rows. size of display
 lcd.clear();                         // clear the screen
 /*
 lcd.print("Solar-Charger");
 lcd.setCursor(0, 1);
 lcd.print("V.0.17, by OS 2014");
 delay(10);
 lcd.clear();
 */
 
    
 // duty = 50;
 
 

}





// void loop_disabled() void loop() {

 lcd.setCursor(16,1); // set the cursor outside the display count
 lcd.print(" ");      // print empty character
 timestamp = millis();
 
 ///////////////////////////  VOLTAGE SENSING ////////////////////////////////////////////
 int zaehler = 10;
 
 for(int i=0;i<zaehler;i++)
 {
   sample1+=analogRead(A1);  //read the input voltage from solar panel
   sample2+=analogRead(A2);  //read the battery voltage 
   sample3+=analogRead(A0);  //read the battery amperage 
   delay(4);
 }
 sample1=sample1/zaehler; 
 sample2=sample2/zaehler; 
 sample3=sample3/zaehler; 
 
 delay(1);
  
  // Kalibrierung
  // vsys = 4.200;         // gemessene Spannung am Arduino, versorgt durch PC
  // rfaktor = 1.1122;      // rfaktor bei PC-Versorgung
  vsys = 5.003;         // gemessene Spannung am BuckBoost-Converter ==> Arduino-5V-Pin (Achtung nicht Vin nehmen, da linearregler >= 7V verlangt !!!)
  rfaktor = 1;
  // rfaktor = 0.98;         // Anpassung an zweites Multimeter
  // vsys = 3.95;         // gemessene Spannung am Arduino, versorgt durch Batterie mit BuckBoost-Converter
  //// rfaktor = 1.10396;    // rfaktor bei buckbooster-Betrieb
  // rfaktor = 1.106;    // rfaktor gemittelt aus PC- und Buckbooster-Betrieb
  
  r1 = 9.96;            // gemessener R1 von Spannungsteiler Batterie
  r2 = 4.67;            // gemessener R2 von Spannungsteiler Batterie
   
  rel = (r1+r2)/r2;          // Verhältniss R2 zu R1
  onebit = vsys/1023;   // 1 Bit entspricht rund 4.89mV (=5.02V / 1024 Bit)
  
  // Spannungsteiler Batterie
  bat_volt = sample2*onebit;  // tatsächlich durch ADC gemessene VBat - uninterpretiert
  bat_volt = bat_volt/rfaktor;  // Realitätsfaktor gegenüber Multimetermessung: 1.1122
  bat_volt = bat_volt * rel; // umgerechnet in Gesamtvolt
  // Spnnungsteiler ExternalInput (z.B. Solar, oder Netzteil)
  solar_volt = sample1*onebit;  // tatsächlich durch ADC gemessene VBat - uninterpretiert
  solar_volt = solar_volt/rfaktor;  // Realitätsfaktor gegenüber Multimetermessung: 1.1122
  solar_volt = solar_volt * rel; // umgerechnet in Gesamtvolt


 ///////////////////////////  AMPERAGE SENSING ////////////////////////////////////////////
  // Amperemessung Batterie, mittels ACS714
  //// sample3 = sample3+36;
  //sample3 = sample3+30;
  bat_amp = map(sample3, 102, 921, -300, 300)/10.00;
  //bat_amp = bat_amp * 0.5; // Anpassung an mein Multimeter  Alternative: Amp-Wert ca 1000 mal messen und mitteln, nähert sich dadurch meinem Multimeter an
  // bat_amp = bat_amp * 0.76; // Anpassung an mein Multimeter  Alternative: Amp-Wert ca 1000 mal messen und mitteln, nähert sich dadurch meinem Multimeter an
  double Current = currentSensor(analogRead(0));  // Read  analog value
  // printDouble(Current, 2);                  
   bat_amp = (float) Current;

// Glättung /*

  old_bat_amp = 0;
  for(i=1; i<(fenster-1); i++)
  {
    gleiwin[i-1] = gleiwin[i];
    old_bat_amp = old_bat_amp + gleiwin[i];
  }
  gleiwin[fenster-1] = bat_amp;
  old_bat_amp = old_bat_amp + bat_amp;
  bat_amp = old_bat_amp / fenster;
  • /

//bat_amp = bat_amp -0.9;

bat_amp = bat_amp +2.9;
bat_amp = bat_amp / 3;

// bat_amp = bat_amp +0.03;

  // bat_amp = bat_amp * fenster;
  

// old_bat_amp = bat_amp + old_bat_amp; // old_bat_amp = old_bat_amp / 2;


 ///////////////////////////  DATA OUTPUT ////////////////////////////////////////////
 lcd.setCursor(0,0); // set the cursor at 1st col and 1st row
 lcd.print("Vs:");
 lcd.print(solar_volt);
 
 lcd.setCursor(8,0); // set the cursor at 8st col and 1st row
 lcd.print("Vb:");
 lcd.print(bat_volt);
 //lcd.print(rel);
 //lcd.print(sample2);
 lcd.setCursor(8,1); // set the cursor at 8st col and 2nd row
 lcd.print("Ab:             ");
 lcd.setCursor(11,1); // set the cursor at 8st col and 2nd row
 lcd.print(bat_amp);
 
 lcd.setCursor(0,1); // set the cursor at 8st col and 2nd row
 lcd.print("Du:     ");
 lcd.setCursor(3,1); // set the cursor at 8st col and 2nd row
 // lcd.print(duty);
 lcd.print(sample3);


  Serial.print(bat_volt);
  Serial.print(",");   
  Serial.print(bat_amp);
  Serial.print(",");   
  Serial.print(solar_volt);
  Serial.print(",");   
  Serial.print(chargingflag);
  Serial.print(",");   
  Serial.println(duty);
  // Serial.print(",");   
  // Serial.println(timestamp);
 
   

/////////////////////////// State machine ////////////////////////////////////////////////

/* if((solar_volt > bat_volt) && (bat_volt > 0)) // external voltage input and battery are connected {

duty = cc / 0.0172;    // empirisch gemessen

analogWrite(pwm,2.55 * duty);  // float charging 

} else duty = 0;

  • /


if((solar_volt > bat_volt) && (bat_volt > 0)) // external voltage input and battery are connected {

 //********* Charge ************************
 // duty = 30;
 
 // duty = 25;
 if(bat_volt < vladeschluss)  // Charging in CurrentClamp-mode (CC)
 {
   if(chargingflag == 0)  // OFF mode
   {
     if(bat_volt > vfloating_min) chargingflag = 0; // between 3.55 and 3.45 stay off, in floating-mode
     else chargingflag = 1;                         // below 3.45 restart charging, in floating-mode
   }
   else  // chargingflag != 0
   {
     if(chargingflag == 1)
     {
       //Serial.print("CC-Charging: ");
        duty = cc / 0.0172;    // 0.0172 empirisch gemessene charging-rate pro 1% duty
       // if(bat_amp > cc && duty > 0) duty = duty-1;
       // if(bat_amp == cc) duty = duty;  // do nothing
       // if(bat_amp < cc && duty < 100) duty = duty+1;
       analogWrite(pwm,2.55 * duty);  // float charging 
     }
   }
 }


 if(bat_volt >= vladeschluss) // Charging in VoltageClamp-mode (CV)
 {
   if(bat_amp > cc/10) // Charging in VoltageClamp-mode (CV)
   {
     //Serial.print("CV-Charging: ");
     if(bat_volt > cv && duty > 0) duty = duty-1;
     if(bat_volt == cv) duty = duty;  // do nothing
     if(bat_volt < cv && duty < 100) duty = duty+1;
     analogWrite(pwm,2.55 * duty);  // float charging 
     chargingflag = 2;
   }
   else // (bat_amp <= cc/10)) // shut down when battery is fully charged
   {
     // Serial.println("Discharging: ");
     duty = 0;
     analogWrite(pwm,duty);  // stop charging
     chargingflag = 0;  
   }
 }

} // endif solar_volt > bat_volt else // solar_volt <= bat_volt // No external voltage input or no battery is connected {

 // Stop charging anyway
 duty = 0;
 analogWrite(pwm,0); 
 chargingflag = 0;
 
 //********************* Discharge **********************
 //Serial.print("DisCharging: ");
 // Low voltage protection for the Battery
 if( bat_volt <= ventladeschluss )
 {
   chargingflag = 1;
   
   // Verbraucher abklemmen
   
   // Arduino shutdown (or go sleep ?)
 }  
 

} // end else


delay(4);

//////////////////////////////LED INDICATION ////////////////////////////////////////


//Red LED will glow when any Solar-Power comes in if(solar_volt > 0) {

 digitalWrite(RED,HIGH);

} else {

 digitalWrite(RED,LOW);

}

//Green LED will glow when a battery is connected if(bat_volt > 0) {

 digitalWrite(GREEN,HIGH);

} else {

 digitalWrite(GREEN,LOW);

}


/* // external voltage is there, but to weak for charging. if(solar_volt <= bat_volt) {

 digitalWrite(RED,HIGH);

}

  • /


if (chargingflag == 1) {

// Red LED will blink continiously indicating charging is going on
if(redflag == 0) 
{
  digitalWrite(RED,HIGH);
  redflag = 1;
}
else
{
  digitalWrite(RED,LOW);
  redflag = 0;
}
delay(5);

}

if (chargingflag == 2) {

// Green LED will blink continiously indicating charging is going on
if(greenflag == 0) 
{
  digitalWrite(GREEN,HIGH);
  greenflag = 1;
}
else
{
  digitalWrite(GREEN,LOW);
  greenflag = 0;
}
delay(5);

}



} // end loop()

//======================================================================


void test_loop(){

 double Current = currentSensor(analogRead(0));  // Read  analog value
 Serial.print(", VariationFromNull: "); 
 printDouble(Current, 2);                                     // display Current
 Serial.print(" A");
 Serial.println("");
 delay(1000);

}


// --------------------------------------------------------------------------------------------------------

// Print decimal numbers

void printDouble(double val, byte precision) {

 Serial.print (int(val));                                     // Print int part
 if( precision > 0) {                                         // Print decimal part
   Serial.print(".");
   unsigned long frac, mult = 1;
   byte padding = precision -1;
   while(precision--) mult *=10;
   if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val) - val) * mult;
   unsigned long frac1 = frac;
   while(frac1 /= 10) padding--;
   while(padding--) Serial.print("0");
   Serial.print(frac,DEC) ;
 }

}

// Read 1.1V reference against AVcc

long readInternalVcc() {

 long result;
 ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
 delay(2);                                                    // Wait for Vref to settle
 ADCSRA |= _BV(ADSC);                                         // Convert
 while (bit_is_set(ADCSRA,ADSC));
 result = ADCL;
 result |= ADCH<<8;
 result = 1126400L / result;                                  // Back-calculate AVcc in mV
 return result;

}

// Calculate current with Allegro ACS714

double currentSensor(int RawADC) {

 int    Sensitivity    = 66; // mV/A
 long   InternalVcc    = readInternalVcc();
 double ZeroCurrentVcc = InternalVcc / 2;
 double SensedVoltage  = (RawADC * InternalVcc) / 1024;
 double Difference     = SensedVoltage - ZeroCurrentVcc;
 double SensedCurrent  = Difference / Sensitivity;
 //Serial.print("ADC: ");
 //Serial.print(RawADC);
 //Serial.print("/1024");
 //Serial.print(", Sensed Voltage: ");
 //printDouble(SensedVoltage, 1);
 //Serial.print("mV");
 //Serial.print(", 0A at: ");
 // printDouble(ZeroCurrentVcc, 1);
 //Serial.print("mV");
 return SensedCurrent;                                        // Return the Current

}