-->
Page 1 of 2

Blink Power Meter

PostPosted: Sat Nov 12, 2016 12:31 pm
by freedom2000
HI,

Here is a really simple sketch used to measure Power consumption of my house.
It simply "snif" the LED blinking on my powermeter any time 1Wh has elapsed.

I use a very cheap light sensor to trigger an interrupt on my ESP board
you can find them on ebay searching for : Lm393 Light Sensor Module For Arduino

I have attached the module into a piece of wood so that no light can enter into the led (but of course the Power meter led). The LED is thus jus in front of the blinking led.

LED_Blinking.jpg


Of course this is a dirty prototype, I will unsolder the led later :D

Then every minute (it's a parameter) I upload the pulses count to thingspeak.

Here is the result with french legend !

example.jpg


And finally here is the code.
Most of it is to setup the ESP with SSID, password and ApiKey + Channel ID + refresh rate. I use the excellent WifiManager library for that.

The debouncing is done this way :

Code: Select allif (abs(millis() - LastPulse) > 100 ) //debounce light sensor --> 10 Wh/s max !
  {
    LastPulse = millis();
    PulseCount++;
    #ifdef xDEBUG
      Serial.print("\nPulseCount = ");
      Serial.println(PulseCount);
    #endif
  }


As you see I trigger immediately when Led is On, but I "wait" 100ms to allow a second pulse.
The drawback is that you only allow 10 pulses (Wh) per second... which is 10*60*60 = 36 kW/h ... It's enough for me !

Enjoy !
JP

The full code :

Code: Select all#include <FS.h>                   //this needs to be first, or it all crashes and burns...
#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
#include <WiFiClient.h>
//#include <WiFiServer.h>
//#include <WiFiUdp.h>

//needed for Wifi Manager library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson

#include <Ticker.h>               //used to call Thingspeak periodically
Ticker TimerTS;

//define your default values here, if there are different values in config.json, they are overwritten.
char Channel_ID[11] = "";         //ThingSpeak Channel ID
char ApiKey[17] = "";             //
char TimeOut[17] = "";            //TimeOut to refresh ThingSpeak
int iTimeOut=10;                  // same into integer value

#define TRIGGER_PIN 13            //interrupt from light sensor
long PulseCount = 0;
long SavePulseCount = 0;
long LastPulse = 0;

#define DEBUG
#define xDEBUG

WiFiServer server(80);
const char* host = "api.thingspeak.com";
int httpConnectCounter= 0;
bool DoTS = false;                //flag for triggering ThingSpeak


bool shouldSaveConfig = false;    //flag for saving data after WifiManager

//*********************************************
//callback notifying WifiManager to save config
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

//*********************************************
//callback for WattMeter interrupt
void WattMeter_Interrupt()
{
  if (abs(millis() - LastPulse) > 100 ) //debounce light sensor --> 10 Wh/s max !
  {
    LastPulse = millis();
    PulseCount++;
    #ifdef xDEBUG
      Serial.print("\nPulseCount = ");
      Serial.println(PulseCount);
    #endif
  }
}

//*********************************************
// put your setup code here, to run once :
void setup() {
 
  Serial.begin(115200);
  Serial.println();


  pinMode(TRIGGER_PIN, INPUT);  //interrupt on this pin
  attachInterrupt(TRIGGER_PIN, WattMeter_Interrupt, RISING);

 
  //clean FS, for testing
  //SPIFFS.format();

  //read configuration from FS json
  Serial.println("mounting FS...");

  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file : ");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile)
      {
        //Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);
        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success())
        {
          strcpy(Channel_ID, json["Channel_ID"]);
          strcpy(ApiKey, json["ApiKey"]);
          strcpy(TimeOut, json["TimeOut"]);
        }
        else {
          Serial.println("failed to load json config");
        }
      }
    }
  }
  else
  {
    Serial.println("failed to mount FS");
  }
  //end read



  // The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // (id, name, placeholder, prompt default length)
 
  WiFiManagerParameter custom_Channel_ID("Channel_ID", "channel ID", Channel_ID, 7);
  WiFiManagerParameter custom_ApiKey("ApiKey", "ThingSpeak API Key", ApiKey, 17);
  WiFiManagerParameter custom_TimeOut("TimeOut", "Refresh rate", TimeOut, 17);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  //set custom ip for portal (default : 192.168.4.1)
  //wifiManager.setAPStaticIPConfig(IPAddress(192,168,4,1), IPAddress(192,168,4,1), IPAddress(255,255,255,0));
 
  //set static ip (default = DNS)
  //wifiManager.setSTAStaticIPConfig(IPAddress(192,168,0,99), IPAddress(192,168,0,1), IPAddress(255,255,255,0));
 
  //add all your parameters here
   wifiManager.addParameter(&custom_ApiKey);
   wifiManager.addParameter(&custom_Channel_ID);
   wifiManager.addParameter(&custom_TimeOut);
 
  //reset settings - for testing
  //wifiManager.resetSettings();

  //set minimu quality of signal so it ignores AP's under that quality
  //defaults to 8%
  //wifiManager.setMinimumSignalQuality();
 
  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  wifiManager.setTimeout(120);

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  //if (!wifiManager.autoConnect("AutoConnectAP", "password")) {
    if (!wifiManager.autoConnect("Config AP", "password")) {
    Serial.println("failed to connect and hit timeout : reset now ");
    delay(3000);
    //reset and try again, or maybe put it to deep sleep
    ESP.reset();
    delay(5000);
  }

  //if you get here you have connected to the WiFi
  Serial.println("connected...yeey :)");

  //read updated parameters
  strcpy(ApiKey, custom_ApiKey.getValue());
  strcpy(Channel_ID, custom_Channel_ID.getValue());
  strcpy(TimeOut, custom_TimeOut.getValue());

  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["ApiKey"] = ApiKey;
    json["Channel_ID"] = Channel_ID;
    json["TimeOut"] = TimeOut;
 

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }

    //json.printTo(Serial);
    json.printTo(configFile);
    configFile.close();
    //end save
  }

  Serial.println("local ip");
  Serial.println(WiFi.localIP());
  String sTimeOut;
  sTimeOut = TimeOut;
  iTimeOut= sTimeOut.toInt() ;
  #ifdef x²DEBUG
    Serial.print("\nrefresh rate (s) : ");
    Serial.println(iTimeOut);
  #endif
  TimerTS.attach(iTimeOut, DoTimerTS);
 
}


//*********************************************
// put your main code here, to run repeatedly :
void loop()
{
 
  if (DoTS == true)
  {
     #ifdef DEBUG
       Serial.print("connecting to ");
       Serial.println(host);
     #endif
    // Use WiFiClient class to create TCP connections
    httpConnectCounter++;
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort))
    {
      Serial.println("http connection failed, will retry");
      if (httpConnectCounter < 5)
      {
        delay(20);
        return; // retry connection
      }
      else
      {
        // 20 times no success give up, reset board
        Serial.println("http give up, will restart");
   
        delay(1000);
        abort();
      }
    }
    DoTS = false;
    //the connection is Ok
    httpConnectCounter = 0;
    SavePulseCount = PulseCount;    // pick up the Watt values (1 flash = 1Wh)
    PulseCount = 0;
    // We now create a URL for the request
    String url = "/update";
    url += "?key=";
    url += ApiKey;
    url += "&field1=";
    url += SavePulseCount;
 
    #ifdef xDEBUG
      Serial.print("Requesting URL: ");
      Serial.println(url);
    #endif
    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");
    delay(200);
 
    // Read all the lines of the reply from server and print them to Serial
    if (client.available())
    {
      // print first line
      String line = client.readStringUntil('\r');
      #ifdef xDEBUG
        Serial.print(line);
      #endif
    }
    while (client.available()) String line = client.readStringUntil('\r');
 
    Serial.println();
    Serial.println("closing connection");
    client.stop();
    // all done
  }
}

// *******************************************
// interrupt routine to trigger ThingSpeak
void DoTimerTS()
{
   DoTS = true;
}

Re: Blink Power Meter

PostPosted: Sun Nov 13, 2016 8:43 am
by freedom2000
Well it works so well that I have finally fully integrated the proto into... two milk caps !

Here it is (blue cap)

finished.jpg


JP

Re: Blink Power Meter

PostPosted: Thu Feb 02, 2017 6:19 pm
by rtra
Hi,
Can you tell me what hw to you use?
I now you used a Lm393 Light Sensor Module For Arduino, but what else?
maybe a esp board, the ones with nodemcu ?
I'am a completely newbie, so give me a break xD
Thank you

Re: Blink Power Meter

PostPosted: Fri Feb 03, 2017 2:05 am
by freedom2000
Hi,

Yes I do use an ESP12E board. But it is one that I have designed myself.
However you can use any board you want providied you have one digital pin to capture interrupt coming from the light sensor !

JP