Arduino Due kwh meter mit Ethershield

Hallo zusammen,

ich vermute es wurde schon oft angesprochen mit vielen anderen Modellen wie ich mir bei Tante Google anlesen konnte. (ca. 40 Topic's oder mehr, habe den Überblick verloren ab und an auch ein mit dem DUE aber nie mit richtiger Lösung oder Code)

Weiter muss dazu sagen, ich arbeite mich in den Arduino noch rein.

Den Schaltaufbau für die Zähler zum Arduino mit Level Shifter auf 3,3 V ist alles geben und ich bekomme auch noch etwas auf dem Serial-Monitor ausgeben wenn der Oktukoppler geschlossen ist.

Aufbau sieht daher zz wie foglt aus:

S0+ -> Level Shfiter -> Digitaler Pin 22 (Input)
S0- -> 4K7 Widerstand -> GND

Mir ist bewusst das ich auch anders lösen könnte und S0- an den Input anschließen könnte.
Zusätzlich muss ich sagen das ich die analogen Eingänge nicht nutze da, diese im Endprojekt nicht mehr ausreichen würden.( 16 Sensoren zum Anfang, evtl. folgen noch Temperaturmesser, Gas und Wasser).

Materialen:

Stromzähler mit S0 2000Imps
Arduino Due + Ethershield

Bisheriger Code lohnt sich noch nicht wirklich zu posten,
er besteht nur aus einer einfachen Zuweisung und Ausgabe + Ethernet Config.

Nun zur Frage:

Könnte man mir hier einen Denkanstoß geben wie ich nun genau den Interrupt für die Flankenzählung beim Due schreibe ? mit der Ordentlichen ms Zählung.

Die Übergabe an einem Server zur Darstellung und langzeit logging werde ich dann hoffentlich wieder hinbekommen (hier bin ich aber auf für Vorschläge offen, welches OpenSource Produkt empfohlen werden kann).

Grüße,
Bombur

Ps. Ich glaube einfach das ich nicht mehr durchsteige weil ich einfach zu viel gelesen habe...

Hallo,
willkommen im Forum...
Eine auf Dich zugeschnittene richtige Lösung wirst Du nicht finden. Das mußt Du selbst machen.
Als erstes würde ich Dir einmal empfehlen das Ethershield wieder in der Schublade verschwinden zu lassen.
Das ist eine andere Baustelle, die später bearbeitet werden kann..

Wie Du den S0-Ausgang am Arduino nutzen kannst, steht hier bis ins kleinste beschrieben.

Wenn Du das hinbekommen hast, dann kannst Du das probieren.
Das funktioniert mit einem bis acht Zählern.

"nur aus einer einfachen Zuweisung und Ausgabe"

Auch in einfachen Zuweisungen und Ausgaben können sich Fehler einschleichen, die einen in den Wahnsinn
treiben können. Wir sind immer dankbar, wenn wir einen Sketch zu sehen bekommen. Wir haben zwar alle
Glaskugeln, sind es aber leid, die immer- und immer wieder zu putzen.
Falls Du tatsächlich einmal Hilfe für einen SELBST GESCHRIEBENEN Sketch benötigst, so ist es üblich diesen
in Code-tag´s zu setzten </>. Oben links im Editor.
Gruß und Spaß
Andreas

Hallo Andreas,

Danke erst einmal fürs Willkommen heißen.

Ich habe mir den Thread einmal durch gelesen ( mehr oder weniger, den Teil mit dem geeignenten Testobjekt und den Störimplusen aus dem Netz "beim Licht flackern" ).

Habe auch zum Testen dort den Sketch von dir aus Probiert und nur auf meinen Aufbau anpasst.

Das lass ich jetzt auch erst einmal so laufen und versuche dann morgen mit klaren Kopf nach der Arbeit das von Wolle umzusetzen.

Grüße,
Bombur

Ps. Jetzt weiß ich auch wieder warum ich nicht den Anwendungsentwickler gelernt habe :smiley:

So.. ich habe dann auch Endlich mal Zeit gefunden den 2. Link ab zu arbeiten.

EDIT//
Das läuft auch soweit alles ganz gut, es wir schön gezählt wieviele ms zwischen den Flanken vergehen.

Bei A (12.5W Last) ca. alle 7,1min.
Bei B (90W Last) ca. alle 2,29min.

Es muss ich das nur noch für mehr als 8 Zähler hinbekommen und die weitergabe an den Verarbeiter geben etc. ( Vorschläge sind gerne gesehen).

Grüße,

Hallo *,

so ich bin dann mal weiter gekommen (mehr oder weniger).

Glaube der Code wäre so erst einmal nutzbar aber bestimmt noch optimierungsfähig..

Die Annahme der Daten auf dem Server muss ich noch umsetzen aber da habe ich auch schon etwas gefunden (emoncms oder Splunk(würde mich ein Kollege kurz zusammen schreiben) nehme aber auch alternativen).

Soweit geht der Code auch schon bis nach dem starten der Ethernet Verbindung, diese wird noch aufgebaut aber dann scheint der Code zuhängen. (IP bekommt das Shield auch schon und ist Pingbar).

Anmerkung die "Serial.println" im Setup Teil sind fürs Debuggen.

Hier endet die Ausgabe nach dem durchführen des Ethernet.begin Befehls mit einem "M" (vom Serial.println( "My ..."); .

//libs
#include <SPI.h>
#include <Ethernet.h>
#include <avr/dtostrf.h>
//Adapted from a sample Arduino sketch and openenergymonitor.com, by chris at tinkerfailure.com


//Mac-Adresse

byte mac[] = {
  0x00,0x50,0x56, 0x0A, 0xD8, 0x01 };

//IP-Adresse 

IPAddress ip(192, 168, 0, 6);
IPAddress gateway(192, 168,0, 1);
IPAddress subnet(255, 255, 255, 0);


// fill in your Domain Name Server address here:
IPAddress dnServer(192, 168, 0, 1);

// initialize the library instance:
EthernetClient client;

char server[] = "192.168.0.5";

unsigned long lastConnectionTime = 0;          // last time connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 60*1000;  // delay between updates, in milliseconds

//Number of pulses, used to measure energy.
long pulseCount = 0;   

//Used to measure power.
unsigned long pulseTime,lastTime;

//power and energy
double power, elapsedkWh;

//Number of pulses per wh - found or set on the meter.
int ppwh = 0.5; //2000 pulses/kwh = 0.5 pulse per wh

//pin definitons
int z1 = 22;
int z2 = 23;
int z3 = 24;
int z4 = 25;
int z5 = 26;
int z6 = 27;
int z7 = 28;
int z8 = 29;
int z9 = 30;
int z10 = 31;
int z11 = 32;
int z12 = 33;
int z13 = 34;
int z14 = 35;
int z15 = 36;
int z16 = 37;


void setup()
{
  Serial.begin(9600);
  Serial.println("delay start");
  // give the ethernet module time to boot up:
  delay(500);
  Serial.println("delay fertig");
  // start the Ethernet connection using a fixed IP address and DNS server:
  Serial.println("IP start");
  Ethernet.begin(mac, ip, subnet, gateway, dnServer);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
 // Serial.println(Ethernet.localIP());
 Serial.println("IP fertig");

  // interrupt
  Serial.println("Interrupts start");
  attachInterrupt(digitalPinToInterrupt(z1), onPulse, FALLING);
  attachInterrupt(z2, onPulse, FALLING);
  attachInterrupt(z3, onPulse, FALLING);
  attachInterrupt(z4, onPulse, FALLING);
  attachInterrupt(z5, onPulse, FALLING);
  attachInterrupt(z6, onPulse, FALLING);
  attachInterrupt(z7, onPulse, FALLING);
  attachInterrupt(z8, onPulse, FALLING);
  attachInterrupt(z9, onPulse, FALLING);
  attachInterrupt(z10, onPulse, FALLING);
  attachInterrupt(z11, onPulse, FALLING);
  attachInterrupt(z12, onPulse, FALLING);
  attachInterrupt(z13, onPulse, FALLING);
  attachInterrupt(z14, onPulse, FALLING);
  attachInterrupt(z15, onPulse, FALLING);
  attachInterrupt(z16, onPulse, FALLING);
  Serial.println("Interrupts end");
 //pins as Input
 Serial.println("PinMode start");
  pinMode(z1,INPUT);
  pinMode(z2,INPUT);
  pinMode(z3,INPUT);
  pinMode(z4,INPUT);
  pinMode(z5,INPUT);
  pinMode(z6,INPUT);
  pinMode(z7,INPUT);
  pinMode(z8,INPUT);
  pinMode(z9,INPUT);
  pinMode(z10,INPUT);
  pinMode(z11,INPUT);
  pinMode(z12,INPUT);
  pinMode(z13,INPUT);
  pinMode(z14,INPUT);
  pinMode(z15,INPUT);
  pinMode(z16,INPUT);
  Serial.println("PinMode end");
  //set Pins at HIGH
  digitalWrite(z1,HIGH);
  digitalWrite(z2,HIGH);
  digitalWrite(z3,HIGH);
  digitalWrite(z4,HIGH);
  digitalWrite(z5,HIGH);
  digitalWrite(z6,HIGH);
  digitalWrite(z7,HIGH);
  digitalWrite(z8,HIGH);
  digitalWrite(z9,HIGH);
  digitalWrite(z10,HIGH);
  digitalWrite(z11,HIGH);
  digitalWrite(z12,HIGH);
  digitalWrite(z13,HIGH);
  digitalWrite(z14,HIGH);
  digitalWrite(z15,HIGH);
  digitalWrite(z16,HIGH);
  Serial.print("Pins auf HIGH");
}

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    httpRequest();
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void httpRequest() {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");

// prepare the variables  
  char powerString[8] = "";
  char elapsedString[8] = "";
  //convert to strings  
  dtostrf(power, 7, 4, powerString);
  dtostrf(elapsedkWh, 4, 3, elapsedString);
  String valueOne = powerString;
  String valueTwo = elapsedString;
  //assemble query  
  String stringOne = "GET /energymonitorscript.php/?power=";
  String stringTwo = "&elapsed=";
  String stringThree = " HTTP/1.0 \r\n";
  String stringOut = stringOne + valueOne + stringTwo + valueTwo + stringThree; 

    // send the HTTP PUT request:
    client.println(stringOut);
    client.println("User-Agent: arduino-ethernet \r\n");
    client.println("Connection: close \r\n");
    client.println();

    // note the time that the connection was made:
    lastConnectionTime = millis();
  } 
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting.");
    client.stop();
  }
}

// The interrupt routine
void onPulse()
{

//used to measure time between pulses.
lastTime = pulseTime;
pulseTime = micros();

//pulseCounter
pulseCount++;

//Calculate power
power = (3600000000.0 / (pulseTime - lastTime))/ppwh;

//Find kwh elapsed
elapsedkWh = (1.0*pulseCount/(ppwh*1000)); //multiply by 1000 to pulses per wh to kwh convert wh to kwh

//Print the values.
Serial.print(power,4);
Serial.print(" ");
Serial.println(elapsedkWh,3);

//make the http request
httpRequest();
}

Sprich wenn ich das richtig sehe, komme ich nicht mal bis zum "loop".

Grüße,

ok.. ich habe jetzt noch einmal von vorne angefangen und erst einmal alles was nicht so geklappt hat raus geworfen und ein script von dir (Andreas) genommen um einfach mal nur die impulse zu zählen.

Sprich Kontakt offen = nichts
Kontakt geschlossen = impuls

//libs
#include <SPI.h>
#include <Ethernet.h>




//Mac-Adresse

byte mac[] = {
  0x00,0x50,0x56, 0x0A, 0xD8, 0x01 };

//IP-Adresse 

IPAddress ip(192, 168, 0, 6);
IPAddress gateway(192, 168,0, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dnServer(192, 168, 0, 1);

// initialize the library instance:
EthernetClient client;

char server[] = "192.168.0.5";



//pin definitons
int z1 = 22;
int z2 = 23;
int z3 = 24;
int z4 = 25;
int z5 = 26;
int z6 = 27;
int z7 = 28;
int z8 = 29;
int z9 = 30;
int z10 = 31;
int z11 = 32;
int z12 = 33;
int z13 = 34;
int z14 = 35;
int z15 = 36;
int z16 = 37;


static boolean RunAction = true; // für einmal zaehlen
int zlWSZ = 0; // Zaehler für Impuls
int z2WSZ = 0; // Zaehler für Impuls
int z3WSZ = 0; // Zaehler für Impuls
int z4WSZ = 0; // Zaehler für Impuls
int z5WSZ = 0; // Zaehler für Impuls
int z6WSZ = 0; // Zaehler für Impuls


void setup()
{
  Serial.begin(9600);
   // give the ethernet module time to boot up:
  delay(500);
  // start the Ethernet connection using a fixed IP address and DNS server:
  Ethernet.begin(mac, ip, subnet, gateway, dnServer);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
 

  pinMode(z1, INPUT);
  pinMode(z2, INPUT);
  pinMode(z3, INPUT);
  pinMode(z4, INPUT);
  pinMode(z5, INPUT);
  pinMode(z6, INPUT);
  digitalWrite(z1, HIGH);
  digitalWrite(z2, HIGH);
  digitalWrite(z3, HIGH);
  digitalWrite(z4, HIGH);
  digitalWrite(z5, HIGH);
  digitalWrite(z6, HIGH);

}


void loop()
{
if (digitalRead(z1) == LOW)

{
if(RunAction) // 1 impuls einmal zaehlen
{
(zlWSZ++);

  Serial.print("Zaehler1:");
  Serial.println(zlWSZ);
RunAction = false;
}
}
else
{
  RunAction = true;
}
if (digitalRead(z2) == LOW)

{
if(RunAction) // 1 impuls einmal zaehlen
{
(z2WSZ++);

  Serial.print("Zaehler2:");
  Serial.println(z2WSZ);
RunAction = false;
}
}
else
{
  RunAction = true;
}
if (digitalRead(z3) == LOW)

{
if(RunAction) // 1 impuls einmal zaehlen
{
(z3WSZ++);

  Serial.print("Zaehler3:");
  Serial.println(z3WSZ);
RunAction = false;
}
}
else
{
  RunAction = true;
}
if (digitalRead(z4) == LOW)

{
if(RunAction) // 1 impuls einmal zaehlen
{
(z4WSZ++);

  Serial.print("Zaehler4:");
  Serial.println(z4WSZ);
RunAction = false;
}
}
else
{
  RunAction = true;
}
if (digitalRead(z5) == LOW)

{
if(RunAction) // 1 impuls einmal zaehlen
{
(z5WSZ++);

  Serial.print("Zaehler5:");
  Serial.println(z5WSZ);
RunAction = false;
}
}
else
{
  RunAction = true;
}
if (digitalRead(z6) == LOW)

{
if(RunAction) // 1 impuls einmal zaehlen
{
(z6WSZ++);

  Serial.print("Zaehler6:");
  Serial.println(z6WSZ);
RunAction = false;
}
}
else
{
  RunAction = true;
}
}

Das ganze sieht jetzt so wie hier aus, müsste das jetzt sofern ich mich nicht irrie nur in eine abholbares Format (http/php etc.) umschreiben / schreiben lassen.

Dabei bin ich mir aber nicht so sicher bzw. steht das jetzt ganz hinten an.

Ich gehe auch davon aus, das der loop schnell genung ist um alle 16 Zähler durch weg mit zu bekommen, obwohl ich hier auch eher an einem Interrupt gedacht habe um sicher zu sein - das alles mit dabei ist.

Bin hier aber wirklich für Meinungen offen und hoffe das ich jetzt nicht die ganze Zeit "selbstgespräche" führen darf..

Hallo,
im Großen und Ganzen wird Dein Code vielleicht funktionieren- wenn keine Leistung an den Zählern anliegt.

Schreibe Dir doch einmal einen Sketch für einen (1) Zähler. An diesen betreibst Du eine 100W Glühlampe,
nennen wir diese G1.
Die G1 markierst Du Dir mit G1, nimmst die Zeit mit einer StoppUhr und zählst die Impulse.
So kommst Du auf die Wirkleistung von G1- sagen wir 0,0981W.

Nun nimmst Du noch G2 bis G6 am Zähler G2 bis G6. Du nimmst die gleiche Zeit wie bei G1 und ermittelst die
verschiedenen Wirkleistungen. Du solltest jetzt in der gleichen Zeit 6 verschiedene Werte notiert haben.

Wenn Du Dir so jeden Zähler mit der dazu gehörigen Glühlampe "geeicht" hast, dann verdrahtest Du alles
richtig und läßt Deinen Sketch mit den 6 Zählern laufen.

Dein Sketch sollte Dir jetzt für jeden Zähler den gleichen Wert liefern, wie Du ihn in der Einzel-Messung
ermittelt hast.

Falls das widererwartend funktionieren sollte, nimmst Du einmal "richtige" Verbraucher.
Z.B. Wasserkocher, 1000W HalogenStrahler und Haartrockner.

Hier wirst Du wahrscheinlich sehen, das Dein Sketch zu langsam ist...
Dann zählst Du NUR- Impulse! Wie willst Du auf die Wirkleistung kommen? Woher nimmst Du die Zeit?
Ich würde die Eingänge in ein Array legen und das abfragen.
Schau Dir doch einmal den Code von "elektrowolle" an (Link in #1)
Gruß und Spaß
Andreas

Hallo Andreas,

wenn ich mir jetzt den sketech von elektrowolle wieder vornehme, geht dieser auch bis zu 8 Zählen und es läuft wie es soll.

Sprich wenn ich Theoretisch es schaffe den Code so um zuschreiben das ich mehr als 8 Zähler nutzen kann, muss ich sofern das alles wirklich geht - nur noch die Übergabe an einen Server gestalten.

Naja ich melde mich wenn ich wieder etwas Zeit hatte, evtl. habe ich dann schon wieder einen ganz anderen Ansatz.

Grüße,
Bombur