44#define CHIP_NAME "Sensirion SGP30"
45#define MANUFACTURER_NAME "Sensirion"
46#define SUPPLY_VOLTAGE_MIN 1.62f
47#define SUPPLY_VOLTAGE_MAX 1.98f
48#define MAX_CURRENT 48.8f
49#define TEMPERATURE_MIN -40.0f
50#define TEMPERATURE_MAX 85.0f
51#define DRIVER_VERSION 2000
56#define SGP30_ADDRESS (0x58 << 1)
61#define SGP30_COMMAND_IAQ_INIT 0x2003U
62#define SGP30_COMMAND_MEASURE_IAQ 0x2008U
63#define SGP30_COMMAND_GET_IAQ_BASELINE 0x2015U
64#define SGP30_COMMAND_SET_IAQ_BASELINE 0x201EU
65#define SGP30_COMMAND_SET_ABSOLUTE_HUMIDITY 0x2061U
66#define SGP30_COMMAND_MEASURE_TEST 0x2032U
67#define SGP30_COMMAND_GET_FEATURE_SET 0x202FU
68#define SGP30_COMMAND_MEASURE_RAW 0x2050U
69#define SGP30_COMMAND_GET_TVOC_INCEPTIVE_BASELINE 0x20B3U
70#define SGP30_COMMAND_SET_TVOC_BASELINE 0x2077U
71#define SGP30_COMMAND_SOFT_RESET 0x0006U
72#define SGP30_COMMAND_GET_SERIAL_ID 0x3682U
77#define SGP30_CRC8_POLYNOMIAL 0x31
78#define SGP30_CRC8_INIT 0xFF
93static uint8_t a_sgp30_iic_read(
sgp30_handle_t *handle, uint8_t addr, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
97 memset(buf, 0,
sizeof(uint8_t) * 2);
98 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
99 buf[1] = (uint8_t)(reg & 0xFF);
127static uint8_t a_sgp30_iic_write(
sgp30_handle_t *handle, uint8_t addr, uint16_t reg, uint8_t *data, uint16_t len)
136 memset(buf, 0,
sizeof(uint8_t) * 16);
137 buf[0] = (uint8_t)((reg >> 8) & 0xFF);
138 buf[1] = (uint8_t)(reg & 0xFF);
139 for (i = 0; i < len; i++)
141 buf[2 + i] = data[i];
144 if (handle->
iic_write_cmd(addr, (uint8_t *)buf, len + 2) != 0)
161static uint8_t a_sgp30_generate_crc(uint8_t* data, uint8_t count)
163 uint8_t current_byte;
167 for (current_byte = 0; current_byte < count; ++current_byte)
169 crc ^= (data[current_byte]);
170 for (crc_bit = 8; crc_bit > 0; --crc_bit)
172 if ((crc & 0x80) != 0)
211 memset(buf, 0,
sizeof(uint8_t) * 3);
212 buf[0] = (tvoc_baseline >> 8) & 0xFF;
213 buf[1] = (tvoc_baseline >> 0) & 0xFF;
214 buf[2] = a_sgp30_generate_crc((uint8_t *)buf, 2);
218 handle->
debug_print(
"sgp30: write tvoc baseline failed.\n");
252 memset(buf, 0,
sizeof(uint8_t) * 3);
256 handle->
debug_print(
"sgp30: read tvoc baseline failed.\n");
260 if (buf[2] != a_sgp30_generate_crc((uint8_t *)buf, 2))
266 *tvoc_baseline = (uint16_t)(((uint16_t)buf[0]) << 8 | buf[1]);
297 handle->
debug_print(
"sgp30: write iaq init failed.\n");
334 handle->
debug_print(
"sgp30: write soft reset failed.\n");
367 memset(buf, 0,
sizeof(uint8_t) * 9);
371 handle->
debug_print(
"sgp30: read serial id failed.\n");
375 if (buf[2] != a_sgp30_generate_crc((uint8_t *)&buf[0], 2))
377 handle->
debug_print(
"sgp30: crc 1 check failed.\n");
381 if (buf[5] != a_sgp30_generate_crc((uint8_t *)&buf[3], 2))
383 handle->
debug_print(
"sgp30: crc 2 check failed.\n");
387 if (buf[8] != a_sgp30_generate_crc((uint8_t *)&buf[6], 2))
389 handle->
debug_print(
"sgp30: crc 3 check failed.\n");
393 id[0] = (uint16_t)((((uint16_t)buf[0]) << 8) | buf[1]);
394 id[1] = (uint16_t)((((uint16_t)buf[3]) << 8) | buf[4]);
395 id[2] = (uint16_t)((((uint16_t)buf[6]) << 8) | buf[7]);
426 memset(buf, 0,
sizeof(uint8_t) * 6);
430 handle->
debug_print(
"sgp30: read measure iaq failed.\n");
434 if (buf[2] != a_sgp30_generate_crc((uint8_t *)buf, 2))
436 handle->
debug_print(
"sgp30: co2 eq crc check error.\n");
440 if (buf[5] != a_sgp30_generate_crc((uint8_t *)&buf[3], 2))
442 handle->
debug_print(
"sgp30: tvoc crc check error.\n");
446 *co2_eq_ppm = (uint16_t)(((uint16_t)buf[0]) << 8 | buf[1]);
447 *tvoc_ppb = (uint16_t)(((uint16_t)buf[3]) << 8 | buf[4]);
478 memset(buf, 0,
sizeof(uint8_t) * 6);
482 handle->
debug_print(
"sgp30: read measure iaq failed.\n");
486 if (buf[2] != a_sgp30_generate_crc((uint8_t *)buf, 2))
488 handle->
debug_print(
"sgp30: co2 eq crc check error.\n");
492 if (buf[5] != a_sgp30_generate_crc((uint8_t *)&buf[3], 2))
494 handle->
debug_print(
"sgp30: tvoc crc check error.\n");
498 *co2_eq = (uint16_t)(((uint16_t)buf[0]) << 8 | buf[1]);
499 *tvoc = (uint16_t)(((uint16_t)buf[3]) << 8 | buf[4]);
530 memset(buf, 0,
sizeof(uint8_t) * 6);
531 buf[0] = (tvoc >> 8) & 0xFF;
532 buf[1] = tvoc & 0xFF;
533 buf[2] = a_sgp30_generate_crc((uint8_t *)buf, 2);
534 buf[3] = (co2_eq >> 8) & 0xFF;
535 buf[4] = co2_eq & 0xFF;
536 buf[5] = a_sgp30_generate_crc((uint8_t *)&buf[3], 2);
540 handle->
debug_print(
"sgp30: write iaq baseline failed.\n");
574 memset(buf, 0,
sizeof(uint8_t) * 3);
575 buf[0] = (humidity >> 8) & 0xFF;
576 buf[1] = (humidity >> 0) & 0xFF;
577 buf[2] = a_sgp30_generate_crc((uint8_t *)buf, 2);
581 handle->
debug_print(
"sgp30: write absolute humidity failed.\n");
605 float absolute_humidity;
606 float intpart, fractpart;
617 absolute_humidity = (rh / 100.0f * 6.112f * expf( (17.62f * temp) / (243.12f + temp) )) /
618 (273.15f + temp) * 216.7f;
619 fractpart = modff(absolute_humidity, (
float *)&intpart);
620 *reg = (uint16_t)(intpart) << 8 | (uint8_t)(fractpart * 256);
650 memset(buf, 0,
sizeof(uint8_t) * 3);
654 handle->
debug_print(
"sgp30: read measure test failed.\n");
658 if (buf[2] != a_sgp30_generate_crc((uint8_t *)buf, 2))
660 handle->
debug_print(
"sgp30: measure test check error.\n");
664 *result = (uint16_t)(((uint16_t)buf[0]) << 8 | buf[1]);
695 memset(buf, 0,
sizeof(uint8_t) * 3);
699 handle->
debug_print(
"sgp30: get feature set failed.\n");
703 if (buf[2] != a_sgp30_generate_crc((uint8_t *)buf, 2))
705 handle->
debug_print(
"sgp30: feature set check error.\n");
709 *product_type = buf[0] & 0xF;
710 *product_version = buf[1];
741 memset(buf, 0,
sizeof(uint8_t) * 6);
745 handle->
debug_print(
"sgp30: read measure raw failed.\n");
749 if (buf[2] != a_sgp30_generate_crc((uint8_t *)buf, 2))
751 handle->
debug_print(
"sgp30: co2 eq crc check error.\n");
755 if (buf[5] != a_sgp30_generate_crc((uint8_t *)&buf[3], 2))
757 handle->
debug_print(
"sgp30: tvoc crc check error.\n");
761 *h2_raw = (uint16_t)(((uint16_t)buf[0]) << 8 | buf[1]);
762 *ethanol_raw = (uint16_t)(((uint16_t)buf[3]) << 8 | buf[4]);
795 handle->
debug_print(
"sgp30: iic_deinit is null.\n");
801 handle->
debug_print(
"sgp30: iic_write_cmd is null.\n");
807 handle->
debug_print(
"sgp30: iic_read_cmd is null.\n");
853 handle->
debug_print(
"sgp30: soft reset failed.\n");
894 memset(buf, 0,
sizeof(uint8_t) * 6);
898 handle->
debug_print(
"sgp30: read measure iaq failed.\n");
902 if (buf[2] != a_sgp30_generate_crc((uint8_t *)buf, 2))
904 handle->
debug_print(
"sgp30: co2 eq crc check error.\n");
908 if (buf[5] != a_sgp30_generate_crc((uint8_t *)&buf[3], 2))
910 handle->
debug_print(
"sgp30: tvoc crc check error.\n");
914 *co2_eq_ppm = (uint16_t)(((uint16_t)buf[0]) << 8 | buf[1]);
915 *tvoc_ppb = (uint16_t)(((uint16_t)buf[3]) << 8 | buf[4]);
944 return a_sgp30_iic_write(handle,
SGP30_ADDRESS, reg, buf, len);
971 return a_sgp30_iic_read(handle,
SGP30_ADDRESS, reg, buf, len, 20);
#define SGP30_CRC8_POLYNOMIAL
crc8 definition
#define SGP30_COMMAND_GET_SERIAL_ID
#define SGP30_COMMAND_GET_IAQ_BASELINE
#define SGP30_COMMAND_MEASURE_RAW
#define SGP30_COMMAND_SET_TVOC_BASELINE
#define SUPPLY_VOLTAGE_MAX
#define SGP30_ADDRESS
chip address definition
#define SGP30_COMMAND_SET_IAQ_BASELINE
#define SGP30_COMMAND_GET_TVOC_INCEPTIVE_BASELINE
#define MANUFACTURER_NAME
#define SUPPLY_VOLTAGE_MIN
#define SGP30_COMMAND_GET_FEATURE_SET
#define SGP30_COMMAND_MEASURE_TEST
#define CHIP_NAME
chip information definition
#define SGP30_COMMAND_MEASURE_IAQ
#define SGP30_COMMAND_IAQ_INIT
chip command definition
#define SGP30_COMMAND_SET_ABSOLUTE_HUMIDITY
uint8_t sgp30_get_measure_raw(sgp30_handle_t *handle, uint16_t *h2_raw, uint16_t *ethanol_raw)
get measure raw
uint8_t sgp30_get_iaq_baseline(sgp30_handle_t *handle, uint16_t *tvoc, uint16_t *co2_eq)
get the chip iaq baseline
uint8_t sgp30_set_tvoc_baseline(sgp30_handle_t *handle, uint16_t tvoc_baseline)
set the chip tvoc baseline
struct sgp30_handle_s sgp30_handle_t
sgp30 handle structure definition
uint8_t sgp30_init(sgp30_handle_t *handle)
initialize the chip
uint8_t sgp30_absolute_humidity_convert_to_register(sgp30_handle_t *handle, float temp, float rh, uint16_t *reg)
convert the absolute humidity to the register data
uint8_t sgp30_deinit(sgp30_handle_t *handle)
close the chip
struct sgp30_info_s sgp30_info_t
sgp30 information structure definition
uint8_t sgp30_get_serial_id(sgp30_handle_t *handle, uint16_t id[3])
get the chip serial id
uint8_t sgp30_set_iaq_baseline(sgp30_handle_t *handle, uint16_t tvoc, uint16_t co2_eq)
set the chip iaq baseline
uint8_t sgp30_set_absolute_humidity(sgp30_handle_t *handle, uint16_t humidity)
set the chip absolute_humidity
uint8_t sgp30_read(sgp30_handle_t *handle, uint16_t *co2_eq_ppm, uint16_t *tvoc_ppb)
read the iaq measure result
uint8_t sgp30_get_feature_set(sgp30_handle_t *handle, uint8_t *product_type, uint8_t *product_version)
get the chip feature
uint8_t sgp30_info(sgp30_info_t *info)
get chip information
uint8_t sgp30_soft_reset(sgp30_handle_t *handle)
soft reset the chip
uint8_t sgp30_measure_test(sgp30_handle_t *handle, uint16_t *result)
run the chip measure test
uint8_t sgp30_measure_iaq(sgp30_handle_t *handle, uint16_t *co2_eq_ppm, uint16_t *tvoc_ppb)
get the iaq measure result
uint8_t sgp30_iaq_init(sgp30_handle_t *handle)
initialize the chip iaq
uint8_t sgp30_get_tvoc_inceptive_baseline(sgp30_handle_t *handle, uint16_t *tvoc_baseline)
get the chip tvoc inceptive baseline
uint8_t sgp30_set_reg(sgp30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
set the chip register
uint8_t sgp30_get_reg(sgp30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
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