Send sensor data from scd30 over wifi

Hi Guys,

My first post here so sorry if any of the formatting is off.

I am basing my project from before made examples for scd30 measurements, for the sending part i am basing it on DHT11 to thinger.io post made here

my first goal was to get serial print working then to move on the WiFi part :).

I can provide the circuit board drawings or anything more needed

Anyhow i am trying to send the data from scd30 sensor over WiFi using esp12f. But there is an issue.
I cannot seem to be able to connect to the WiFi because of time syncing. Does anyone know how to fix this issue i tried to google for answers but i came up short. I know the best would be to avoid delays everywhere but in some cases it is not possible to do so i believe.

Thank You for Your help :slight_smile:

#include <Adafruit_SCD30.h>
#define THINGER_SERIAL_DEBUG
#define DEBUG

#include <ThingerESP8266.h>
#include "arduino_secrets.h"

ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);

Adafruit_SCD30  scd30;

void setup(void) {
  Serial.begin(115200);
  //delay(1000);
  //while (!Serial) delay(10);     // will pause Zero, Leonardo, etc until serial console opens
   thing.add_wifi(SSID, SSID_PASSWORD);

  Serial.println("Adafruit SCD30 Sensor adjustment test!");



 thing["scd30"] >> [](pson& out){
    // Add the values and the corresponding code
    out["humidity"] = scd30.relative_humidity;
    out["celsius"] = scd30.temperature;
    out["co2"] = scd30.CO2, 3;

 };




  
  // Try to initialize!
  if (!scd30.begin()) {
    Serial.println("Failed to find SCD30 chip");
    while (1) { delay(10); }
  }
  Serial.println("SCD30 Found!");

  /***
   * The code below will report the current settings for each of the
   * settings that can be changed. To see how they work, uncomment the setting
   * code above a status message and adjust the value
   *
   * **Note:** Since Automatic self calibration and forcing recalibration with
   * a reference value overwrite each other, you should only set one or the other
  ***/


  /*** Adjust the rate at which measurements are taken, from 2-1800 seconds */
 if (!scd30.setMeasurementInterval(5)) {
    Serial.println("Failed to set measurement interval");
   while(1){ delay(10);}
  }
  Serial.print("Measurement interval: ");
  Serial.print(scd30.getMeasurementInterval());
  Serial.println(" seconds");


  /*** Restart continuous measurement with a pressure offset from 700 to 1400 millibar.
   * Giving no argument or setting the offset to 0 will disable offset correction
   */
  // if (!scd30.startContinuousMeasurement(15)){
  //   Serial.println("Failed to set ambient pressure offset");
  //   while(1){ delay(10);}
  // }
  Serial.print("Ambient pressure offset: ");
  Serial.print(scd30.getAmbientPressureOffset());
  Serial.println(" mBar");


  /*** Set an altitude offset in meters above sea level.
   * Offset value stored in non-volatile memory of SCD30.
   * Setting an altitude offset will override any pressure offset.
   */
  // if (!scd30.setAltitudeOffset(110)){
  //   Serial.println("Failed to set altitude offset");
  //   while(1){ delay(10);}
  // }
  Serial.print("Altitude offset: ");
  Serial.print(scd30.getAltitudeOffset());
  Serial.println(" meters");


  /*** Set a temperature offset in hundredths of a degree celcius.
   * Offset value stored in non-volatile memory of SCD30.
   */
  // if (!scd30.setTemperatureOffset(1984)){ // 19.84 degrees celcius
  //   Serial.println("Failed to set temperature offset");
  //   while(1){ delay(10);}
  // }
  Serial.print("Temperature offset: ");
  Serial.print((float)scd30.getTemperatureOffset()/100.0);
  Serial.println(" degrees C");


  /*** Force the sensor to recalibrate with the given reference value
   * from 400-2000 ppm. Writing a recalibration reference will overwrite
   * any previous self calibration values.
   * Reference value stored in non-volatile memory of SCD30.
   */
  if (!scd30.forceRecalibrationWithReference(800)){
    Serial.println("Failed to force recalibration with reference");
    while(1) { delay(5); }
   }
  Serial.print("Forced Recalibration reference: ");
  Serial.print(scd30.getForcedCalibrationReference());
  Serial.println(" ppm");


  /*** Enable or disable automatic self calibration (ASC).
   * Parameter stored in non-volatile memory of SCD30.
   * Enabling self calibration will override any previously set
   * forced calibration value.
   * ASC needs continuous operation with at least 1 hour
   * 400ppm CO2 concentration daily.
   */
  // if (!scd30.selfCalibrationEnabled(true)){
  //   Serial.println("Failed to enable or disable self calibration");
  //   while(1) { delay(10); }
  // }
  if (scd30.selfCalibrationEnabled()) {
    Serial.print("Self calibration enabled");
  } else {
    Serial.print("Self calibration disabled");
  }

  Serial.println("\n\n");
}

void loop() {
thing.handle();
 
 if (scd30.dataReady()) {
    
  if (!scd30.read()){ 
     Serial.println("Error reading sensor data"); 
      return; 
    }

    Serial.print("Temperature: ");
    Serial.print(scd30.temperature);
    Serial.println(" degrees C");
    
    Serial.print("Relative Humidity: ");
    Serial.print(scd30.relative_humidity);
    Serial.println(" %");
    
    Serial.print("CO2: ");
    Serial.print(scd30.CO2, 3);
    Serial.println(" ppm");
   
     
    Serial.print("Measurement interval: ");
    Serial.print(scd30.getMeasurementInterval());
    Serial.println(" seconds");
    Serial.println("");
  }

}

Hi,

Which library version have you installed? There was some issues regarding the time sync but them were solved at lastest versions, I have thinger library 2.25.2 and esp8266 3.0.2 and it works, at VSCode thinger 2.25.2 and esp8266 3.1.0 and it works.

Let us know about your developing environment.

Hello,

I am using Thinger.io library version 2.25.2 and esp8266 version 3.0.2.

Please let me know if there is additional info that i need to give :).

I was connected for a short amount of time when i first tried the ESP8266 example but after that it started doing this time sync error

Edit#1: i am basing my testing on ESP8266 to eliminate any possibility of my code being wrong; The error stays the same

It seems to be ok, but Idk why the device is not getting an answer from the ntp server.

Try pinging to “pool.ntp.org”, let us know the answer.

P.D.: Is not necessary to paste an image to show us the answer, paste the text, select all the code or debug answer, and press the “</>” button at the toolbar, so it get code format for easy reading.

This is the result i get from pinging:

Pinging pool.ntp.org [89.212.9.180] with 32 bytes of data:
Reply from 89.212.9.180: bytes=32 time=6ms TTL=58
Reply from 89.212.9.180: bytes=32 time=6ms TTL=58
Reply from 89.212.9.180: bytes=32 time=6ms TTL=58
Reply from 89.212.9.180: bytes=32 time=6ms TTL=58

Ping statistics for 89.212.9.180:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 6ms, Maximum = 6ms, Average = 6ms

For future references this is the code example i am trying to run:

#define THINGER_SERIAL_DEBUG

#include <ThingerESP8266.h>
#include "arduino_secrets.h"

ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);

void setup() {
  // open serial for monitoring
  Serial.begin(115200);

  // set builtin led as output
  pinMode(LED_BUILTIN, OUTPUT);

  // add WiFi credentials
  thing.add_wifi(SSID, SSID_PASSWORD);

  // digital pin control example (i.e. turning on/off a light, a relay, configuring a parameter, etc)
  thing["led"] << digitalPin(LED_BUILTIN);

  // resource output example (i.e. reading a sensor value)
  thing["millis"] >> outputValue(millis());

  // more details at http://docs.thinger.io/arduino/
}

void loop() {
  thing.handle();
}

Now i got a new error, not sure if its a step in the right direction:

22:12:44.708 -> [NETWORK] Starting connection...
22:12:44.708 -> [NETWORK] Connecting to network ********
22:13:14.687 -> [NETWORK] Cannot connect!

i really appreciate Your help :slight_smile: and im sorry for bothering with this

EDIT#1

I tried running this code:

#include "ESP8266WiFi.h"

const char* ssid = ""; //Enter SSID
const char* password = ""; //Enter Password

void setup(void)
{ 
  Serial.begin(115200);
  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
     delay(500);
     Serial.print("*");
  }
  
  Serial.println("");
  Serial.println("WiFi connection Successful");
  Serial.print("The IP Address of ESP8266 Module is: ");
  Serial.print(WiFi.localIP());// Print the IP address
}

void loop() 
{
  // EMPTY
}

It still does not connect, this code worked before :frowning:

I am lost sorry

EDIT#2: I couldnt sleep so one restart of pc router and esp board later i ran the same example code:

22:44:27.803 -> [NETWORK] Connected!
22:44:27.803 -> [_SOCKET] Connecting to iot.thinger.io:25202...
22:44:27.803 -> [_SOCKET] Using secure TLS/SSL connection: yes
22:44:27.803 -> [NTP_SYN] Waiting for NTP time sync from: pool.ntp.org

So back to square 1 im afraid :(, will call the ISP tomorrow if they can reset something

Hi,

If you have doubt from your ISP, you can share internet from your cellphone and code its shared network, so the device will connect across the mobile service, not the local ISP.

But is weird that sometimes it gets connection and sometimes does not.

hello,

Good news, we had a storm here and the network crashed. After the resets it connected successfully.

The example that is i will try to run my code once again.

For anyone in the same position as me try to restart the network and it might resolve the issue.

i will let You know if any data is sent to the Thinger.io

Hello,

Good news but a follow up question

So my board is connected to the thingerio, i am getting data with serial write but on the device API i get only 0, did i do something wrong?

This is my code:

/*
  Reading CO2, humidity and temperature from the SCD30
  By: Nathan Seidle
  SparkFun Electronics
  Date: May 22nd, 2018
  License: MIT. See license file for more information but you can
  basically do whatever you want with this code.

  Feel like supporting open source hardware?
  Buy a board from SparkFun! https://www.sparkfun.com/products/15112

  This example gets the SCD30's settings using the new getSettingValue function (thank you paulvha)

  Hardware Connections:
  Attach RedBoard to computer using a USB cable.
  Connect SCD30 to RedBoard using Qwiic cable.
  Open Serial Monitor at 115200 baud.
*/
#define THINGER_SERIAL_DEBUG

#include <ThingerESP8266.h>
#include "arduino_secrets.h"
#define DEBUG
#include <Wire.h>
ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);

#include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30
SCD30 airSensor;
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1000;



void setup()
{
    Serial.begin(115200);
    Serial.println("SCD30 Example");
    Wire.begin();
    startMillis = millis(); 
    //Start sensor using the Wire port, but disable the auto-calibration
    if (airSensor.begin(Wire, false) == false)
    {
        Serial.println("Air sensor not detected. Please check wiring. Freezing...");
        while (1)
            ;
    }

    uint16_t settingVal; // The settings will be returned in settingVal
    
   //////////////////////////////////////////////////////////////////////////////////////// 
    //DEKLERACIJA REFERENC
    airSensor.setAutoSelfCalibration(false); //Najprej izklop avto kalibracije
    airSensor.setMeasurementInterval(10); //definicija časa med meritvam
    airSensor.setTemperatureOffset(0);  //referenca za temperaturo   
    airSensor.setAltitudeCompensation(181); //Novo mesto cca 181m
    airSensor.setForcedRecalibrationFactor(800); //referenca za co2
   
    ///////////////////////////////////////////////////////////////////////////////////


    thing.add_wifi(SSID, SSID_PASSWORD);
    
    thing["scd30"] >> [](pson& out){
      out["vlaznost"] = airSensor.getHumidity(), 1;
      out["temp"] = airSensor.getTemperature(), 1;
      out["co2"] = airSensor.getCO2();
}; 

    
    if (airSensor.getForcedRecalibration(&settingVal) == true) // Get the setting
    {
      Serial.print("Forced recalibration factor (ppm) is ");
      Serial.println(settingVal);
    }
    else
    {
      Serial.print("getForcedRecalibration failed! Freezing...");
      while (1)
        ; // Do nothing more
    }
  
    if (airSensor.getMeasurementInterval(&settingVal) == true) // Get the setting
    {
      Serial.print("Measurement interval (s) is ");
      Serial.println(settingVal);
    }
    else
    {
      Serial.print("getMeasurementInterval failed! Freezing...");
      while (1)
        ; // Do nothing more
    }

    if (airSensor.getTemperatureOffset(&settingVal) == true) // Get the setting
    {
      Serial.print("Temperature offset (C) is ");
      Serial.println(((float)settingVal) / 100.0, 2);
    }
    else
    {
      Serial.print("getTemperatureOffset failed! Freezing...");
      while (1)
        ; // Do nothing more
    }

    if (airSensor.getAltitudeCompensation(&settingVal) == true) // Get the setting
    {
      Serial.print("Altitude offset (m) is ");
      Serial.println(settingVal);
    }
    else
    {
      Serial.print("getAltitudeCompensation failed! Freezing...");
      while (1)
        ; // Do nothing more
    }

    if (airSensor.getFirmwareVersion(&settingVal) == true) // Get the setting
    {
      Serial.print("Firmware version is 0x");
      Serial.println(settingVal, HEX);
    }
    else
    {
      Serial.print("getFirmwareVersion! Freezing...");
      while (1)
        ; // Do nothing more
    }
    
    Serial.print("Auto calibration set to ");
    if (airSensor.getAutoSelfCalibration() == true)
        Serial.println("true");
    else
        Serial.println("false");

      
}

void loop()
{
    thing.handle();
   currentMillis = millis();  
  if (currentMillis - startMillis >= period)  
  {
     if (airSensor.dataAvailable())
    {
        Serial.print("co2(ppm):");
        Serial.print(airSensor.getCO2());

        Serial.print(" temp(C):");
        Serial.print(airSensor.getTemperature(), 1);

        Serial.print(" humidity(%):");
        Serial.print(airSensor.getHumidity(), 1);

        Serial.println();
    }
        
    startMillis = currentMillis;  
  }
    
    
   /* if (airSensor.dataAvailable())
    {
        Serial.print("co2(ppm):");
        Serial.print(airSensor.getCO2());

        Serial.print(" temp(C):");
        Serial.print(airSensor.getTemperature(), 1);

        Serial.print(" humidity(%):");
        Serial.print(airSensor.getHumidity(), 1);

        Serial.println();
    }
    else
        Serial.println("Waiting for new data");

    delay(500); */ 
}

Hi,

Nice that you could achieve the device connect into the cloud.

I would suggest you to use a global variable to store the values, and use that variable into the “thing”.

something like
float hum;

as global variable, and then

hum = airSensor.getHumidity();
Serial.print(" humidity(%):");
Serial.print(hum, 1);

this code does the same, but you keep the last read value into hum

And I would define the resource as:

thing["scd30"] >> [](pson& out){
out["vlaznost"] = hum;
out["temp"] = temp;
out["co2"] = co2;
};

For sure you need to do the same with the other two variables.

Hope this helps.

Hello,

Thank you that worked like a charm :slight_smile:

My final question before clearing up the code and posting it here for anyone else to use would be:

if i want to control the offsets via thinger.io i would need to report them back to the dashboard/API. Going from the provided example the code would be like this ?

thing["co2offset"] << [](pson& in){
    if(in.is_empty()){
        in = airSensor.getForcedRecalibration(&settingVal) == true;
    }
    else{
       airSensor.setForcedRecalibrationFactor(?); = in;
    }
};

Hi,

Maybe something like this could work

thing["co2offset"] << [](pson& in){
    if(in.is_empty()){
        airSensor.getForcedRecalibration(&settingVal);
        in = settingVal;
    }
    else{
       airSensor.setForcedRecalibrationFactor(in);
    }
};

[/quote]

But being honest, I would store the calibration into different variables, because why not? using settingVal as unique resource may be confusing, meanwhile using different variables reduces the confusion probability, I would do as you are doing just if the uC is close to memory lack.

Hope this helps.

Hello,
setingVal is from the libary i am basing my project on for each of the parameters i declared a new variable:

float hum;
float temp;
float Co2;
float co2offset = 800;
float tempoffset = 10;
float nadmvis = 181;
float interval = 10;
bool autocal = false;
  airSensor.setAutoSelfCalibration(autocal); //First we disable autocalibrate
    airSensor.setMeasurementInterval(interval); //time between measurements 
    airSensor.setTemperatureOffset(tempoffset);  //temperature offset
    airSensor.setAltitudeCompensation(nadmvis); //altitude offset
    airSensor.setForcedRecalibrationFactor(co2offset); //co2 offset


So i added the below code to void setup, but if i try to edit it via thinger.io it will reset back to 800,

    float co2offset = 800;
   

 thing["co2 offset"] << [](pson& in){
    if(in.is_empty()){
        co2offset;
        in = co2offset;
    }
    else{
       airSensor.setForcedRecalibrationFactor(in);
    }

also i noticed i can only have either a toggle or a slider for setting values might that play a role?

EDIT#1 i had to comment out setting val as after declaring all of the parameters with variables i received error that it was not captured, no idea what that is about but code seems to work and read fine without it

Hi,

The previous code, did work?

Try this one:

 thing["co2 offset"] << [](pson& in){
    if(in.is_empty()){
        in = co2offset;
    }
    else{
       co2offset = in;
       airSensor.setForcedRecalibrationFactor(co2offset);
    }

This should work without issues.

Yes, you may set values at the remote device with those widgets.

Let me know how it goes.

Hi,

Sorry for the late reply i was on a weekend getaway.

Anyhow the code works like a charm now.

Is there any specific way to post the whole code for anyone else that wants to use it or do i just copy paste the code from IDE

Thank you

Hi,

There is no a particular way or specific format, just paste is as code (with the “</>” button) and that’s it.

What I would recommend is to use an appropriate title, so it can be listed if someone looks for it, also it would be nice a little bit of context, about the creation of your project and the personal experience developing this, besides the technical documentation you want to share.

Thank you for your good will with the forum.