maarten-pennings / CCS811

Arduino library for the CCS811 gas sensor for monitoring indoor air quality.
MIT License
165 stars 46 forks source link

How To: use multiple CJMCU-8110 #47

Closed KapakoProf closed 4 years ago

KapakoProf commented 4 years ago

Hi, I am rather new in programming and wonder how to compact the code I wrote for using a flexible number of CJMCU-8110 connected to my NodeMCU. In the attached test code below I have 2 connected, but in the near future I want to expand to 3 or 4 and would like to drive that by a variable (f.i. int SensorNumber = 2) instead of duplicating the code for each sensor.

Who can guide me to a solution?

#include <Arduino.h>
#include <Wire.h>    // I2C library
#include "ccs811.h"  // CCS811 library
#include "ClosedCube_HDC1080.h"

CCS811 ccs811_1;
CCS811 ccs811_2;

ClosedCube_HDC1080 HDC1080_1;
ClosedCube_HDC1080 HDC1080_2;

int SDApin;
int SCLpin = D1;

HDC1080_SerialNumber sernum;
char format[12];
bool vBootphase = true;
uint16_t eco2, etvoc, errstat, raw;

void setup() {Serial.begin(115200); while(!Serial){;}}

void loop() 
{
  if (vBootphase == true)
  {
    // Channel 1: Setup
    SDApin = D2;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.println("");
    Serial.println("*** CCS1 ***");
    Serial.print("CCS :");
    ccs811_1.set_i2cdelay(50);
    ccs811_1.begin();
    delay(500);
    ccs811_1.start(CCS811_MODE_1SEC);
    delay(1000);
    Serial.print("setup: hardware    version: "); Serial.println(ccs811_1.hardware_version(),HEX);
    Serial.print("setup: bootloader  version: "); Serial.println(ccs811_1.bootloader_version(),HEX);
    Serial.print("setup: application version: "); Serial.println(ccs811_1.application_version(),HEX);
    // HDC1080
    HDC1080_1.begin(0x40);
    Serial.print("Manufacturer ID=0x");
    Serial.println(HDC1080_1.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments
    Serial.print("Device ID=0x");
    Serial.println(HDC1080_1.readDeviceId(), HEX); // 0x1050 ID of the device
    Serial.print("Device Serial Number=");
    sernum = HDC1080_1.readSerialNumber();
    sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast);
    Serial.println(format);

    // Channel 2: Setup
    SDApin = D6;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.println("*** CCS2 ***");
    // Print CCS811 versions
    Serial.print("CCS2 :");
    ccs811_2.set_i2cdelay(50);
    ccs811_2.begin();
    delay(500);
    ccs811_2.start(CCS811_MODE_1SEC);
    delay(1000);
    Serial.print("setup: hardware    version: "); Serial.println(ccs811_2.hardware_version(),HEX);
    Serial.print("setup: bootloader  version: "); Serial.println(ccs811_2.bootloader_version(),HEX);
    Serial.print("setup: application version: "); Serial.println(ccs811_2.application_version(),HEX);
    // HDC1080
    HDC1080_2.begin(0x40);
    Serial.print("Manufacturer ID=0x");
    Serial.println(HDC1080_2.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments
    Serial.print("Device ID=0x");
    Serial.println(HDC1080_2.readDeviceId(), HEX); // 0x1050 ID of the device
    Serial.print("Device Serial Number=");
    sernum = HDC1080_2.readSerialNumber();
    sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast);
    Serial.println(format);

    vBootphase = false;
  }
  else
  {
    // Channel 1
    SDApin = D2;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.print("\nSensor connected on: ");
    Serial.print("SDA - ");Serial.print(SDApin); Serial.print(" | SCL - ");Serial.print(SCLpin);
    Serial.print("\n");
    ccs811_1.read(&eco2,&etvoc,&errstat,&raw);
    delay(500);
    Serial.print("ErrStat: ");Serial.print(errstat);Serial.print(" | ");Serial.println(ccs811_1.errstat_str(errstat));
    if(!errstat==CCS811_ERRSTAT_OK) 
    {
      Serial.print("CCS811-1: ");
      Serial.println("Failed to read from sensor");
      ccs811_1.begin();
      delay(500);
      ccs811_1.start(CCS811_MODE_1SEC);
    }
    else
    { 
      Serial.print("CCS811-1: ");
      Serial.print("eco2=");    Serial.print(eco2);     Serial.print(" ppm | ");
      Serial.print("etvoc=");   Serial.print(etvoc);    Serial.print(" ppb");
      Serial.print("\n");
    }
    // ** HDC1080 **
    Serial.print("T="); Serial.print(HDC1080_1.readTemperature()); Serial.print("C");
    Serial.print(", RH="); Serial.print(HDC1080_1.readHumidity()); Serial.println("%");

    // Channel 2
    SDApin = D6;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.print("Sensor connected on: ");
    Serial.print("SDA - ");Serial.print(SDApin); Serial.print(" | SCL - ");Serial.print(SCLpin);
    Serial.print("\n");
    ccs811_2.read(&eco2,&etvoc,&errstat,&raw);
    delay(500);
    Serial.print("ErrStat: ");Serial.print(errstat);Serial.print(" | ");Serial.println(ccs811_2.errstat_str(errstat));
    if(errstat!=CCS811_ERRSTAT_OK) 
    {
      Serial.print("CCS811-2: ");
      Serial.println("Failed to read from sensor");
      ccs811_1.begin();
      delay(500);
      ccs811_2.start(CCS811_MODE_1SEC);
    }
    else
    { 
      Serial.print("CCS811-2: ");
      Serial.print("eco2=");    Serial.print(eco2);     Serial.print(" ppm | ");
      Serial.print("etvoc=");   Serial.print(etvoc);    Serial.print(" ppb");
      Serial.print("\n");
    }
    // ** HDC1080 **
    Serial.print("T="); Serial.print(HDC1080_1.readTemperature()); Serial.print("C");
    Serial.print(", RH="); Serial.print(HDC1080_1.readHumidity()); Serial.println("%");

    delay(10000);
  }
}

20200514_PostedCode.txt

maarten-pennings commented 4 years ago

There are two problems. The first problem, the one you ask, is a software design problem "how to avoid duplication of code". What I would suggest is to create an array of ccs811 objects. That way you can simply loop over them.

The second problem is a hardware problem. I2C devices have an address. On one I2C bus every address can only occur once! The ccs811 helps a bit: there is an io pin you can pull high or low and with that you can select between two addresses. In short one I2C bus has max two ccs811s.

KapakoProf commented 4 years ago

Thanks Maarten. I have changed my code to use an array and now loop the code which is single available. While I do not have enough pins available (other sensors and muxes) yo create multiple I2C busses I now share the SCL pin between 4 css811 and have 2 different pins for SDA which are set in the loop. Works perfect. May be I eventually will end up in using multiple NodeMCU, but for now it is ok. Thanks.