Tuesday, March 22, 2011

Code for Current Cost CC128 3phase to SD (and LCD) project

// 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;
}

No comments:

Post a Comment