I now have a code for my sensors! but

I now have a code for my sensors which works by taking readings every 15 minutes, for 5 minutes.

However, i cannot seem to actually turn off the power of the sensors with just digitalWrite function..

Is there a way to actually adjust power to the sensors through the pins without turning off the whole arduino, so that they can start back up after 12 minutes to warm up, take readings after 15 minutes of being on, then turn off after the 5 minute data reading period (20 mins total)?

Here is my code:

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

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

//- Print PM data to CSV 
//- Turn PM & VOC pins off after 20 mins 
//- Calibrate BME
//- Calibrate VOC sensor (potentiometer on back adjusts zero threshold)



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




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

//Real Time Clock
RTC_DS1307 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

uint32_t delayMS;

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

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


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 {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t unused;
  uint16_t checksum;
} pms5003dataStruct;

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

  // Declaring VOC variables
  int a;
  int b;


void setup() {

  // TVOC Setup
  pinMode(Aout, INPUT); //Analog output of TVOC
  pinMode(Dout, INPUT); //Digital output of TVOC
//  digitalWrite(Aout,LOW);
//  digitalWrite(Dout,LOW);
//  
//  
//  //PM Setup
//  pinMode(2, INPUT);
//  digitalWrite(2,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);


//RTC begin
  if (! rtc.begin()) {
    Serial.println(F("Couldn't find RTC"));
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println(F("RTC is NOT running!"));
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2020, 12, 16, 10, 36, 0));
  }

//delay(1000);

//Find PM sensor
  // if (! aqi.begin_I2C()) {      // connect to the sensor over I2C
  //if (! aqi.begin_UART(&Serial1)) { // connect to the sensor over hardware serial
  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() {
  
//  LowPower.deepSleep(eventInterval);   // Sets the Arduino Board to take a deep sleep for 15 minutes.
  //if ( millis() > event_1 ){ //I think this is for doing more than 1 event at the same time 

//  if((currentTime - startTime) >= 20000)
    
//    Serial.print((currentTime - startTime), "\n" );


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

  digitalWrite(Aout,HIGH);
  digitalWrite(Dout,HIGH);
  digitalWrite(3,HIGH);
  delay(10);
  //Serial.println(millis());
  unsigned long i=millis();
  while ((long)((i+readingInterval)-millis())>=0){
  //Get the values of the sensors
  GetRTC_Readings();
  GetVOC_Readings();
  GetPM_Readings();
  GetBME_Readings();

  // Store the three sensor values to the SD card.
  //print2SD();
  //if((long)((i+readingInterval)-millis())<5000){
  //  break;
  //}
  Serial.println((long)((i+readingInterval)-millis()));
  delay(5000);
  }
     digitalWrite(Aout,LOW);
     digitalWrite(Dout,LOW);
     digitalWrite(3,LOW);
     
  startTime = millis()+ eventInterval;  
  
 }
}

 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*****************************/
  PM25_AQI_Data data;
  
//  if (! aqi.read(&data)) {
//    Serial.println(F("Could not read from AQI"));
//    delay(500);  // try again in a bit!
//    return;
//  }
  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(rtcs); 
    dataFile.print(":");              
    dataFile.print(rtchr);
    dataFile.print(":");             
    dataFile.print(rtcmin);
    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 ************/
 // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  DateTime now = rtc.now();

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

  //Serial.print(" since midnight 1/1/1970 = ");
  //Serial.print(now.unixtime());
  //Serial.print("s = ");
  //Serial.print(now.unixtime() / 86400L);
  //Serial.println("d");


  //DateTime now = rtc.now();
  rtcs = now.second();
  rtcmin = now.minute();
  rtchr = now.hour();
  rtcy = now.year();
  rtcm = now.month();
  rtcd = now.day();


}

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

Please provide a schematic of the project. Show all components, their values and/or part numbers and all power supplies.

Depending on how much power all those sensors require, you may have to have a transistor between +5V and all the sensors that is controlled by a digital pin on your arduino. If you use a PNP transistor, it will be on by default and your code will have to turn it off when you are done with your readings.

Note, code like this
startTime = millis()+ eventInterval;

is NOT the proper way of dealing with elapsed time. The only way to properly deal with unsigned values like millis() is subtraction. If your code runs for a long time, millis() will eventually overflow and your code will break.

elapsedTime = millis() - startTime;
if ( elapsedTime >= desiredInterval ) {
  // do something
  startTime = millis();
}
1 Like

Here is my schematic, excuse the laughable drawing sorry i have not had time to get used to online schematics, i am still pretty new and self taught. I had help with this code though.

Schematic: note that MS1100 pin D0 is now D7 & PMS5003 pin A2 is actually D3

See sensors below
plantower-pms5003-manual_v2-3.pdf (761.2 KB)
MS1100-ETC.pdf (433.6 KB)
BST-BME280-DS002-1509607.pdf (1.4 MB)

Thank you! Would it be okay for 1 week?