4

During the last two months I have been working on a project that consists of using a Seeeduino Stalker V2.3, two AM2305 sensors, a TSL2561 sensor, an HC-05 XBee module, a 1,800 mAh 3.7V LiPo, a 7 cm x 7 cm 5V solar cell, and a waterproof suction box, to assemble a portable and waterproof environmental data logger that can be used to take samples on a continuous basis (1 sample every 30 minutes, 48 samples per day).

After struggling to make my logger work, I finally did it last week. It all runs fine, except that the intervals between readings are incorrect. When I program my board to store samples every 30 minutes (1,800,000), it takes them every 30 minutes and some extra seconds. When I try the same but with a rate of 1 sample every 10 seconds, my device logs data every 13 seconds more or less...

Here is the code I have been using:

#include "SPI.h"
#include "Wire.h"
#include "SD.h"
#include "DS3231.h"**

DS3231 clock;
RTCDateTime dt;

#include "DHT.h"

#define DHTPIN 8
#define DHTTYPE DHT21
DHT dht1(DHTPIN, DHTTYPE);
#define DHTPIN2 7
DHT dht2(DHTPIN2, DHTTYPE);
#include "TSL2561.h"
TSL2561 tsl(TSL2561_ADDR_FLOAT);

const int chipSelect = 10;
int XBEE = 5;
int FLASH = 4;

void setup() {
  pinMode(5, OUTPUT);
  digitalWrite(XBEE, HIGH);
  Serial.begin(9600);
  Wire.begin();
  clock.begin();
  analogReference(INTERNAL);
  pinMode(10, OUTPUT);
  pinMode(4, INPUT);
  SD.begin(10);
  dht1.begin();
  dht2.begin();
  Serial.println("EcoLOGGER DE PRUEBA PARA GENERACION DE DATOS ...");
  Serial.println(" ");
  delay(3000);
  Serial.println("RECUERDA QUE ESTE PROYECTO NO HUBIERA SIDO POSIBLE SIN LA AYUDA DE LA COMUNIDAD ARDUINO...");
  Serial.println(" ");
  delay(3000);
}

int counter = 0;

void loop() {
  float h = dht1.readHumidity();
  float t = dht1.readTemperature();
  float f = dht1.readTemperature(true);
  float h2 = dht2.readHumidity();
  float t2 = dht2.readTemperature();
  float f2 = dht2.readTemperature(true);
  dt = clock.getDateTime();
  if (tsl.begin()) {
  } else {
    while (1);
  }
  tsl.setGain(TSL2561_GAIN_0X);
  tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS);
  uint16_t x = tsl.getLuminosity(TSL2561_FULLSPECTRUM);
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum >> 16;
  full = lum & 0xFFFF;
  float vis = full-ir;
  Serial.print("Muestreo: ");
  Serial.println(counter);
  Serial.print("Fecha: ");
  Serial.print(dt.day);
  Serial.print('/');
  Serial.print(dt.month);
  Serial.print('/');
  Serial.println(dt.year);
  Serial.print("Hora: ");
  Serial.print(dt.hour);
  Serial.print(':');
  Serial.print(dt.minute);
  Serial.print(':');
  Serial.println(dt.second);
  Serial.print("Temperatura sistema: ");
  Serial.print(clock.readTemperature());
  Serial.println("*C ");
  Serial.print("Voltaje bateria: ");
  Serial.print(analogRead(A7) * (1.1 / 1024)* (10+2)/2);
  Serial.println(" V ");
  Serial.print("Carga bateria: ");
  Serial.print(-149.4 + 59.52 * (analogRead(A7) * (1.1 / 1024)* (10+2)/2));
  Serial.println("% ");
  Serial.print("Luz FULL: ");
  Serial.println(full);
  Serial.print("Temperatura ambiente: ");
  Serial.print(t);
  Serial.println(" *C ");
  Serial.print("Humedad relativa: ");
  Serial.print(h);
  Serial.println("%");
  Serial.print("Temperatura suelo: ");
  Serial.print(t2);
  Serial.println(" *C ");
  Serial.print("Humedad suelo: ");
  Serial.print(h2);
  Serial.println("%");
  Serial.println(" ");
  digitalWrite (FLASH, HIGH);
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.print(" Muestreo: ");
    dataFile.print(counter);
    dataFile.print(",");
    dataFile.print(" Fecha: ");
    dataFile.print(dt.day);
    dataFile.print('/');
    dataFile.print(dt.month);
    dataFile.print('/');
    dataFile.print(dt.year);
    dataFile.print(",");
    dataFile.print(" Hora: ");
    dataFile.print(dt.hour);
    dataFile.print(':');
    dataFile.print(dt.minute);
    dataFile.print(':');
    dataFile.print(dt.second);
    dataFile.print(",");
    dataFile.print(" Temperatura sistema: ");
    dataFile.print(clock.readTemperature());
    dataFile.print("*C ");
    dataFile.print(",");
    dataFile.print(" Voltaje bateria: ");
    dataFile.print(analogRead(A7) * (1.1 / 1024)* (10+2)/2);
    dataFile.print(" V ");
    dataFile.print(",");
    dataFile.print(" Porcentaje carga: ");
    dataFile.print(-149.4 + 59.52 * (analogRead(A7) * (1.1 / 1024)* (10+2)/2));
    dataFile.print("% ");
    dataFile.print(",");
    dataFile.print(" Luz FULL: ");
    dataFile.print(full);
    dataFile.print(",");
    dataFile.print(" Temperatura ambiente: ");
    dataFile.print(t);
    dataFile.print(" *C ");
    dataFile.print(",");
    dataFile.print(" Humedad relativa: ");
    dataFile.print(h);
    dataFile.print("%");
    dataFile.print(",");
    dataFile.print(" Temperatura suelo: ");
    dataFile.print(t2);
    dataFile.print(" *C ");
    dataFile.print(",");
    dataFile.print(" Humedad suelo: ");
    dataFile.print(h2);
    dataFile.print("%");
    dataFile.println("");
    dataFile.close();
    digitalWrite (FLASH, LOW);
  } else {
    Serial.println("");
    Serial.println("IMPOSIBLE GUARDAR DATOS");
    Serial.println("");
  }
  counter++;
  if (counter > 5) {
    delay (1000);
    digitalWrite (XBEE, LOW);
    delay (1799000);
  } else
    digitalWrite (XBEE, HIGH);
  delay (10000);
}

I have been trying to find possible solutions, but I am just lost. Do any of you have an idea of what could be going on?

Thank you in advance :)

dda
  • 1,595
  • 1
  • 12
  • 17
OpenAGRO
  • 41
  • 2

2 Answers2

3

The problem is that you are using delay().

delay() will wait, from the moment delay() is called, for the given number of milliseconds.

That is, in more structured terms:

  1. Do something
  2. Do something else
  3. Do something more
  4. Wait 30 minutes

That will only take precisely 30 minutes if steps 1 to 3 take absolutely no time at all. And that will never be the case. Things take time. Reading from sensors, writing to SD cards, etc, all take time.

So waiting for 30 minutes between doing things means that every 30 minutes will be slightly later than the one before.

And as you saw the difference is more pronounced when you have 10 seconds instead - it ends up as 13 seconds. So your other actions - reading from sensors, writing to SD card, etc, must be taking about 3 seconds each time.

So instead of "Stop everything for half an hour", you need to think slightly differently:

  1. Look at the time.
  2. Decide if 30 minutes have passed since the last time you ran the code
  3. Remember the time so you can know when 30 minutes have elapsed next time
  4. Do your sensor/SD actions.

Since you're now keying things happening on the difference between now and when you last started to do things you get a 30 minute total delay, rather than a 30 minute delay plus other bits.

For an example of how this is done programatically you can look at the BlinkWithoutDelay example in the Arduino IDE.

Majenko
  • 105,851
  • 5
  • 82
  • 139
2

The second problem is that delay() on the arduino uses the on-board clock cycle. This is powered by a resonator, which can be off by as much as 10%. If you need accurate timings and timestamps, you will want to use a Real-Time Clock (RTC) module.

Instead of using delay, the loop() asks the RTC what time it is, and uses that to determine if it's time to take another reading.

Another very common thing for this type of monitoring is for the arduino to go into sleep mode and be woken by a tick from the RTC every second (or longer), in order to extend the battery life.