Hello, I have a Yun+emonTx shield that had been monitoring some heat pumps for over a year and continued after I installed a home server and aimed it at that instead of emoncms.org. After getting it a nifty new case (and possibly updating libraries or Arduino board info) and reinstalling it, after each reboot it would only update the feeds once. It continues running the sketch, writing to serial, and flashing the LED at each update, but without any further activity visible on the server.
If I were very organized I would have made notes of any changes or code ācleanupā I may have done when this started happening but I didnāt, and then I set it aside while I worked on other things so my memory is extra fuzzy. I just ran diff on an older version of my sketch that used emoncms.org and this one and didnāt notice anything more than trivial differences in comments and expected changes like the api key.
I wondered if the way the data and api strings were assembled was it since that could be different the first vs subsequent times, but the code looks ok to me and if I copy the string from the serial monitor and paste it into a browser, it is accepted as a new update.
The Yun stays online during this process, visible on the router and accessible through its linux interface.
Any ideas about what could be wrong?
Hereās my sketch:
// based on http://forum.arduino.cc/index.php?topic=201925.0
#include "EmonLib.h" //for energy monitoring
#include <Bridge.h> //for Yun linux to Arduino connection
#include <OneWire.h> //for thermometer
#include <DallasTemperature.h> //for thermometer
#include <FileIO.h> //for writing to SD card
//#include <avr/wdt.h> // My energy monitor goes down every couple of days or after several months, so I added a watchdog timer.
//At first try of the WDT, I could only get one data point so I diasbled it until I can troubleshoot.
#define DEBUG 1
#ifdef DEBUG
#define DEBUG_PRINTLN(x) Serial.println(x)
#else..
#define DEBUG_PRINTLN(x)
#endif
// Create instances for each CT channel
EnergyMonitor ct1; //ct1 is HPWH for 71
EnergyMonitor ct2; //ct2 is HPWH for 73
EnergyMonitor ct3; //ct3 is ASHP for 71
EnergyMonitor ct4; //ct4 is ASHP for 73
// On-board emonTx LED
const int LEDpin = 9;
//Setup thermometer
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
const unsigned long postingInterval = 60000;
unsigned long lastRequest = 0;
String Timestamp = "";
String dataString = "";
String APIKEY = "api key here";
void setup() {
DEBUG_PRINTLN("Finished initialization, entering setup");
// Initialize Bridge
Bridge.begin();
// Initialize Console
Console.begin();
// Start serial port
Serial.begin(9600);
// Start file system for SD card logging
FileSystem.begin();
// Start up the thermometer library
sensors.begin();
// 1st arg: pin number
// 2nd arg: Calibration factor = CT ratio / burden resistance = (100A / 0.05A) / 33 Ohms = 60.606
ct1.current(1, 20);
ct2.current(2, 20);
ct3.current(3, 25);
ct4.current(4, 25);
// (ADC input, calibration, phase_shift)
ct1.voltage(0, 130, 1.7);
ct2.voltage(0, 130, 1.7);
ct3.voltage(0, 130, 1.7);
ct4.voltage(0, 130, 1.7);
// Setup indicator LED
pinMode(LEDpin, OUTPUT);
DEBUG_PRINTLN("Finished setup, entering delay to wait for wifi");
// Hoping a delay allows the wifi connection to establish for more reliable operation
delay(15000);
//wdt_enable(WDTO_8S); // Setup watchdog timer, after the delay
}
void loop() {
DEBUG_PRINTLN("Entering loop");
long now = millis();
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
sensors.requestTemperatures(); // Send the command to get temperatures
// Calculate all. No.of crossings, //time-out
ct1.calcVI(20, 2000);
ct2.calcVI(20, 2000);
ct3.calcVI(20, 2000);
ct4.calcVI(20, 2000);
if (now - lastRequest >= postingInterval) {
// wdt_reset(); //once here in the main loop 'if' and once at the start of each of these routines
updateData();
sendData();
writeToCard();
lastRequest = now;
}
DEBUG_PRINTLN("Finished loop, about to delay");
//broke thirty second delay into 5-second chunks to keep watchdog happy. Could also disable it for this, but someone online
//specifically suggested someone use the approach below instead of disabling it
/* wdt_reset();
delay(5000);
wdt_reset();
delay(5000);
wdt_reset();
delay(5000);
wdt_reset();
delay(5000);
wdt_reset();
delay(5000);
wdt_reset();
delay(5000);
wdt_reset();*/
delay(10000);
}
void updateData() {
//wdt_reset();
// convert the readings to a String to send it:
digitalWrite(LEDpin, HIGH); //turn emon shield red LED on
//Timestamp moved to the write to card portion only because that has no other timestamp and the Emon server doesn't like the timestamp format
dataString = "Temperature:"; //need to add a comma in front, and switch to += if I turn the timestamp back on
dataString += sensors.getTempFByIndex(0);
dataString += ",ct1.apparentPower:";
dataString += 2*ct1.apparentPower;//these have 2x because the CTs are around 240v circuits while the voltage sensor is plugged into 120v
dataString += ",ct2.apparentPower:";
dataString += 2*ct2.apparentPower;
dataString += ",ct3.apparentPower:";
dataString += 2*ct3.apparentPower;
dataString += ",ct4.apparentPower:";
dataString += 2*ct4.apparentPower;
digitalWrite(LEDpin, LOW); //turn emon shield red LED off
DEBUG_PRINTLN("updateData: ");
DEBUG_PRINTLN(dataString);
DEBUG_PRINTLN("Finished updateData");
}
// this method makes a HTTP connection to the server:
void sendData() {
//wdt_reset();
// form the string for the API header parameter:
String apiString = "apikey=";
apiString += APIKEY;
// form the string for the URL parameter:
// specify the server address
String url = "http://192.168.1.116/emoncms/input/post?";
url += "node=Yun";
url += "&csv=";
url += dataString;
url += "&";
url += apiString;
DEBUG_PRINTLN("sendData dataString: ");
DEBUG_PRINTLN(dataString);
DEBUG_PRINTLN("sendData url: ");
DEBUG_PRINTLN(url);
// Is better to declare the Process here, so when the
// sendData function finishes the resources are immediately
// released. Declaring it global works too, BTW.
Process emoncms;
Console.print("\n\nSending data to EmonCMS... ");
emoncms.begin("curl");
//emoncms.addParameter("-g"); //was commented in my old sketch, tried in this one when I was only getting one data post per boot
emoncms.addParameter(url);
emoncms.run();
Console.println("upload to EmonCMS done!");
DEBUG_PRINTLN("upload to EmonCMS done!");
// If there's incoming data from the net connection,
// send it out the Console:
while (emoncms.available()>0) {
char c = emoncms.read();
Console.write(c);
DEBUG_PRINTLN(c);
}
}
void writeToCard() {
//wdt_reset();
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
// The FileSystem card is mounted at the following "/mnt/FileSystema1"
File dataFile = FileSystem.open("/mnt/sd/arduino/emon/datalog.csv", FILE_APPEND);
Timestamp = getTimeStamp();
dataString += ",Timestamp:";
dataString += Timestamp;
// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
}
// if the file isn't open, pop up an error:
else {
Console.println("error opening datalog.csv");
DEBUG_PRINTLN("error opening datalog.csv");
}
DEBUG_PRINTLN("Finished writeToCard");
}
// This function return a string with the time stamp
// from the bottom of this Yun specific tutorial https://www.arduino.cc/en/Tutorial/YunDatalogger
String getTimeStamp() {
//wdt_reset();
String result;
Process time;
// date is a command line utility to get the date and the time
// in different formats depending on the additional parameter
time.begin("date");
time.addParameter("+%D-%T");
// parameters: D for the complete date mm/dd/yy
// T for the time hh:mm:ss
time.run(); // run the command
// read the output of the command
while (time.available() > 0) {
char c = time.read();
if (c != '\n')
result += c;
}
return result;
DEBUG_PRINTLN("Got TimeStamp");
}