42#define CHIP_NAME "Sensirion SCD4X"
43#define MANUFACTURER_NAME "Sensirion"
44#define SUPPLY_VOLTAGE_MIN 2.40f
45#define SUPPLY_VOLTAGE_MAX 5.50f
46#define MAX_CURRENT 205.0f
47#define TEMPERATURE_MIN -10.0f
48#define TEMPERATURE_MAX 60.0f
49#define DRIVER_VERSION 1000
54#define SCD4X_ADDRESS (0x62 << 1)
59#define SCD4X_COMMAND_START_PERIODIC 0x21B1U
60#define SCD4X_COMMAND_READ 0xEC05U
61#define SCD4X_COMMAND_STOP_PERIODIC 0x3F86U
62#define SCD4X_COMMAND_SET_TEMPERATURE_OFFSET 0x241DU
63#define SCD4X_COMMAND_GET_TEMPERATURE_OFFSET 0x2318U
64#define SCD4X_COMMAND_SET_SENSOR_ALTITUDE 0x2427U
65#define SCD4X_COMMAND_GET_SENSOR_ALTITUDE 0x2322U
66#define SCD4X_COMMAND_SET_AMBIENT_PRESSURE 0xE000U
67#define SCD4X_COMMAND_GET_AMBIENT_PRESSURE 0xE000U
68#define SCD4X_COMMAND_PERFORM_FORCED_RECALIBRATION 0x362FU
69#define SCD4X_COMMAND_SET_AUTO_SELF_CALIBRATION 0x2416U
70#define SCD4X_COMMAND_GET_AUTO_SELF_CALIBRATION 0x2313U
71#define SCD4X_COMMAND_START_LOW_POWER_PERIODIC 0x21ACU
72#define SCD4X_COMMAND_GET_DATA_READY_STATUS 0xE4B8U
73#define SCD4X_COMMAND_PERSIST_SETTINGS 0x3615U
74#define SCD4X_COMMAND_GET_SERIAL_NUMBER 0x3682U
75#define SCD4X_COMMAND_PERFORM_SELF_TEST 0x3639U
76#define SCD4X_COMMAND_PERFORM_FACTORY_RESET 0x3632U
77#define SCD4X_COMMAND_REINIT 0x3646U
78#define SCD4X_COMMAND_MEASURE_SINGLE_SHOT 0x219DU
79#define SCD4X_COMMAND_MEASURE_SINGLE_SHOT_RHT_ONLY 0x2196U
80#define SCD4X_COMMAND_POWER_DOWN 0x36E0U
81#define SCD4X_COMMAND_WAKE_UP 0x36F6U
82#define SCD4X_COMMAND_SET_AUTO_SELF_CALIBRATION_INIT_PERIOD 0x2445U
83#define SCD4X_COMMAND_GET_AUTO_SELF_CALIBRATION_INIT_PERIOD 0x2340U
84#define SCD4X_COMMAND_SET_AUTO_SELF_CALIBRATION_STANDARD_PERIOD 0x244EU
85#define SCD4X_COMMAND_GET_AUTO_SELF_CALIBRATION_STANDARD_PERIOD 0x234BU
86#define SCD4X_COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_TARGET 0x243AU
87#define SCD4X_COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_TARGET 0x233FU
88#define SCD4X_COMMAND_GET_SENSOR_VARIANT 0x202FU
93#define SCD4X_CRC8_POLYNOMIAL 0x31
94#define SCD4X_CRC8_INIT 0xFF
110static uint8_t a_scd4x_iic_read_with_param(
scd4x_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len,
111 uint16_t delay_ms, uint8_t *output, uint16_t output_len)
120 memset(buf, 0,
sizeof(uint8_t) * 16);
121 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
122 buf[1] = (uint8_t)(reg & 0xFF);
123 for (i = 0; i < len; i++)
125 buf[2 + i] = data[i];
155static uint8_t a_scd4x_iic_read(
scd4x_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
159 memset(buf, 0,
sizeof(uint8_t) * 2);
160 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
161 buf[1] = (uint8_t)(reg & 0xFF);
188static uint8_t a_scd4x_iic_write(
scd4x_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len)
197 memset(buf, 0,
sizeof(uint8_t) * 16);
198 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
199 buf[1] = (uint8_t)(reg & 0xFF);
200 for (i = 0; i < len; i++)
202 buf[2 + i] = data[i];
222static uint8_t a_scd4x_generate_crc(uint8_t* data, uint8_t count)
224 uint8_t current_byte;
228 for (current_byte = 0; current_byte < count; ++current_byte)
230 crc ^= (data[current_byte]);
231 for (crc_bit = 8; crc_bit > 0; --crc_bit)
233 if ((crc & 0x80) != 0)
315 handle->
debug_print(
"scd4x: start periodic measurement failed.\n");
342 uint16_t *temperature_raw,
float *temperature_s,
343 uint16_t *humidity_raw,
float *humidity_s)
361 handle->
debug_print(
"scd4x: get data ready status failed.\n");
365 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
371 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
372 if ((prev & 0x07FF) == 0)
374 handle->
debug_print(
"scd4x: data is not ready.\n");
387 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
393 if (buf[5] != a_scd4x_generate_crc(&buf[3], 2))
399 if (buf[8] != a_scd4x_generate_crc(&buf[6], 2))
406 *co2_raw = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
407 *temperature_raw = (uint16_t)(((uint16_t)buf[3]) << 8) | buf[4];
408 *humidity_raw = (uint16_t)(((uint16_t)buf[6]) << 8) | buf[7];
410 *temperature_s = -45.0f + 175.0f * (float)(*temperature_raw) / 65535.0f;
411 *humidity_s = 100.0f * (float)(*humidity_raw) / 65535.0f;
442 handle->
debug_print(
"scd4x: stop periodic measurement failed.\n");
476 buf[0] = (offset >> 8) & 0xFF;
477 buf[1] = (offset >> 0) & 0xFF;
478 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
482 handle->
debug_print(
"scd4x: set temperature offset failed.\n");
520 handle->
debug_print(
"scd4x: get temperature offset failed.\n");
524 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
530 *offset = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
557 *reg = (uint16_t)(degrees * (65535.0f / 175.0f));
584 *degrees = (float)(reg) * 175.0f / 65535.0f;
614 buf[0] = (altitude >> 8) & 0xFF;
615 buf[1] = (altitude >> 0) & 0xFF;
616 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
620 handle->
debug_print(
"scd4x: set sensor altitude failed.\n");
658 handle->
debug_print(
"scd4x: get sensor altitude failed.\n");
662 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
668 *altitude = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
695 *reg = (uint16_t)(m);
752 buf[0] = (pressure >> 8) & 0xFF;
753 buf[1] = (pressure >> 0) & 0xFF;
754 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
758 handle->
debug_print(
"scd4x: set ambient pressure failed.\n");
796 handle->
debug_print(
"scd4x: get ambient pressure failed.\n");
800 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
806 *pressure = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
833 *reg = (uint16_t)(pa / 100.0f);
860 *pa = (float)(reg * 100.0f);
893 in_buf[0] = (co2_raw >> 8) & 0xFF;
894 in_buf[1] = (co2_raw >> 0) & 0xFF;
895 in_buf[2] = a_scd4x_generate_crc(&in_buf[0], 2);
897 in_buf, 3, 400, out_buf, 3);
900 handle->
debug_print(
"scd4x: perform forced recalibration failed.\n");
904 if (out_buf[2] != a_scd4x_generate_crc(&out_buf[0], 2))
910 *frc = (uint16_t)(((uint16_t)out_buf[0]) << 8) | out_buf[1];
937 *reg = (uint16_t)(ppm);
996 buf[0] = (prev >> 8) & 0xFF;
997 buf[1] = (prev >> 0) & 0xFF;
998 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
1002 handle->
debug_print(
"scd4x: set automatic self calibration failed.\n");
1041 handle->
debug_print(
"scd4x: get automatic self calibration failed.\n");
1045 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1051 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1083 handle->
debug_print(
"scd4x: start low power periodic measurement failed.\n");
1121 handle->
debug_print(
"scd4x: get data ready status failed.\n");
1125 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1131 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1132 if ((prev & 0x07FF) != 0)
1170 handle->
debug_print(
"scd4x: persist settings failed.\n");
1208 handle->
debug_print(
"scd4x: get serial number failed.\n");
1212 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1218 if (buf[5] != a_scd4x_generate_crc(&buf[3], 2))
1224 if (buf[8] != a_scd4x_generate_crc(&buf[6], 2))
1230 number[0] = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1231 number[1] = (uint16_t)(((uint16_t)buf[3]) << 8) | buf[4];
1232 number[2] = (uint16_t)(((uint16_t)buf[6]) << 8) | buf[7];
1267 handle->
debug_print(
"scd4x: perform self test failed.\n");
1271 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1277 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1316 handle->
debug_print(
"scd4x: perform factory reset failed.\n");
1385 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1393 handle->
debug_print(
"scd4x: measure single shot failed.\n");
1427 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1435 handle->
debug_print(
"scd4x: measure single shot rht only failed.\n");
1469 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1477 handle->
debug_print(
"scd4x: power down failed.\n");
1509 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1548 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1552 if ((hour % 4) != 0)
1554 handle->
debug_print(
"scd4x: hour is not integer multiples of 4.\n");
1559 buf[0] = (hour >> 8) & 0xFF;
1560 buf[1] = (hour >> 0) & 0xFF;
1561 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
1565 handle->
debug_print(
"scd4x: set automatic self calibration initial period failed.\n");
1602 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1610 handle->
debug_print(
"scd4x: get automatic self calibration initial period failed.\n");
1614 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1620 *hour = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1653 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1657 if ((hour % 4) != 0)
1659 handle->
debug_print(
"scd4x: hour is not integer multiples of 4.\n");
1664 buf[0] = (hour >> 8) & 0xFF;
1665 buf[1] = (hour >> 0) & 0xFF;
1666 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
1670 handle->
debug_print(
"scd4x: set automatic self calibration standard period failed.\n");
1707 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1715 handle->
debug_print(
"scd4x: get automatic self calibration standard period failed.\n");
1719 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1725 *hour = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1755 buf[0] = (co2_ppm >> 8) & 0xFF;
1756 buf[1] = (co2_ppm >> 0) & 0xFF;
1757 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
1761 handle->
debug_print(
"scd4x: set automatic self calibration target failed.\n");
1799 handle->
debug_print(
"scd4x: get automatic self calibration target failed.\n");
1803 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1809 *co2_ppm = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1845 handle->
debug_print(
"scd4x: get sensor variant failed.\n");
1849 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1855 *variant = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1882 handle->
debug_print(
"scd4x: iic_init is null.\n");
1888 handle->
debug_print(
"scd4x: iic_deinit is null.\n");
1894 handle->
debug_print(
"scd4x: iic_write_cmd is null.\n");
1900 handle->
debug_print(
"scd4x: iic_read_cmd is null.\n");
1906 handle->
debug_print(
"scd4x: delay_ms is null.\n");
1949 handle->
debug_print(
"scd4x: stop periodic measurement failed.\n");
1956 handle->
debug_print(
"scd4x: iic close failed.\n");
1989 return a_scd4x_iic_write(handle, reg, buf, len);
2017 return a_scd4x_iic_read(handle, reg, buf, len, delay_ms);
#define SCD4X_COMMAND_GET_AUTO_SELF_CALIBRATION_INIT_PERIOD
#define SCD4X_COMMAND_GET_AUTO_SELF_CALIBRATION
#define SCD4X_COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_TARGET
#define SCD4X_COMMAND_GET_SENSOR_VARIANT
#define SCD4X_CRC8_POLYNOMIAL
crc8 definition
#define SCD4X_COMMAND_PERFORM_FORCED_RECALIBRATION
#define SCD4X_COMMAND_STOP_PERIODIC
#define SCD4X_COMMAND_PERFORM_FACTORY_RESET
#define SCD4X_COMMAND_SET_TEMPERATURE_OFFSET
#define SCD4X_COMMAND_POWER_DOWN
#define SCD4X_COMMAND_MEASURE_SINGLE_SHOT
#define SCD4X_COMMAND_GET_SERIAL_NUMBER
#define SUPPLY_VOLTAGE_MAX
#define SCD4X_COMMAND_SET_SENSOR_ALTITUDE
#define SCD4X_COMMAND_START_LOW_POWER_PERIODIC
#define SCD4X_COMMAND_PERSIST_SETTINGS
#define SCD4X_COMMAND_SET_AUTO_SELF_CALIBRATION
#define SCD4X_COMMAND_REINIT
#define SCD4X_COMMAND_GET_TEMPERATURE_OFFSET
#define SCD4X_COMMAND_PERFORM_SELF_TEST
#define SCD4X_ADDRESS
chip address definition
#define SCD4X_COMMAND_READ
#define SCD4X_COMMAND_GET_SENSOR_ALTITUDE
#define SCD4X_COMMAND_SET_AUTO_SELF_CALIBRATION_INIT_PERIOD
#define SCD4X_COMMAND_START_PERIODIC
chip command definition
#define MANUFACTURER_NAME
#define SCD4X_COMMAND_WAKE_UP
#define SUPPLY_VOLTAGE_MIN
#define SCD4X_COMMAND_GET_AUTO_SELF_CALIBRATION_STANDARD_PERIOD
#define SCD4X_COMMAND_GET_DATA_READY_STATUS
#define SCD4X_COMMAND_SET_AUTO_SELF_CALIBRATION_STANDARD_PERIOD
#define SCD4X_COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_TARGET
#define CHIP_NAME
chip information definition
#define SCD4X_COMMAND_SET_AMBIENT_PRESSURE
#define SCD4X_COMMAND_MEASURE_SINGLE_SHOT_RHT_ONLY
#define SCD4X_COMMAND_GET_AMBIENT_PRESSURE
uint8_t scd4x_get_automatic_self_calibration_target(scd4x_handle_t *handle, uint16_t *co2_ppm)
get automatic self calibration target
uint8_t scd4x_wake_up(scd4x_handle_t *handle)
wake up
uint8_t scd4x_set_automatic_self_calibration_standard_period(scd4x_handle_t *handle, uint16_t hour)
set automatic self calibration standard period
uint8_t scd4x_set_automatic_self_calibration_initial_period(scd4x_handle_t *handle, uint16_t hour)
set automatic self calibration initial period
uint8_t scd4x_power_down(scd4x_handle_t *handle)
power down
uint8_t scd4x_measure_single_shot(scd4x_handle_t *handle)
measure single shot
uint8_t scd4x_get_automatic_self_calibration_standard_period(scd4x_handle_t *handle, uint16_t *hour)
get automatic self calibration standard period
uint8_t scd4x_get_automatic_self_calibration_initial_period(scd4x_handle_t *handle, uint16_t *hour)
get automatic self calibration initial period
uint8_t scd4x_set_automatic_self_calibration_target(scd4x_handle_t *handle, uint16_t co2_ppm)
set automatic self calibration target
uint8_t scd4x_get_sensor_variant(scd4x_handle_t *handle, uint16_t *variant)
get sensor variant
uint8_t scd4x_measure_single_shot_rht_only(scd4x_handle_t *handle)
measure single shot rht only
struct scd4x_info_s scd4x_info_t
scd4x information structure definition
uint8_t scd4x_get_type(scd4x_handle_t *handle, scd4x_t *type)
get type
uint8_t scd4x_get_data_ready_status(scd4x_handle_t *handle, scd4x_bool_t *enable)
get data ready status
uint8_t scd4x_stop_periodic_measurement(scd4x_handle_t *handle)
stop periodic measurement
uint8_t scd4x_get_sensor_altitude(scd4x_handle_t *handle, uint16_t *altitude)
get sensor altitude
uint8_t scd4x_sensor_altitude_convert_to_data(scd4x_handle_t *handle, uint16_t reg, float *m)
convert the register raw data to the sensor altitude
uint8_t scd4x_set_temperature_offset(scd4x_handle_t *handle, uint16_t offset)
set temperature offset
uint8_t scd4x_get_serial_number(scd4x_handle_t *handle, uint16_t number[3])
get serial number
uint8_t scd4x_deinit(scd4x_handle_t *handle)
close the chip
uint8_t scd4x_get_automatic_self_calibration(scd4x_handle_t *handle, scd4x_bool_t *enable)
get automatic self calibration status
uint8_t scd4x_set_ambient_pressure(scd4x_handle_t *handle, uint16_t pressure)
set ambient pressure
uint8_t scd4x_co2_convert_to_register(scd4x_handle_t *handle, float ppm, uint16_t *reg)
convert the co2 to the register raw data
uint8_t scd4x_read(scd4x_handle_t *handle, uint16_t *co2_raw, uint16_t *co2_ppm, uint16_t *temperature_raw, float *temperature_s, uint16_t *humidity_raw, float *humidity_s)
read data
uint8_t scd4x_set_type(scd4x_handle_t *handle, scd4x_t type)
set type
uint8_t scd4x_get_temperature_offset(scd4x_handle_t *handle, uint16_t *offset)
get temperature offset
uint8_t scd4x_temperature_offset_convert_to_register(scd4x_handle_t *handle, float degrees, uint16_t *reg)
convert the temperature offset to the register raw data
uint8_t scd4x_reinit(scd4x_handle_t *handle)
reinit
uint8_t scd4x_ambient_pressure_convert_to_register(scd4x_handle_t *handle, float pa, uint16_t *reg)
convert the ambient pressure to the register raw data
uint8_t scd4x_co2_convert_to_data(scd4x_handle_t *handle, uint16_t reg, float *ppm)
convert the register raw data to the co2
uint8_t scd4x_set_automatic_self_calibration(scd4x_handle_t *handle, scd4x_bool_t enable)
enable or disable automatic self calibration
uint8_t scd4x_init(scd4x_handle_t *handle)
initialize the chip
uint8_t scd4x_perform_forced_recalibration(scd4x_handle_t *handle, uint16_t co2_raw, uint16_t *frc)
perform forced recalibration
uint8_t scd4x_perform_factory_reset(scd4x_handle_t *handle)
perform factory reset
uint8_t scd4x_persist_settings(scd4x_handle_t *handle)
persist settings
uint8_t scd4x_start_periodic_measurement(scd4x_handle_t *handle)
start periodic measurement
struct scd4x_handle_s scd4x_handle_t
scd4x handle structure definition
uint8_t scd4x_perform_self_test(scd4x_handle_t *handle, scd4x_bool_t *malfunction_detected)
perform self test
uint8_t scd4x_info(scd4x_info_t *info)
get chip information
uint8_t scd4x_ambient_pressure_convert_to_data(scd4x_handle_t *handle, uint16_t reg, float *pa)
convert the register raw data to the ambient pressure
uint8_t scd4x_set_sensor_altitude(scd4x_handle_t *handle, uint16_t altitude)
set sensor altitude
uint8_t scd4x_sensor_altitude_convert_to_register(scd4x_handle_t *handle, float m, uint16_t *reg)
convert the sensor altitude to the register raw data
uint8_t scd4x_temperature_offset_convert_to_data(scd4x_handle_t *handle, uint16_t reg, float *degrees)
convert the register raw data to the temperature offset
scd4x_t
scd4x type enumeration definition
scd4x_bool_t
scd4x bool enumeration definition
uint8_t scd4x_get_ambient_pressure(scd4x_handle_t *handle, uint16_t *pressure)
get ambient pressure
uint8_t scd4x_start_low_power_periodic_measurement(scd4x_handle_t *handle)
start low power periodic measurement
uint8_t scd4x_set_reg(scd4x_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
set the chip register
uint8_t scd4x_get_reg(scd4x_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len, uint16_t delay_ms)
get the chip register
void(* delay_ms)(uint32_t ms)
void(* debug_print)(const char *const fmt,...)
uint8_t(* iic_init)(void)
uint8_t(* iic_read_cmd)(uint8_t addr, uint8_t *buf, uint16_t len)
uint8_t(* iic_deinit)(void)
uint8_t(* iic_write_cmd)(uint8_t addr, uint8_t *buf, uint16_t len)
float supply_voltage_max_v
char manufacturer_name[32]
float supply_voltage_min_v