Go Down

Topic: pulsenteller dmv interrupts (Read 5382 times) previous topic - next topic

postbus24

Hoi allen,

Gebeten door het Arduino virus naar aanleiding van deze webpagina:
http://www.fun-tech.se/FunTechHouse/ElectricityMeter/index.php

Ben ik druk bezig om ongeveer hetzelfde te bouwen met mijn Arduino Uno rev3
een weerstand van 10K tussen GND en pin2
+5V via de opto coupel van de kWh meter verbonden met pin 2
Alleen registreert de Arduino soms meerdere pulsen van de kWh teller terwijl er in werkelijkheid maar ééntje geweest is.

Ik heb al geprobeerd om een delay in de interrupt functie te zetten maar dat is helaas niet de oplossing. Blijkbaar worden alle pulsen gebufferd en als er 5 pulsen tegelijk komen gebeurt die vertraging ook 5x na mekaar.

Bestaat hier een oplossing voor ?

Alvast bedankt,
Bart

astrofrostbyte

Ik heb al een tijdje iets soortgelijks,  ik lees echter het knipperledje uit. blijkbaar heb jij een echt schakelcontact.

Google sites webpage https://sites.google.com/site/yaeuls/
De energiemeter(kWh) via de knipperled die daar opzit (1pulse/Wh) uitlezen en via ethernet/internet versturen naar een 'internet of things' logging server Cosm.


Laat ff je code zien, kijken we even mee.
Gear: Arduino- Uno,Due,Ethernet,  OLS, Buspirate, J-Link, TDS1002, Rigol DG1022

postbus24

Ik heb de code niet zo direkt bij de hand maar ze is zowat één op één dezelfde als in de link hierboven, alleen dan voor één meter ipv 2.
Code: [Select]
void onPulse1()
{
    //pulseCounter
    pulseCount1_Wh++;
    if(pulseCount1_Wh == 1000)
    {
        pulseCount1_Wh = 0;
        pulseCount1_kWh++;
    }
}

maar dit stukje van uw link is zeer interessant:
Code: [Select]
/-------------------------------------------------------------------------------------
//- Interupt routine - count number of pulses, initialized in setup()
//-                                                                                   -
//-------------------------------------------------------------------------------------
void Int_LedPulse()
{ if ( digitalRead(LEDPIN) == LOW )            // to flush false triggers
  { LedPulse.EventMillis = millis();           // capture timer
    LedPulse.Event=true;                       // set flag to signal PulseSensor_manager()
    LedPulse.Watthour++;
    if (LedPulse.Cnt++ == 0)
      LedPulse.Overflow = true;
  }
}//Int_LedPulse


// to flush false triggers  XD

... eigelijk is dat hele programma wel interessant, bedankt hiervoor !
Ook het ethernet gedeelte, voorlopig zit ik met een laptop die op de kast ligt te prutsen, maar je moet ergens beginnen, toch ?

Ik hou jullie op de hoogte  ;)


robtillaart


Wat je moet doen is de tijd vd puls meten en onthouden en vergelijken met de vorige tijdstempel
Dit is zo ongeveer de simpelste vorm
Code: [Select]

volatile unsigned long prevTime = 0;

ISR()
{
  if (millis() - prevTime < 10) // minder dan 10 millisec geleden?
  {
    return;  // ignore irq
  }
  // langer dan 10 millis.. dat is een echte
  prevTime = millis();
  kwhCount++;
}

   

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

postbus24

Om een of andere reden kreeg ik tussendoor en snachts af en toe nog een 'puls' ingelezen terwijl dit onmogelijk kon. Na wat ge-experimenteer  lijkt deze code redelijk waterdicht te zijn als ik mijn pulsenteller vergelijk met de kWh meter zelf.
Mocht iemand hier nog wat aan hebben :
Code: [Select]
void onPulse1()
{

   if (millis() - prevTime < 10000) // minder dan 10 sec geleden?
  {
    return;  // dit kan niet goed zijn  ...
  }

  if ( digitalRead(PULSEPIN) == HIGH ) {           // kijken hoelang de pin hoog blijft ...
    delay(10);   //30 mili sec 
    if ( digitalRead(PULSEPIN) == HIGH ) {         // na 30 ms nog steeds hoog ?
       pulseCount1_10Wh++;                              // is een echte puls
        prevTime = millis();                                  // start 10 sec timer
        Serial.println("PULS");
    }
  }
  return;
}

robtillaart

Thanks, werkende code is altijd nuttig

Code: [Select]
delay(10);   //30 mili sec 
conflict between comment and code ....

Quote
nog een 'puls' ingelezen terwijl dit onmogelijk kon

Hoe weet je dat zo zeker?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

postbus24

Ik heb de commentaar achteraf toegevoegd blijkbaar is daar dan wat mis mee  :*

Dat ik valse pulsen kreeg weet ik omdat de zonnepanelen in het midden van de nacht electriciteit aant produceren waren  :)

robtillaart

Quote
omdat de zonnepanelen in het midden van de nacht electriciteit aant produceren waren

Die zou ik eens heel vlug patenteren als ik jou was ;)

Maar inderdaad een onwaarschijnlijke puls! (ik moet wel denken aan die meteoriet in Rusland pas, gaf ook veel licht)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

postbus24

#8
Mar 30, 2013, 09:04 am Last Edit: Mar 31, 2013, 12:19 pm by postbus24 Reason: 1
De pulsenteller werkt ondertussen vlekkeloos en nu hebben we er een Ethernet shield op gezet zodat het opzet zelfstandig kan werken.
We hebben er ook enkele temp sensoren bij gehangen om de status van de zonneboiler te meten en dan gelijk ook een warmluchtcollector 'sturing' bijgebouwd.
Dit alles werkt netjes  :) ... voor een paar uur en dan stopt de arduino ermee  :~
Wel lastig om de oorzaak te vinden aangezien je een dag of een halve dag moet wachten bij elke verandering om te kijken of het nog mis loopt maar dat zie ik als onderdeel van de hobby    ]:D

Mocht iemand interesse hebben hier is de code die ik verzonnen heb als daar grote hiaten in zitten hoor ik dat graag natuurlijk:
Code: [Select]

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <Ethernet.h>

// PIN definition
#define PULSEPIN 2      // kWh meter puls pin
#define ONE_WIRE_BUS 3  // temp data wire
#define FAN_RELAY 4     // fan for solar collector
#define ERROR_LED 5     // Error led


#define TEMP_VERSCHIL 10  // delta-T to activate keuken fa


// ethernet
byte mac[] = {  
 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
char serverName[] = "emon.site";
EthernetClient client;
// temperature stuff
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress BruineThermometerKeuken = {
 0x28, 0xE6, 0xAC, 0x00, 0x04, 0x00, 0x00, 0x09 };//bruin
DeviceAddress BlauweThermometerKeuken = {
 0x28, 0x2D, 0xC5, 0x00, 0x04, 0x00, 0x00, 0x8C}; //blauw
//  DeviceAddress BruineThermometer = { 0x28, 0x36, 0xD7, 0x00, 0x04, 0x00, 0x00, 0xD0 };//bruin
DeviceAddress BruineThermometer = {
 0x28, 0xED, 0xD4, 0x00, 0x04, 0x00, 0x00, 0xA2 };//bruin
DeviceAddress BlauweThermometer = {
 0x28, 0xFF, 0xDA, 0x00, 0x04, 0x00, 0x00, 0x35 }; //blauw

//interupt pulse counter
volatile unsigned int pulseCount1_10Wh  = 0;  
volatile unsigned long prevTime = 0;
int busy = 0;

// global variabeles
char urlStr[128];

/******************************************
*  Pulse interupt handler
******************************************/
void onPulse1()
{
   Serial.println("interupt");
 if (millis() - prevTime < 5000){ // less than 5 sec ago?
   return;  // ignore irq
 }
 if ( digitalRead(PULSEPIN) == HIGH ) {           // to flush false triggers
   delay(10);   //30 mili sec  
   if ( digitalRead(PULSEPIN) == HIGH ) {         // still low
     pulseCount1_10Wh++;            // it must be a pulse
     prevTime = millis();
     Serial.println("PULS");
   }
 }
 return;
}
/******************************************
*  SETUP
******************************************/
void setup(void)
{
 // start serial port
 Serial.begin(9600);  //start serial port
 Serial.println("Hello");

 sensors.begin();     // Start up the library
 sensors.setResolution(BruineThermometerKeuken, 9); // set the resolution to 10 bit (good enough?)
 sensors.setResolution(BlauweThermometerKeuken, 9);
 sensors.setResolution(BruineThermometer, 9); // set the resolution to 10 bit (good enough?)
 sensors.setResolution(BlauweThermometer, 9);  
 //sensors.requestTemperatures();
 delay(3000);
 pinMode(FAN_RELAY, OUTPUT);
 pinMode(ERROR_LED, OUTPUT);
 initEth();
 delay(3000);
  attachInterrupt(0,onPulse1,RISING);

}
/******************************************
*  Initialise Ethernet
******************************************/
void initEth()
{
 Serial.println("Init Ethernet");
 // start the Ethernet connection:
 if (Ethernet.begin(mac) == 0) {
   Serial.println("Failed to configure Ethernet using DHCP");
   // no point in carrying on, so do nothing forevermore:
   while(true);
 }
 // give the Ethernet shield a second to initialize:
 delay(3000);
 Serial.println("connecting...");
}

/******************************************
*  get temperature from sensor
******************************************/
float getTemperature(DeviceAddress deviceAddress)
{
 sensors.requestTemperatures();
 float tempC = sensors.getTempC(deviceAddress);
 if (tempC == -127.00) {
   Serial.println("Failed to read temperature");
   return (0);
 }
   Serial.print("Temp is:");
   Serial.println(tempC);

 return (tempC);
}
/******************************************
*  Switch keuken ventilator
******************************************/
void fanControl()
{
 float deltaT = getTemperature(BruineThermometerKeuken) - getTemperature(BlauweThermometerKeuken);
 if (deltaT > TEMP_VERSCHIL){
   digitalWrite(FAN_RELAY, HIGH);
 }
 else {
   digitalWrite(FAN_RELAY, LOW);
 }
}
/******************************************
*  Format URL to update emon site
******************************************/
void sendData2()
{
 if (client.connect(serverName, 80)) {
   Serial.println("connected");
   // Make a HTTP request:
   //client.println("GET http://emoncms.org/input/post.json?json={power:**************** HTTP/1.0");
   client.print("GET http://emoncms.org/input/post.json?node=2&csv=");
   client.print(pulseCount1_10Wh*10*12); // avge Watt 5min
   client.print(",");
   client.print(getTemperature(BruineThermometer));
   client.print(",");
   client.print(getTemperature(BlauweThermometer));
   client.print(",");
   client.print(getTemperature(BruineThermometerKeuken));
   client.print(",");
   client.print(getTemperature(BlauweThermometerKeuken));
   if ( digitalRead(FAN_RELAY) == HIGH ) {         // fan on
     client.print(",10");
   }
   else {
     client.print(",0");
   }
   client.println("&apikey=***************** HTTP/1.0");


   client.println();

   Serial.println("read from server.");
   while (client.available()) { // print response ...
     char c = client.read();
     Serial.print(c);
   }

   Serial.println("done sending data, disconnect from emon.");
   client.stop();  //disconnect
   pulseCount1_10Wh = 0;  //reset counter
   digitalWrite(ERROR_LED, LOW); // disable alarm

 }
 else {
   digitalWrite(ERROR_LED, HIGH);
   // kf you didn't get a connection to the server:
   Serial.println("connection failed");
 }

}

/******************************************
*  Format URL to update emon site (1st attempt)
******************************************/
void sendData()
{

 if (client.connect(serverName, 80)) {
   Serial.println("start sending data to emon server :-) ");
   // Make a HTTP request:
   client.print("GET http://emoncms.org/input/post.json?node=2&cvs=0,");
   //client.print("GET http://emoncms.org/input/post.json?json={power:220}");
   client.print(pulseCount1_10Wh*10*12); // avge Watt 5min
   client.print(",");
   client.print(getTemperature(BruineThermometer));
   client.print(",");
   client.print(getTemperature(BlauweThermometer));
   client.print(",");
   client.print(getTemperature(BruineThermometerKeuken));
   client.print(",");
   client.print(getTemperature(BlauweThermometerKeuken));
   if ( digitalRead(FAN_RELAY) == HIGH ) {         // fan on
     client.print(",10");
   }
   else {
     client.print(",0");
   }
   client.println("&apikey=****************** HTTP/1.0");
   client.println();



   Serial.print("GET http://emoncms.org/input/post.json?node=2&csv=0,");
   //Serial.print("GET http://emoncms.org/input/post.json?json={power:220}");
   Serial.print(pulseCount1_10Wh*10*12); // avge Watt 5min
   Serial.print(",");
   Serial.print(getTemperature(BruineThermometer));
   Serial.print(",");
   Serial.print(getTemperature(BlauweThermometer));
   Serial.print(",");
   Serial.print(getTemperature(BruineThermometerKeuken));
   Serial.print(",");
   Serial.print(getTemperature(BlauweThermometerKeuken));
   if ( digitalRead(FAN_RELAY) == HIGH ) {         // fan on
     Serial.print(",10");
   }
   else {
     Serial.print(",0");
   }
   Serial.println("&apikey=**************** HTTP/1.0");


   Serial.println("read from server.");
   while (client.available()) { // print response ...
     char c = client.read();
     Serial.print(c);
   }

   Serial.println("done sending data, disconnect from emon.");
   client.stop();  //disconnect
   pulseCount1_10Wh = 0;  //reset counter

 }
 else {
   // if you didn't get a connection to the server:
   Serial.println("cannot connect to emon server :-(");
 }

}

/******************************************
*  Main loop
******************************************/
void loop(void)
{
 //delay(2000);

 // Serial.print(",");
 //  Serial.println(getTemperature(BruineThermometer));
 //  Serial.println(",");
 //  Serial.println(getTemperature(BlauweThermometer));

 //  
 for (int i = 0; i < 5; i++) { // loop 5 times/minutes

   fanControl(); // check fan evry minute
   Serial.println("check fan");
   delay(60000);   //60 000 =1min  
 }
 Serial.println("send url");
 sendData2();  // evry 5 mins update site


}




Jantje

Bart
Voor dit probleem is de watchog uitgevonden als "workaround".
Met vriendelijke groet.
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

postbus24

Bedankt voor de tip, hij blijft nu al enkele dagen draaien zonder vast te lopen !  :D


Jantje

Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Go Up