Event code, can't sleep arduino for correct amount of time

So i have had produced this code, but i cannot seem to sleep my Arduino Uno for my desired time. I need the Arduino Uno to sleep for 12 minutes, wake up and take readings after 3 minutes (warm up time for my sensors), then take readings for 5 minutes. I have got the wake up and reading times correct, just can't seem to get sleep time correct.

Can anyone help? These are the snippets of code that conrol the time:

const unsigned long eventInterval = (1000UL*60*3);   //Assign the time in millis for event interval (every 15 minutes) 
unsigned long startTime =  millis()+ eventInterval;
unsigned long readingInterval= (1000UL*60*5);             //Assign the time in millis for reading (every 5 minutes) 

//SD stack select
const int chipSelect = 10;
//const int pingPin = 7;


//RTC Module Global Variables
const int time_interval= 12 ;  // Sets the wakeup interval in minutes. 

....and.....

    /* This is the event */
 if ((long)(millis()-startTime)>=0) {


  delay(10);
  unsigned long i=millis();
  while ((long)((i+readingInterval)-millis())>=0){
  //Get the values of the sensors
  GetRTC_Readings();
  GetVOC_Readings();
  GetPM_Readings();
  GetBME_Readings();
  delay (5000); // to give time for PMS to take readings?

  // Store the three sensor values to the SD card.
  print2SD();
  delay(5000);
  } 
   
  digitalWrite(indicator,HIGH);
  delay(2000); 
  digitalWrite(indicator,LOW);
  Serial.println("Going to sleep for 24 seconds");
  digitalWrite(Relay_pin,LOW);
  digitalWrite(Relay_pin2,LOW);
 
  delay(100);
  for(int i = 0; i<= 6*time_interval; i++) //this is sleeping arduino for 12 seconds
  {
  LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,SPI_OFF, USART0_OFF, TWI_OFF);
  }
  delay(1000);
  startTime = millis()+ eventInterval; //this is what affects the time
  Serial.println("Arduino: Hey I just Woke up");
  Serial.println("");
  delay(1000);
  
 }
}

Full code below:

//********************Start of code for TPH, PM, VOC sensor***********************

//*** TO DO LIST ***//

//pinmap with relay
//documentation
//- Calibrate BME
//- Calibrate VOC sensor (potentiometer on back adjusts zero threshold)


#include <RtcDS3231.h>

#include <DS3232RTC.h>
#include <LowPower.h> 
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_I2CRegister.h>
#include <Adafruit_SPIDevice.h>

#include <avr/sleep.h>

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SoftwareSerial.h>
#include "Adafruit_PM25AQI.h"
#include <BME280I2C.h>
#include <SPI.h>
#include <SD.h>


char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

//Real Time Clock
DS3232RTC rtc;

//BME280 - TPH
BME280I2C bme;

//PM Sensor
SoftwareSerial pmsSerial(3,4);
Adafruit_PM25AQI aqi = Adafruit_PM25AQI();
//#define 2 

//TVOC sensor
#define Aout A0 //Define pins for TVOC sensor
#define Dout 7

//Set up pin 9
#define Relay_pin 9
#define Relay_pin2 6


uint32_t delayMS;

//eventinterval is when the arduino starts taking readings from sensos
//then redinginterval is how long the reading of sensor values happens
//time_interval is how long the arduino sleeps for
//meaning there will be a 3 minute warm up period for PMS and CJMCU-MS1100 until the next reading event

const unsigned long eventInterval = (1000UL*60*3);   //Assign the time in millis for event interval (every 15 minutes) 
unsigned long startTime =  millis()+ eventInterval;
unsigned long readingInterval= (1000UL*60*5);             //Assign the time in millis for reading (every 5 minutes) 

//SD stack select
const int chipSelect = 10;
//const int pingPin = 7;


//RTC Module Global Variables
const int time_interval= 12 ;  // Sets the wakeup interval in minutes. 
unsigned int rtcd;
unsigned int rtcm;
unsigned int rtcy;
unsigned int rtcs;
unsigned int rtcmin;
unsigned int rtchr;


// Structure to hold pms sensor data.
struct pms5003data {
volatile uint16_t framelen;
volatile  uint16_t pm10_standard, pm25_standard, pm100_standard;
volatile  uint16_t pm10_env, pm25_env, pm100_env;
volatile  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
volatile  uint16_t unused;
volatile  uint16_t checksum;
} pms5003dataStruct;

  //Declaring BME variables
  float preshpa; 
  float corr_temp; 
  float corr_hum; 
  float corr_preshpa;

  // Declaring VOC variables
  byte a;
  byte b;


  // 
  #define interruptPin 2
  #define indicator 8

  PM25_AQI_Data data;

 
void setup() {

pinMode(Relay_pin, OUTPUT);
pinMode(Relay_pin2, OUTPUT);

digitalWrite(Relay_pin,HIGH);
digitalWrite(Relay_pin2,HIGH);


  pinMode(indicator,OUTPUT);
 // pinMode(interruptPin, INPUT_PULLUP);
  digitalWrite(indicator, LOW);
 
  
  // Open serial communications and wait for port to open:
  //Serial.begin(9600);


  // PM sensor debugging output
  Serial.begin(115200);
  while (!Serial) delay(10);

  // PM sensor baud rate is 9600
  pmsSerial.begin(9600);


//remember to copy and paste the RTC code from other code to reset RTC to current time!

//delay(1000);

//Find PM sensor
  if (! aqi.begin_UART(&pmsSerial)) { // connect to the sensor over software serial 
    Serial.println(F("Could not find PM 2.5 sensor!"));
    while (1) delay(10);
  }

  Serial.println(F("PM25 found!"));



//Find BME280 TPH sensor
  while (!bme.begin())
  {
    Serial.println(F("Could not find BME280 sensor!"));
  //  delay(1000);
  }

  // bme.chipID(); // Deprecated. See chipModel().
  switch (bme.chipModel())
  {
    case BME280::ChipModel_BME280:
      Serial.println(F("Found BME280 sensor! Success."));
      break;
    case BME280::ChipModel_BMP280:
      Serial.println(F("Found BMP280 sensor! No Humidity available."));
      break;
    default:
      Serial.println(F("Found UNKNOWN sensor! Error!"));
  }
  
  // Storing the CSV file header/title.
  printHeader();
}


void loop() {
digitalWrite(Relay_pin,HIGH);
digitalWrite(Relay_pin2,HIGH);



    /* This is the event */
 if ((long)(millis()-startTime)>=0) {


  delay(10);
  unsigned long i=millis();
  while ((long)((i+readingInterval)-millis())>=0){
  //Get the values of the sensors
  GetRTC_Readings();
  GetVOC_Readings();
  GetPM_Readings();
  GetBME_Readings();
  delay (5000); // to give time for PMS to take readings?

  // Store the three sensor values to the SD card.
  print2SD();
  delay(5000);
  } 
   
  digitalWrite(indicator,HIGH);
  delay(2000); 
  digitalWrite(indicator,LOW);
  Serial.println("Going to sleep for 24 seconds");
  digitalWrite(Relay_pin,LOW);
  digitalWrite(Relay_pin2,LOW);
 
  delay(100);
  for(int i = 0; i<= 6*time_interval; i++) //this is sleeping arduino for 24 seconds
  {
  LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,SPI_OFF, USART0_OFF, TWI_OFF);
  }
  delay(1000);
  startTime = millis()+ eventInterval; //this is what affects the time
  Serial.println("Arduino: Hey I just Woke up");
  Serial.println("");
  delay(1000);
  
 }
}
//}

 void printHeader(){
  
//Initialize and find SD card
  Serial.print(F("Initializing SD card..."));

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println(F("Card failed, or not present"));
    // don't do anything more:
    while (1);
  }
  Serial.println(F("card initialized."));
   File dataFile = SD.open("datalog.csv", FILE_WRITE);


  // if the file is available, write to it:
  if (dataFile) {

    //dataFile.print(cm);        dataFile.print(",CM,");
    dataFile.print("DATE,");
    dataFile.print("TIME,");
    dataFile.print("Temperature,");
    dataFile.print("Pressure,");
    dataFile.print("Humidity,");
    dataFile.print("TVOC Digital,");
    dataFile.print("TVOC Analogue,");
    dataFile.print("PM 0.3,");
    dataFile.print("PM 2.5,");
    dataFile.print("PM 10");
 
 //   dataFile.print(aqi.read(&data)); dataFile.print
    

    delay(2000);
    dataFile.close();

  }
  
 }

 void GetBME_Readings(){
  /*****************Get Temp, Pressure and Humidity********************/

  float temp(NAN), hum(NAN), pres(NAN);

  BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
  BME280::PresUnit presUnit(BME280::PresUnit_Pa);

  bme.read(pres, temp, hum, tempUnit, presUnit);

  preshpa = (pres / 100); //create space for conversion of pascals to hectopascals (hPa) which is more usual measure
  corr_temp = (temp - 0.0); //create space for correction of temperature according to unique sensor validation (will be different for each sensor)
  corr_hum = (hum + 0); //create space for correction of humidity according to unique sensor validation (will be different for each sensor)
  corr_preshpa = (preshpa + 10); //create space for correction of pressure according to unique sensor validation (will be different for each sensor)

  Serial.print(F("Temp: "));
  Serial.print(corr_temp);
  Serial.print("°" + String(tempUnit == BME280::TempUnit_Celsius ? 'C' : 'F'));
  Serial.print(F("\t\tHumidity: "));
  Serial.print(corr_hum);
  Serial.print(F("% RH"));
  Serial.print(F("\t\tPressure: "));
  Serial.print(corr_preshpa);
  Serial.println(F(" hPa"));

 }

 void GetPM_Readings(){
//  /******************GET PM SENSOR DATA*****************************/
 
  boolean ret = aqi.read(&data);
 Serial.println(ret);
  if (ret) {
  Serial.println(F("AQI reading success"));

//  Serial.println();
  Serial.println(F("---------------------------------------"));
  Serial.println(F("Concentration Units (standard)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_standard);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_standard);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_standard);
  Serial.println(F("Concentration Units (environmental)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_env);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_env);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_env);
  Serial.println(F("---------------------------------------"));
  Serial.print(F("Particles > 0.3um / 0.1L air:")); Serial.println(data.particles_03um);
  Serial.print(F("Particles > 0.5um / 0.1L air:")); Serial.println(data.particles_05um);
  Serial.print(F("Particles > 1.0um / 0.1L air:")); Serial.println(data.particles_10um);
  Serial.print(F("Particles > 2.5um / 0.1L air:")); Serial.println(data.particles_25um);
  Serial.print(F("Particles > 5.0um / 0.1L air:")); Serial.println(data.particles_50um);
  Serial.print(F("Particles > 10 um / 0.1L air:")); Serial.println(data.particles_100um);
  Serial.println(F("---------------------------------------"));
}
 }

 void GetVOC_Readings(){
  /*****************GET VOC**********************/
  a = analogRead(Aout);
  b = digitalRead(Dout);
  Serial.print("D0:");
  Serial.print(b);
  Serial.print("   A0:");
  Serial.println(a);
 }


 void print2SD(){

  
  /*********STORE DATA TO SD CARD ************/

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.csv", FILE_WRITE);


  // if the file is available, write to it:
  if (dataFile) {

    //dataFile.print(cm);        dataFile.print(",CM,");
    dataFile.print("\n");  
    dataFile.print(rtcy); 
    dataFile.print("/");              
    dataFile.print(rtcd); 
    dataFile.print("/");              
    dataFile.print(rtcm);
    dataFile.print(",");              
    dataFile.print(rtchr); 
    dataFile.print(":");              
    dataFile.print(rtcmin);
    dataFile.print(":");             
    dataFile.print(rtcs);
    dataFile.print(",");             
    dataFile.print(corr_temp);
    dataFile.print(",");             
    dataFile.print(corr_preshpa);
    dataFile.print(",");             
    dataFile.print(corr_hum);
    dataFile.print(",");         
    dataFile.print(b);
    dataFile.print(",");      
    dataFile.print(a);
    dataFile.print(",");
    dataFile.print(data.particles_03um);
    dataFile.print(",");
    dataFile.print(data.particles_25um);
    dataFile.print(",");
    dataFile.print(data.particles_100um);

    dataFile.close();
    delay(10);
    // print to the serial port too:
    //Serial.println(cm);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println(F("error opening datalog.csv"));
  }
    
  delay(20);
 }
 
void GetRTC_Readings(){
  /*********GET TIME ************/
  time_t p;     //create time object for time and date stamp
  p=RTC.get();  //gets the time from RTC

  
  Serial.print(year(p));
  Serial.print('/');
  Serial.print(month(p));
  Serial.print('/');
  Serial.print(day(p));
  Serial.print(" (");
//  Serial.print(daysOfTheWeek[dayOfTheWeek(p)]);
  Serial.print(") ");
  Serial.print(hour(p));
  Serial.print(':');
  Serial.print(minute(p));
  Serial.print(':');
  Serial.print(second(p));
  Serial.println();

 //Serial.println(String(hour(p))+":"+String(minutes(p))+":"+String(second(p)));
 
  rtcs =  second(p);
  rtcmin = minute(p);
  rtchr = hour(p);
  rtcy = year(p);
  rtcm = month(p);
  rtcd = day(p);
}

// ***********************End of Code -- you are DONE!*******************************

The comment on the first line is completely wrong. One loop run sleeps for 8 seconds (as SLEEP_8S selects), so the complete loop sleeps for 6128 = 576 seconds so about 9 and a half minutes.

Because you didn't tell us what sleeping time you actually get I guess it's that error you experienced.

Ah my bad dude, it has been changed to 12 minutes which is what it was meant to be . Thank you for that calculation though! even if it is 9 and a half minutes, it seems to add on a minute odd every time it sleeps, unsure why...

The "8 second sleep" uses the watchdog timer, and its frequency can be off by up to about 10%.

If you need accurate sleep times in the range of minutes add an RTC to your project and wait for it's interrupt to wake from sleep.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.