Combined sensors HELP!

Hello,

I am trying to code this sensor, well 3 sensors, (Grove PM2.5 Sensor, CJMCU-MS1100 TVOC sensor and BME280 TPH sensor together with a relay module) to take readings every 15 minutes, for 5 minutes (3 readings/hour), using the relay module. I understand i must use Millis() function and equation to create timed events. However, i am still very much a novice with code and have no idea how to integrate all codes for each sensor into one, with the relay and timed events.

Here is the code:

---------------------TPH, PM2.5 AND TVOC SENSOR WITH SD DATA LOG-------------------------//
//This sensor measures Temperature, Pressure, Humidity, Particulates <0.1 microns and Total Volotile Organic Compounds//

//--------------------------------------------------------------------------------------------
//                                          LIBRARIES
//--------------------------------------------------------------------------------------------

#include <SPI.h>             // library for SD logging
#include <SD.h>
#include "RTClib.h"
#include <BME280I2C.h>       //BME Sensor 
#include <RTClib.h>          // library for the Real Time Clock
#include <Seeed_HM330X.h>   //Grove PM2.5 Sensor


//--------------------------------------------------------------------------------------------
//                                           DEFINES
//--------------------------------------------------------------------------------------------


#define Aout A0              //TVOC Pins
#define Dout 2


const int chipSelect = 10;   // pin 10 for SD shield

const int pingPin = 7;       // something


File DataFile;               //create a file to store data

BME280I2C bme;               //TPH sensor

RTC_DS1307 rtc;              //RTC

#ifdef  ARDUINO_SAMD_VARIANT_COMPLIANCE // Grove PM2.5 Sensor
    #define SERIAL_OUTPUT SerialUSB
#else
    #define SERIAL_OUTPUT Serial
#endif


const unsigned long eventInterval = 900000; //Assign the time in millis for event interval (every 15 minutes)
unsigned long previousTime = 0;           //Set previous time to 0 so that it can be subtracted from event interval in void loop

int relay in 1 = 9;                            //Relay = pin 9
int relay in 2 = 8;                            //Relay = pin 8

volatile byte relayState = LOW;           //Relay is off (LOW voltage) until event begins
long debounceDelay = 300000;             //Keep relay on for 5 minutes?? unsure if this will work without

const char* str[] = {"sensor num: ", "PM1.0 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM2.5 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM10 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM1.0 concentration(Atmospheric environment,unit:ug/m3): ",
                     "PM2.5 concentration(Atmospheric environment,unit:ug/m3): ",
                     "PM10 concentration(Atmospheric environment,unit:ug/m3): ",
                    };
                    
//--------------------------------------------------------------------------------------------
//                                            SETUP
//--------------------------------------------------------------------------------------------

void setup() {
  
  pinMode(10,OUTPUT);      //Setup for Relay
  pinMode(Aout,INPUT);     // Setup for VOC
  pinMode(Dout,INPUT);


  Serial.begin(115200);  //initializing Serial monitor

  // setup for the RTC
  while (!Serial);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  else {
    //set RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
  }

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

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

  // setup for the SD card
  Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  //open file
  DataFile = SD.open("Data.txt", FILE_WRITE);

  // if the file opened ok, write to it:
  if (DataFile) {
    Serial.println("File opened ok");
    // print the headings for data
    DataFile.println("Date,Time,dBA");
  }
  DataFile.close();
}


HM330XErrorCode print_result(const char* str, uint16_t value) {
    if (NULL == str) {
        return ERROR_PARAM;
    }
  SERIAL_OUTPUT.print(str);
  SERIAL_OUTPUT.println(value);
  return NO_ERROR;
}

/*parse buf with 29 uint8_t-data*/
HM330XErrorCode parse_result(uint8_t* data) {
    uint16_t value = 0;
    if (NULL == data) {
        return ERROR_PARAM;
    }
    for (int i = 1; i < 8; i++) {
        value = (uint16_t) data[i * 2] << 8 | data[i * 2 + 1];
        print_result(str[i - 1], value);

    }

    return NO_ERROR;
}

HM330XErrorCode parse_result_value(uint8_t* data) {
    if (NULL == data) {
        return ERROR_PARAM;
    }
    for (int i = 0; i < 28; i++) {
        SERIAL_OUTPUT.print(data[i], HEX);
        SERIAL_OUTPUT.print("  ");
        if ((0 == (i) % 5) || (0 == i)) {
            SERIAL_OUTPUT.println("");
        }
    }
    uint8_t sum = 0;
    for (int i = 0; i < 28; i++) {
        sum += data[i];
    
    if (sum != data[28]) {
        SERIAL_OUTPUT.println("wrong checkSum!!!!");
    }
    SERIAL_OUTPUT.println("");
    return NO_ERROR;
}
//--------------------------------------------------------------------------------------------
//                                            FUNCTIONS
//--------------------------------------------------------------------------------------------

void loggingTime() ;
  DateTime now = rtc.now();
  DataFile = SD.open("Data.txt", FILE_WRITE);
  if (DataFile) {
    DataFile.print(now.year(), DEC);
    DataFile.print('/');
    DataFile.print(now.month(), DEC);
    DataFile.print('/');
    DataFile.print(now.day(), DEC);
    DataFile.print(',');
    DataFile.print(now.hour(), DEC);
    DataFile.print(':');
    DataFile.print(now.minute(), DEC);
    DataFile.print(':');
    DataFile.print(now.second(), DEC);
    DataFile.print(",");
  }
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.println(now.day(), DEC);
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.println(now.second(), DEC);
  DataFile.close();
  delay(800);
}

void loggingBME()  ;

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

File dataFile = SD.open("Data.txt", FILE_WRITE);
if (DataFile) {
  dataFile.print(corr_temp);             dataFile.print(",Temperature,");
  dataFile.print(corr_preshpa);             dataFile.print(",Pressure,");
  dataFile.print(corr_hum);             dataFile.print(",Humidity,");
    delay(1000);
       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 data.txt");
  }
  }


void loggingVOC()  ;

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

  File dataFile = SD.open("Data.txt", FILE_WRITE);
  if (DataFile) {
    dataFile.print(b);             dataFile.print(",TVOC Digital,");
    dataFile.print(a);             dataFile.println(",TVOC Analogue");
    delay(1000);
       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 data.txt");
  }

void loggingPM();  {

HM330X sensor;
uint8_t buf[30];


const char* str[] = {"sensor num: ", "PM1.0 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM2.5 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM10 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM1.0 concentration(Atmospheric environment,unit:ug/m3): ",
                     "PM2.5 concentration(Atmospheric environment,unit:ug/m3): ",
                     "PM10 concentration(Atmospheric environment,unit:ug/m3): ",
                    };
                    
 
   // delay(100);
    SERIAL_OUTPUT.println("Serial start");
    if (sensor.init()) {
        SERIAL_OUTPUT.println("HM330X init failed!!!");
        while (1);
    }
 if (sensor.read_sensor_value(buf, 29)) {
        SERIAL_OUTPUT.println("HM330X read result failed!!!");
    }
    parse_result_value(buf);
    parse_result(buf);
    SERIAL_OUTPUT.println("");
}

//File dataFile = SD.open("Data.txt", FILE_WRITE);
if (DataFile) {
  dataFile.print(str);             dataFile.print(",Temperature,");
  dataFile.println(value);             dataFile.print("PM1.0 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM2.5 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM10 concentration(CF=1,Standard particulate matter,unit:ug/m3): ",
                     "PM1.0 concentration(Atmospheric environment,unit:ug/m3): ",
                     "PM2.5 concentration(Atmospheric environment,unit:ug/m3): ",
                     "PM10 concentration(Atmospheric environment,unit:ug/m3): ");
    delay(1000);
       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 data.txt");
  }
  }
  

//--------------------------------------------------------------------------------------------
//                                         MAIN LOOP
//--------------------------------------------------------------------------------------------

void loop() ;

 /* Updates frequently */
  unsigned long currentTime = millis();

  /* This is the event */
  if (currentTime - previousTime >= eventInterval) {
    /* Event code */
    digitalWrite(relaye, HIGH) ;
    
   /* Update the timing for the next time around */
    previousTime = currentTime;
  
  loggingTime();
  loggingDecibels();
  loggingBME();
  loggingVOC();
  loggingGrove();
  
  delay(1000);
}



//-------------------------END-------------------------//

I am also getting the error message a lot:
" Combined_Sensors_HenryLayout:213:4: error: 'bme' does not name a type
bme.read(pres, temp, hum, tempUnit, presUnit);
^~~
Combined_Sensors_HenryLayout:220:7: error: 'Serial' does not name a type
Serial.print("Temp: ");
^~~~~~
Combined_Sensors_HenryLayout:221:4: error: 'Serial' does not name a type
Serial.print(corr_temp);
^~~~~~
Combined_Sensors_HenryLayout:222:4: error: 'Serial' does not name a type
Serial.print("°"+ String(tempUnit == BME280::TempUnit_Celsius ? 'C' :'F'));
^~~~~~
Combined_Sensors_HenryLayout:223:4: error: 'Serial' does not name a type
Serial.print("\t\tHumidity: ");
^~~~~~
Combined_Sensors_HenryLayout:224:4: error: 'Serial' does not name a type
Serial.print(corr_hum);
^~~~~~
Combined_Sensors_HenryLayout:225:4: error: 'Serial' does not name a type
Serial.print("% RH");
^~~~~~
Combined_Sensors_HenryLayout:226:4: error: 'Serial' does not name a type
Serial.print("\t\tPressure: ");
^~~~~~
Combined_Sensors_HenryLayout:227:4: error: 'Serial' does not name a type
Serial.print(corr_preshpa);
^~~~~~
Combined_Sensors_HenryLayout:228:4: error: 'Serial' does not name a type
Serial.println(" hPa");
^~~~~~
Combined_Sensors_HenryLayout:231:1: error: expected unqualified-id before 'if'
if (DataFile) {
^~
Combined_Sensors_HenryLayout:242:3: error: expected unqualified-id before 'else'
else {
^~~~
Combined_Sensors_HenryLayout:245:3: error: expected declaration before '}' token
}
^
exit status 1
'bme' does not name a type "

It is probably how I have structured the code, but again, I am not sure as I am so new to C++ and coding in general.

Here is a picture of my connections, am I right in having my ground pins from the sensors connected to the normally closed pins on the relay, and the VCC pins from the sensors connected to the common pins on the relay?

Connections:

BME280 soldered to the 5V GND SDA SCL pins on RTC stack)
5V - Pin A2
GND - Pin A3
SDA - Pin A4
SCL - Pin A5

CJMCU-MS1100
GND - Relay NC pin
DOUT - Pin D2
AOUT - Pin A0
VCC - Relay COM pin

Grove PM2.5 HM-3300/3600 Dust Sensor
GND - Relay NC pin
VCC - Relay COM pin
SDA - SDA pin
SCL - SCL pin

2 Channel Relay
GND - GND pin
IN 1 - pin 9
IN 2 - pin 8
VCC - VCC pin

If anyone is able to help me code this correctly, to the correct hardware pins with the relay and produce the timed events required, I would be eternally grateful!!!!

Is anyone able to help me out? I know this code is also messy (well, looks like it to me) so any advice on clearer structure of code would be amazing too!

Hardware and Datasheets below:

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

Grove PM2.5 Laser Sensor.pdf (744.8 KB)

MS1100-ETC.pdf (433.6 KB)

Thank you,
Callum. :dragon_face: :uk:


void loggingTime() ;
  DateTime now . rtcnow();
  DataFile = SD.open("Data.txt", FILE_WRITE);
  if (DataFile) {
    DataFile.print(now.year(), DEC);

That's not how to write a function.
In your code you have setup() coded correctly, then many other functions are completely wrong syntax (including the loop function).

You have to follow the language rules exactly everywhere, you can't just guess!

1 Like

Include a schematic, not a frizzy thing. switching the ground of the sensors is a very bad practice. I would try to work with each sensor/actuator one at a time and write code to control and or read them. You will be much better equipped to put all of them in one piece of code.

1 Like

Thank you both. I have been set this task to complete by the end of July with no help/previous knowledge of coding or this hardware, so it is pretty difficult. I appreciate your help and honesty.

I was thinking i need to go back and start sensor by sensor so i will do this.

Cheers!

Good idea. Write a separate sketch for each sensor - the library examples should help. Then combine them one by one.

2 Likes

Absolutely, top advice. You never want to be in a situation where you combine any components (hw or sw) you haven't individually tested. You certainly never want to combine many untested components.

2 Likes

Thanks for letting us know we are glad we were able to help. We are here if you need help. Remember the only bad question is the one that does not get asked. We realize people ask questions about something they are not sure of that is why they ask. Yes they will sometimes get terms wrong.

1 Like