Spook pulsen

Software vragen voor ESP chip familie
Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Spook pulsen

Berichtdoor René » 15 Feb 2017, 12:24

Mijn schakeling/applicatie heeft last van spook pulsen.
MBV een kwh meter die pulsen afgeeft meet ik de prestatie van mijn zonnepanelen.
De pulsen "tap" ik af van de kwh meter en stuur die via een emittervolger naar een ESP8266.
In een periode van 5 minuten meet ik de pulsen en hun afstand in de tijd om het vermogen van de zonnepanelen te meten. Elke puls wordt gegenereerd na 1 Wh energie.
In de periode van 5 minuten komen afhankelijk van de zonneschijn meer of minder pulsen langs. Elke keer bereken ik het vermogen.
Wat ik waarneem is dat er af en toe een niet reële piek ontstaat in het vermogen. Ik vermoed dat de ontstaat door elektromagnetische storingen die de schakeling op pakt.(het hele gedoetje zit in de meterkast en kan ik niet afschermen omdat de ESP8266 vooral ook een WIFI functie heeft)
Op dit moment meet ik of er een puls is met een interrupt functie.

cpp code
void onPulse() {

static uint32_t last_interrupt_time = 0; // moment van laatste interrupt
uint32_t interrupt_time = millis(); // haal de interne millis tijd op

if (interrupt_time - last_interrupt_time > 1500) { //declare the debounce/block out interval in setup
pulse = true;
}

last_interrupt_time = interrupt_time; // en bewaar dit moment voor de volgende puls
}

Iemand een suggestie?

De gehele code staat hier onder
cpp code
#include <Arduino.h>
/*
* versie 7 dd 14 februari 2017
* programma meet de SO pulsen van een kwh meter die de levering van zonnepanelen meet
* programma stuurt data via HTTP GET requests naar PVoutput.org service.
* elke 5 minuten wordt de maximale power in die 5 minuten en de totale opbrangst van de dag tot op dat moment verstuurd
* programma draait op een esp8266 v1.5.0
* via NTP server nl.pool.ntp.org wordt om 00:00:30 uur de tijd opgehaald
* in het programma worden geen Strings gebruikt
* de interrupt functie pulse is zo kaal mogelijk gehouden
* veel dank aan Nico Verduin voor de ingewikkelde zaken mbt pointers en array's
*
*/
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <time.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>

const int UPDATE_FREQ =1000; // elke sec de tijd updaten
const int GMT_CORRECTIE = 3600; // pas de tijd aan aan NL. = + 1 uur

unsigned int localPort = 265; // local port to listen for UDP packets
//
// internet specifieke zaken
//
const char* ssid = "rebr";
const char* password = "rabarber eb soep";
const char* host = "pvoutput.org";
const char* SystemId = "49832";
const char* APIKey = "c68ae892fa3a6644c5a6d0dd1cde82cbf37dc659";

//
// NTP stuff
//
IPAddress timeServerIP;
const char* ntpServerName = "nl.pool.ntp.org";
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_PACKET_SIZE+1]; //buffer to hold incoming and outgoing packets

WiFiUDP udp; // udp object
//
// klok stuff
//
uint32_t epoch; // seconden teller in UNIX tijd
struct tm *lt; // struct om UNIX tijd op te breken in losse onderdelen
struct tm myTime;
time_t t; // Unix tijd in seconden
char * c_time_string; // pointer naar geformatteerde char array van datum en tijd
uint32_t timer = 0; // onze klok timer
uint8_t dag; // dagnummer
uint8_t maand; // maandnummer
uint16_t jaar; // jaartal
uint8_t uur; // uren
uint8_t minuut; // minuten
uint8_t seconde; // seconden

//
// programma constanten
//
const uint32_t SEND_TIME = 300000; // tijd tussen verzenden data TIJDELIJK op 30 seconden normaal 5 minuten
const uint32_t NO_POWER_TIME = 1000 * 60 * 20; // tijdsduur geen pulsen meer ontvangen (normaliter 20 minuten)

//
// Stroom en puls variabelen
//
uint32_t pulseCount = 0; // Number of pulses, used to measure energy.
uint32_t pulseTime; // moment waarop de pulse wordt verwerkt
uint32_t lastTime; // vorige moment waarop de puls is verwerkt
volatile boolean pulse = false; // indicator dat er een puls is geweest
volatile boolean maximum = true; // indicator om maximale power binnen sentTime te berekenen

//power and energy
double power; // vermogen dat is geleverd sinds de vorige pulse
double maxpower; // maximale vermogen binnen sentTime
double opbrengst; // totale opbrengst van een dag
uint32_t ppwh = 1; // 1000 pulses/kwh = 1 pulse per wh
uint32_t sent = 0; // tijd tussen verzenden data
//
// timers
//
uint32_t RTCTimer; // onze softwarematige RTC
uint32_t noPowerTimer; // timer die vaststeld hoelang er geen power is
uint32_t sendTimer; // timer die bepaalt wanneer er verzonden wordt

void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
//
// connectie met lokaal wifi netwerk
//
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
//
// ophalen NTP tijd voor de eerste keer
//
if (waitForNTPTime()) {
Serial.println("No time received after 10 retries");
}

timer = millis(); // start onze seconden teller
noPowerTimer = millis(); // start de no power timer
sendTimer = noPowerTimer; // start de zend timer

// KWH pulsen worden geteld via interrupt
attachInterrupt(2, onPulse, FALLING);
}
/**
* @name loop
* Wordt eindeloos aangeroepen
*/
void loop() {
uint32_t ditMoment = millis(); // nu
//
// een keer per dag even de tijd synchroniseren met de NTP server
//
if (uur == 0 && minuut == 0 && seconde == 30) {
if (waitForNTPTime()) {
Serial.println("No time received after 10 retries");
}
}
//
// kijk of de klok bijgewerkt moet worden
//
if ((ditMoment - timer) > UPDATE_FREQ) {
//
// een seconde verlopen
//
epoch += 1; // verhoog de seconden
t = (time_t)epoch; // maak een time_t element van
c_time_string = ctime(&t); // maak er een string van
lt = localtime(&t); // zet onze unix tijd in een char array

//
// bewaar onze parameters omdat we ze anders kwijt zijn vanwege heap
// tevens correctie van maand: Die lopen van 0-11
// en jaar omdat de standaard telling vanaf 1900 loopt.
//
dag = lt->tm_mday;
maand = lt->tm_mon + 1; // maanden lopen van 0-11
jaar = lt->tm_year + 1900; // startpunt van tellen was 1900
uur = lt->tm_hour;
minuut = lt->tm_min;
seconde = lt->tm_sec;
timer = ditMoment; // start onze timer opnieuw
}
//
// check of er een puls is binnengekomen
//
if (pulse) {
pulse = false; // deze puls is verwerkt



pulseCount++; // verhoog aantal pulsen voor totale opbrengst verwerking
lastTime = pulseTime; // bewaar vorige puls moment
pulseTime = ditMoment; // zet de huidige tijd vast
//
// Calculate power
//
power = (3600000.0 / double((pulseTime - lastTime))) / (double)ppwh;
if (maximum) maxpower = power;


//
Serial.print("nieuw ");
Serial.println(power);


if (maxpower > power) power = maxpower;
maxpower = power;
maximum = false;


Serial.print("max ");
Serial.println(maxpower);

//Find Wh elapsed
//
opbrengst = (1.0 * (double)pulseCount / (double)(ppwh));
//
// er komt nog steeds stroom binnen dus reset de nopower timer
//
noPowerTimer = ditMoment;
}

//
// kijk of we de limiet van geen stroom nog niet zijn overschreden
//
if (ditMoment - noPowerTimer < NO_POWER_TIME) {
//
// er is op zijn minst binnen de afgelopen 20 minuten NOG stroom geleverd
//
if ((ditMoment - sendTimer) > SEND_TIME) {





//
// We now create a URI for the request
//
char url [200]; // char array om url op te bouwen
char opbrengstStr[10]; // om een float in char array om te zetten
char powerStr[10]; // om een float in char array om te zetten

dtostrf(opbrengst, 7, 2, opbrengstStr); // zet de float om in een 7.2 cijfer
strcpy(opbrengstStr, trimLeadingSpaces(opbrengstStr)); // en haal de voorloop spaties weg

dtostrf(maxpower, 7, 2, powerStr);
strcpy(powerStr, trimLeadingSpaces(powerStr));
//
// bouw de url op
//
sprintf(url, "/service/r2/addstatus.jsp?key=%s&sid=%s&d=%4d%02d%02d&t=%02d:%02d&v1=%s&v2=%s",
APIKey,
SystemId,
jaar,
maand,
dag,
uur,
minuut,
opbrengstStr,
powerStr);
Serial.println(url);
//
// De data verzenden naar onze host
//
//
// //Serial.print("connecting to ");
// //Serial.println(host);
// // Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}

// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" + //TIJDELIJK UITGEZET
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
//Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while(client.available()) {
String line = client.readStringUntil('\r');
//Serial.print(line);
}
//Serial.println();
//Serial.println("closing connection");
//
// reset de send timer
//


sendTimer = ditMoment;
maximum = true;
//
// als er binnen 8 minuten geen pulsen zijn binnengekomen
// dan zetten we het vermogen op 0
//
if ((ditMoment - pulseTime) > 560000) {
power = 0.0; // als er 10 minuten geen pulsen zijn gekomen is power 0
maxpower = 0; // ook maxpower moet dan naar 0 want die wordt verzonden
}



}
} else {
//
// we hebben al meer dan 20 minuten geen power
//
if (uur == 22) {
//
// na 22:00 worden de totalen op 0 gezet
//
pulseCount = 0;
opbrengst = 0.0;
power = 0.0;
}
}
} // einde loop

/**
* @name onPulse
* Wordt via een interrupt aangeroepen
*/
void onPulse() {

static uint32_t last_interrupt_time = 0; // moment van laatste interrupt
uint32_t interrupt_time = millis(); // haal de interne millis tijd op

if (interrupt_time - last_interrupt_time > 1500) { //declare the debounce/block out interval in setup
pulse = true;
}

last_interrupt_time = interrupt_time; // en bewaar dit moment voor de volgende puls
}
/**
* @name trimLeadingSpaces
* @param charString pointer to string containing chars
* @return new pointer to first non space
*/
char * trimLeadingSpaces(char * charString) {

char *ptr = charString;

for (uint16_t i = 0; i < strlen(charString); i++) {
//
// kijk of het een spatie is
if (*ptr == 0x20 ) {
ptr++;
} else {
//
// we zijn er dus klaar
//
break;
}
}
return ptr;
}
/**
* @name sentNTPpacket
* @param address IP Address of server
* Sends a request to the NTP server
*/
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address) {
Serial.println("sending NTP packet...");
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;

// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
udp.beginPacket(address, 123); //NTP requests are to port 123
udp.write(packetBuffer, NTP_PACKET_SIZE);
udp.endPacket();
return 0;
}
/**
* @ name wait for a time back from the NPT server
* @return 1= OK 0=Error (after 10 times)
*/
uint8_t waitForNTPTime() {
uint8_t returnCode = 1; // de return code of dit wel/niet succesvol was

Serial.println("Starting UDP");
udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(udp.localPort());
//get a random server from the pool
WiFi.hostByName(ntpServerName, timeServerIP);

for (uint8_t i = 0; i < 10; i++) {

sendNTPpacket(timeServerIP); // send an NTP packet to a time server
// wait to see if a reply is available
delay(1000);

int cb = udp.parsePacket();
if (!cb) {
Serial.println("no packet yet");
} else {
Serial.print("packet received, length=");
Serial.println(cb);
// We've received a packet, read the data from it
udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

//the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:

unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = ");
Serial.println(secsSince1900);

// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
epoch = secsSince1900 - seventyYears;
//
// GMT correctie
//
epoch = epoch + GMT_CORRECTIE;

// print Unix time:
Serial.println(epoch);
//
// breek onze tijd op in de verschillende componenten
//
t = (time_t) epoch;
returnCode = 0;
break;
}
}
return returnCode;
}

Advertisement

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Spook pulsen

Berichtdoor nicoverduin » 15 Feb 2017, 12:35

Kan je wai meer vertellen hoe die pulsen uit die meter komen?
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: Spook pulsen

Berichtdoor René » 15 Feb 2017, 13:41

Tja lastig,

ik heb dat ding via marktplaats gekocht en kan er geen specs van vinden.
Als ik de uitgang aan de scoop hang zie ik een "open uitgang" die bij een pulse gesloten is.( alsof je naar een relaiscontact kijk)
Het signaal gaat naar een emmiter volger( so uitgag naar "+" en basis, basis met R naar 0, collector naar "+" emmiter via R naar 0. Emmiter naar ingang ESP8266.
Op de scoop ziet het er dan goed uit.


[url][URL=http://s1129.photobucket.com/user/renevandenbroek/media/IMG_20170215_121718_zpssvvcub7z.jpg.html]Afbeelding[/url][/url]

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: Spook pulsen

Berichtdoor René » 15 Feb 2017, 13:44

op het plaatje van PVoutput zie je het effect. In de 5 minuten periode gaat het af en toe fout waardoor ik een te hoge piek waarde krijg.

http://pvoutput.org/intraday.jsp?id=548 ... 5&gs=0&m=0

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Spook pulsen

Berichtdoor nicoverduin » 15 Feb 2017, 14:05

Mooi plaatje :0 En op de scope zie je ook die pulsen? Kan natuurlijk zijn dat dat ding niet helemaal lekker is. Is het een relais oid in die meter? of zit daar ook een open collector uitgang op? Tenslotte zou je nog een Schmitt trigger achter het signaal kunnen gooien om er een mooie blok golf van te maken.

Op een of ander site kwam ik tegen dat er een 24V pulse uitgang is met een duur van 90mSec. Je zou dus op de opgaande flank kunnen triggeren en dan iets van 200mSec wachten tot de ellende voorbij is :mrgreen:
EN je gebruikt een spanningsdeler om naar wat meer gewone spanningen te gaan? waarbij de stroom belasting van die spanningsdeler on de 27mA blijft?

deze specs kwam ik tegen
cpp code
Eigenschappen
Spanning: 230V +/-20%
Stroom: 0.25-5(50)A
Nauwkeurigheidsklasse: B
Standard: EN50470-1/3
Frequency: 50Hz
Puls frequentheid: 1000imp/kWh
Display mode: LCD 5+2 = 99999.99kWh
Counter 5+1 = 99999.9kWh
Opgenomen vermogen: <8VA <0.4W
Temperatuur omgeving: -25~55°C
Puls indicatie: Flitsend rood LED
Gemiddelde luchtvochtheid gedurende 1 jaar: 75%
Maximale luchtvochtheid: 95%

Puls aansluiting:
Spanning 12-27V, vermogen <27mA, maximale aansluitingslengte :20 meter
Pulse duur 90ms, aansluitklem 20 en 21
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: Spook pulsen

Berichtdoor René » 15 Feb 2017, 14:17

Ik weet niet hoe het van binnen zit. Het gedrag lijkt op een relais contact. Ik meet geen spanning.
Toen de schakeling nog "op tafel lag" zag ik spookpulsen ontstaan op het moment dat ik een dichtbij staande lamp aan/ uit zetten. Daarom heb ik ik dat debounchen er in opgenomen.
Ik denk dat de pulslengte 50 tot 90 ms is. Zo zit het tenminsten bij andere kwh meters waar ik wel een spec van vind.
Ik dacht ik ga iets doen met de pulslengte( ik veronderstel dat spook pulsen heel kort zijn?) Iets met pulseIn() ?

Berichten: 126
Geregistreerd: 21 Feb 2013, 16:04

Re: Spook pulsen

Berichtdoor René » 15 Feb 2017, 14:30

Ik heb een testje gedaan met

Code: Alles selecteren
int pin = 2;

unsigned long duration;



void setup()

{
 Serial.begin(115200);
  pinMode(pin, INPUT);

}



void loop()

{

  duration = pulseIn(pin, HIGH);

  Serial.println(duration);

}



En zie vervolgens dit



Code: Alles selecteren
73104
0
0
0
0
73289
0
0
0
75086
6
4
0
0
0
76949
0
0
0
72887
0
0
0
74304
0
0
0
0
78624
0
0
0
0
0
0
74333
2
0
0


die van 70000 zijn de "echte"

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Spook pulsen

Berichtdoor nicoverduin » 15 Feb 2017, 14:38

En dat zie je ook op de scope?
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 1482
Geregistreerd: 06 Aug 2016, 01:03

Re: Spook pulsen

Berichtdoor Koepel » 15 Feb 2017, 14:39

Meet je de pulsen van een led ?
Dan hebben we toch echt het schema nodig, en alle waarden en types van transistors en weerstanden. Als je iets gekocht hebt, waarvan dat niet is te achterhalen, dan hebben jij en wij er weinig aan. Kun je er een link naar toe geven ?

De storing er softwarematig uit filteren is het allerlaatste redmiddel. Om de storing er softwarematig uit te filteren, zou je meer over die puls moeten weten. Anders zou je een keer een storingpuls kunnen opvatten als een normale puls zodat de volgende normale puls verkeerd gaat. Een bepaalde tijdsduur van de puls meten is goed mogelijk.

De ESP8266 kan een vrij grote piekstroom nodig hebben. Misschien is het de ESP8266 die zelf je eigen schakeling beïnvloed. Kun je een flinke elco op de voeding er bij zetten ?

Het is zelfs mogelijk dat jouw elektronica (vooral de ESP8266 wifi) de meter zelf beïnvloed: https://tweakers.net/nieuws/121247/onderzoek-universiteit-twente-elektronica-interfereert-met-deel-energiemeters.html.

Bij mij zijn de zonnepanelen nog steeds niet aangesloten.

Gebruikers-avatar
Berichten: 4645
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Spook pulsen

Berichtdoor nicoverduin » 15 Feb 2017, 14:40

Of je gaat een "threshold" inbouwen. Alles onder de ? 100 gelijk in de vuilnisbak...
Docent Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Volgende

Terug naar ESP Software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 1 gast