Open Energy Monitor mit dem ESP32: Unterschied zwischen den Versionen

Aus Technik-fan.de Wiki
Wechseln zu: Navigation, Suche
(Spezielle Hinweise für den ESP32)
Zeile 128: Zeile 128:
 
}
 
}
 
</source>
 
</source>
 +
 +
==Download Arduino Sketch==
 +
[[Media:EmonCMS ESP32 v1.zip|Download Arduino Sketch: Emon ESP32]]
  
 
==Kalibrierung==
 
==Kalibrierung==

Version vom 5. Februar 2018, 14:04 Uhr

Einleitung

In dieser Anleitung wird beschrieben wie mit Hilfe einer ESP32 Platine ein Strom Sensor für 3 Phasen Wechselstrom aufgebaut werden kann. Der Spannungsteiler aus den 10kOhm Widerständen erzeugt 1,6V für die SCT-013-030 Strom Sensoren. Die Stromsensoren werden mit den ADC Pin's des ESP32 verbunden. Natürlich sind die Messungen nicht sonderlich genau, da die Phasenverschiebung und Spannung nicht berücksichtigt wird. Auch das wäre durch zusätzliche Transformatoren möglich die dann auf die ADC Pin's geführt werden. Da ich damit nur meinen ungefähren Stromverbrauch zuhause messen möchte ist die Schaltung völlig ausreichend. Die Kosten für die einzelnen Komponenten sollten 30€ nicht übersteigen.

Folgende Bauteile werden benötigt:

-Board: DOIT ESP32 DEVKIT V1 (ca. 10€)
-Strom Sensor SCT-013-30 (30A) oder SCT-013-100 (100A) siehe: http://openenergymonitor.org/emon/node/156
-6x 10kOhm Widerstände 1/4W
-3x Elko 10 uF
-Universalplatine
-evtl. USB Netzteil oder anderes Netzteil für die Spannungsversorgung
-Pfosten Stecker Rastermaß: 2.54mm
-3 x 3,5 mm Audio Anschluss
-Optional: 1000uF / 10V Kondensator zur Stabilisierung

Pinbelegung des DOIT ESP32 DEVKIT V1 Board:

https://github.com/playelek/pinout-doit-32devkitv1

Grundlagen

Auf der Seite von Open Energy Monitor finden sich genügend Informationen über die Grundlagen der Leistungsberechnung. Das Prinzip lässt sich 1:1 vom Aufbau eines Arduinos übernehmen. Der ESP32 verkraftet jedoch maximal 3,3V am Analog Eingang.

https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/interface-with-arduino

Aufbau

Auf die Lochrasterplatine müssen nur wenige Bauteile. Die Teile lassen sich relativ einfach einlöten. Für den Aufbau werden nur wenige PIN's des ESP32 benötigt. Bei meinem Aufbau gibt es am obersten Sensor Anschluss noch einen zusätzlichen Burden Widerstand von 200 Ohm. Das liegt daran das der SCT-013-030 Sensor schon einige Jahre alt ist. Bei den neuen Sensoren sind keine Burden Widerstände nötig, da diese schon einen 62 Ohm Burden eingebaut haben. Ein 1000uF Kondensator zwischen 5V und GND ist empfehlenswert, da je nach 5V Netzteil die Messwerte stark schwanken.

Klicken um zu vergrößern

Klicken um zu vergrößern

Klicken um zu vergrößern

Software

Ich verwende zum programmieren immer die Arduino Gui. Es sind zuerst einige Anpassungen nötig damit das DOIT ESP32 Board von der Arduino Software erkannt wird. Hierzu muss diese Anleitung umgesetzt werden:

https://github.com/espressif/arduino-esp32

Nach dem Neustart der Arduino Software kann dann das passende ESP32 Board ausgewählt werden. In meinem Beispiel ist es ein DOIT V1 Board.

Klicken um zu vergrößern

Spezielle Hinweise für den ESP32

Bei der Programmierung des ESP32 gibt es ein paar Dinge zu beachten. Auf den Boards ist meist ein passender Spannungsregler für 3,3V und ein passender FTDI Chip aufgelötet. Somit entfällt eine weitere Schaltung zur Spannungsversorgung. Zudem wird das Board vom FTDI Chip durch die Arduino Software automatisch in den "Upload Modus" versetzt. Man muss also nicht wie beim ESP8266 bestimmte Taster drücken (Flash und Reset) um das Board in den "Upload Modus" zu bringen.

Ich habe öfters die WifiManager Library für das WLAN verwendet. Auf Dauer hatte ich damit jedoch immer wieder Probleme, so das ich meine WLAN Daten mit Absicht "fest" in das Programm einbaue. Zudem ergibt sich beim WLAN noch ein Problem wenn auf einmal die WLAN Verbindung unterbrochen wird, z.B. wenn der Router neu gestartet wird. Danach verbindet sich der ESP32 nämlich nicht mehr automatisch mit dem WLAN. Um das zu verhindern habe ich folgende Funktion in den Code eingebaut. Die Funktion WifiEvent startet den ESP32 neu wenn keine Verbindung mehr zum WLAN besteht. Leider funktioniert jeder andere Weg im Moment nicht zuverlässig.

#include <Arduino.h>
#include <WiFi.h>
 
//WiFi
const char* ssid     = "AccessPoint";
const char* password = "pass";
 
//WiFi
void WIFI_Connect()
{
  digitalWrite(2,1);
  WiFi.disconnect();
  Serial.println("Booting Sketch...");
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
    // Wait for connection
  for (int i = 0; i < 25; i++)
  {
    if ( WiFi.status() != WL_CONNECTED ) {
      delay ( 250 );
      digitalWrite(2,0);
      Serial.print ( "." );
      delay ( 250 );
      digitalWrite(2,1);
    }
  }
  digitalWrite(2,0);
}
 
 
void setup() {
  Serial.begin(115200);
  delay(500);
  //WiFi Part
  WIFI_Connect();
}
 
void loop() {
//Wifi WatchDog
WiFi.onEvent(WiFiEvent);
//Check if WiFi is here
//Automatically reconnect the ESP32 if the WiFi Router is not there...
if (WiFi.status() != WL_CONNECTED)
    {
      WiFi.onEvent(WiFiEvent);
      WIFI_Connect();
    } else {
      //Do something if the WiFi is available
    }
}
 
//Wifi Watchdog
void WiFiEvent(WiFiEvent_t event) {
  Serial.printf("[WiFi-event] event: %d  - ", event);
  switch(event) {
  case SYSTEM_EVENT_STA_GOT_IP:
      Serial.println("WiFi connected");
      Serial.print("IP address: "); Serial.println(WiFi.localIP());
      break;
  case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("WiFi lost connection");
      WiFi.begin();   // <<<<<<<<<<<  added  <<<<<<<<<<<<<<<
      ESP.restart();
      break;
  case SYSTEM_EVENT_STA_START:
      Serial.println("ESP32 station start");
      break;
  case SYSTEM_EVENT_STA_CONNECTED:
      Serial.println("ESP32 station connected to AP");
      break;
  case SYSTEM_EVENT_STA_LOST_IP:
      Serial.println("ESP32 Lost IP");
      WiFi.begin();   // <<<<<<<<<<<  added  <<<<<<<<<<<<<<<
      ESP.restart();
      break;
  }
}

Download Arduino Sketch

Download Arduino Sketch: Emon ESP32

Kalibrierung

Als nächstes müssen die Stromsensoren kalibriert werden. Dazu sollten folgende Variablen angepasst werden. Die Kalibrierung habe ich mit einer 100W Lampe und einem Wasserkocher 1800W durchgeführt. Eine genaue Stromzange oder eine Wattmeter sind sehr nützliche Hilfsmittel. In meinem Fall kann der SCT-013-030 als kleinste Einheit 100mA Strom erkennen. Die Sensoren haben 1800 Wicklungen und einen 62 Ohm Burden Widerstand. Der Offset Wert sollte nicht am PC USB Port sondern an einem separaten 5V Netzteil kalibriert werden. Denn die meisten PC USB Anschlüsse liefern bei 200mA nur noch eine Spannung von 4,5V.

ICAL    = Kalibrierung
filteredI = 0.9989 * (lastFilteredI+sampleI-lastSampleI); //Kalibrierung
Irms1 = (I_RATIO * sqrt(sumI / numberOfSamples)) - 0.06;//Offset


#include <Arduino.h>
#include <WiFi.h>
 
void setup() {
  Serial.begin(115200);
  delay(500);
}
 
//Setup variables
int numberOfSamples = 4000;
double ICAL = 1.08;
 
//Set Voltage and current input pins
int inPinI1 = 34;
 
// CT: Voltage depends on current, burden resistor, and turns
#define CT_BURDEN_RESISTOR    62
#define CT_TURNS              1800
#define VOLTAGE               225
 
// Initial gueses for ratios, modified by VCAL/ICAL tweaks
double I_RATIO = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 3.3 / 4096 * ICAL;
 
//Filter variables 1
double lastFilteredI, filteredI;
double sqI,sumI;
//Sample variables
int lastSampleI,sampleI;
double Irms1;
unsigned long timer;
 
void loop() {
timer = millis();
//**************************************************************************
//Phase1 
  for (int n=0; n<numberOfSamples; n++)
{
 
   //Used for offset removal
   lastSampleI=sampleI;
 
   //Read in voltage and current samples.   
   sampleI = analogRead(inPinI1);
 
   //Used for offset removal
   lastFilteredI = filteredI;
 
   //Digital high pass filters to remove 1.6V DC offset.
   filteredI = 0.9989 * (lastFilteredI+sampleI-lastSampleI);
 
   //Root-mean-square method current
   //1) square current values
   sqI = filteredI * filteredI;
   //2) sum 
   sumI += sqI;
   delay(0.0002);
}
 
//Calculation of the root of the mean of the voltage and current squared (rms)
//Calibration coeficients applied. 
Irms1 = (I_RATIO * sqrt(sumI / numberOfSamples)) - 0.06;
if (Irms1 < 0){ Irms1 = 0; }; //Set negative Current to zero
sumI = 0;
 
Serial.println("Irms1:"+String(Irms1));
}