Gravity: Factory Calibrated Electrochemical Oxygen / O2 Sensor (0-25%Vol, I2C & UART)
I have the sensor hooked up to a UART on a Pic32 microcontroller. The sensor will send data for several hours and then just stop. The only way to fix the problem is to power cycle the sensor. I have looked at the data lines with an oscilloscope and can see that the pic is requesting data but there is no reply from the sensor. Power cycle just the sensor and it starts working again. Has anyone else had this problem?
Here is the code
void task_dfrobot_sensor(void *pvParameters){
/* skipping some initialization */
while(1)
{
if (DFR_MODE == DFROBOT_SETTING_QA_MODE)
{
vTaskDelayUntil( &pxPreviousWakeTime, 1000 / portTICK_PERIOD_MS);
} else {
vTaskDelay( 600 / portTICK_PERIOD_MS);
}
if (DFR_INTERVAL == 0) { continue; }
switch (ro_state)
{
case RO_INIT:
df_err = _open_driver(&df_handle, uart_num);
df_handle.mode = DFR_MODE;
if (df_err == DFROBOT_SUCCESS)
{
ro_state = RO_MODE;
}
else
{
_send_no_sensor(uart_num);
}
break;
case RO_MODE:
_send_info_msg(uart_num, "RO_MODE state"); /* debug code */
_flush_uart(uart_num);
df_err = DFROBOT_set_mode(&df_handle, DFR_MODE);
if (df_err == DFROBOT_SUCCESS)
{
ro_state = RO_SENS_TYPE;
missed_reading_cnt = 0;
break;
}
else if (df_err == DFROBOT_ERR_TIMEOUT)
{
_send_no_sensor(uart_num);
}
else
{
_send_err(uart_num, df_err);
}
if (_missed_cnt_over_max(&missed_reading_cnt))
{
ro_state = RO_PWR_CYCL_SENS;
}
break;
case RO_SENS_TYPE:
_flush_uart(uart_num);
if (DFR_MODE == DFROBOT_SETTING_ACTIVE_MODE) {
df_err = DFROBOT_read_gas_temp(&df_handle, &gas_type, &gas, &temp);
} else {
df_err = DFROBOT_read_gas(&df_handle, &gas_type, &gas);
}
if (df_err == DFROBOT_SUCCESS)
{
/* different sensors can be set to different intervals */
itrvl_idx = _get_intrvl_indx(gas_type);
ro_state = RO_RUN;
missed_reading_cnt = 0;
break;
}
else if (df_err == DFROBOT_ERR_TIMEOUT)
{
_send_no_sensor(uart_num);
DFROBOT_set_mode(&df_handle, DFR_MODE);
}
else
{
_send_err(uart_num, df_err);
}
if (_missed_cnt_over_max(&missed_reading_cnt))
{
ro_state = RO_PWR_CYCL_SENS;
}
break;
case RO_RUN:
_flush_uart(uart_num);
if (DFR_MODE == DFROBOT_SETTING_ACTIVE_MODE) {
df_err = DFROBOT_read_gas_temp(&df_handle, &gas_type, &gas, &temp);
} else {
df_err = DFROBOT_read_gas(&df_handle, &gas_type, &gas);
}
if (df_err)
{
_send_err(uart_num, df_err);
if (df_err == DFROBOT_ERR_TIMEOUT)
{
_send_no_sensor(uart_num);
}
if (_missed_cnt_over_max(&missed_reading_cnt))
{
ro_state = RO_PWR_CYCL_SENS;
}
break;
} else {
/* Add reading to buffer for median filter */
avg_filter_push_float (&rbuff, gas);
missed_reading_cnt = 0;
}
if ((next_send_time - xTaskGetTickCount()) < DFR_INTERVAL)
{
break;
}
if( !avg_filt_get_median_float(&rbuff, &gas) ) /* filter out any outliers */
{
_send_gas(gas_type, gas);
_check_limits(gas_type, gas);
}
next_send_time = xTaskGetTickCount() + DFR_INTERVAL;
break;
case RO_PWR_CYCL_SENS:
_send_info_msg(uart_num, "STATE - RO_PWR_CYCL_SENS");
_ms_delay(100);
_sens_pwr_cycl(uart_num);
ro_state = RO_MODE;
break;
default:
break;
}
}
}
DFROBOT_ERR DFROBOT_read_gas(DFROBOT_s *handle, int *gas_type, float *gas)
{
DFROBOT_ERR err;
uint8_t read_msg[DFROBOT_BUFF_LEN];
/* if in QA mode then request the reading */
err = _request_gas(handle);
if (err != DFROBOT_SUCCESS)
{
return err;
}
handle->delay(50);
// wait for response
err = _read_and_verify(handle, read_msg, DFROBOT_BUFF_LEN);
if (err != DFROBOT_SUCCESS)
{
return err;
}
// passive response
// 0xFF, 0x86, gas high, gas low, gas type, decimal places, 0, 0, check sum
// check command type
if (read_msg[1] != 0x86)
{
return DFROBOT_ERR_SENSOR;
}
*gas_type = read_msg[4];
float temp;
/* reusing this. temp will get set to 0.0 */
err = _extract_gas_temp(read_msg, gas, &temp);
if (err != DFROBOT_SUCCESS) return err;
return DFROBOT_SUCCESS;
}
STATIC DFROBOT_ERR _request_gas(DFROBOT_s *handle)
{
uint8_t buff[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
buff[8] = _check_value(buff, DFROBOT_BUFF_LEN);
return _write(handle, buff, DFROBOT_BUFF_LEN);
}
/**
* @brief Takes the full buffer of data returned from the sensor. From this
* the gas values and temperature value are calculated and returned.
*
* Note: the temperature value has not been implemented.
*
* @param buff
* @param gas
* @param temp - always 0.0
* @return STATIC
*/
STATIC DFROBOT_ERR _extract_gas_temp(uint8_t *buff, float *gas, float *temp)
{
uint8_t gas_high = buff[2];
uint8_t gas_low = buff[3];
uint8_t resolution = buff[5];
*gas = _calc_gas(gas_high, gas_low, resolution);
if (*gas == -555.5) /* calc_gas returns this exact value if there was an error */
{
return DFROBOT_ERR_SENSOR;
}
/* have not implemented the temperature calculation */
*temp = 0.0;
return DFROBOT_SUCCESS;
}
STATIC float _calc_gas(uint8_t gas_high, uint8_t gas_low, uint8_t resolution)
{
uint16_t ugas = (gas_high << 8) | gas_low;
float fgas = (float)ugas;
float res = 0.0;
switch (resolution)
{
case DFROBOT_GAS_1:
res = 1.0f;
break;
case DFROBOT_GAS_0_1:
res = 0.1f;
break;
case DFROBOT_GAS_0_01:
res = 0.01;
break;
default:
return -555.5;
break;
}
return fgas * res;
}
/**
* @brief Takes the entire 9 byte buffer and calculates the checksum
*
* @param buff
* @param len
* @return uint8_t checksum
*/
STATIC uint8_t _check_value(uint8_t *buff, int len)
{
int j;
uint8_t tempq = 0;
buff++;
for (j=0; j<(len-3); j++)
{
tempq += *buff;
buff++;
}
return (~tempq) + 1;
}
Hi,
My sensor is not connecting.
I get NO Deivces !
NO Deivces !
NO Deivces !
NO Deivces !
NO Deivces !
NO Deivces !
NO Deivces !
I am using the code below:
#include "DFRobot_MultiGasSensor.h"
//Enabled by default, use IIC communication at this time. Use UART communication when disabled
#define I2C_COMMUNICATION
#ifdef I2C_COMMUNICATION
#define I2C_ADDRESS 0x74
DFRobot_GAS_I2C gas(&Wire ,I2C_ADDRESS);
#else
#if (!defined ARDUINO_ESP32_DEV) && (!defined __SAMD21G18A__)
/**
UNO:pin_2-----RX
pin_3-----TX
*/
SoftwareSerial mySerial(22,21);
DFRobot_GAS_SoftWareUart gas(&mySerial);
#else
/**
ESP32:IO16-----RX
IO17-----TX
*/
DFRobot_GAS_HardWareUart gas(&Serial2); //ESP32HardwareSerial
#endif
#endif
void setup() {
Serial.begin(115200);
while(!gas.begin())
{
Serial.println("NO Devices !");
delay(1000);
}
Serial.println("The device is connected successfully!");
gas.changeAcquireMode(gas.PASSIVITY);
delay(1000);
gas.setTempCompensation(gas.OFF);
}
void loop() {
Serial.print("Ambient ");
Serial.print(gas.queryGasType());
Serial.print(" concentration is: ");
Serial.print(gas.readGasConcentrationPPM());
Serial.println(" %vol");
//The measurement unit will only be %vol when the sensor is SEN0465
//Otherwise the unit will be PPM
Serial.print("The board temperature is: ");
Serial.print(gas.readTempC());
Serial.println(" ℃");
Serial.println();
delay(1000);
}
My connectivity is:
O2 sensor -> FireBeetle ESP32
D/T -> GPIO 21
C/R -> GPIO 22
- -> GND
+ -> 3.3V
dydmarcoHi,
I am seeing a similar failure using IC2 ("QWIIC" Connect) on a Sparkfun Redboard (arduino uno), using the same (?) DF Robot O2 Sensor:
https://www.dfrobot.com/product-2052.html
The arduino is using 2 separate sensors: CO2 and O2, logging data to an SD Card.
The O2 has been working, and then just stopped (returning zero always).
The CO2 sensor from Sensiron continues to work fine.
Wiring is straightforward in that both sensors are connected via I2C ("QWIIC") connections.
O2 was and has been working fine and now just reports zero values.
Error Detection in setup() (see below) does not indicate a failure to connect, so it seems things are connected ok.
// CODE BELOW
#include<SPI.h>#include "DFRobot_OxygenSensor.h" // for the O2 sensor#include "SdFat.h"#include <Wire.h> // for CO2 sensor#include "SparkFun_SCD30_Arduino_Library.h" // for CO2 sensor Click here to get the library: http://librarymanager/All#SparkFun_SCD30SCD30 co2Sensor; // a handle for CO2 sensor
/*** i2c slave Address, The default is ADDRESS_3.* ADDRESS_0 0x70 i2c device address.* ADDRESS_1 0x71* ADDRESS_2 0x72* ADDRESS_3 0x73*/
#define Oxygen_IICAddress ADDRESS_3
#define COLLECT_NUMBER 10 // collect number, the collection range is 1-100.
//
// GLOBALS
//
DFRobot_OxygenSensor oxygenSensor; // a handle for the O2 sensorunsigned short CO2Data;float humidityData;float airTemp;SdFat Sd;File dataFile;
//
// SETUP FUNCTION
//
void setup(){ Serial.begin(9600);
// SD SETUP while (!Sd.begin(8)) { Serial.println("aaa"); delay(1); }
Serial.println(F("SD OK"));
// O2 SETUPwhile(oxygenSensor.begin(Oxygen_IICAddress) == false ) // keep checking while O2 is not responding{Serial.println("O2 Sensor Error");delay(1000); // pause for 1 sec before we try again}
// CO2 SETUPWire.begin();while (co2Sensor.begin() == false) // keep checking while CO2 is not responding{Serial.println("CO2 sensor Error.");delay(1000); // pause for 1 sec before we try again}
// OK - both sensors seem ok...
} // end setup()
//
// LOOP FUNCTION
//
void loop(void){
if (co2Sensor.dataAvailable()) // if co2 sensor has data for us.... { dataFile=Sd.open("datalog.csv", FILE_WRITE); CO2Data=co2Sensor.getCO2(); airTemp=co2Sensor.getTemperature(); humidityData=co2Sensor.getHumidity(); //get and print CO2 ppm data, along with temp and humidity (from theSensirion CO2 sensor) Serial.print("co2(ppm):"); Serial.print(CO2Data); Serial.print(","); // add a comma so the serial plotter will display Serial.print("temp(C):"); Serial.print(airTemp); Serial.print(","); // add a comma so the serial plotter will display Serial.print("humidity(%):"); Serial.print(humidityData); Serial.print(","); // add a comma so the serial plotter will display // now we can get the oxygen data (by volume) float oxygenData = oxygenSensor.getOxygenData(COLLECT_NUMBER); // get O2 data by %volume Serial.print("O2(%vol):"); // update for Serial Plotter
Serial.println(oxygenData); // !!!!!! FAILURE OCCURS HERE: WE ONLY GET ZERO VALUES (ALWAYS) AFTER PRIOR CORRECT VALUES (~24%)
dataFile.close(); } // end CO2 check (contains o2 check)
delay(1000); // pause for 1 sec so sensors can sample again (increase to slow down sampling
} // end loop() function
ubaccaHi!
Will the two problematic sensors output normal values when they are powered on again?
For SEN0322:
You can try recalibrating the sensor via the button on the sensor with the example code. (on the Arduino UNO)
There could be errors in the software code that interacts with the sensor, leading to communication issues. For instance, if the sensor and the microcontroller are not synchronized correctly, it might result in data loss or communication failures.
bidrohini.bidrohiniHi!
Sorry to hear this.
What environment does the sensor work in? What is the sensor powered by?
Thanks for more details.
jenna