adafruit / adafruit_sgp30 Goto Github PK
View Code? Open in Web Editor NEWArduino library for SGP30
License: Other
Arduino library for SGP30
License: Other
SGP30 Unable to Accept Setting Baseline
Description
Before my board powers down, I want to record the latest baseline in order to restart the sensor with that baseline later and not have to wait for it to recalibrate. I can pull the baseline no problem, but attempting to set the baseline causes the sensor to output the default values of TVOC 0ppb and eCO2 400ppm. These values never change. When I restart the board without setting the baseline values, it works no problem and starts establishing a new baseline like normal.
I would like to believe this is a code issue because I have troubleshooted every possible alternative issue I could think of over the past 6 hours. I also posted this on the forum to no avail.
Repro
#include <Arduino.h>
#include <Wire.h> // I2C library
#include "Adafruit_SGP30.h"
#include "DHT.h"
#include <EEPROM.h>
// Flash Memory addresses
#define SGP_CO2_BASELINE 0
#define SGP_TVOC_BASELINE 1
#define DHT_TYPE DHT22
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
// approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
return absoluteHumidityScaled;
}
// Create sensors
Adafruit_SGP30 sgp;
DHT dht(DHT_PIN, DHT_TYPE);
void setup() {
Serial.begin(115200);
// Enable EEPROM
EEPROM.begin(64); // 64 bytes of memory
// Set up DHT22
dht.begin();
// Set up SGP30
if (! sgp.begin()){
Serial.println("Sensor not found :(");
while (1);
}
// Start at baseline if it exists
uint16_t co2_baseline = EEPROM.read(SGP_CO2_BASELINE);
uint16_t tvoc_baseline = EEPROM.read(SGP_TVOC_BASELINE);
// *** I even tried setting the values manually here with no luck *** <-----
// co2_baseline = 0xEE; //238;
// tvoc_baseline = 0xAF; //175;
Serial.println("Retrieved baselines from memory:");
Serial.print(" eCO2: 0x"); Serial.print(co2_baseline, HEX);
Serial.print(" & TVOC: 0x"); Serial.println(tvoc_baseline, HEX);
if (co2_baseline != NULL && tvoc_baseline != NULL) {
Serial.println("Setting baselines");
sgp.setIAQBaseline(co2_baseline, tvoc_baseline); // <--- If you remove this line, it runs like normal. With it in, it outputs defaults
}
Wire.begin();
delay(3000);
Serial.println("setup: done");
}
int counter = 0;
void loop() {
float rh = dht.readHumidity();
double temp = dht.readTemperature();
sgp.setHumidity(getAbsoluteHumidity(temp, rh));
if (! sgp.IAQmeasure()) {
Serial.println("Measurement failed");
return;
}
Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");
delay(500);
counter++;
if (counter == 30) {
counter = 0;
uint16_t TVOC_base, eCO2_base;
if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
Serial.println("Failed to get baseline readings");
return;
}
Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
EEPROM.write(SGP_CO2_BASELINE, eCO2_base);
EEPROM.write(SGP_TVOC_BASELINE, TVOC_base);
EEPROM.commit();
}
}
Can we add include guards?
#ifndef ADAFRUIT_SGP30_H
#define ADAFRUIT_SGP30_H
/* ... */
#endif ADAFRUIT_SGP30_H
Hello,
I'm not using your library but having a look at your code I noticed that Adafruit_SGP30::softReset has the following issue:
The reset command shouldn't be{ i2c_addr, 0x00, 0x06} but {0x00, 0x06}
I can see 2 quick ways to fix it:
or
What do you think?
Replication:
Outcome:
See:
Adafruit_SGP30/Adafruit_SGP30.cpp
Line 50 in 00569ee
The library for this sensor does call begin()
on the I2C bus.
A library should never call functions like these on a shared medium without explicit call to do so.
A library should just add support for some sensor or device and should never change things on a shared medium.
This does cause undefined behavior when using the library together with other sensors on the same bus.
If you really need to have it done in the begin
function of your library, then please either add an optional parameter to not call begin or use defines in the code to exclude it.
From the SGP30 doc:
Humidity Compensation
The SGP30 features an on-chip humidity compensation for the air quality signals (CO2eq and TVOC) and sensor raw signals (H2-signal and Ethanol_signal). To use the on-chip humidity compensation an absolute humidity value from an external humidity sensor like the SHTxx is required. Using the “Set_humidity” command, a new humidity value can be written to the SGP30 by sending 2 data bytes (MSB first) and 1 CRC byte. The 2 data bytes represent humidity values as a fixed-point 8.8bit number with a minimum value of 0x0001 (=1/256 g/m3) and a maximum value of 0xFFFF (255 g/m3 + 255/256 g/m3). For instance, sending a value of 0x0F80 corresponds to a humidity value of 15.50 g/m3 (15 g/m3 + 128/256 g/m3).
After setting a new humidity value, this value will be used by the on-chip humidity compensation algorithm until a new humidity value is set using the “Set_humidity” command. Restarting the sensor (power-on or soft reset) or sending a value of 0x0000 (= 0 g/m3) sets the humidity value used for compensation to its default value (0x0B92 = 11.57 g/m3) until a new humidity value is sent. Sending a humidity value of 0x0000 can therefore be used to turn off the humidity compensation.
Facilitating this would be greatly appreciated :)
I use SGP30 together with esp8266.
I noticed that after a few hours of operation, the sensor seems to freeze. The TVOC and eCO2 indications are 60,000. Only the nodemcu reset helps.
Why is this happening?
I noticed one more thing.
Sometimes the sensor after a long operation begins to show high TVOC values over 300 and eCO2 over 800. I know that there are no such values at the measurement site. After the reset NODEMCU already shows the true values.
The library docs / comments clearly state that calling IAQInit is required after the device is started.
https://github.com/adafruit/Adafruit_SGP30/blob/master/Adafruit_SGP30.cpp#L96-L101
This appears to not be the case, it is not required before calling IAQmeasure, as the example sketch shows.
No apparent value change or range change when added to example sketch.
I wonder if it's only required before restoring / setting a new initial baseline etc, which would come before IAQmeasure.
Hi,
I have Issues with the SGP30 after the ESP goes to deep sleep.
The sensor is only getting the same value every time. Even after hours of running.
If I remove the deep sleep and add a simple delay the sensor is working just fine.
My assumption is the sgp.begin() is resetting the sensor.
Is there a way to fix this?
I just got the Adafruit_SGP30 sensor, ran the provided test, and it gives the expected output. Good.
But when I scan the I2C bus I see the 0x58 (this sensor, ok), plus other sensors (ok), plus also a "Device" at 0x00. It is present ONLY when the SGP30 is also present, and absent with any of the other 3 sensors.
I think it should not be there? What is this?
If I set setIAQBaseline, I won't get the dynamic baseline value (always the set value)
Is this normal?
void setup(){
//.....
sgp.setIAQBaseline(100, 100);
}
void loop(){
//Output 100 forever
sgp.getIAQBaseline(co2, tvoc);
}
In the file Adafruit_SGP30.h on lines 58 - 68 the same comment was used 3 times referencing CO2. As a result H2 and Ethanol do not have a comment.
Would adding a soft reset function (Address byte 0x00, Second(data) byte 0x06) be a good idea without causing any issues?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.