// 3 channels of data from CC128 to SD card with a LCD read out
#include <SdFat.h>
#include <Wire.h>
#include "RTClib.h"
#include <NewSoftSerial.h> // supports 57600 baud
#include <LiquidCrystal.h>
#include <string.h> // for strlen();
//#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#endif
#define LOG_INTERVAL 1000 // mills between entries
#define ECHO_TO_SERIAL 1 // echo data to serial port
#define WAIT_TO_START 0 // Wait for serial input in setup()
#define SYNC_INTERVAL 10000 // mills between calls to sync()
uint32_t syncTime = 0; // time of last sync()
// LED onboard
#define ledPin 13
// the digital pins that connect to the 3 LEDs. set to non existent pins
#define redLEDpin 301
#define yellowLEDpin 302
#define greenLEDpin 303 //was pin 4
// Define the pins used for the software serial port. Note that we won't
// actually be transmitting anything over the transmit pin.
#define rxPin 3
#define txPin 300 // again a non existing pin, compiler is OK with this...
// Set up the NewSoftserial port
NewSoftSerial currentcost(rxPin, txPin);
char stringData[16];
int content_length;
// what to look for in the XML data stream - add more if you want.. ie IMAs
char startPwr[] = "<ch1><watts>";
char startPwr2[] = "<ch2><watts>";
char startPwr3[] = "<ch3><watts>";
char startTmpr[] = "<tmpr>";
char endChar = '<';
char readChar = 0xFF;
int sizePwr = sizeof(startPwr)-1;
int sizePwr2 = sizeof(startPwr2)-1;
int sizePwr3 = sizeof(startPwr3)-1;
int sizeTmpr = sizeof(startTmpr)-1;
int statePwr = sizePwr;
int statePwr2 = sizePwr2;
int statePwr3 = sizePwr3;
int stateTmpr = sizeTmpr;
int newstate = 0;
int newstate2 = 0;
int newstate3 = 0;
long PwrNum = 0;
long PwrNum2 = 0;
long PwrNum3 = 0;
double TmprDouble = 0;
char Pwr[16] = "";
char Pwr2[16] = "";
char Pwr3[16] = "";
char Tmpr[16] = "";
// Packet buffer, must be big enough to packet and payload
#define BUFFER_SIZE 150
static uint8_t buf[BUFFER_SIZE+1];
// define LCD pins
LiquidCrystal lcd(8, 11, 9, 4, 5, 6, 7);
char ready = 0;
// define the Real Time Clock
RTC_DS1307 RTC;
// The objects that talk to the SD card
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
void error(char *str)
{
Serial.print("error: ");
Serial.println(str);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("error");
lcd.setCursor(0, 1);
lcd.print(str);
while(1); //this prints out "error" to the Serial and LCD, then sits in a while(1); loop forever, ie a halt
}
void setup() {
// Display welcome message on LCD screen.
lcd.begin(16, 2);
lcd.print("CC128 3CH SD LCD");
// Define pin modes for tx and rx pins:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
// Set the data rate for the NewSoftSerial port.
currentcost.begin(57600);
// Set the data rate for the hardware serial port
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
Serial.println(); // drops down 1 line on serial port
#if WAIT_TO_START
Serial.println("Type any character to start");
while (!Serial.available());
#endif //If we set WAIT_TO_START to anything but 0, the Arduino will wait until the user types something in.
// initialize the SD card
if (!card.init()) error("card.init");
// initialize a FAT volume
if (!volume.init(card)) error("volume.init");
// open root directory
if (!root.openRoot(volume)) error("openRoot");
// create a new file
char name[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
name[6] = i/10 + '0';
name[7] = i%10 + '0';
if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;
}
if (!file.isOpen()) error ("file.create");
Serial.print("Logging to: ");
Serial.println(name);
// write header
file.writeError = 0; //
Wire.begin();
if (!RTC.begin()) {
file.println("RTC failed");
#if ECHO_TO_SERIAL
Serial.println("RTC failed");
#endif //ECHO_TO_SERIAL
}
file.println("millis,stamp,datetime,CH1,CH2,CH3"); // print headers once to file
#if ECHO_TO_SERIAL
Serial.println("millis,stamp,datetime,CH1,CH2,CH3"); // echo headers to serial
#endif //ECHO_TO_SERIAL
// attempt to write out the header to the file
if (file.writeError || !file.sync()) {
error("write header");
}
pinMode(redLEDpin, OUTPUT); // pin 6
pinMode(greenLEDpin, OUTPUT); // pin 7 was pin 4
pinMode(yellowLEDpin, OUTPUT); // pin 5
}
void loop(void) {
readChar = currentcost.read(); // get data from cc128
if (readChar > 31) {
stateTmpr = parseDataTmpr(stateTmpr, readChar);
if (stateTmpr < 0) {
Tmpr[abs(stateTmpr)-1] = readChar;
}
statePwr = parseDataPwr(statePwr, readChar);
if (statePwr < 0) {
Pwr[abs(statePwr)-1] = readChar;
}
statePwr2 = parseDataPwr2(statePwr2, readChar);
if (statePwr2 < 0) {
Pwr2[abs(statePwr2)-1] = readChar;
}
statePwr3 = parseDataPwr3(statePwr3, readChar);
if (statePwr3 < 0) {
Pwr3[abs(statePwr3)-1] = readChar;
}
}
else if (readChar == 13) {
PwrNum = atol(Pwr);
PwrNum2 = atol(Pwr2);
PwrNum3 = atol(Pwr3);
TmprDouble = strtod(Tmpr,NULL);
DateTime now;
// clear print error
file.writeError = 0;
// delay for the amount of time we want between readings
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
digitalWrite(redLEDpin, HIGH);
// log milliseconds since starting
uint32_t m = millis();
file.print(m); // milliseconds since start
file.print(", ");
#if ECHO_TO_SERIAL
Serial.print(m); // milliseconds since start
Serial.print(", ");
#endif
now = RTC.now();
// log time
file.print(now.unixtime()); // seconds since 1/1/1970
file.print(", ");
file.print('"');
file.print(now.year(), DEC);
file.print("/");
file.print(now.month(), DEC);
file.print("/");
file.print(now.day(), DEC);
file.print(" ");
file.print(now.hour(), DEC);
file.print(":");
file.print(now.minute(), DEC);
file.print(":");
file.print(now.second(), DEC);
file.print('"');
file.print(", ");
// log data
file.print(PwrNum);
file.print(", ");
file.print(PwrNum2);
file.print(", ");
file.println(PwrNum3);
#if ECHO_TO_SERIAL
// send time serial
Serial.print(now.unixtime()); // seconds since 1/1/1970
Serial.print(", ");
Serial.print('"');
Serial.print(now.year(), DEC);
Serial.print("/");
Serial.print(now.month(), DEC);
Serial.print("/");
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(":");
Serial.print(now.minute(), DEC);
Serial.print(":");
Serial.print(now.second(), DEC);
Serial.print('"'); // aded ln to test
Serial.print(", ");
//send data to serial
Serial.print(PwrNum);
Serial.print(", ");
Serial.print(PwrNum2);
Serial.print(", ");
Serial.println(PwrNum3);
Serial.flush();
#endif //ECHO_TO_SERIAL
// Write to the LCD screen.
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ch1");
lcd.setCursor(6, 0);
lcd.print("Ch2");
lcd.setCursor(12, 0);
lcd.print("Ch3");
lcd.setCursor(0, 1);
lcd.print(PwrNum);
lcd.print("W");
lcd.setCursor(6, 1);
lcd.print(PwrNum2);
lcd.print("W");
lcd.setCursor(12, 1);
lcd.print(PwrNum3);
lcd.print("W");
// if you have larger display than 16x2 you can include more info, ie temp
//lcd.print("Temp: ");
//lcd.print(TmprDouble);
//lcd.print("C");
//Sync data to SD card
if (file.writeError) error("write data");
digitalWrite(redLEDpin, LOW);
//don't sync too often - requires 2048 bytes of I/O to SD card
if ((millis() - syncTime) < SYNC_INTERVAL) return;
syncTime = millis();
// blink LED to show we are syncing data to the card & updating FAT!
digitalWrite(greenLEDpin, HIGH);
if (!file.sync()) error("sync");
digitalWrite(greenLEDpin, LOW);
//digitalWrite(ledPin, LOW); //Flashes the on board LED
// Indicate that data is ready to be sent.
ready = 1;
}
if (ready == 1) {
ready = 0;
digitalWrite(ledPin, HIGH); //Flashes the on board LED
sprintf(stringData, " %lu, %lf", PwrNum, TmprDouble);
content_length = strlen(stringData);
// Serial.flush();
//DEBUG_PRINTLN(stringData);
// Serial.flush();
}
}
//TEMP
int parseDataTmpr(int oldstate, char chr) {
newstate = oldstate;
if (newstate > 0) {
if (chr == startTmpr[sizeTmpr-newstate]) {
newstate--;
}
else {
newstate = sizeTmpr;
}
}
else if (newstate <= 0) {
newstate--;
if (chr == endChar) {
newstate = sizeTmpr;
}
}
return newstate;
}
//CH1
int parseDataPwr(int oldstate, char chr) {
newstate = oldstate;
if (newstate > 0) {
if (chr == startPwr[sizePwr-newstate]) {
newstate--;
}
else {
newstate = sizePwr;
}
}
else if (newstate <= 0) {
newstate--;
if (chr == endChar) {
newstate = sizePwr;
}
}
return newstate;
}
//CH2
int parseDataPwr2(int oldstate2, char chr) {
newstate2 = oldstate2;
if (newstate2 > 0) {
if (chr == startPwr2[sizePwr2-newstate2]) {
newstate2--;
}
else {
newstate2 = sizePwr2;
}
}
else if (newstate2 <= 0) {
newstate2--;
if (chr == endChar) {
newstate2 = sizePwr2;
}
}
return newstate2;
}
//CH3
int parseDataPwr3(int oldstate3, char chr) {
newstate3 = oldstate3;
if (newstate3 > 0) {
if (chr == startPwr3[sizePwr3-newstate3]) {
newstate3--;
}
else {
newstate3 = sizePwr3;
}
}
else if (newstate3 <= 0) {
newstate3--;
if (chr == endChar) {
newstate3 = sizePwr3;
}
}
return newstate3;
}