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
90#define SCD4X_CRC8_POLYNOMIAL 0x31
91#define SCD4X_CRC8_INIT 0xFF
107static uint8_t a_scd4x_iic_read_with_param(
scd4x_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len,
108 uint16_t delay_ms, uint8_t *output, uint16_t output_len)
117 memset(buf, 0,
sizeof(uint8_t) * 16);
118 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
119 buf[1] = (uint8_t)(reg & 0xFF);
120 for (i = 0; i < len; i++)
122 buf[2 + i] = data[i];
152static uint8_t a_scd4x_iic_read(
scd4x_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
156 memset(buf, 0,
sizeof(uint8_t) * 2);
157 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
158 buf[1] = (uint8_t)(reg & 0xFF);
185static uint8_t a_scd4x_iic_write(
scd4x_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len)
194 memset(buf, 0,
sizeof(uint8_t) * 16);
195 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
196 buf[1] = (uint8_t)(reg & 0xFF);
197 for (i = 0; i < len; i++)
199 buf[2 + i] = data[i];
219static uint8_t a_scd4x_generate_crc(uint8_t* data, uint8_t count)
221 uint8_t current_byte;
225 for (current_byte = 0; current_byte < count; ++current_byte)
227 crc ^= (data[current_byte]);
228 for (crc_bit = 8; crc_bit > 0; --crc_bit)
230 if ((crc & 0x80) != 0)
312 handle->
debug_print(
"scd4x: start periodic measurement failed.\n");
339 uint16_t *temperature_raw,
float *temperature_s,
340 uint16_t *humidity_raw,
float *humidity_s)
358 handle->
debug_print(
"scd4x: get data ready status failed.\n");
362 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
368 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
369 if ((prev & 0x0FFF) == 0)
371 handle->
debug_print(
"scd4x: data is not ready.\n");
384 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
390 if (buf[5] != a_scd4x_generate_crc(&buf[3], 2))
396 if (buf[8] != a_scd4x_generate_crc(&buf[6], 2))
403 *co2_raw = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
404 *temperature_raw = (uint16_t)(((uint16_t)buf[3]) << 8) | buf[4];
405 *humidity_raw = (uint16_t)(((uint16_t)buf[6]) << 8) | buf[7];
407 *temperature_s = -45.0f + 175.0f * (float)(*temperature_raw) / 65535.0f;
408 *humidity_s = 100.0f * (float)(*humidity_raw) / 65535.0f;
439 handle->
debug_print(
"scd4x: stop periodic measurement failed.\n");
473 buf[0] = (offset >> 8) & 0xFF;
474 buf[1] = (offset >> 0) & 0xFF;
475 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
479 handle->
debug_print(
"scd4x: set temperature offset failed.\n");
517 handle->
debug_print(
"scd4x: get temperature offset failed.\n");
521 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
527 *offset = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
554 *reg = (uint16_t)(degrees * (65535.0f / 175.0f));
581 *degrees = (float)(reg) * 175.0f / 65535.0f;
611 buf[0] = (altitude >> 8) & 0xFF;
612 buf[1] = (altitude >> 0) & 0xFF;
613 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
617 handle->
debug_print(
"scd4x: set sensor altitude failed.\n");
655 handle->
debug_print(
"scd4x: get sensor altitude failed.\n");
659 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
665 *altitude = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
692 *reg = (uint16_t)(m);
749 buf[0] = (pressure >> 8) & 0xFF;
750 buf[1] = (pressure >> 0) & 0xFF;
751 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
755 handle->
debug_print(
"scd4x: set ambient pressure failed.\n");
793 handle->
debug_print(
"scd4x: get ambient pressure failed.\n");
797 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
803 *pressure = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
830 *reg = (uint16_t)(pa / 100.0f);
857 *pa = (float)(reg * 100.0f);
890 in_buf[0] = (co2_raw >> 8) & 0xFF;
891 in_buf[1] = (co2_raw >> 0) & 0xFF;
892 in_buf[2] = a_scd4x_generate_crc(&in_buf[0], 2);
894 in_buf, 3, 400, out_buf, 3);
897 handle->
debug_print(
"scd4x: perform forced recalibration failed.\n");
901 if (out_buf[2] != a_scd4x_generate_crc(&out_buf[0], 2))
907 *frc = (uint16_t)(((uint16_t)out_buf[0]) << 8) | out_buf[1];
934 *reg = (uint16_t)(ppm);
993 buf[0] = (prev >> 8) & 0xFF;
994 buf[1] = (prev >> 0) & 0xFF;
995 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
999 handle->
debug_print(
"scd4x: set automatic self calibration failed.\n");
1038 handle->
debug_print(
"scd4x: get automatic self calibration failed.\n");
1042 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1048 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1080 handle->
debug_print(
"scd4x: start low power periodic measurement failed.\n");
1118 handle->
debug_print(
"scd4x: get data ready status failed.\n");
1122 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1128 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1129 if ((prev & 0x0FFF) != 0)
1167 handle->
debug_print(
"scd4x: persist settings failed.\n");
1205 handle->
debug_print(
"scd4x: get serial number failed.\n");
1209 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1215 if (buf[5] != a_scd4x_generate_crc(&buf[3], 2))
1221 if (buf[8] != a_scd4x_generate_crc(&buf[6], 2))
1227 number[0] = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1228 number[1] = (uint16_t)(((uint16_t)buf[3]) << 8) | buf[4];
1229 number[2] = (uint16_t)(((uint16_t)buf[6]) << 8) | buf[7];
1264 handle->
debug_print(
"scd4x: perform self test failed.\n");
1268 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1274 prev = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1313 handle->
debug_print(
"scd4x: perform factory reset failed.\n");
1382 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1390 handle->
debug_print(
"scd4x: measure single shot failed.\n");
1424 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1432 handle->
debug_print(
"scd4x: measure single shot rht only failed.\n");
1466 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1474 handle->
debug_print(
"scd4x: power down failed.\n");
1506 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1545 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1549 if ((hour % 4) != 0)
1551 handle->
debug_print(
"scd4x: hour is not integer multiples of 4.\n");
1556 buf[0] = (hour >> 8) & 0xFF;
1557 buf[1] = (hour >> 0) & 0xFF;
1558 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
1562 handle->
debug_print(
"scd4x: set automatic self calibration initial period failed.\n");
1599 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1607 handle->
debug_print(
"scd4x: get automatic self calibration initial period failed.\n");
1611 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1617 *hour = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1650 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1654 if ((hour % 4) != 0)
1656 handle->
debug_print(
"scd4x: hour is not integer multiples of 4.\n");
1661 buf[0] = (hour >> 8) & 0xFF;
1662 buf[1] = (hour >> 0) & 0xFF;
1663 buf[2] = a_scd4x_generate_crc(&buf[0], 2);
1667 handle->
debug_print(
"scd4x: set automatic self calibration standard period failed.\n");
1704 handle->
debug_print(
"scd4x: only scd41 and scd43 has this function.\n");
1712 handle->
debug_print(
"scd4x: get automatic self calibration standard period failed.\n");
1716 if (buf[2] != a_scd4x_generate_crc(&buf[0], 2))
1722 *hour = (uint16_t)(((uint16_t)buf[0]) << 8) | buf[1];
1749 handle->
debug_print(
"scd4x: iic_init is null.\n");
1755 handle->
debug_print(
"scd4x: iic_deinit is null.\n");
1761 handle->
debug_print(
"scd4x: iic_write_cmd is null.\n");
1767 handle->
debug_print(
"scd4x: iic_read_cmd is null.\n");
1773 handle->
debug_print(
"scd4x: delay_ms is null.\n");
1816 handle->
debug_print(
"scd4x: stop periodic measurement failed.\n");
1822 handle->
debug_print(
"scd4x: iic close failed.\n");
1855 return a_scd4x_iic_write(handle, reg, buf, len);
1883 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_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 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_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_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