Long term data logging from our projects is a great when it comes to developing the system further, from the data we can fine tune our grow bed ratio's work on controlling any variables that vary more than we would like and attribute the causes of a exceptionally good or bad crop.

 

In another Blog we will be sending our data to the "cloud" but it is best if we make a backup version on a SD card too. DAB mentioned saving the data as plain text, a great idea and that is what we will be doing, Sd storage is cheap and it will take a hell of a lot of text to fill up the smallest SD card I have to hand.

 

What you will need:

>Arduino

>SD Card

>Arduino Sd card reader/writer [we will be using the one found on most ethernet shields]

 

Jeremy Blum has already covered this topic, much better than I could ever do. Take a look at his video on the subject:

[Thanks Element14 for supporting Jeremy with his arduino blogs, I found them really useful!]

 

The Code

unfortunately Jeremy's tutorials are starting to show their age a little, some of the coding syntax has changed since he wrote his tutorial, but we can use his code as a base for our own and even make it a little better.

Some small improvements:

>Functions to flip between using SD slot and ethernet [cant run both at the same time]

>Sd writing survives a Sd card removal and replacement

>We are logging variables that dont need external hardware [good for a quick test]

 

Header 1

 

 

 

/*

This script measures the enviroment withing a greenhouse

 

 

 

 

Sends data to SD Card with Time Stamp

 

 

 

 

 

 

 

 

Michael Ratcliffe  mike@michaelratcliffe.com

 

    This program is free software: you can redistribute it and/or modify

    it under the terms of the GNU General Public License as published by

    the Free Software Foundation, either version 3 of the License, or

    (at your option) any later version.

 

 

 

 

    This program is distributed in the hope that it will be useful,

    but WITHOUT ANY WARRANTY; without even the implied warranty of

    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

    GNU General Public License for more details.

 

 

 

 

    You should have received a copy of the GNU General Public License

    along with this program.  If not, see <http://www.gnu.org/licenses/>.

 

    >Arduino

    >Ethernet shield Arduino Ethernet shield R3 with micro SD connector

 

Much of this code is largely based on Jeremy Blum's Tutorials Thanks for the great work!

 

 

 

 

*/

 

 

 

 

 

 

 

 

#include <SPI.h>

#include <SD.h>

 

 

 

 

//*******************************User Defined Variables **********************************//

const int Spacing=10; //how long in sconds to wait between logging data

 

 

// what we will print at the top of log [collums]

String header = "Seconds, Analog_Average, Ram,";

//******** Change Value Below For Board Of Choice *********//

/* ATMega168 ATMega328P ATmega1280 ATmega2560

SRAM 1024 bytes 2048 bytes 8192 Bytes 8192 Bytes

*/

 

 

const int Total_Ram = 8192 ; //change this value for the correct one from above data

 

 

 

 

//******************** End of Recomended Changes ****************************//

 

 

 

 

 

 

 

 

int Ram=0;

float  max_Ram=0;

 

 

 

 

#define SS_SD_CARD   4

#define SS_ETHERNET 10

 

 

 

 

float Analog_Value=0;

 

 

 

 

//Some stuff for making second readings

unsigned  long Second=0;

unsigned long Last_Send= 0;

 

 

//Some stuff for making second readings

long Last_Second=0;

int Reading=0;

 

 

 

 

//******************Seting up the Ram check**************************//

int freeRam () {

extern int __heap_start, *__brkval;

int v;

return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);

};

//******************************************************************//

 

 

 

 

 

 

 

 

 

 

 

 

//*****************************Setup Loop *************************************//

void setup() {

  // Open serial communications

  Serial.begin(9600);

 

 

digitalWrite(SS_ETHERNET, HIGH); // Ethernet not active

digitalWrite(SS_SD_CARD, LOW);  // SD Card ACTIVE

 

 

 

 

  Serial.print("Initializing SD card...");

 

 

 

 

  // see if the card is present and can be initialized:

  if (!SD.begin(SS_SD_CARD)) {

    Serial.println("Card failed, or not present");

    // don't do anything more:

  }

   else Serial.println("card initialized.");

 

 

//Printing the file header

  File dataFile = SD.open("datalog.txt", FILE_WRITE);

 

 

 

 

  // if the file is available, write a header to it:

  if (dataFile) {

    dataFile.println("  ");

    dataFile.println(header);

 

    dataFile.close();

 

 

  }

  // if the file isn't open, pop up an error:

  else {

    Serial.println("error opening datalog.txt");

  }

 

 

 

 

 

 

}

//********************************* End Of Setup ********************************//

 

 

 

 

//********************************* Main Loop **********************************//

void loop() {

 

 

Second=millis()/1000;

//Taking one reading every second

if(Second!=Last_Second){

   Analog_Value=(analogRead(A0)+ Analog_Value);

   Last_Second=Second;

   Reading++ ;

   }

//Checking how much ram we are using

if(freeRam()>=Ram){

             Ram=(freeRam());

             max_Ram=(((Total_Ram-Ram)/Total_Ram)*100);

};

 

 

 

 

//Averaging Readings and calling the logging functions [see below code]

if(Second%Spacing==0 && Second!=Last_Send){

   Last_Send= Second;

     Analog_Value=Analog_Value/Reading;

     Reading=0; //setting things back ready for more readigs

     Second=millis()/1000;

     Activate_SD();

     Log_SD();

     Activate_Eth();

     Analog_Value=0;

}

 

 

 

 

};

//********************************* End Of Main **********************************//

 

 

 

 

//*************** Activating Sd Card **************************//

void Activate_SD(){

  digitalWrite(SS_ETHERNET, HIGH); // Ethernet not active

  digitalWrite(SS_SD_CARD, LOW);  // SD Card ACTIVE

delay(10);

if (!SD.begin(SS_SD_CARD)) {

    Serial.println("Card failed, or not present");

    // don't do anything more:

  }

   else Serial.println("card initialized.");

 

 

 

 

 

 

};

 

 

 

 

//**************** Function To activate ethernet *************//

void Activate_Eth(){

  digitalWrite(SS_ETHERNET, LOW); // Ethernet not active

  digitalWrite(SS_SD_CARD, HIGH);  // SD Card ACTIVE

};

 

 

 

 

//**************** Function to Log SD **********************//

void Log_SD(){

  File dataFile = SD.open("datalog.txt", FILE_WRITE);

 

 

 

 

  // if the file is available, write to it one variable at a time

  if (dataFile) {

    dataFile.print("");

    dataFile.print(Second);

    dataFile.print(",  ");

    dataFile.print(Analog_Value);

    dataFile.print(",  ");

    dataFile.println(max_Ram);

    dataFile.close();

    // print to the serial port too:

 

 

 

 

    Serial.println("Posting!");

    Serial.print("Analog_Average: ");

    Serial.println(Analog_Value);

    Serial.print("Max_Ram: ");

    Serial.println(max_Ram);

    Serial.print("Seconds: ");

    Serial.println(Second);

    Serial.println("Data Logged");

 

  }

  // if the file isn't open, pop up an error:

  else {

    Serial.println("error opening datalog.txt");

  }

 

 

};

 

 

 

 

A Example of SD-Card Log

The logging system works just as we expected, and adding a SD.begin before every write means we dont have to reboot every time we remove the sd card for backup. You can import the text file into Exel by special pasting and using commas as cell breaks.

Log

 

 

A Example of transporting the data to excel

Here is a plot for the same code, logging temperature near my PC fan as it warms up before removing it to cool:

temp

 

Keep an eye out for the next blogs on where else we can store arduino related data.