ZACmeter-Anwendungsprogram

Aus Open Source Ecology - Germany
Zur Navigation springen Zur Suche springen
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,178,4 };

byte Ethernet::buffer[500];
BufferFiller bfill;

// word len;
// word pos;

LiquidCrystal_I2C lcd(0x20,8,2);  // set the LCD address to 0x20 for a 16 chars and 2 line display

const int s1 = 10;     // the number of the pushbutton pin
const int s2 = 9;     // the number of the pushbutton pin

// Referenzwert zur Multiplikation mit den Werten der Analogports (0...1023), 
// um auf die Voltzahl zu kommen (0...5). 
// Ergibt sich aus 5/1024. (d.h., Systemspanung / Bit-Auflösung)
// z.B. const float referenzwert = 0.0048828125;	// Referenzwert in Volt
// oder const float referenzwert = 4.8828125;	        // Referenzwert in mV
const float Usys = 5.16;   // Systemspannung an AVR-NetIO mit PC-Netzteil
// const float Usys = 4.89;   // Systemspannung an Arduino-Mega mit USB-Stromversorgung
float referenzwert = Usys/1024*1000; // Referenzwert in mV

#define  PINUbatt   13       // Analog PIN Batteriespannung
#define  PINUDS     14       // Analog PIN Spannungsabfall am FET (Drain-Source)
#define  PINRelais  15       // Digital PIN Relais oder MOSFET
#define  PINStart   9       // Digital PIN Startknopf 
#define  PINStart2  10       // Digital PIN Startknopf 

#define  Umin 950           // mV Spannung bei der Entladung abgebrochen wird
#define  INTERVAL  2000     // Zeit fuer Schleife


// div. Globals
long loopTime = INTERVAL;
long loopUsedTime = INTERVAL;
long loopStart = 0;
long uhrzeit = 0;
long verstrichen = 0;
float U = 0;
float Ufet = 0;
float Udiff = 0;
float Uopen = 0;
float I = 0;
float P = 0;
float Q = 0;
float Ah = 0;
float Rlast = 1.5; // Lastwiderstand zur Entladung
float Rbat = 0;  // Innenwiderstand der Batterie

long loopCount = 0;
boolean start = false;
boolean ende = false;

void setup()  {
  //Serial.begin(19200);
  pinMode(PINRelais, OUTPUT);
  pinMode(PINStart, INPUT); // Start Taster 
  //digitalWrite(PINStart, HIGH); // je nachdem, ob High- oder Low-aktiver Button
  digitalWrite(PINStart, LOW);
  
  digitalWrite(PINRelais,LOW);   // Relais bzw. Mosfet aus 
  
  lcd.init();                      // initialize the lcd 
 
  if (ether.begin(sizeof Ethernet::buffer, mymac,28) == 0)
  {
    // Serial.println( "Failed to access Ethernet controller");
    lcd.setCursor(0,0);
    lcd.print("eth0 failed");
    delay(1000);
    lcd.clear();
  }  
  ether.staticSetup(myip);
 
  // Print a message to the LCD.
  lcd.setCursor(0,0);
  lcd.print("Kap-tester V.005");
  lcd.setCursor(0,1);
  lcd.print("by OS 04/2013");
  delay(2000);
  lcd.clear();
  
  Uopen = analogRead(PINUbatt)*referenzwert;       // in mV
  
}

void loop()  {
 
  // start = true;   // Für (Batterie-)Messung bis zum bitteren Ende, d.h. Tiefentladung
  
  // erstmal Spannung messen  - solange der Starttknopf nicht gedrueckt wurde - nach dem Test auch wieder hier rein...
  while (start==false) 
  { 
    U = analogRead(PINUbatt)*referenzwert;       // in mV
    Uopen = U;
    //print_ser();
    print_lcd();
    //if (digitalRead(PINStart)==LOW) {
    if (digitalRead(PINStart)==HIGH) {
    start = true;
    ende = false;
  }
 
 
  uhrzeit = millis();
  verstrichen = millis()-uhrzeit;

  while(verstrichen < INTERVAL-10)
  {
    word len = ether.packetReceive();
    word pos = ether.packetLoop(len);  
    if (pos)  // check if valid tcp data is received
      ether.httpServerReply(homePage()); // send web page data
      
    verstrichen = millis()-uhrzeit;
  } // end of while  
   
  //delay(2000);
  } // end of while
  
  digitalWrite(PINRelais,HIGH);   // Relais ein  
  
  loopStart = millis();
  
  U = analogRead(PINUbatt)*referenzwert;      // in mV
  Ufet = analogRead(PINUDS)*referenzwert;     // in mV
  Udiff = U-Ufet;
  
  //I = Udiff/1.5;     // in mA
  //I = U-Ufet/1.5;    // in mA  Achtung: Falsche Schreibweise !!! Punkt vor Strichrechnung !!!
  I = Udiff/Rlast;   // in mA

  // Leistung
  P = (I*U)/1000;   // in mW
  Q += P * loopTime / 3600 / 1000;         // in mWh
  
  // Kapazität in mAh
  Ah += I * loopTime / 3600 / 1000;          // in mAh
  
  // Innenwiderstand der Batterie
  Rbat = (Uopen - U) / I;
  
  //print_ser();
  print_lcd();
  
  if(U <= Umin) {                     // wenn Batteriespannung unter eingest. Mindestspannung faellt
    digitalWrite(PINRelais,LOW);      // Test abbrechen
    start = false;
    //Serial.println("Stop");
    ende = true;
   }

  loopCount++;
  loopUsedTime = millis()-loopStart;
 

  while(loopUsedTime < INTERVAL-10)
  {
    word len = ether.packetReceive();
    word pos = ether.packetLoop(len);  
    if (pos)  // check if valid tcp data is received
      ether.httpServerReply(homePage()); // send web page data
      
    loopUsedTime = millis()-loopStart;
  } // end of while  
  
  loopTime = millis() - loopStart;
  
}


void print_lcd()  {
  lcd.clear();
  lcd.print(U/1000,2);    // Spannung in Volt anzeigen
  lcd.print("V");
  lcd.setCursor(6,0);
  format_print(I);
  lcd.print("mA"); 
  lcd.setCursor(13,0);
  if (start==false && ende == false) lcd.print("STA");   //  ST - Startknopf druecken
  if (start==true) lcd.print("RUN");                     //  RU - Test runnig...
  if (ende==true) lcd.print(" END");                      //  E  - Test Ende
  lcd.setCursor(0,1);
  format_print(Q);
  lcd.print("mWh");
  
/*  lcd.setCursor(10,1);
  //lcd.print(Ufet/1000,4);
  lcd.print(Udiff/1000,4);
*/


  lcd.setCursor(11,1);
  lcd.print(loopCount/(60000/INTERVAL));                
  lcd.print(":");
  if(((loopCount%(60000/INTERVAL))*INTERVAL/1000)<10)  lcd.print("0");
  lcd.print((loopCount%(60000/INTERVAL))*INTERVAL/1000);  
   
  }

void format_print (float value){ // in Ausgabe passende Anzahl Spaces einfuegen - 4stellige Zahl
  if (value < 1000)lcd.print(" ");
  if (value < 100) lcd.print(" ");
  if (value < 10)  lcd.print(" ");
  lcd.print(value,0);
}

//void print_ser()  {
//  Serial.print(loopCount/(60000/INTERVAL));
//  Serial.print(":");
//  if(((loopCount%(60000/INTERVAL))*INTERVAL/1000)<10)  Serial.print("0");
//  Serial.print((loopCount%(60000/INTERVAL))*INTERVAL/1000);
//  Serial.print("    ");
//  Serial.print((int)U);                       Serial.print(" mV   ");
//  Serial.print((int)Ufet);                    Serial.print(" mV   ");
//  Serial.print((int)I);                       Serial.print(" mA   ");
//  Serial.print((int)P);                       Serial.print(" mW       ");
//  Serial.print((int)Q);                       Serial.println(" mAh");
//}


static word homePage() {
  long t = millis() / 1000;
  word h = t / 3600;
  byte m = (t / 60) % 60;
  byte s = t % 60;
  
  word Up = U;
  word Ip = I;
  word Qp = Q;
  word Ap = Ah;
  word Rp = Rbat;
  
  bfill = ether.tcpOffset();
  bfill.emit_p(PSTR(
    "HTTP/1.0 200 OK\r\n"
    "Content-Type: text/html\r\n"
    "Pragma: no-cache\r\n"
    "\r\n"
    "<meta http-equiv='refresh' content='10'/>"
    "<title>Kapazitaetslogger</title>" 
    // "<h1>$D$D:$D$D:$D$D <br><br> $DmV $DmA $DmAh</h1>"),
    "<h1>$D$D:$D$D:$D$D $D $D $D $D $D </h1>"),
      h/10, h%10, m/10, m%10, s/10, s%10, Up, Ip, Qp, Ap, Rp);
  return bfill.position();
}