Thanks Paul, #1, single quotes around the data does preserve the double quotes around the variable names and works!
I also got the watchdog timer working, and experimented to find out where resets were needed. That’s not relevant to this thread, but is an update in the code below compared to the code above. Once again, here’s the working code for reference:
To get an Arduino Yun with the EmonTX shield to POST(not GET) to emoncms in fulljson:
// based on http://forum.arduino.cc/index.php?topic=201925.0
#include <EmonLib.h> //for energy monitoring
#include <Process.h> //for Yun
#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> //watchdog timer
#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 71 HPWH on Yun, dryer on Seeed (15A, 120V)("30A, 220V when used with NEMA adapter" why 4x the power with the adapter!?)
EnergyMonitor ct2; //ct2 is 73 HPWH on Yun, washer on Seeed (12A draw, 20A breaker recommended, 240V)
EnergyMonitor ct3; //ct3 is 71 ASHP on Yun, laundry room heat on Seeed (specs?)
EnergyMonitor ct4; //ct4 is 73 ASHP on Yun, not used on Seeed
// 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; //one minute
unsigned long lastRequest = 0;
String Timestamp = "";
String dataString = "";
String APIKEY = "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn";
void setup() {
DEBUG_PRINTLN("Finished initialization, entering setup");
// Initialize Bridge
Bridge.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);
}
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
wdt_reset();
ct1.calcVI(20, 2000);
ct2.calcVI(20, 2000);
wdt_reset(); // these calculations must be slow because the WDT(8s) will act if this reset is not here
ct3.calcVI(20, 2000);
ct4.calcVI(20, 2000);
wdt_reset(); // if one or both the resets before/after aren't present, it will post, reset, post, reset around every 85-90s instead of 60s
if (now - lastRequest >= postingInterval) {
updateData();
sendData();
writeToCard(); // only for the Yun, the Seeeduino doesn't have an sdcard
lastRequest = now;
}
}
void updateData() {
// convert the readings to a String to send it:
digitalWrite(LEDpin, HIGH);
//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);
DEBUG_PRINTLN("updateData: ");
DEBUG_PRINTLN(dataString);
DEBUG_PRINTLN("Finished updateData");
}
// this method makes a HTTP connection to the server:
void sendData() {
String apiString = "apikey=";
apiString += APIKEY;
// form the string for the URL parameter:
// specify the server address
String url = "curl --data 'node=Seeed&fulljson=";
url += dataString;
url += "}&";
url += apiString;
url += "' \"http://192.168.1.116/input/post\"";
Process p; // Yun's special libraries that pass code between the Arduino and Linux sides
DEBUG_PRINTLN("\n\nSending data... ");
p.runShellCommand(url); // run some code on the Linux side
DEBUG_PRINTLN("Wrote to EmonCMS ");
DEBUG_PRINTLN(url);
while (p.running()); //wait for the process to finish
// If there's incoming data from the net connection,
// send it out the Serial:
while (p.available()>0) {
char c = p.read();
Serial.print(c); //print the entire server response as one line
}
}
void writeToCard() {
// 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 += "}";
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 {
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() {
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");
}