Skip to content

Instantly share code, notes, and snippets.

@ybizeul
Created November 18, 2018 09:12
Show Gist options
  • Save ybizeul/b38ce5d05014557595e07116ef501d90 to your computer and use it in GitHub Desktop.
Save ybizeul/b38ce5d05014557595e07116ef501d90 to your computer and use it in GitHub Desktop.
#include <Arduino.h>
#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <SPI.h>
#include "FS.h"
#include "EmonLib.h" // Include Emon Library
// Global Configuration
#define WIFI_AP "SSID"
#define WIFI_PW "passwd"
#define EMON_CALIBRATION 110
IPAddress server(10,0,1,210);
#define GRAPHITE_ROOT "electricity"
// End of configuration
// Define to 1 to log each loop value to serial
#define LIVE_LOG 0
// lastSpinMs holds the millis() of the last detected revolution
// We make the difference and with the delay, deduct Wh
unsigned long lastSpinMs;
// ads is a unique instance of ADS1115 to handle both CTs
ADS1115 ads(ADS1115_ADDRESS_ADDR_GND);
// NTP
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000);
WiFiClient client;
int status = WL_IDLE_STATUS; // the Wifi radio's status
// This array contains up to 4 EnergyMonitor objects for 4 potential CTs
EnergyMonitor ct_emons[4];
// This could be optimized to use one multidimensional array but well...
int ct_count[4];
int ct_sum[4];
int ct_lastUpdate[4];
int emon_pins[4] = { 1, 2, -1, -1 };
// Define analog pin where the light sensor goes
int sensorPin = 0;
// Define the pin where the led to blink is.
int led=2;
// High and low value to account for a light event
//int highest=0;
int high=600; // 1875mV
//int high=19200;
//int high 15000;
int low=0;
bool up = false;
unsigned long increment = 0;
#define SECONDS (timeClient.getEpochTime())
void setup() {
Serial.begin(115200);
Wire.begin();
// Read last value
SPIFFS.begin();
File f=SPIFFS.open("/count", "r");
char incrementBuffer[10];
if (f) {
int i=0;
int c=0;
while((c = f.read()) && c != -1 && i<10)
incrementBuffer[i++]=c;
incrementBuffer[i] = '\0';
increment = strtoul(incrementBuffer,NULL,10);
f.close();
}
// Connect to WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_AP, WIFI_PW);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
Serial.println("Connected to wifi");
// Initialize OTA updates
ArduinoOTA.setHostname("meter2");
ArduinoOTA.onStart([]() {
Serial.println("Firmware Update");
if (client.connect(server, 2080)) {
char query[1024];
char data[1024];
//$ curl -X POST "http://graphite/events/"
//-d '{ "what": "Event - deploy", "tags": ["deploy"], "when": 1467844481,
//"data": "deploy of master branch happened at Wed Jul 6 22:34:41 UTC 2016" }'
sprintf(data,"{ \"what\": \"Firmware Update\", \"tags\": [\"update\"], \"when\": %i }",SECONDS);
sprintf(query,"POST /events/ HTTP/1.1\nHost: 10.0.1.210:2080\nContent-length: %i\n\n%s",strlen(data),data);
client.print(query);
client.stop();
}
});
ArduinoOTA.begin();
// Initialize Time
timeClient.begin();
low=high*0.9;
Serial.println(ads.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed");
ads.initialize();
ads.setGain(ADS1115_PGA_4P096);
ads.setRate(ADS1115_RATE_860);
ads.setMode(ADS1115_MODE_CONTINUOUS);
#ifdef EMON_ADS1115
for (int i=0;i<4;i++) {
if (emon_pins[i] > -1) {
ct_emons[i].setAds(ads);
ct_emons[i].current(emon_pins[i], EMON_CALIBRATION); // Current: input pin, calibration.
//ct_emons[i].current(emon_pins[i], 2.35); // Current: input pin, calibration.
}
}
#endif
}
void loop() {
// Handle OTA updates
ArduinoOTA.handle();
// Handle time update
timeClient.update();
// Loop to ADC test
//adcTest();
int16_t value;
// Read light value and notify
ads.setMultiplexer(ADS1115_MUX_P0_NG);
value = ads.getConversion(true);
char s[10];
if(LIVE_LOG) {
sprintf(s,"Value %i",value);
Serial.println(s);
}
delay(10);
if (value > high) {
//highest = round(value * 0.95);
if (!up) {
sprintf(s,"UP %lu %i -> %i",millis(),value,low);
Serial.println(s);
up=true;
increment++;
notify();
}
}
else if ((value < low) && (up==true)) {
sprintf(s,"DOWN %lu %i",millis(),value);
Serial.println(s);
up=false;
}
// Run CT 1
loop_ct(0);
// Run CT 2
loop_ct(1);
delay(5000);
}
void loop_ct(int e) {
// Measure on CT e and push the result to graphite
EnergyMonitor emon=ct_emons[e];
// Get current TS
unsigned long now=millis();
// If we're coming here for the first time
if (!ct_lastUpdate[e])
ct_lastUpdate[e]=now;
double Irms = emon.calcIrms(1480); // Calculate Irms only
char data[100];
// Get the string value of the double Irms1
char str_Irms[6];
dtostrf(Irms*125, 4, 2, str_Irms);
// Create the query
sprintf(data,"%s.watts.ct%i %s %i\n",GRAPHITE_ROOT,e+1,str_Irms,SECONDS);
Serial.println(data);
client.connect(server, 2003);
// Send to graphite
client.print(data);
// CLeanup
client.stop();
//while (client.connected())
// delay(10);
}
void notify() {
return;
unsigned long v=increment;
// Write latest increment in file
File f = SPIFFS.open("/count", "w");
if (f) {
char strValue[10];
sprintf(strValue,"%lu",increment);
f.write((const unsigned char*)strValue,strlen(strValue));
f.close();
}
char query[1024];
char data[100];
// Calculate instan Watts
int w=0;
unsigned long now=millis();
if (lastSpinMs) {
unsigned long elapsed = now-lastSpinMs;
w = 3.6*(1000.0/elapsed)*3600;
}
lastSpinMs=now;
client.connect(server, 2003);
sprintf(data,"%s.watts.main %i %i\n",GRAPHITE_ROOT,w,SECONDS);
client.print(data);
client.stop();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment