SCD4X: Add calibration commands for #1056.

pull/1057/head
Phil Howard 2025-02-21 10:22:36 +00:00
rodzic 9866736ffd
commit cfa3d1d90d
4 zmienionych plików z 90 dodań i 3 usunięć

Wyświetl plik

@ -35,5 +35,25 @@ while True:
time.sleep(1.0)
```
The `measure()` method will return a Tuple containing the CO2 reading, temperature in degrees C and humidity.
The `measure()` method will return a Tuple containing the CO reading, temperature in degrees C and humidity.
## Changing Calibration
By default the SCD41 will perform automatic self calibration, which could lead to drift in readings over time.
You can stop this with `breakout_scd41.set_automatic_self_calibration(False)`.
You can then use force recalibration with a known good CO₂ PPM baseline to calibrate your sensor:
```python
correction_amount = breakout_scd41.scd41_perform_forced_recalibration(target_co2_concentration);
```
`correction_amount` is the resulting correction in CO₂ PPM.
To successfully conduct an accurate forced recalibration, the following steps must be carried out:
1. Operate the SCD4x in a periodic measurement mode for > 3 minutes in an environment with homogenous and constant CO₂ concentration. (read: don't breathe)
2. Stop periodic measurement.
3. Wait 500 ms.
4. Issue the perform_forced_recalibration command.

Wyświetl plik

@ -20,6 +20,10 @@ static MP_DEFINE_CONST_FUN_OBJ_0(scd41_get_data_ready_obj, scd41_get_data_ready)
static MP_DEFINE_CONST_FUN_OBJ_1(scd41_set_temperature_offset_obj, scd41_set_temperature_offset);
static MP_DEFINE_CONST_FUN_OBJ_0(scd41_get_temperature_offset_obj, scd41_get_temperature_offset);
static MP_DEFINE_CONST_FUN_OBJ_1(scd41_perform_forced_recalibration_obj, scd41_perform_forced_recalibration);
static MP_DEFINE_CONST_FUN_OBJ_1(scd41_set_automatic_self_calibration_obj, scd41_set_automatic_self_calibration);
static MP_DEFINE_CONST_FUN_OBJ_0(scd41_get_automatic_self_calibration_obj, scd41_get_automatic_self_calibration);
static MP_DEFINE_CONST_FUN_OBJ_1(scd41_set_sensor_altitude_obj, scd41_set_sensor_altitude);
static MP_DEFINE_CONST_FUN_OBJ_1(scd41_set_ambient_pressure_obj, scd41_set_ambient_pressure);
@ -39,6 +43,10 @@ static const mp_map_elem_t scd41_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_temperature_offset), MP_ROM_PTR(&scd41_set_temperature_offset_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_temperature_offset), MP_ROM_PTR(&scd41_get_temperature_offset_obj) },
{ MP_ROM_QSTR(MP_QSTR_perform_forced_recalibration), MP_ROM_PTR(&scd41_perform_forced_recalibration_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_automatic_self_calibration), MP_ROM_PTR(&scd41_set_automatic_self_calibration_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_automatic_self_calibration), MP_ROM_PTR(&scd41_get_automatic_self_calibration_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_sensor_altitude), MP_ROM_PTR(&scd41_set_sensor_altitude_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_ambient_pressure), MP_ROM_PTR(&scd41_set_ambient_pressure_obj) },
};

Wyświetl plik

@ -88,11 +88,66 @@ mp_obj_t scd41_get_data_ready() {
mp_raise_msg(&mp_type_RuntimeError, READ_FAIL_MSG);
return mp_const_none;
}
// The datasheet doesn't really say *which* bit might be 1 if data is ready...
// so check if the least significant eleven bits are != 0
return data_ready ? mp_const_true : mp_const_false;
}
/*
To successfully conduct an accurate forced recalibration, the following
steps need to be carried out:
1. Operate the SCD4x in a periodic measurement mode for > 3 minutes in an
environment with homogenous and constant CO concentration.
2. Stop periodic measurement. Wait 500 ms.
3. Subsequently issue the perform_forced_recalibration command and
optionally read out the baseline correction. A return value of 0xffff
indicates that the forced recalibration failed.
*/
mp_obj_t scd41_perform_forced_recalibration(mp_obj_t target_co2_concentration_in) {
if(!scd41_initialised) {
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
return mp_const_none;
};
uint16_t frc_correction;
uint16_t target_co2_concentration = mp_obj_get_int(target_co2_concentration_in);
int error = scd4x_perform_forced_recalibration(target_co2_concentration, &frc_correction);
if(error) {
mp_raise_msg(&mp_type_RuntimeError, FAIL_MSG);
}
// FRC correction value in CO₂ ppm or 0xFFFF if the
// command failed. Convert value to CO₂ ppm with: value - 0x8000
// The mp_const_none return and guardrails here are hopefully unecessary
// since it'll throw an error
return frc_correction == 0xffff ? mp_const_none : mp_obj_new_int(frc_correction - 0x8000);
}
mp_obj_t scd41_set_automatic_self_calibration(mp_obj_t asc_enabled) {
if(!scd41_initialised) {
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
return mp_const_none;
};
int error = scd4x_set_automatic_self_calibration(asc_enabled == mp_const_true ? 1u : 0u);
if(error) {
mp_raise_msg(&mp_type_RuntimeError, FAIL_MSG);
}
return mp_const_none;
}
mp_obj_t scd41_get_automatic_self_calibration() {
if(!scd41_initialised) {
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
return mp_const_none;
}
uint16_t asc_enabled;
int error = scd4x_get_automatic_self_calibration(&asc_enabled);
if(error) {
mp_raise_msg(&mp_type_RuntimeError, FAIL_MSG);
return mp_const_none;
}
return asc_enabled ? mp_const_true : mp_const_false;
}
mp_obj_t scd41_set_temperature_offset(mp_obj_t offset) {
if(!scd41_initialised) {
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);

Wyświetl plik

@ -14,3 +14,7 @@ extern mp_obj_t scd41_set_temperature_offset(mp_obj_t offset);
extern mp_obj_t scd41_get_temperature_offset();
extern mp_obj_t scd41_set_sensor_altitude(mp_obj_t altitude);
extern mp_obj_t scd41_set_ambient_pressure(mp_obj_t pressure);
extern mp_obj_t scd41_perform_forced_recalibration(mp_obj_t target_co2_concentration_in);
extern mp_obj_t scd41_set_automatic_self_calibration(mp_obj_t asc_enabled);
extern mp_obj_t scd41_get_automatic_self_calibration();