Go Down

Topic: Seeeduino Stalker Sketches (Read 10312 times) previous topic - next topic

CRS8291

I have been working with the Seeeduino Stalker for a couple of weeks and thought I would pass on what I have learned about it. I bought mine from Robotshop, I also bought a Seeedstudio UartSB V2.2 USB to Serial module to interface with it. Info can be found at:

http://www.robotshop.com/seeedstudio-stalker-wireless-sensor-network-node.html
http://www.robotshop.com/seeedstudio-uartsb-v2-2-usb-to-serial.html

I've noticed that the documentation and demo sketches for the Stalker is somewhat sparse so I am going to post some of the code I have been working on here. I will start with a rework of the demo code that is supplied with the Stalker. I will follow up with more sketches as time permits.

Code: [Select]
#include "FileLogger.h" // http://code.google.com/p/arduino-filelogger/
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>  // a basic DS1307 library - http://www.arduino.cc/playground/Code/Time

byte start[7]= {
 'B','e','g','i','n',0x0D,0x0A};
byte Buffer[23]; //Buffer for printing to SD card
int temp; //temp test data
time_t oldtime=0; //last time loop has ran
int result; //status of SD card write - 0 = "OK", 1 = "Fail initializing", 2 = "Fail appending"
unsigned long loggingRate=5; //logging rate in seconds
int length; //length of buffer string

void setup(void)
{
 do
 {
   result = FileLogger::append("data.txt", start, 7);//Initialize the SD Card
 }
 while(result != 0);

 // the next two lines can be removed if the RTC has been set

 //  setTime(17,05,0,1,3,10); // set time to 17:05:00  1 Mar 2010 (see below)
 //  RTC.set(now());  // set the RTC to the current time (set in the previous line)

 // format for setting time - setTime(hr,min,sec,day,month,yr);

 setSyncProvider(RTC.get);   // the function to get the time from the RTC

 Serial.begin(9600); //initialize serial port
}

void loop(void)
{
 //if( now() >= oldtime + loggingRate) //proceed with loop if loggingRate seconds have elapsed
 if(minute() != oldtime) //use this if 1 minute intervals is desired
 {
   //oldtime = now(); //use this if loggingRate seconds is desired
   oldtime = minute(); //use this if 1 minute intervals is desired
   do
   {
     temp=month();
     Buffer[0]=(temp/10)+'0';
     Buffer[1]=(temp%10)+'0';
     Buffer[2]='/';
     temp=day();
     Buffer[3]=(temp/10)+'0';
     Buffer[4]=(temp%10)+'0';
     Buffer[5]='/';
     temp=year();
     Buffer[6]=((temp-2000)/10)+'0';
     Buffer[7]=((temp-2000)%10)+'0';
     Buffer[8]=' ';
     temp=hour();
     Buffer[9]=(temp/10)+'0';
     Buffer[10]=(temp%10)+'0';
     Buffer[11]=':';
     temp=minute();
     Buffer[12]=(temp/10)+'0';
     Buffer[13]=(temp%10)+'0';
     Buffer[14]=':';
     temp=second();
     Buffer[15]=(temp/10)+'0';
     Buffer[16]=(temp%10)+'0';
     Buffer[17]=' ';
     temp=999;
     Buffer[18]=(temp/100)+'0';
     Buffer[19]=((temp%100)/10)+'0';
     Buffer[20]=(temp%10)+'0';
     Buffer[21]=0x0D;
     Buffer[22]=0x0A;

     length=sizeof(Buffer);
     result = FileLogger::append("data.txt", Buffer, length); //write data to SD card
   }
   while( result != 0); //repeat loop until successful write to SD card

   for (int i=0; i < length ;i++) {
     Serial.print(Buffer[i]); //Serial print buffer string to serial monitor or xBee
   }
 }
}



JocTheCroc

Hi
You got that right .... nice improvement on the original code, as I'm new to arduino and stalker it was a good insite ... cant wait for your next instalment.

cheers
Jack

CRS8291

Jack,
There has been a discussion about the Stalker demo code in the Syntax & Program section that you might want to look at. The link is:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267698132

Following are two updated demo codes. The first has a small modification for the time function.

Code: [Select]
#include "FileLogger.h" // http://code.google.com/p/arduino-filelogger/
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>  // a basic DS1307 library - http://www.arduino.cc/playground/Code/Time

byte start[7]= {
 'B','e','g','i','n',0x0D,0x0A};
byte Buffer[23]; //Buffer for printing to SD card
int temp; //temp test data
time_t oldtime=0; //last time loop has ran
int result; //status of SD card write - 0 = "OK", 1 = "Fail initializing", 2 = "Fail appending"
unsigned long loggingRate=5; //logging rate in seconds
int length; //length of buffer string

void setup(void)
{
 do
 {
   result = FileLogger::append("data.txt", start, 7);//Initialize the SD Card
 }
 while(result != 0);

 // the next two lines can be removed if the RTC has been set

 //  setTime(17,05,0,1,3,10); // set time to 17:05:00  1 Mar 2010 (see below)
 //  RTC.set(now());  // set the RTC to the current time (set in the previous line)

 // format for setting time - setTime(hr,min,sec,day,month,yr);

 setSyncProvider(RTC.get);   // the function to get the time from the RTC

 Serial.begin(9600); //initialize serial port
}

void loop(void)
{
 time_t t = now();
 //if( t >= oldtime + loggingRate) //proceed with loop if loggingRate seconds have elapsed
 if(minute(t) != oldtime) //use this if 1 minute intervals is desired
 {
   //oldtime = t; //use this if loggingRate seconds is desired
   oldtime = minute(t); //use this if 1 minute intervals is desired
   do
   {
     temp=month(t);
     Buffer[0]=(temp/10)+'0';
     Buffer[1]=(temp%10)+'0';
     Buffer[2]='/';
     temp=day(t);
     Buffer[3]=(temp/10)+'0';
     Buffer[4]=(temp%10)+'0';
     Buffer[5]='/';
     temp=year(t);
     Buffer[6]=((temp-2000)/10)+'0';
     Buffer[7]=((temp-2000)%10)+'0';
     Buffer[8]=' ';
     temp=hour(t);
     Buffer[9]=(temp/10)+'0';
     Buffer[10]=(temp%10)+'0';
     Buffer[11]=':';
     temp=minute(t);
     Buffer[12]=(temp/10)+'0';
     Buffer[13]=(temp%10)+'0';
     Buffer[14]=':';
     temp=second(t);
     Buffer[15]=(temp/10)+'0';
     Buffer[16]=(temp%10)+'0';
     Buffer[17]=' ';
     temp=999;
     Buffer[18]=(temp/100)+'0';
     Buffer[19]=((temp%100)/10)+'0';
     Buffer[20]=(temp%10)+'0';
     Buffer[21]=0x0D;
     Buffer[22]=0x0A;

     length=sizeof(Buffer);
     result = FileLogger::append("data.txt", Buffer, length); //write data to SD card
   }
   while( result != 0); //repeat loop until successful write to SD card

   for (int i=0; i < length ;i++) {
     Serial.print(Buffer[i]); //Serial print buffer string to serial monitor or xBee
   }
 }
}


For the second demo sketch I wrote a function that will pad the data values without the cascading modulo divide statements. On the demo sketch it increased the sketch size slightly but on another sketch I wrote it reduced the sketch size by about 600 bytes.

Code: [Select]
#include "FileLogger.h" // http://code.google.com/p/arduino-filelogger/
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>  // a basic DS1307 library - http://www.arduino.cc/playground/Code/Time

byte start[7]= {
 'B','e','g','i','n',0x0D,0x0A};
byte Buffer[23]; //Buffer for printing to SD card
int temp; //temp test data
time_t oldtime=0; //last time loop has ran
int result; //status of SD card write - 0 = "OK", 1 = "Fail initializing", 2 = "Fail appending"
unsigned long loggingRate=5; //logging rate in seconds
int length; //length of buffer string

void setup(void)
{
 do
 {
   result = FileLogger::append("data.txt", start, 7);//Initialize the SD Card
 }
 while(result != 0);

 // the next two lines can be removed if the RTC has been set

 //  setTime(17,05,0,1,3,10); // set time to 17:05:00  1 Mar 2010 (see below)
 //  RTC.set(now());  // set the RTC to the current time (set in the previous line)

 // format for setting time - setTime(hr,min,sec,day,month,yr);

 setSyncProvider(RTC.get);   // the function to get the time from the RTC

 Serial.begin(9600); //initialize serial port
}

void loop(void)
{
 time_t t = now();
 //if(t >= oldtime + loggingRate) //proceed with loop if loggingRate seconds have elapsed
 if(minute(t) != oldtime) //use this if 1 minute intervals is desired
 {
   //oldtime = t; //use this if loggingRate seconds is desired
   oldtime = minute(t); //use this if 1 minute intervals is desired
   do
   {
     printDigits(month(t),0,2); //month
     Buffer[2]='/';
     printDigits(day(t),3,2); //day
     Buffer[5]='/';
     printDigits(year(t)-2000,6,2); //year-yy
     Buffer[8]=',';
     printDigits(hour(t),9,2); //hour
     Buffer[11]=':';
     printDigits(minute(t),12,2); //minutes
     Buffer[14]=':';
     printDigits(second(t),15,2); //seconds
     Buffer[17]=',';
     printDigits(123,18,3); //test data
     Buffer[21]=0x0D;
     Buffer[22]=0x0A;

     length=sizeof(Buffer);
     result = FileLogger::append("data.txt", Buffer, length); //write data to SD card
   }
   while( result != 0); //repeat loop until successful write to SD card

   for (int i=0; i < length ;i++) {
     Serial.print(Buffer[i]); //Serial print buffer string to serial monitor or xBee
   }
 }
}

void printDigits(unsigned long tempBuffer, int bufferPntr, int numberDigits)
{
 unsigned long modDivide = 1;
 for (int i = 0; i < numberDigits; i++) {
   Buffer[bufferPntr+numberDigits-1-i]=((tempBuffer%(modDivide*10))/modDivide)+'0';
   modDivide=modDivide*10;
 }
}


CRS8291

#3
May 16, 2010, 03:03 am Last Edit: May 16, 2010, 03:06 am by CRS8291 Reason: 1
The original reason I started with the Arduino was to log data from my smart electrical meter. The following is the latest code from that project and is built using the demo code. I have another version that shows the data on a LCD but I need to adapt it to the Stalker.

Code: [Select]
//Meter reading program using Itron smart meter
//Added LED that turns on/off with each watt

#include "FileLogger.h" // http://code.google.com/p/arduino-filelogger/
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h> // a basic DS1307 library - http://www.arduino.cc/playground/Code/Time

const int ledPin = 14; // LED watt indicator initialization. Turns on or off each time a watt is measured
int ledState = LOW;

volatile unsigned long wattSensor=0;  //Counts power pulses in interrupt, 1 pulse = 1 watt
unsigned long wattSensorTemp=0;  //Temporary power pulse counts for printing - watts
unsigned long totalWatts=0; //Temporary total power used for printing - watts

byte start[7]= {
 'B','e','g','i','n',0x0D,0x0A};
byte Buffer[31]; //Buffer for printing to SD card
time_t oldtime=0; //last time loop has ran
int result; //status of SD card write - 0 = "OK", 1 = "Fail initializing", 2 = "Fail appending"
unsigned long loggingRate=5; //logging rate in seconds
int length; //length of buffer string

void setup(void)
{
 pinMode(ledPin, OUTPUT);  // LED watt indicator initialization
 attachInterrupt(1, wattSensorInterrupt, FALLING);  //interrupt1 - digital pin 3 - If we detect a change from HIGH to LOW we call wattSensorInterrupt

 do
 {
   result = FileLogger::append("data.txt", start, 7);//Initialize the SD Card
 }
 while(result != 0);

 // the next two lines can be removed if the RTC has been set
 //  setTime(17,05,0,1,3,10); // set time to 17:05:00  1 Mar 2010
 //  RTC.set(now());  // set the RTC to the current time (set in the previous line)

 // format for setting time - setTime(hr,min,sec,day,month,yr);

 setSyncProvider(RTC.get);   // the function to get the time from the RTC

 Serial.begin(9600);
}

void loop(void)
{
 time_t t = now();
 //  if(t >= oldtime + loggingRate) //proceed with loop if loggingRate seconds have elapsed
 if( minute(t) != oldtime) //use this if 1 minute intervals is desired
 {
   wattSensorTemp=wattSensor; //number of watts for interval
   wattSensor=0; //reset watts counter
   totalWatts=totalWatts+wattSensorTemp; //total watts counter
   oldtime = minute(t); //use this for one minute interval
   //oldtime = t; //or this for loggingRate interval

   do
   {
     Buffer[0]='A'; //start packet/Site ID
     Buffer[1]=','; //start of data string
     //format of printDigits - printDigits(tempBuffer,bufferPntr,numberDigits)
     printDigits(t,2,10); //t = now()
     Buffer[12]=',';
     printDigits(wattSensorTemp,13,5); //wattSensorTemp
     Buffer[18]=',';
     printDigits(totalWatts,19,8); //totalWatts
     Buffer[27]=',';
     Buffer[28]='>'; //end data packet
     Buffer[29]=0x0D;
     Buffer[30]=0x0A;

     length=sizeof(Buffer);
     result = FileLogger::append("data.txt", Buffer, length);
   }
   while( result != 0);

   for (int i=0; i < length ;i++) {
     Serial.print(Buffer[i]); //Serial print buffer string to serial monitor or xBee
   }
 }
}

void wattSensorInterrupt() //Interrupt1 counter routine for counting watts
{
 wattSensor=wattSensor+1;  //Update number of pulses, 1 pulse = 1 watt
 if (ledState == LOW) //Cycle LED on or off each time one watt is counted
   ledState = HIGH;
 else
   ledState = LOW;
 digitalWrite(ledPin, ledState);
}

void printDigits(unsigned long tempBuffer, int bufferPntr, int numberDigits) //assign data to output array
{
 unsigned long modDivide = 1;
 for (int i = 0; i < numberDigits; i++) {
   Buffer[bufferPntr+numberDigits-1-i]=((tempBuffer%(modDivide*10))/modDivide)+'0';
   modDivide=modDivide*10;
 }
}


edit: corrected the location of the time library

point5

Hi CRS8291,

Thanks for sharing - much appreciated.

I would like to try your meter logger out here in the UK, can I check I understand the code right :-)

You have a light sensor hooked up to pin 14 and placed over the meter LED.
Stalker counts how many light impuleses occur on the meter LED in a 5 second interval (each pulse being 1W).
At the end of every 5 second time frame Stalker writes to the SD card the time stamp and number of impulses (watts)......

About right?   :)


CRS8291

Hi point5,

The IR sensor is connected to digital pin 3 and is declared in the attachInterrupt statement:

Code: [Select]
 attachInterrupt(1, wattSensorInterrupt, FALLING);  //interrupt1 - digital pin 3 - If we detect a change from HIGH to LOW we call wattSensorInterrupt


The LED connected to pin 14 is a visual indicator that turns on or off each time the IR sensor detects an IR pulse. This is not needed but lets the user know that the Stalker is detecting pulses.

The sketch has two time options. As it it written now, it will record pulse totals every minute. This can be easily changed by commenting out the one minute options and uncommenting the two lines that use the 5 second intervals. Here are the lines of the sketch that control the time:

Code: [Select]
[glow]  //  if(t >= oldtime + loggingRate) //proceed with loop if loggingRate seconds have elapsed
 if( minute(t) != oldtime) //use this if 1 minute intervals is desired[/glow]
 {
   wattSensorTemp=wattSensor; //number of watts for interval
   wattSensor=0; //reset watts counter
   totalWatts=totalWatts+wattSensorTemp; //total watts counter
[glow]    oldtime = minute(t); //use this for one minute interval
   //oldtime = t; //or this for loggingRate interval[/glow]


You can change the loggingRate interval variable for other intervals or replace the minute(t) with other logging intervals such as hour(t), day(t), month(t) or year(t).

I have been gone for about two weeks and just checked the Stalker and it looks like it has collected all of the power data while I was away.

point5

Hi CRS8291,

Thanks for getting back to me with a clear explaination - I understand much better now :-)

May I ask a couple more questions?

What type of sensor should I use, IR photodiode or IR phototransistor?
I also noticed my suppernoob mistake in that there is no pin 14... would this mean that the onboard 'user' LED is used in this case?

It all seems to be working fine but of course counting = 0 as I have no sensor as yet :-)

Thanks

CRS8291

point5,

Pin 14 is the designation for analog pin 0. I was using pin 13 on the Arduino but the Stalker uses pin 13 to indicate writes to the SD card. The onboard led at pin 13 is useful to see that the Stalker is functioning properly. Everytime data is written to the card the onboard led should flash. The Stalker uses a number of pins for the SD card and the RTC so they need to be avoided in sketches. Details about Stalker pin usage can be found at:

http://www.seeedstudio.com/forum/viewtopic.php?f=4&t=727

I have not found the perfect sensor yet because the ones I have been using are affected by ambient light. I have gotten around this by covering the meter with a bucket to keep light out. I would like to find a better solution but have not had time. I think I need to use a light filter like the ones on the front of a TV, DVD player, etc. The sensor I am using now is a Light to Voltage TAOS Photodiode part number TSL267-LF from Mouser. I like this sensor because it is easy to hook up and is side looking so it lays flat on the meter port. I've tried other sensors which all work but require playing with resistor values to get a good signal. Pictures of my light cover and other sensor and sketch ideals can be found at:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1258971285/15

For testing, I connected a red LED and IR LED to a pin and added code to the sketch that would flash them at a known rate which I then could measure with the sensor. I also tested the code by connecting the sensor pin to the test 500 hz signal on the JYEscope. This worked but can over run the buffer quickly.

point5

Hi CRS8291,

Becoming clearer all the time :-)

I have hunted round for a filtered IR photodiode and found these which I though could be worth a try?  OSRAM SFH203-FA - I will let you know how I get on - hopefully later this week - I would be happy to send you couple of these as a small token of thanks if you fancy a play?

And another noob question.... relating to the time stamp.  My output is shown below..... how would I get the time to be formated as follows.... 20:13:00,07/06/10 - ie time,date?

A,1275941545,00000,00000000,>
A,1275941580,00000,00000000,>

CRS8291

Hi point5,

Quote
And another noob question.... relating to the time stamp.  My output is shown below..... how would I get the time to be formated as follows.... 20:13:00,07/06/10 - ie time,date?

A,1275941545,00000,00000000,>


It depends whether you want the Stalker sketch to do it or post process the data. If you want to go the Stalker route, the demo sketches that I posted earlier would require minor adjustments to get the format you want. You might want to play with the demo code and reorder the date and time to your specifications.

Currently the power meter sketch is outputting the date in Unix time which is the number of seconds since 1/1/1970. I am using Excel and Access to handle the data and they measure the date/time as the number of days since 1/1/1900. To convert a value from Unix to Excel/Access I use the following formula:

Excel/Access Date/Time = (Unix Time/86400)+25569

From here the data can be formated to your needs. The link I posted on May 15 to the Syntax and Program section offers more info regarding date and time. On that thread mem posted example code that would calculate time in Excel/Access format but would require floating point math which might tax the limited amount of resources the Stalker has available.

point5

Hi CRS8291,

I have now got the sensor working correctly with the test code below.  Unfortunately I don't understand, at all, how the digital pin 3 is assigned to the sensor in your code and was wondering if you might be able to help me merge the two to get my analog sensor working in your sketch?

Code: [Select]
int ledPin =  13;    // LED connected to digital pin 13
int sensorPin = 1;   // SFH203FA connected to analog pin 1
int sensorState = 0;



void setup()   {
 // initialize the digital pin as an output:
 pinMode(ledPin, OUTPUT);
 pinMode(sensorPin, INPUT);
Serial.begin(9600);
}

void loop(){
 // read the state of the sensor value:
 sensorState = analogRead(sensorPin);

 // check if the sensor is receiving.
 // if it is, the ledState is HIGH - have guessed a theshhold value of 100?
 if (sensorState > 100) {
   // turn LED on:
   digitalWrite(ledPin, HIGH);
 }
 else {
   // turn LED off:
   digitalWrite(ledPin, LOW);
 }
 Serial.println(sensorState);
}

CRS8291

Hi point5,

The sketch is using an interrupt for counting pulses. I have configured the interrupt to count a pulse whenever it sees the signal falling. I did this because I was picking up low light signals that were giving false counts when using the rising condition. The interrupt is called out in the following line:

Code: [Select]
attachInterrupt(1, wattSensorInterrupt, FALLING);  //interrupt1 - digital pin 3 - If we detect a change from HIGH to LOW we call wattSensorInterrupt

The interrupt calls function wattSensorIntterupt any time it detects a falling signal. There is a good explanation of the attachInterrupt in the help section:

http://www.arduino.cc/en/Reference/AttachInterrupt

There are further examples and help in the playground:

http://www.arduino.cc/playground/Main/GeneralCodeLibrary

I hope that helps and look forward to seeing your project.

point5

Hi CRS8291,

Thanks for helping - I get it now :-)  I have the logger running at the moment - looking forward to seeing the results.

One of the problems I was having turned out to be the power supply - I was running the Stalker off the Seeedstudio Solar Sheild with LiPo battery - this casued the sensor to flicker on and off very quickly.  Swapping to a 9V battery straight in to the Stalker has solved this, I guess it must be noise of some kind?

Anyway, thanks again CRS8291 - you have been a great help and it's much appreciated.

nasukaren

Great thread! It's really helping me set up my Stalker.

Here's a very basic sketch for someone who just wants to set / read the RTC and don't need the SD card code. I'm sure most people can figure it out from the code above, but this is it stripped to the bare minimum:

Code: [Select]
#include <Wire.h>

#include "Time.h"
#include "DS1307RTC.h"


void setup()
{
    Serial.begin(9600);

 // the next two lines can be removed if the RTC has been set

 //  setTime(6,51,0,6,8,10); // set time to 17:05:00  1 Mar 2010 (see below)
 //  RTC.set(now());  // set the RTC to the current time (set in the previous line)

 // format for setting time - setTime(hr,min,sec,day,month,yr);

 setSyncProvider(RTC.get);   // the function to get the time from the RTC

}


void loop()
{
  Serial.print( "The time is ");

 Serial.print( year() );
  Serial.write('/');

  Serial.print( month() );
  Serial.write('/');

  Serial.print( day() );
  Serial.write(' ');

  Serial.print( hour() );
  Serial.write(':');

  Serial.print( minute() );
  Serial.write(':');

  Serial.println( second() );
       

}



CRS8291

There has been a new example for power monitoring posted on the Seeedunio forum. It has good documentation and will be useful for many users. I have rewritten my sketch using some of the code from the example with some other changes to fit my needs.

One change was using a Switch....Case statement for determining when different events would happen. At this time when seconds = 0 it averages the power usage and writes the data to the SD card. This allows me to easily add other timed events as needed.

Code: [Select]
/*
* StalkerFile16Logger.pde - Meter reading logic for logging
* This version logs pulses on digital pin 3
*
* This program is combination of Stalker example sketch:
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273413449%20
* and
* AirSensorMeterLogger example
* http://www.airsensor.co.uk/component/zoo/item/energy-monitor.html
*
* CRS8291 - Arduino forum username
*/

#include <Fat16.h>      // the SD Card library - http://code.google.com/p/fat16lib/
#include <Wire.h>  
#include <Time.h>  
#include <DS1307RTC.h> // a basic DS1307 library - http://www.arduino.cc/playground/Code/Time

// LED pins
const int  dataLedPin    =  4;  // LED indicating sensor data is received
const int  logLedPin     =  5;  // LED flashes during a log attemp
const int  fileLedPin    =  6;  // LED turns on if a file error occurs

const int  siteID        =  10;  // Site identifier

const char *fileName = "logdata.csv";  // the name of the log file

const int logInterrupt = 1; // ATmega 168 and 328 - interrupt 0 = pin 2, 1 = pin 3
const int interruptPin = 3;

SdCard card;
Fat16 LogFile;

volatile unsigned long wattSensor = 0;  // Counts power pulses in interrupt, 1 pulse = 1 watt
volatile byte          dataState  = 0;  // used to blink the Led to indicate data updates

unsigned long wattSensorCount; //number of watts during logging interval
unsigned long totalWatts = 0;  // Total power used since the sketch started ???

unsigned long startDelayMillis;

void setup(void)
{
 setSyncProvider(RTC.get);   // the function to get the time from the RTC

 pinMode(dataLedPin, OUTPUT);    // LED interrupt indicator initialization
 pinMode(logLedPin, OUTPUT);      
 pinMode(fileLedPin, OUTPUT);  

 pinMode(interruptPin, INPUT);    
 digitalWrite(interruptPin, HIGH);  

 attachInterrupt(logInterrupt, interruptHandler, FALLING);

 // initialize the SD card
 if (!card.init())
   error(1);

 // initialize a FAT16 volume
 if (!Fat16::init(&card))
   error(2);

 // open file for append, create if it doesn't exist
 if (!LogFile.open(fileName, O_CREAT | O_APPEND | O_WRITE))
   error(3);

 // clear write error
 LogFile.writeError = false;
 LogFile.println("Start");

 Serial.begin(9600);
}

void loop(void)
{  
 time_t t = now();

 switch(second(t)) {

 case 0: // Log data if second(t) = 0
   digitalWrite(logLedPin, HIGH);
   LogFile.print(siteID); //Site identifier
   LogFile.print(',');
   LogFile.print(t); //Unix time - Excel Time = (t/86400)+25569
   MeterPulseLog(); // Number of watts during logging interval
   LogFile.println();
   // write the data to the card at the end of every line
   if (!LogFile.sync())
     error(4);

   Serial.print(siteID); //Site identifier
   Serial.print(',');
   Serial.print(t); //Unix time - Excel Time = (t/86400)+25569
   Serial.print(',');
   Serial.print(wattSensorCount); // Number of watts during logging interval
   Serial.print(',');
   Serial.println(totalWatts); // Total power used since the sketch started

   digitalWrite(logLedPin, LOW);
   pauseWithoutDelay (1000); // Delay sketch for one second
   break;
   // default:
 }
 // blink the LED to show meter pulses
 if( digitalRead(interruptPin)== LOW ) // Light the LED when data pin is LOW
 {
   digitalWrite(dataLedPin, HIGH);    
   pauseWithoutDelay (50); // light for at least 100 ms
 }
 else
   digitalWrite(dataLedPin, LOW);  
}

void MeterPulseLog()
{
 uint8_t oldSREG = SREG;   // save interrupt register
 cli();                    // prevent interrupts while accessing the count  
 wattSensorCount = wattSensor; //get the count from the interrupt handler
 wattSensor = 0;           //reset the watts count
 SREG = oldSREG;           // restore interrupts

 totalWatts = totalWatts + wattSensorCount; //total watts counter
 LogFile.print(',');   // print comma to seprate from previous data
 LogFile.print(wattSensorCount);
 LogFile.print(',');
 LogFile.print(totalWatts);        
}

// routine handle file errors
void error(int err)
{
 // blink forever
 while(1)
 {
   digitalWrite(fileLedPin, HIGH);
   delay(err * 200);
   digitalWrite(fileLedPin, LOW);
   delay(200);  
 }
}

void pauseWithoutDelay (unsigned long delayInterval)
{
 startDelayMillis = millis();
 do {
 }
 while (millis() - startDelayMillis < delayInterval);
}

void interruptHandler() // routine called when external interrupt is triggered
{
 wattSensor = wattSensor + 1;  //Update number of pulses, 1 pulse = 1 watt
}

Go Up