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.
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:
Keep an eye out for the next blogs on where else we can store arduino related data.