Home energy meter met esp8266 en mega.

Hallo allemaal,

Ik ben bezig met mijn huis slim te maken. En wil het energieverbruik in kaart brengen. Heb momenteel een Mega met esp8266 aan de praat met daaraan een tcrt5000 sensor welke mijn kWh meter uitleest. Het geheel heb ik geprogrsammerd met een interrupt, zodat de data wel verzameld wordt terwijl er een upload (elke 20sec) plaatsvind.
Nou heb ik dit allemaal werkend, maar welke data is nou echt relevant om te versturen, ik heb nu even simpel alleen maar de pulsen tussen uploads en het totale aantal pulsen op de verzendlijst staan.
Eigenlijk wil ik bij elke upload het huidige verbruik versturen, maar kom er niet echt uit. Lijkt mij dat ik moet kijken naar millis tussen de pulsen en dan verbruik berekenen. Maar hoe kan ik nou het gemiddelde berekenen als er binnen de uploadtijd meerdere pulsen vallen?
Iemand die mij opweg kan helpen?
En oh ja hoe voeg je op dit forum je code toe?

De waarde die je verstuurt is altijd een oude waarde, want er kan altijd net een update geweest zijn.
Dus moet je dan gaan werken met de waardes uit het verleden.
Als je werkt met een waarde die tijdens de bewerking kan veranderen, gaat alles natuurlijk mis.
Dus moet je telkens werken met de waardes die tot aanvang van de berekening bekend waren.
Daarvoor zou je dan dus een soort van tussenopslag moeten gebruiken.

En code voeg je toe door 'm tussen [code] [/code] tags te zetten.

Ah

#include <SPI.h>
#define SSID ""
#define PASS ""
#define IP "api.thingspeak.com"

long pulseCount = 0;   
long pulseCountT = 0;

unsigned long pulseTime,lastTime;
unsigned long prevMillis = 0;    // starttime Stroom
const int ledPin = 8;

//================================Declarations for Thingspeak================================
String GET = "GET /update?key=hierdeapi&"; 
String GET1 = "field1=";
String GET2 = "&field2=";
String GET3 = "&field3=";
String GET4 = "&field4=";

//================================What to do on Pulse================================
void onPulse()
{
//pulseCounter
pulseCount++;
pulseCountT++;
digitalWrite(ledPin, HIGH);
delay(10);
digitalWrite(ledPin, LOW);

//Print the values.
Serial.print(pulseCount);
Serial.print("\t");
Serial.print(pulseCountT);
Serial.print("\t");
Serial.println();
}

//================================Function to update Thingspeak================================

 void updateFunction(){
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  sendDebug(cmd);
  delay(5);
  if(Serial2.find("Error"))
  {
    Serial.print("Recieved: Error");
    return;
  }
  cmd = GET + GET1;
  cmd += pulseCount;
  cmd += GET2;
  cmd += pulseCountT;
  cmd += "\r\n";
  Serial.print(cmd);
  Serial2.print("AT+CIPSEND=");
  Serial2.println(cmd.length());
  if (Serial2.find(">"))
  {
    Serial.print(">");
    Serial.print(cmd);
    Serial2.print(cmd);
  }
  else
  {
    sendDebug("AT+CIPCLOSE");
  }
  if(Serial2.find("OK"))
  {
    Serial.println("Received: OK");
  }
  else
  {
    Serial.println("Recieved: Error");
  }
}

//================================Function to connect to WiFi================================
boolean connectWiFi()
{
  Serial2.println("AT+CWMODE=1");
  delay(200);
  String cmd = "AT+CWJAP=\"";
  cmd += SSID;
  cmd += "\",\"";
  cmd += PASS;
  cmd += "\"";
  
  Serial2.println(cmd);
  Serial.println(cmd);
  delay(5000);
  if(Serial2.find("OK"))
  {
    Serial.println("OK, connected to WiFi.");
    return true;
  }
  else
  {
    Serial.println("Cannnot connect to WiFi.");
    return false;
  }
}

//================================Send Debug================================
void sendDebug(String cmd)
{
  Serial.print("SEND: ");
  Serial.println(cmd);
  Serial2.println(cmd);
}

//================================SETUP================================
void setup() {
      //interrupt reserve for IRQ0andpinD2
  attachInterrupt(0, onPulse, RISING);
   pinMode(8, OUTPUT);
   
     //Setting up for ESP8266
  Serial2.begin(115200);
  Serial2.setTimeout(2000);
  
  Serial.begin(115200);
  
  while(!Serial);
  while(!Serial2);
  
  Serial.println("ESP8266 Reciever Module");
  
  while(Serial2.available()>0) Serial2.read();
  
  delay(1000);
  Serial2.println("AT");
  delay(2000);
  Serial.println("Resetting module");
  Serial2.flush();
  
  if(Serial2.find("OK"))
  {
    Serial.println("Module is Ready");
  }
  else
  {
    Serial.println("Module have no response.");
    while(1);
  }
  delay(1000);
  
  //Access to wifi Function
  boolean connected = false;
  for(int i=0; i<5; i++)
  {
    if(connectWiFi())
    {
      connected = true;
      break;
    }
  }
  if(!connected){while(1);}
  delay(5000);
 
  //Set Singale Connection
  Serial2.println("AT+CIPMUX=0");
  
  }

void loop() {
    
{
/*
if (sensorStroom > drempelStroom) {pulseStroom = true;}
 
if (sensorStroom < drempelStroom && pulseStroom) { 
  pulseStroom = false;
  pulseCountS++;
  pulseCountTotal++;
  pulseTimeS = (millis() - prevMillisS);  
  prevMillisS = millis();
  curWatts = (( 3600000 / Stroom_C ) * 1000 ) / pulseTimeS;
  totalWh = (pulseCountS * 1000) / Stroom_C;  // LET OP Wh!
  totalKwh = (1000 / Stroom_C) * pulseCountTotal;  // Totale KWh.
}
*/
// elke 20sec de standen loggen via ethernet
if ((millis() - prevMillis) >= 20000) {
  prevMillis = millis();
 updateFunction();
 pulseCount = 0;
 

 }
 
Serial.println(pulseCount);
delay(10);
}
}

Gelukt das mooi. En die oude data valt toch wel mee, ik stuur elke 20sec mijn data weg, dus tussenopslag lijkt mij niet zo nodig denk ik.

Ik gaf een antwoord op een probleem dat jij zag.
Ik had geen idee hoe vaak er wat werd weggeschreven, hoe lang dat duurt, hoe lang je bezig bent met het berekenen, en hoe vaak de pulsen komen.
Jij gaf aan dat het een probleem zou kunnen vormen en daar was mijn antwoord op gebaseerd.
En met tussen opslag moet je niet iets heel ingewikkelds bedenken hoor.
Het is gewoon een extra variabele waarin je de te bewerken waarde kopieert uit de waarde die zou kunnen veranderen tijdens je berekeningen.

20 seconden is voor jou niet zoveel tijd.
Maar het zijn 320.000.000 handelingen die je Arduino dan zou kunnen doen.
Tijd is ook relatief.

Het begint allemaal een beetje te dagen bedankt voor je antowoord in ieder geval.
Heb in voorbeelden een hoop gezien en geleerd. Ik ga nu de tijd tussen twee pulsen meten met millis en prevmillis. En deze dan omrekenen naar Wh verbruik. Deze waarde ga ik dan middelen door te delen door de pulsecounts in die periode. Na het uploaden van de data zet ik de tellers weer op nul. En dan begint het weer opnieuw. Moet ik nog erens rekening mee houden mey millis? Zoals een overflow,of is er misschien een simulator waarin ik kan zien of mijn code een overflow kan krijgen?
Oh ja kan het zijn dat een const int geen getal kan zijn met decimalen? Had een voorbeeld code gezien wasrin ik opgeef hoeveel omwentelingen van mijn kwh meter 1Kwh is. Bij invullen van 187.5 kreeg ik last van afronding, wanneer ik alles bekeek in de serial monitor. Iemand een idee. 187.5 pulsen kwam toen overeen met 930watt ofzo. Wanneer ik Const int niet gebruikte en gewoon in de berekening 187.5 invulde ging het wel goed.

De millis zullen een overflow meemaken.
Dat duurt ongeveer anderhalve maand (45 dagen) als ik het me goed herinner.
En elke keer als er een reset plaatsvindt zul je ook weer van voor af aan beginnen.
Een reset gebeurt ook als je een seriële verbinding start, tenzij je een kleine aanpassing doet aan je Arduino.
Die aanpassing zal dan wel leiden tot het lastiger kunnen uploaden van software.
Een oplossing kan zijn dat je bij de data ook een volgnummer gaat bijhouden.
Dan kun je dus zien hoe vaak er data is weggeschreven sinds een reset.
Een overflow is geen reset, alleen de timer word dan gereset.
Er zijn technieken waarmee je geen last hebt van een overflow als je de tijd gaat bijhouden.
Je moet ook nooit kijken of er een bepaald aantal millis zijn geweest, maar of je boven dat aantal bent uitgekomen.
Als je alleen kijkt naar een specifiek aantal millis, dan kan het zijn dat je pas kijkt als die al voorbij zijn en zul je 'm dus nooit zien.

Een integer (klik !) (int) heeft alleen gehele getallen.
Je wil een Floating Point (float) gebruiken.
Als je m niet als int initieert, ziet de IDE dat er een punt in staat en weet ie dus dat het geen int maar een float moet worden.

Zo weer een update:
Ik vraag me alleen nog af welke waardes je welke naam geeft zoals unsigned long, int, float etc. Kan iemand mij opweg helpen, ik heb namelijk het idee dat er iets fout gaat, wannneer deze een tijdje draait.

#include <SPI.h>
#define SSID ""
#define PASS ""
#define IP "api.thingspeak.com"

//================================Benodigdheden voor Kwh meter================================
const float Stroom_C = 187.5; 
unsigned long pulseCountTotalStroom = 0;      // pulsenteller totalen stroom
unsigned long pulseCountStroom = 0;           // pulsencounter Stroom
unsigned long prevMillisStroom = 0;           // starttime Stroom
unsigned long pulseTimeStroom = 0;            // time for 1 pulse
int curWatts = 0;                   // current watts
float totalWh = 0;                            // total Wh
float totalKwh = 0;                           // total Kwh
int ledPin = 8;                               // knipperen bij puls

//================================Wifi updatek===============================================
unsigned long prevMillisWifi = 0;                 // tijd voor de wifi update

//================================Declarations for Thingspeak================================
String GET = "GET /update?key=L89H6IX3W1LD2T9P"; 
String GET1 = "&field1=";
String GET2 = "&field2=";
String GET3 = "&field3=";
String GET4 = "&field4=";

//================================What to do on Pulse================================
void onPulseStroom()
{
  pulseCountStroom++;                                              //pulsenteller +1
  pulseCountTotalStroom++;                                         //totale pulsenteller +1
  pulseTimeStroom = (millis() - prevMillisStroom);                 //bereken pulstijd
  prevMillisStroom = millis();                                     //reset de tijd
  curWatts = (( 3600000 / Stroom_C ) * 1000 ) / pulseTimeStroom;   //bereken huidige verbruik
  totalKwh = (1 / Stroom_C) * pulseCountTotalStroom;               // Totale KWh.

digitalWrite(ledPin, HIGH);                                        //Laat de led knipperen bij Puls
delay(10);                                                         //10 millis aan
digitalWrite(ledPin, LOW);                                         //dan weer uit

//Print de waardes in de Serial Monitor.
Serial.print("pulsecounts = ");
Serial.print(pulseCountStroom);
Serial.print("\t");
Serial.print("pulsecounttotal = ");
Serial.print(pulseCountTotalStroom);
Serial.print("\t");
Serial.print("currwatts = ");
Serial.print(curWatts);
Serial.print("\t");
Serial.print("totalKwh = ");
Serial.print(totalKwh,4);
Serial.println();

}
//================================Function to update Thingspeak================================

 void updateFunction(){
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  sendDebug(cmd);
  delay(5);
  if(Serial2.find("Error"))
  {
    Serial.print("Recieved: Error");
    return;
  }
  cmd = GET + GET1;
  cmd += pulseCountStroom;
  cmd += GET2;
  cmd += pulseCountTotalStroom;
  cmd += GET3;
  cmd += curWatts;
  cmd += GET4;
  cmd += totalKwh;
  cmd += "\r\n";
  Serial.print(cmd);
  Serial2.print("AT+CIPSEND=");
  Serial2.println(cmd.length());
  if (Serial2.find(">"))
  {
    Serial.print(">");
    Serial.print(cmd);
    Serial2.print(cmd);
  }
  else
  {
    sendDebug("AT+CIPCLOSE");
  }
  if(Serial2.find("OK"))
  {
    Serial.println("Received: OK");
  }
  else
  {
    Serial.println("Recieved: Error");
  }
}

//================================Function to connect to WiFi================================
boolean connectWiFi()
{
  Serial2.println("AT+CWMODE=3");
  delay(200);
  String cmd = "AT+CWJAP=\"";
  cmd += SSID;
  cmd += "\",\"";
  cmd += PASS;
  cmd += "\"";
  
  Serial2.println(cmd);
  Serial.println(cmd);
  delay(5000);
  if(Serial2.find("OK"))
  {
    Serial.println("OK, connected to WiFi.");
    return true;
  }
  else
  {
    Serial.println("Cannnot connect to WiFi.");
    return false;
  }
}

//================================Send Debug================================
void sendDebug(String cmd)
{
  Serial.print("SEND: ");
  Serial.println(cmd);
  Serial2.println(cmd);
}

//================================SETUP================================
void setup() {
      //interrupt reserve for IRQ0andpinD2
  attachInterrupt(0, onPulseStroom, RISING);
   pinMode(8, OUTPUT);
   
     //Setting up for ESP8266
  Serial2.begin(115200);
  Serial2.setTimeout(2000);
 
  Serial.begin(115200);
  
  while(!Serial);
  while(!Serial2);
  
  Serial.println("ESP8266 Reciever Module");
  
  while(Serial2.available()>0) Serial2.read();
  
  delay(1000);
  Serial2.println("AT");
  delay(2000);
  Serial.println("Resetting module");
  Serial2.flush();
  
  if(Serial2.find("OK"))
  {
    Serial.println("Module is Ready");
  }
  else
  {
    Serial.println("Module have no response.");
    while(1);
  }
  delay(1000);
  
  //Access to wifi Function
  boolean connected = false;
  for(int i=0; i<5; i++)
  {
    if(connectWiFi())
    {
      connected = true;
      break;
    }
  }
  if(!connected){while(1);}
  delay(5000);
 
  //Set Singale Connection
  Serial2.println("AT+CIPMUX=0");
  
  }

void loop() {
    
{

// elke 20sec de standen loggen via ethernet
if ((millis() - prevMillisWifi) >= 20000) {
  prevMillisWifi = millis();
 updateFunction();
 pulseCountStroom = 0;
 

 }
 
}
}

Wat dacht je van de Arduino reference? Arduino - Home

Die vind je ook als je hier op het forum bent, en dan in het drop down menu onder learning klikt.
Daar vind je een schat aan informatie, inclusief voorbeeldjes.

Ja die had Ik ook al gevonden en daar is juist waar ik het kwijtgeraakt ben.
Ik ga wel kijken wat er gebeurt als de duino twee maanden draait.
Voorlopig vind ik hem goed zo.

Hallo,
daar ben ik weer.
Ik heb het eea herschreven en ben niet helemaal tevreden, iemand die hem even kan nagaan en kan kijken waar ik kan verbeteren???
Upload gaat nog vaak fout, uploaderror counter komt te vaak voor, maar kan instabiliteit van de esp8266 zijn.
Tevens tel ik te veel pulsen, maar dat kan komen door de TCRT5000. Moet nog even kijken hoe ik deze op een andere manier aan kan sluiten en een goed waarde op de digitale input krijg welke genoeg is om de pin van 0-->1 te laten gaan.

#include <SPI.h>

//================================Benodigdheden voor Kwh meter==========================================
const float Stroom_C = 187.5; 
unsigned long pulseCountTotalStroom = 0;      // pulsenteller totalen stroom
unsigned long pulseCountStroom = 0;           // pulsencounter Stroom
unsigned long prevMillisStroom = 0;           // starttime Stroom
unsigned long pulseTimeStroom = 0;            // time for 1 pulse
volatile int wattpulse = LOW;
float curWatts = 0;                           // current watt
float totalWh = 0;                            // total Wh
float totalKwh = 0;                           // total Kwh
int ledPinStroom = 8;                         // knipperen bij puls
unsigned long uploaderror = 0 ;
int ledState = LOW; 

//================================Wifi update en settings===============================================
unsigned long prevMillisWifi = 0;                 // tijd voor de wifi update
#define SSID "rgrgegr"                           // accespoint naam
#define PASS "gerrreg"                         // wachtwoord

//================================Declarations for Exosite================================
#define IP "m2.exosite.com"                             //IP waarmee de TCP verbinding wordt gemaakt
#define CIK "ja"  //unieke identifier voor de upload
String myDataString = "";                               //string maken voor de te verzenden data


//================================Function to update Thingspeak=========================================

 void updateFunction(){
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  sendDebug(cmd);
  delay(5);
  if(Serial2.find("Error"))
  {
    Serial.print("Recieved: Error");
    return;
  }
  myDataString = "test";
      myDataString += "=";  
      myDataString += (pulseCountStroom); 
      myDataString += "&";
      myDataString += "test2";
      myDataString += "=";
      myDataString += (pulseCountTotalStroom); 
      myDataString += "&";
      myDataString += "test3";
      myDataString += "=";
      myDataString += (curWatts);
      myDataString += "&";
      myDataString += "test4";
      myDataString += "=";
      myDataString += (totalKwh);
      myDataString += "&";
      myDataString += "error";
      myDataString += "=";
      myDataString += (uploaderror);
            
  cmd = "POST /onep:v1/stack/alias HTTP/1.1";
  cmd += "\r\n";
  cmd += "Host: m2.exosite.com";
  cmd += "\r\n";
  cmd += "X-Exosite-CIK: ";
  cmd += CIK;
  cmd += "\r\n";
  cmd += "Content-Type: application/x-www-form-urlencoded; charset=utf-8";
  cmd += "\r\n";
  cmd += "Accept: application/xhtml+xml";
  cmd += "\r\n";
  cmd += "Content-Length: ";
  cmd += (myDataString.length()); 
  cmd += "\r\n";
  cmd += "\r\n";
  cmd += (myDataString);
  Serial.print(cmd);
  Serial2.print("AT+CIPSEND=");
  Serial2.println(cmd.length());
  if (Serial2.find(">"))
  {
    Serial.print(">");
    Serial.println(cmd);
    Serial2.println(cmd);
  }
  else
  {
    sendDebug("AT+CIPCLOSE");
  }
  if(Serial2.find("OK"))
  {
    Serial.println("Received: OK");
  }
  else
  {
    Serial.println("Recieved: Error");
    uploaderror ++;
    return;
  
  }
}

//================================Function to connect to WiFi===========================================
boolean connectWiFi()
{
  Serial2.println("AT+CWMODE=3");
  delay(200);
  String cmd = "AT+CWJAP=\"";
  cmd += SSID;
  cmd += "\",\"";
  cmd += PASS;
  cmd += "\"";
  
  Serial2.println(cmd);
  Serial.println(cmd);
  delay(3000);
  if(Serial2.find("OK"))
  {
    Serial.println("OK, connected to WiFi.");
    return true;
  }
  else
  {
    Serial.println("Cannnot connect to WiFi.");
    return false;
  }
}

//================================Send Debug============================================================
void sendDebug(String cmd)
{
  Serial.print("SEND: ");
  Serial.println(cmd);
  Serial2.println(cmd);
}

//================================SETUP=================================================================
void setup() {
  pinmode(2,INPUT);
  attachInterrupt(0, onPulseStroom, RISING);           //Pin D2 voor kwh TCRT5000     
   pinMode(8, OUTPUT);                                 //led kwh
  //Setting up for ESP8266
   Serial2.begin(115200);
  Serial2.setTimeout(2000);
  Serial.begin(115200);
  while(!Serial);
  while(!Serial2);
  
  Serial.println("ESP8266 Reciever Module");
  
  while(Serial2.available()>0) Serial2.read();
  
  delay(1000);
  Serial2.println("AT");
  delay(2000);
  Serial.println("Resetting module");
  Serial2.flush();
  
  if(Serial2.find("OK"))
  {
    Serial.println("Module is Ready");
  }
  else
  {
    Serial.println("Module have no response.");
    while(1);
  }
  delay(1000);
  
  //Access to wifi Function
  boolean connected = false;
  for(int i=0; i<5; i++)
  {
    if(connectWiFi())
    {
      connected = true;
      break;
    }
  }
  if(!connected){while(1);}
  delay(5000);
 
  //Set Singale Connection
  Serial2.println("AT+CIPMUX=0");

  }

void loop() {
    
if (wattpulse == HIGH)
{
  pulseCountStroom++;                                              //pulsenteller +1
  pulseCountTotalStroom++;                                         //totale pulsenteller +1
  pulseTimeStroom = (millis() - prevMillisStroom);                 //bereken pulstijd
  prevMillisStroom = millis();                                     //reset de tijd
  curWatts = (( 3600000 / Stroom_C ) * 1000 ) / pulseTimeStroom;   //bereken huidige verbruik
  totalKwh = (1 / Stroom_C) * pulseCountTotalStroom;               //Totale KWh.
  if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
  digitalWrite(ledPinStroom, ledState);

//Print de waardes in de Serial Monitor.
Serial.print("pulsecounts = ");
Serial.print(pulseCountStroom);
Serial.print("\t");
Serial.print("pulsecounttotal = ");
Serial.print(pulseCountTotalStroom);
Serial.print("\t");
Serial.print("currwatts = ");
Serial.print(curWatts,0);
Serial.print("\t");
Serial.print("totalKwh = ");
Serial.print(totalKwh,4);
Serial.print("\t");
Serial.print("tijd tussen pulsen= ");
Serial.print(pulseTimeStroom);
Serial.print("\t");
Serial.print("error = ");
Serial.print(uploaderror);
Serial.println();
wattpulse = LOW;

} 

// elke 20sec de standen loggen via ethernet
if ((millis() - prevMillisWifi) >= 30000) {
  prevMillisWifi = millis();
 updateFunction();
 pulseCountStroom = 0;

 }
}
 //================================What to do on Pulse=================================================
void onPulseStroom()
{
  if ((millis() - prevMillisStroom) > 2000) 
  {
    wattpulse = HIGH;

  }
  }