Am un sistem de monitorizare a energiei produse de panourile fotovoltaice. Până la sfârșitul anului trecut a funcționat pe Blynk, dar au oprit serverul gratuit.
Am decis să trec monitorizarea pe ThingSpeak. Am reușit să fac un program care funcționează.
/*
INA226 Bi-directional Current/Power Monitor. Simple Example.
Read more: http://www.jarzebski.pl/arduino/czujniki-i-sensory/cyfrowy-czujnik-pradu-mocy-ina226.html
GIT: https://github.com/jarzebski/Arduino-INA226
Web: http://www.jarzebski.pl
(c) 2014 by Korneliusz Jarzebski
*/
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>
#include <INA226.h>
#include <Wire.h>
#include <ThingSpeak.h>
//#include <aREST.h>
//#include <EthernetClient.h>
#define SSID "XXXXX"
#define PASSWORD "XXXXXX"
unsigned long myChannelNumber = XXXXX; // Thingspeak channel ID here
const char * myWriteAPIKey = "XXXXXXX"; // Write API key here
const char * myReadAPIKey = "XXXXXX";
char server[] = "api.thingspeak.com"; // Serverul ThingSpeak
INA226 ina;
void checkConfig()
{
Serial.print("Mode: ");
switch (ina.getMode()) {
case INA226_MODE_POWER_DOWN:
Serial.println("Power-Down");
break;
case INA226_MODE_SHUNT_TRIG:
Serial.println("Shunt Voltage, Triggered");
break;
case INA226_MODE_BUS_TRIG:
Serial.println("Bus Voltage, Triggered");
break;
case INA226_MODE_SHUNT_BUS_TRIG:
Serial.println("Shunt and Bus, Triggered");
break;
case INA226_MODE_ADC_OFF:
Serial.println("ADC Off");
break;
case INA226_MODE_SHUNT_CONT:
Serial.println("Shunt Voltage, Continuous");
break;
case INA226_MODE_BUS_CONT:
Serial.println("Bus Voltage, Continuous");
break;
case INA226_MODE_SHUNT_BUS_CONT:
Serial.println("Shunt and Bus, Continuous");
break;
default:
Serial.println("unknown");
}
Serial.print("Samples average: ");
switch (ina.getAverages()) {
case INA226_AVERAGES_1:
Serial.println("1 sample");
break;
case INA226_AVERAGES_4:
Serial.println("4 samples");
break;
case INA226_AVERAGES_16:
Serial.println("16 samples");
break;
case INA226_AVERAGES_64:
Serial.println("64 samples");
break;
case INA226_AVERAGES_128:
Serial.println("128 samples");
break;
case INA226_AVERAGES_256:
Serial.println("256 samples");
break;
case INA226_AVERAGES_512:
Serial.println("512 samples");
break;
case INA226_AVERAGES_1024:
Serial.println("1024 samples");
break;
default:
Serial.println("unknown");
}
Serial.print("Bus conversion time: ");
switch (ina.getBusConversionTime()) {
case INA226_BUS_CONV_TIME_140US:
Serial.println("140uS");
break;
case INA226_BUS_CONV_TIME_204US:
Serial.println("204uS");
break;
case INA226_BUS_CONV_TIME_332US:
Serial.println("332uS");
break;
case INA226_BUS_CONV_TIME_588US:
Serial.println("558uS");
break;
case INA226_BUS_CONV_TIME_1100US:
Serial.println("1.100ms");
break;
case INA226_BUS_CONV_TIME_2116US:
Serial.println("2.116ms");
break;
case INA226_BUS_CONV_TIME_4156US:
Serial.println("4.156ms");
break;
case INA226_BUS_CONV_TIME_8244US:
Serial.println("8.244ms");
break;
default:
Serial.println("unknown");
}
Serial.print("Shunt conversion time: ");
switch (ina.getShuntConversionTime()) {
case INA226_SHUNT_CONV_TIME_140US:
Serial.println("140uS");
break;
case INA226_SHUNT_CONV_TIME_204US:
Serial.println("204uS");
break;
case INA226_SHUNT_CONV_TIME_332US:
Serial.println("332uS");
break;
case INA226_SHUNT_CONV_TIME_588US:
Serial.println("558uS");
break;
case INA226_SHUNT_CONV_TIME_1100US:
Serial.println("1.100ms");
break;
case INA226_SHUNT_CONV_TIME_2116US:
Serial.println("2.116ms");
break;
case INA226_SHUNT_CONV_TIME_4156US:
Serial.println("4.156ms");
break;
case INA226_SHUNT_CONV_TIME_8244US:
Serial.println("8.244ms");
break;
default:
Serial.println("unknown");
}
Serial.print("Max possible current: ");
Serial.print(ina.getMaxPossibleCurrent());
Serial.println(" A");
Serial.print("Max current: ");
Serial.print(ina.getMaxCurrent());
Serial.println(" A");
Serial.print("Max shunt voltage: ");
Serial.print(ina.getMaxShuntVoltage());
Serial.println(" V");
Serial.print("Max power: ");
Serial.print(ina.getMaxPower());
Serial.println(" W");
}
void setup()
{
Serial.begin(115200);
Serial.println("Initialize INA226");
Serial.println("-----------------------------------------------");
// Default INA226 address is 0x40
ina.begin();
// Configure INA226
ina.configure(INA226_AVERAGES_4, INA226_BUS_CONV_TIME_4156US, INA226_SHUNT_CONV_TIME_4156US, INA226_MODE_SHUNT_BUS_CONT);
// Calibrate INA226. Rshunt = 0.01 ohm, Max excepted current = 4A
// ina.calibrate(0.01, 4);
// ina.calibrate(0.01, 0.4);
// ina.calibrate(0.47, 1);
ina.calibrate(0.005, 16.384);
// ina.calibrate(0.047, 1);
// Display configuration
checkConfig();
Serial.println("-----------------------------------------------");
WiFi.hostname("INA226_OTA"); // DHCP Hostname (useful for finding device for static lease)
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
delay(50);
}
ArduinoOTA.setHostname("INA226_OTA");
ArduinoOTA.setPassword("");
ArduinoOTA.begin();
Serial.print("IP address:\t");
IPAddress myIP = WiFi.localIP();
Serial.println(myIP);
WiFiClient client;
ThingSpeak.begin(client);
delay(100);
}
float watthour(0);
//float watthour = ThingSpeak.readFloatField(myChannelNumber, 5, myReadAPIKey);
unsigned long lastMeasureMs;
unsigned long lastReportMs;
float Power(0);
float ppower(0);
const int deltat = 1000;
const int ReportTime = 137000;
unsigned long deltath(0);
float Voltage(0);
float Current(0);
void loop()
{
if (millis() - lastMeasureMs > 999)
{
//Serial.print("Bus voltage: ");
//Serial.print(ina.readBusVoltage() * 10, 5);
//Serial.println(" V");
Voltage = ina.readBusVoltage() * 10;
//Serial.print("Bus power: ");
// Serial.print(ina.readBusPower(), 5);
// Serial.println(" W");
Power = ina.readBusPower() * 10;
//Serial.print("Shunt voltage: ");
//Serial.print(ina.readShuntVoltage() * 1000, 5);
//Serial.println(" mV");
//Serial.print("Shunt current: ");
//Serial.print(ina.readShuntCurrent() * 1000, 5);
//Serial.println(" mA");
Current = ina.readShuntCurrent() * 1000;
deltath = deltat / 3.6e6; // sampling period in hours (deltat in [ms])
watthour = watthour + (Power + ppower) / 2.0 * deltath; // integer for trapezoids
ppower = Power; // then updates the power
// Serial.print("Energy: ");
//Serial.print(watthour);
//Serial.println(" Wh");
//Serial.println("");
lastMeasureMs = millis();
}
if (millis() - lastReportMs > ReportTime)
{
WiFiClient client;
ThingSpeak.begin(client);
ThingSpeak.setField(1, Voltage);
ThingSpeak.setField(2, Power);
ThingSpeak.setField(3, watthour);
ThingSpeak.setField(4, Current);
// Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
// pieces of information in a channel. Here, we write to field 1.
int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if (x == 200) {
Serial.println("Channel update successful.");
Serial.print("Energy: ");
Serial.print(watthour);
Serial.println(" Wh");
}
else {
Serial.println("Problem updating channel. HTTP error code " + String(x));
}
lastReportMs = millis();
}
ArduinoOTA.handle();
delay(1);
}
Doresc să inițializez o variabilă la pornire cu ultima valoare din câmpul ThingSpeak.
Dacă o inițializez cu 0 totul merge perfect
float watthour(0);
Dacă ințializez
float watthour = ThingSpeak.readFloatField(myChannelNumber, 5, myReadAPIKey);
programul se compilează dar placa se resetează în continuu la pornire, nu apucă să facă nici conectarea la Wifi.
Am testat un program care citește o valoare din server cu instrucțiunea respectivă și funcționează, diferența este că citirea se face în bucla principală, dar eu vreau să citesc valoarea o singură dată la pornire, nu la fiecare rular a buclei.
Menționez că nu sunt programator.