Would anyone be willing to mentor me and help me with my indoor air quality sensors project?

I am a student who needs help with a project which needs to be due like next week. Already 2 weeks late. I haven't coded before this project, which i started in May this year, and as much as i love learning how to programme i just don't see myself solving this.

If anyone is willing to help over zoom/teams/in person, for free or for ££$$, I would be eternally grateful and be one step further to starting something great here. Which you could be a part of!

Thank you,
Callum.

I can't promise that my assistance will be of any help, but what are you trying to accomplish? What are you hoping to measure/what sensors do you have? Once that is known, we could assist you better.

I am trying to monitor Indoor Air Quality for domestic settings for literally 1 Week with low-cost environmental sensors, by measuring the following parameters: Temperature, Pressure, Humidity (TPH); Total Volatile Organic Compounds (TVOC); Particulate Matter (PM).

Using the following sensors: BME280 (TPH), CJMCU-MS1100 (TVOC) and PMS5003 (PM). (data sheets attached).

Then log the data with the SD and RTC data logger shield which stacks onto my UNO. Eventually i would like to programme all sensors to take readings every 15 minutes, for 5 minutes and log to the SD. Doing this is another hurdle but i get i can use millis() somehow to do this, especially for the TVOC sensor as it is a hot plate method and can take like 3 minutes to heat up and gather accurate readings. My project should hopefully implement 10 sensors in 10 homes to get data for indoor air quality, which can add to current research in the field.

Of course, the codes work Individually, but when putting them together in the format i have the values do not come back. I feel it may be a memory and/or stability issue as the RTC and SD libraries and code takes up around 48% RAM/memory. But even when i comment those out of the combined code i still can't get readings back which are correct for just one sensor alone.

I am sure this can be done but I don't have the skills to do this as i am a beginner. Posting code and explanations on the forum is great but takes a while compared to over a call, hence why i have asked this lovely community if that could be possible.

BST-BME280-DS002-1509607.pdf (1.4 MB)

MS-1100.pdf (557.0 KB)

plantower-pms5003-manual_v2-3.pdf (761.2 KB)

I'm currently at work, quietly wasting time. Calling could happen later, though. If I had to guess, you are able to get individual sensors to work, but when you connect the plantower PMS5003 to pins 0 and 1 for serial communication, things stop working. These are your serial pins, and they can only handle one thing. If this is the case, you can use software serial to switch the pins that this sensor is plugged into. If you post your code and wiring diagram, I can take a look now and come up with a possible solution to go over later.

I have a similar project.

I am using 2 BME680's and a Waveshare Dust Sensor Detector Module with Sharp GP2Y1010AU0F.

Two weeks, no way.

You are going to need to establish a Index value to use for AIQ. To do that you will want to use a time of the year in the early spring after a rain, clean air kind of day/night. Then you will take measurements on that 'perfect' evening. I did 50 readings over 50 hours. Average them together and record that number. You should get 4 or 5 index measured index values. I used the pick the lowest resistance number from all the readings. You will want to record the date and time and location of when the index value was recorded.

Just getting the Index value will take up 1/2 the project.

I can give you my code I wrote but its for an ESP32 using the freeRTOS OS. Your on your own.

The calculation of the IAQ is done on my RPi in Python. I originally ported the Python calculation for IAQ from C++, it should be easy for you to port back.

Sorry, I cannot be of more help.

I have programmed it to use Pin D2 over software serial already. See my diagram attached (sorry for this drawing, haven't started doing schematics online yet..). see code at end


//********************Start of code for TPH sensor***********************

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

#include "RTClib.h"

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

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

// Temp, pressure, humidity sensor.
Adafruit_BME280 bme;
// Real time clock.
RTC_DS1307 rtc;
// Particular Matter sensor.
SoftwareSerial pmsSerial(2,3);
Adafruit_PM25AQI aqi = Adafruit_PM25AQI();
// TVOC Sensor - come back to this

uint32_t delayMS;

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;

void setup() {

  // TVOC Setup
  pinMode(Aout, INPUT); //Analog output of TVOC
  pinMode(Dout, INPUT); //Digital output of TVOC

  // Open serial communications and wait for port to open:
  //Serial.begin(9600);

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

  
  // sensor baud rate is 9600
  pmsSerial.begin(9600);
  
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  
  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled

    // 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));
  } else
    Serial.println("RTC ready.");
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  delay(1000);

     // 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("Could not find PM 2.5 sensor!");
    while (1) delay(10);
  }

  Serial.println("PM25 found!");


  while (!bme.begin(0x76)){
    Serial.println("Could not find BME280 sensor!");
    delay(1000);
  }
  Serial.println("BME sensor ready.");


  Serial.println("Initializing SD card...");

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

void loop() {

  //if ( millis() > event_1 ){

  /*******************GET PLANTPOWER PM***********************************/
  boolean ret = readPMSdata(&pmsSerial);
 Serial.println(ret);
  if (ret) {
    // reading data was successful!
     
//      Serial.println("---------------------------------------");
//      Serial.println("Concentration Units (standard)");
//      Serial.print("PM 1.0: "); Serial.print(pms5003dataStruct.pm10_standard);
//      Serial.print("\t\tPM 2.5: "); Serial.print(pms5003dataStruct.pm25_standard);
//      Serial.print("\t\tPM 10: "); Serial.println(pms5003dataStruct.pm100_standard);
      Serial.println("---------------------------------------");
      Serial.println("Concentration Units (environmental)");
      Serial.print("PM 1.0: "); Serial.print(pms5003dataStruct.pm10_env);
      Serial.print("\t\tPM 2.5: "); Serial.print(pms5003dataStruct.pm25_env);
      Serial.print("\t\tPM 10: "); Serial.println(pms5003dataStruct.pm100_env);
      Serial.println("---------------------------------------");
//      Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(pms5003dataStruct.particles_03um);
//      Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(pms5003dataStruct.particles_05um);
//      Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(pms5003dataStruct.particles_10um);
//      Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(pms5003dataStruct.particles_25um);
//      Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(pms5003dataStruct.particles_50um);
//      Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(pms5003dataStruct.particles_100um);
//      Serial.println("---------------------------------------");
    

  }

//  /*********GET VOC ************/
//  int a = analogRead(Aout);
//  int b = digitalRead(Dout);
//  Serial.print("D0:");
//  Serial.print(b);
//  Serial.print("   A0:");
//  Serial.println(a);
//
//
//  /*****************Get Temp, Pressure and Humidity********************/
//
//
//  float temp;
//  float pres; 
//  float hum;

//  temp = bme.readTemperature();
//  pres = bme.readPressure();
//  hum = bme.readHumidity();
//  
// /*
//  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);
//
//  float preshpa = (pres / 100); //create space for conversion of pascals to hectopascals (hPa) which is more usual measure
//  float corr_temp = (temp - 0.0); //create space for correction of temperature according to unique sensor validation (will be different for each sensor)
//  float corr_hum = (hum + 0); //create space for correction of humidity according to unique sensor validation (will be different for each sensor)
//  float corr_preshpa = (preshpa + 10); //create space for correction of pressure according to unique sensor validation (will be different for each sensor)
// 
//    Serial.print("Temp: ");
//  Serial.print(corr_temp);
//    Serial.print("°" + String(tempUnit == BME280::TempUnit_Celsius ? 'C' : 'F'));
//    Serial.print("\t\tHumidity: ");
//    Serial.print(corr_hum);
//    Serial.print("% RH");
//    Serial.print("\t\tPressure: ");
//    Serial.print(corr_preshpa);
//    Serial.println(" hPa");
//  */
//  /*********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();
//
//
//  /*********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.txt", FILE_WRITE);
//
//
//  // if the file is available, write to it:
//  if (dataFile) {
//
//    //dataFile.print(cm);        dataFile.print(",CM,");
//    dataFile.print(rtchr);              dataFile.print(":");
//    dataFile.print(rtcmin);             dataFile.print(":");
//    dataFile.print(rtcs);               dataFile.print(",TIME,");
//    dataFile.print(rtcd);               dataFile.print("/");
//    dataFile.print(rtcm);               dataFile.print("/");
//    dataFile.print(rtcy);             dataFile.print(",DATE,");
//    dataFile.print(temperature);             dataFile.print(",Temperature,");
//    dataFile.print(pressure);             dataFile.print(",Pressure,");
//    dataFile.print(humidity);             dataFile.println(",Humidity");
//    dataFile.print(b);             dataFile.print(",TVOC Digital,");
//    dataFile.print(a);             dataFile.println(",TVOC Analogue");
//    dataFile.print(pms5003dataStruct.particles_10um);             dataFile.print(",PM 10um,");
//    dataFile.print(pms5003dataStruct.particles_25um);             dataFile.print(",PM 25um,");
//    dataFile.print(pms5003dataStruct.particles_100um);             dataFile.println(",PM 100um");
//    //delay(899270);
//    delay(5000);
//    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("error opening datalog.txt");
// }


  delay(2000);
}


boolean readPMSdata(Stream *s) {
  Serial.println(s->available());
  if (! s->available()) {
    return false;
  }

  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }

  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }

  uint8_t buffer[32];
  uint16_t sum = 0;
  s->readBytes(buffer, 32);

  // get checksum ready
  for (uint8_t i = 0; i < 30; i++) {
    sum += buffer[i];
  }

  /* debugging
    for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
    }
    Serial.println();
  */

  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i = 0; i < 15; i++) {
    buffer_u16[i] = buffer[2 + i * 2 + 1];
    buffer_u16[i] += (buffer[2 + i * 2] << 8);
  }

  // put it into a nice struct :)
  memcpy((void *)&pms5003dataStruct, (void *)buffer_u16, 30);

  if (sum != pms5003dataStruct.checksum) {
    Serial.println("Checksum failure");
    return false;
  }
  // success!
  return true;
}

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

this is me trying to get one sensor working without SD. I can find the sensors just not get values or true values from them. an error which is frequent is 'checksum error' , from the PMS5003.

Ok so i have done it i think. I just now need to turn the sensors on and off at certain times of the day/every 15 minutes for 5 minutes.

Would it be wise to use transistors for ease of voltage/current regulation?

My code:

//********************Start of code for TPH sensor***********************

#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(2,3);
Adafruit_PM25AQI aqi = Adafruit_PM25AQI();

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

uint32_t delayMS;

//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;



void setup() {

  // TVOC Setup
  pinMode(Aout, INPUT); //Analog output of TVOC
  pinMode(Dout, INPUT); //Digital output of TVOC

  // 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!"));
  }


//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."));
}





void loop() {

  //if ( millis() > event_1 ){


  /*********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();


  /*****************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);

  float preshpa = (pres / 100); //create space for conversion of pascals to hectopascals (hPa) which is more usual measure
  float corr_temp = (temp - 0.0); //create space for correction of temperature according to unique sensor validation (will be different for each sensor)
  float corr_hum = (hum + 0); //create space for correction of humidity according to unique sensor validation (will be different for each sensor)
  float 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"));


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

/******************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("---------------------------------------"));
  


}
  delay(5000);
  
  /*********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(rtchr);              dataFile.print(":");
    dataFile.print(rtcmin);             dataFile.print(":");
    dataFile.print(rtcs);               dataFile.print(",TIME,");
    dataFile.print(rtcd);               dataFile.print("/");
    dataFile.print(rtcm);               dataFile.print("/");
    dataFile.print(rtcy);             dataFile.print(",DATE,");
    dataFile.print(corr_temp);             dataFile.print(",Temperature,");
    dataFile.print(corr_preshpa);             dataFile.print(",Pressure,");
    dataFile.print(corr_hum);             dataFile.println(",Humidity");
    dataFile.print(b);             dataFile.print(",TVOC Digital,");
    dataFile.print(a);             dataFile.println(",TVOC Analogue");
    dataFile.print(pms5003dataStruct.particles_10um);             dataFile.print(",PM 10um,");
    dataFile.print(pms5003dataStruct.particles_25um);             dataFile.print(",PM 25um,");
    dataFile.print(pms5003dataStruct.particles_100um);             dataFile.println(",PM 100um");
    delay(2000);
    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);
}


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

Lets say you use a thingy as power management for a sensor.

So you program loop to enable and disable power to the sensors. When those sensors power up do they need to be configured? How will you cause the sensors to reconfigure after power up?

You said that you need a hot plate turned on for TVOC measurements - for safety it may be wise to use a relay to turn this on and off and a thermistor to ensure it reaches the correct temperature before taking your measurement. If the rest of the project is plugged into the wall I wouldn't worry about current draw. I'm not sure about the other two sensors, but I think the BME is about 25uA which isn't worth powering down. If you want this on a battery for a full year, that may be a different story.

One thing about measuring time (from what I have been told here); millis() tends to drift over long periods, so your 15 minute window may vary. You should instead use the RTC as it is much more accurate and you've already got it.

I don't think they do every time. I will calibrate them against higher quality sensors until they are correct, pilot test them for a week and then do it again for the real thing at some point. So, if they do need to be reconfigured after each power up, ill have to figure out a way to do that or ill have to find a new project aha

Someone did mention a relay before. However, doesnt that need to be powered up too and take up more power?

It will be powered using a powerbank/ some sort of battery unless unsafe to do so. They will get tested for power draw once i understand how to turn them all on and off as needed, then the battery size will be decided and the data collection period (i want a week at least) may have to be altered too. Then they will also get tested for safety.

Thank you for the advice with millis() too! I will work out how to use the RTC for this.

A relay has essentially the same function as a transistor; you power it to turn it on and allow current to flow across it. So yes, it does require power to turn it on, but so would a transistor. I believe the current draw is pretty low for relays. The main difference here would be that you can get relays for mains power, which you likely need for your heating plate. This comes with the usual cautions - this involves wiring mains power, which can kill you. If you are at all uncomfortable with doing it, you should definitely find someone who knows what they are doing. If your heating plate requires something less than mains voltage, cool. But it almost definitely requires more power than your powerbank will provide. Transistors are generally useful at low power, then come MOSFETs. These can handle more current than transistors, but do generate a lot of heat. A relay uses the 5v input from a microcontroller (make sure you get one controllable by 5v) to physically close a circuit (they click when they turn on). This reduces heat and allows a lot more power to be run through it. You will have to check the power for the heat plate and get a relay with specifications that exceed that.

For the 5v power, a powerbank is great. These are usually Li-ion batteries, regulated to 5v and with a battery management system included. Like I said, current draw for most sensors and the Arduino is pretty low, so you should be able to go a long time without depleting the battery. That is a theoretical battery lifetime, your actual mileage may vary.

Awesome. I ordered a few of these and have them with me so I can get started with that straight away: http://www.handsontec.com/dataspecs/2Ch-relay.pdf

This would make it quite easier to turn the sensors on and off too, than it would with transistors or MOFSETs right?

I would just leave the sensors on the 5v rail for simplicity, or use the built in transistors in the Arduino and provide 5v by setting the IO pins high when you want to take a measurement for battery longevity.

The relays would only be needed for your heating plate as it requires higher voltage/current (I'm still assuming here, but generally true for heating elements).

The hot plate is integrated in the TVOC sensor, no need for additional components.

I'm really surprized you aren't thinking to measure CO2 for indoor air quality?

So I can just use it as it is? would transistors make it easier to regulate when I want the sensors to be
on/off?

I am measuring CO2 with another Keystudio VOC & CO2 sensor

You can use the MS-1100 as it is. As for transistors powering/unpowering sensors

  • your document on the MS-1100 specifies a preheat-time of 3-5 minutes after power up;
  • some sensors, e.g. the BME280, require a setup; you would need to do this setup after each power up.