Chat freely about anything...

User avatar
By Oscar Fuentes
#91038 Hi, I am doing my final degree project but but i'm stuck with the dust sensor.

In my project I must use the ESP12-E NodeMcu board and three sensors, temperature and humidity (DHT22), VOC's (CCS811) and particles (PPD42).

When I use only the PPD42 sensor the returned values are correct (range 0 - 1000), but when when I connect the three sensors + wifi, the values are either 0 or they are too large (+1,000,000).

Could you help me?



Code: Select all#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266mDNS.h>
#include <WiFiManager.h>
#include <DHT.h>
#include <Wire.h>

#include "SparkFunCCS811.h" //Click here to get the library: http://librarymanager/All#SparkFun_CCS811
#define CCS811_ADDR 0x5A //Alternate I2C Address

//SEND_DATA
const char* serverName = "http://****";
String serial_numb = "****";
//SEND_DATA

//CCS811
CCS811 myCCS811(CCS811_ADDR);
float CCS811_CO2 = 0;
float CCS811_tVOC = 0;
//CCS811

//for LED status
#include <Ticker.h>
Ticker ticker;

//PPD42
//Set variables for PM10 and PM2,5 readings
 unsigned long starttime;

unsigned long triggerOnP1;
unsigned long triggerOffP1;
unsigned long pulseLengthP1;
unsigned long durationP1;
boolean valP1 = HIGH;
boolean triggerP1 = false;

unsigned long triggerOnP2;
unsigned long triggerOffP2;
unsigned long pulseLengthP2;
unsigned long durationP2;
boolean valP2 = HIGH;
boolean triggerP2 = false;

float ratioP1 = 0;
float ratioP2 = 0;
unsigned long sampletime_ms = 30000;
float countP1;
float countP2;
float concLarge = 0;
float concSmall = 0;
//PPD42

//DHT22
#define PIN_CONEXION D3// A cuál pin está conectado el lector
#define TIPO_SENSOR DHT22 // Puede ser DHT11 también
DHT dht(PIN_CONEXION, TIPO_SENSOR);
float DHThumid, DHTtempC = 0;
//DHT22
 
#ifndef LED_BUILTIN
#define LED_BUILTIN 13 // ESP32 DOES NOT DEFINE LED_BUILTIN
#endif

int LED = LED_BUILTIN;

void tick()
{
  //toggle state
  digitalWrite(LED, !digitalRead(LED));     // set pin to the opposite state
}

//gets called when WiFiManager enters configuration mode
void configModeCallback (WiFiManager *myWiFiManager) {
  Serial.println("Entered config mode");
  Serial.println(WiFi.softAPIP());
  //if you used auto generated SSID, print it
  Serial.println(myWiFiManager->getConfigPortalSSID());
  //entered config mode, make led toggle faster
  ticker.attach(0.2, tick);
}

void setup() {
  wifi();
  setup_CSS811();
}

void wifi() {
  WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
  // put your setup code here, to run once:
  Serial.begin(115200);
 
  //set led pin as output
  pinMode(LED, OUTPUT);
  // start ticker with 0.5 because we start in AP mode and try to connect
  ticker.attach(0.6, tick);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wm;
  //reset settings - for testing
  // wm.resetSettings();

  //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
  wm.setAPCallback(configModeCallback);

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  if (!wm.autoConnect("wifi")) {
    Serial.println("failed to connect and hit timeout");
    //reset and try again, or maybe put it to deep sleep
    ESP.restart();
    delay(1000);
  }

  //if you get here you have connected to the WiFi
  Serial.println("connected...yeey :)");
  ticker.detach();
  //keep LED on
  digitalWrite(LED, LOW);
}

void loop() {
  run_PPD42();
  run_CSS811();
  senddata();
  delay(30000);
}

void setup_CSS811()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("Apply DHT22 data to CCS811 for compensation.");

  Wire.begin();

  //This begins the CCS811 sensor and prints error status of .beginWithStatus()
  CCS811Core::CCS811_Status_e returnCode = myCCS811.beginWithStatus();
  Serial.print("CCS811 begin exited with: ");
  Serial.println(myCCS811.statusString(returnCode));
  //Calling .begin() causes the settings to be loaded
  delay(10); //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up.
  dht.begin();
}
void run_CSS811()
{
  //Check to see if data is available
  if (myCCS811.dataAvailable())
  {
    //Calling this function updates the global tVOC and eCO2 variables
    myCCS811.readAlgorithmResults();
    //printInfoSerial fetches the values of tVOC and eCO2
    printInfoSerial();

    DHTtempC = dht.readTemperature();
    DHThumid = dht.readHumidity();
   
    Serial.print("Applying new values (ªC, Humedad): ");
    Serial.print(DHTtempC);
    Serial.print(",");
    Serial.println(DHThumid);
    Serial.println();

    //This sends the temperature data to the CCS811
    myCCS811.setEnvironmentalData(DHThumid, DHTtempC);
  }
  else if (myCCS811.checkForStatusError())
  {
    //If the CCS811 found an internal error, print it.
    printSensorError();
  }

}

void printInfoSerial()
{
  //getCO2() gets the previously read data from the library
  Serial.println("CCS811 data:");
  Serial.print(" CO2 concentration : ");
  CCS811_CO2 = myCCS811.getCO2();
  Serial.print(CCS811_CO2);
  Serial.println(" ppm");

  //getTVOC() gets the previously read data from the library
  Serial.print(" TVOC concentration : ");
  CCS811_tVOC = myCCS811.getTVOC();
  Serial.print(CCS811_tVOC);
  Serial.println(" ppb");

  Serial.println("DHT22 data:");
  Serial.print(" Temperatura: ");
  Serial.print(dht.readTemperature(), 2);
  Serial.println(" ºC");

  Serial.print(" Humedad: ");
  Serial.print(dht.readHumidity(), 2);
  Serial.println("%");

  Serial.println();
}

void printSensorError()
{
  uint8_t error = myCCS811.getErrorRegister();

  if (error == 0xFF) //comm error
  {
    Serial.println("Failed to get ERROR_ID register.");
  }
  else
  {
    Serial.print("Error: ");
    if (error & 1 << 5)
      Serial.print("HeaterSupply");
    if (error & 1 << 4)
      Serial.print("HeaterFault");
    if (error & 1 << 3)
      Serial.print("MaxResistance");
    if (error & 1 << 2)
      Serial.print("MeasModeInvalid");
    if (error & 1 << 1)
      Serial.print("ReadRegInvalid");
    if (error & 1 << 0)
      Serial.print("MsgInvalid");
    Serial.println();
  }
}

void run_PPD42()
{
  valP1 = digitalRead(14);
  valP2 = digitalRead(12);
 
  if(valP1 == LOW && triggerP1 == false){
    triggerP1 = true;
    triggerOnP1 = micros();
  }
 
  if (valP1 == HIGH && triggerP1 == true){
      triggerOffP1 = micros();
      pulseLengthP1 = triggerOffP1 - triggerOnP1;
      durationP1 = durationP1 + pulseLengthP1;
      triggerP1 = false;
  }
 
    if(valP2 == LOW && triggerP2 == false){
    triggerP2 = true;
    triggerOnP2 = micros();
  }
 
    if (valP2 == HIGH && triggerP2 == true){
      triggerOffP2 = micros();
      pulseLengthP2 = triggerOffP2 - triggerOnP2;
      durationP2 = durationP2 + pulseLengthP2;
      triggerP2 = false;
  }
 
   
    if ((millis() - starttime) > sampletime_ms) {
     
      ratioP1 = durationP1/(sampletime_ms*10.0);  // Integer percentage 0=>100
      ratioP2 = durationP2/(sampletime_ms*10.0);
      countP1 = 1.1*pow(ratioP1,3)-3.8*pow(ratioP1,2)+520*ratioP1+0.62;
      countP2 = 1.1*pow(ratioP2,3)-3.8*pow(ratioP2,2)+520*ratioP2+0.62;
      float PM10count = countP2;
      float PM25count = countP1 - countP2;
     
      // first, PM10 count to mass concentration conversion
      double r10 = 2.6*pow(10,-6);
      double pi = 3.14159;
      double vol10 = (4.0/3.0)*pi*pow(r10,3);
      double density = 1.65*pow(10,12);
      double mass10 = density*vol10;
      double K = 3531.5;
      concLarge = (PM10count)*K*mass10;
     
      // next, PM2.5 count to mass concentration conversion
      double r25 = 0.44*pow(10,-6);
      double vol25 = (4.0/3.0)*pi*pow(r25,3);
      double mass25 = density*vol25;
      concSmall = (PM25count)*K*mass25;
     

      Serial.print("PM10=");
      Serial.print(concLarge);
      Serial.print(", PM25=");
      Serial.println(concSmall);
   
      durationP1 = 0;
      durationP2 = 0;
      starttime = millis();
    }
}

void senddata(){
//Check WiFi connection status
  if(WiFi.status()== WL_CONNECTED){
    HTTPClient http;
   
    // Your Domain name with URL path or IP address with path
    http.begin(serverName);
   
    // Specify content-type header
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
   
    // Prepare your HTTP POST request data
    String httpRequestData = "serial_numb=" + serial_numb + "&DHTtempC=" + String(DHTtempC)
                          + "&DHThumid=" + String(DHThumid) + "&CCS811_CO2=" + String(CCS811_CO2) + "&CCS811_tVOC=" + String(CCS811_tVOC) + "&PM10=" + String(concLarge) + "&PM25=" + String(concSmall) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);
   
   
    int httpResponseCode = http.POST(httpRequestData);
     
   
       
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
  }
  else {
    Serial.println("WiFi Disconnected");
  }
}
User avatar
By davydnorris
#91040 Several things to check here:
- each of the boards may have I2C pull up resistors on them and when you connect them all, the total resistance is too low. Try connecting one by one and see if that changes anything. You may need to remove some of the pull ups from one or more of the boards
- check the I2C bus addresses to make sure they aren't sharing the same address and change if necessary
- the CCS811 requires I2C clock stretch. Make sure you're using a recent Arduino core that includes that capability

In short, try connecting each one at a time and get each one working individually. Then connect two at a time and make sure they still work. Then three.
User avatar
By Oscar Fuentes
#91048
davydnorris wrote:Several things to check here:
- each of the boards may have I2C pull up resistors on them and when you connect them all, the total resistance is too low. Try connecting one by one and see if that changes anything. You may need to remove some of the pull ups from one or more of the boards
- check the I2C bus addresses to make sure they aren't sharing the same address and change if necessary
- the CCS811 requires I2C clock stretch. Make sure you're using a recent Arduino core that includes that capability

In short, try connecting each one at a time and get each one working individually. Then connect two at a time and make sure they still work. Then three.


I have found the problem, if I put // in the void loop delay (delay (30000);) it works fine, but the other sensors measure too fast (I need measurements every 30sec). It has something to do with the variable unsigned long sampletime_ms = 30000;
User avatar
By Oscar Fuentes
#91049
Oscar Fuentes wrote:
davydnorris wrote:Several things to check here:
- each of the boards may have I2C pull up resistors on them and when you connect them all, the total resistance is too low. Try connecting one by one and see if that changes anything. You may need to remove some of the pull ups from one or more of the boards
- check the I2C bus addresses to make sure they aren't sharing the same address and change if necessary
- the CCS811 requires I2C clock stretch. Make sure you're using a recent Arduino core that includes that capability

In short, try connecting each one at a time and get each one working individually. Then connect two at a time and make sure they still work. Then three.


I have found the problem, if I put // in the void loop delay (delay (30000);) it works fine, but the other sensors measure too fast (I need measurements every 30sec). It has something to do with the variable unsigned long sampletime_ms = 30000;


Any idea how to fix it?