Even though this kind of logging need'nt be too accurate, i still decided to leave an interrupt driven code variation for time keeping.
/* A simple data logger for the Arduino */
/* After some studying of both codes, i came up with this.
This is the v.2, with an timer interrupt to keep time, as
oposed to the millis() of arduino !
These example code is in the public domain.
http://dubworks.blogspot.co.uk/2012/11/moisture-and-temperature-sensors-data.html
https://github.com/adafruit/Light-and-Temp-logger
http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/ */
// this code sets up timer CTC for a 1s @ 16Mhz Clock
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#include <SD.h>
// constants won't change. Used here to
// set pin numbers:
const int ledPin = 13; // the number of the LED pin
// the digital pins that connect to the LEDs
#define redLEDpin 2
#define greenLEDpin 3
int seconds = 0;
int minutes = 0;
int hour = 0;
int day = 0;
int week=0;
// Variables will change:
int ledState = LOW; // ledState used to set the LED
int logState = LOW;
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
int Hours_interval = 0; // Hours interval
int Minutes_interval = 0; // Hours interval
int log_Minutes_interval = 1; // interval in mnts at which to log
int log_Hours_interval =4; // interval in hours at which to log
#define ECHO_TO_SERIAL 1 // echo data to serial port
#define WAIT_TO_START 0 // Wait for serial input in setup()
// The analog pins that connect to the sensors
#define Moisture_sensor_Pin 0 // analog 0
#define tempPin 1 // analog 1
#define BANDGAPREF 14 // special indicator that we want to measure the bandgap
#define aref_voltage 3.3 // we tie 3.3V to ARef and measure it with a multimeter!
#define bandgap_voltage 1.1 // this is not super guaranteed but its not -too- off
// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
// the logging file
File logfile;
void error(char *str)
{
Serial.print("error: ");
Serial.println(str);
// red LED indicates error
digitalWrite(redLEDpin, HIGH);
while(1);
}
void setup()
{
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 15624;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
// enable global interrupts:
sei();
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println();
// use debugging LEDs
pinMode(redLEDpin, OUTPUT);
pinMode(greenLEDpin, OUTPUT);
#if WAIT_TO_START
Serial.println("Type any character to start");
while (!Serial.available());
#endif //WAIT_TO_START
// initialize the SD card
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
error("Card failed, or not present");
}
Serial.println("card initialized.");
// create a new file
char filename[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
error("couldnt create file");
}
{
Serial.print("Logging to: ");
Serial.println(filename);
}
logfile.println("time,moisture,temp,vcc");
#if ECHO_TO_SERIAL
Serial.println("time,moisture,temp,vcc");
#endif //ECHO_TO_SERIAL
// If you want to set the aref to something other than 5v
analogReference(EXTERNAL);
}
void log_to_sd()
{
logState = LOW;
//Log code to sd card
logfile.print(minutes); // mnts since start
logfile.print("mnts, ");
logfile.print(hour); // hours since start
logfile.print("hrs, ");
logfile.print(day); // days since start
logfile.print("dd, ");
logfile.print(week); // weeks since start
logfile.print("Week, ");
#if ECHO_TO_SERIAL
Serial.print(minutes); // mnts since start
Serial.print("mnts, ");
Serial.print(hour); // hours since start
Serial.print("hrs, ");
Serial.print(day); // days since start
Serial.print("dd, ");
Serial.print(week); // weeks since start
Serial.print("Week, ");
#endif
analogRead(Moisture_sensor_Pin);
delay(10);
int Moisture_sensor_PinReading = analogRead(Moisture_sensor_Pin);
analogRead(tempPin);
delay(10);
int tempReading = analogRead(tempPin);
// converting that reading to voltage, for 3.3v arduino use 3.3, for 5.0, use 5.0
float voltage = tempReading * aref_voltage / 1024;
float temperatureC = (voltage - 0.5) * 100 ;
//float temperatureF = (temperatureC * 9 / 5) + 32; // uncomment the beggining of this line for F
logfile.print("Moisture, ");
logfile.print(Moisture_sensor_PinReading);
logfile.print("Temp, ");
logfile.print(temperatureC);
#if ECHO_TO_SERIAL
Serial.print("Moisture, ");
Serial.print(Moisture_sensor_PinReading);
Serial.print("Temp, ");
Serial.print(temperatureC);
#endif //ECHO_TO_SERIAL
// Log the estimated 'VCC' voltage by measuring the internal 1.1v ref
analogRead(BANDGAPREF);
delay(10);
int refReading = analogRead(BANDGAPREF);
float supplyvoltage = (bandgap_voltage * 1024) / refReading;
logfile.print("Supply_V, ");
logfile.print(supplyvoltage);
#if ECHO_TO_SERIAL
Serial.print("Supply_V, ");
Serial.print(supplyvoltage);
#endif // ECHO_TO_SERIAL
logfile.println();
#if ECHO_TO_SERIAL
Serial.println();
#endif // ECHO_TO_SERIAL
digitalWrite(greenLEDpin, LOW);
// blink LED to show we are syncing data to the card & updating FAT!
digitalWrite(redLEDpin, HIGH);
logfile.flush();
digitalWrite(redLEDpin, LOW);
}
void loop()
{
// we have a working Timer
// Routines in the loop: keeping time
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
//Keeping time :60 seconds=1minute
if (seconds==60){
seconds=0;// Reset seconds, so we do not end up with massive numbers
minutes = minutes += 1;//Increment 1 minute
Minutes_interval = Minutes_interval += 1;/*Timer for variable for
log, in minutes*/
}
//keeping time: 60 minutes=1hour
if (minutes==60){
minutes = 0;// Reset minutes, so we do not end up with massive numbers
hour= hour += 1;//increment 1 hour
Hours_interval = Hours_interval += 1;/*Timer for variable for
log, in minutes*/
}
//Keeping time :24 hours = 1 day
if (hour == 24){
day = day += 1;//increment 1 day
hour= 0;// Reset hours, so we do not end up with massive numbers
minutes = 0;// Reset minutes
}
/*Keeping time :7 days = 1 week.
This is as far as i gone for logging purposes. Can keep a quite accurate
log of the sensors, while the deviation in time is quite minimal */
if (day == 7 && hour== 23 && minutes == 59 && seconds==59){
day = 0;// Reset days, so we do not end up with massive numbers
week = week +=1;//increment 1 week
};
/* When the interrup timer gets activated, our log state will trigger
both, in turn */
/* log_Hours_interval if hours prefered; i included both, just in case,
for code's readability sake */
if ( Minutes_interval ==log_Minutes_interval ){
Minutes_interval =0;//reset the last interval
Hours_interval = 0; //reset the last interval
logState = HIGH; // if the LOG is off turn it on and vice-versa:
}
// Actual log routine
if (logState == HIGH){
log_to_sd();
}
}
ISR(TIMER1_COMPA_vect)
{
seconds= seconds += 1; // Increment one second
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
}
No comments:
Post a Comment
Feel free to contact me with any suggestions, doubts or requests.
Bless