17#define SPS30_I2C_ADDR (0x69 << 1)
20#define SPS30_CMD_START_MEAS 0x0010
21#define SPS30_CMD_STOP_MEAS 0x0104
22#define SPS30_CMD_READ_DRDY 0x0202
23#define SPS30_CMD_READ_MEAS 0x0300
24#define SPS30_CMD_SOFT_RESET 0xD304
25#define SPS30_CMD_START_CLEAN 0x5607
26#define SPS30_CMD_SLEEP 0x1001
27#define SPS30_CMD_WAKEUP 0x1103
28#define SPS30_CMD_CLEAN_INTERVAL 0x8004
56 else if (pm2_5 <= 35.4f)
61 else if (pm2_5 <= 55.4f)
63 *label =
"Unhealthy for Sensitive Groups";
66 else if (pm2_5 <= 150.4f)
71 else if (pm2_5 <= 250.4f)
73 *label =
"Very Unhealthy";
83int8_t
sps30_Is(I2C_HandleTypeDef *hi2c, int8_t tryInit)
93 HAL_StatusTypeDef status;
100 status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100);
105 if (status == HAL_OK)
112 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
119 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
130 HAL_StatusTypeDef status = HAL_ERROR;
143 while (wakeUp-- > 0 && (status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
146 if (status != HAL_OK)
157 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 5, 100)) != HAL_OK)
177 HAL_StatusTypeDef status = HAL_ERROR;
186 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
192 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
203 HAL_StatusTypeDef status = HAL_ERROR;
213 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
215 if ((status = HAL_I2C_Master_Receive(hi2c,
SPS30_I2C_ADDR, data, 3, 100)) != HAL_OK)
218 status = (data[1] == 1) ? HAL_OK : HAL_BUSY;
228 if (status == HAL_OK)
235 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
238 if ((status = HAL_I2C_Master_Receive(hi2c,
SPS30_I2C_ADDR, buffer, 60, 500)) != HAL_OK)
242 for (
int i = 0; i < 10; i++)
244 uint8_t raw_float[4];
256 raw_float[3] = buffer[b_idx];
257 raw_float[2] = buffer[b_idx + 1];
259 raw_float[1] = buffer[b_idx + 3];
260 raw_float[0] = buffer[b_idx + 4];
263 memcpy(&f_ptr[i], raw_float, 4);
279 if (status == HAL_OK || status == HAL_BUSY)
282 *onOff = (status == HAL_OK);
290 HAL_StatusTypeDef status = HAL_ERROR;
296 status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100);
302 HAL_StatusTypeDef status = HAL_ERROR;
312 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 2, 100)) != HAL_OK)
314 if ((status = HAL_I2C_Master_Receive(hi2c,
SPS30_I2C_ADDR, buffer, 6, 100)) != HAL_OK)
323 *interval_sec = ((uint32_t) buffer[0] << 24) | ((uint32_t) buffer[1] << 16) | ((uint32_t) buffer[3] << 8) | (uint32_t) buffer[4];
331 HAL_StatusTypeDef status = HAL_ERROR;
342 cmd[2] = (uint8_t) (interval_sec >> 24);
343 cmd[3] = (uint8_t) (interval_sec >> 16);
346 cmd[5] = (uint8_t) (interval_sec >> 8);
347 cmd[6] = (uint8_t) (interval_sec & 0xFF);
349 if ((status = HAL_I2C_Master_Transmit(hi2c,
SPS30_I2C_ADDR, cmd, 8, 100)) != HAL_OK)
369 HAL_StatusTypeDef status;
375 writeLog(
"sps30 clearing start, status:%d", (
int) status);
376 if (status == HAL_OK)
379 writeLog(
"sps30 clearing process, status:%d", (
int) status);
381 if (status == HAL_OK)
396 writeLog(
"sps30 clearing stop, status:%d", (
int) status);
This file contains all the function prototypes for the i2c.c file.
HAL_StatusTypeDef I2C_IsDeviceReadyMT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)
Wrapper around HAL_I2C_IsDeviceReady() that recovers from a busy bus. If the HAL I2C bus is in a BUSY...
void writeLog(const char *format,...)
Format and send a log message over UART (printf-style). Available only when WRITELOG is defined; comp...
#define PRIf_02D(fData)
Expands to integer and fractional arguments for use with PRIf_02. Splits a float/double into the inte...
#define PRIf_02
printf format string for printing a float/double as integer with 2 decimal places....
mems_MainBlock_t _memsMainBlock
Global instance of the main flash control block; loaded by mems_ReadMainBlock().
HAL_StatusTypeDef mems_WriteMainBlock()
writing the main block on flash. The main block is stored on address 0
uint8_t systemParams_CalculateCrc(uint8_t *data, uint8_t len)
Calculate a CRC-8 checksum (Sensirion polynomial) over a byte buffer. Used to validate sensor I2C res...
AQI_Level_t sps30_ClassifyPM25(char **label)
Classify the current PM2.5 mass concentration according to the AQI scale.
HAL_StatusTypeDef sps30_Read(I2C_HandleTypeDef *hi2c)
Read data if data is available.
HAL_StatusTypeDef sps30_StartCleaning(I2C_HandleTypeDef *hi2c)
manually start fan for cleaning, runs for about 10s Note: The sensor will be busy cleaning for 10 sec...
static sleeper_t _clearingTime
#define SPS30_CMD_START_CLEAN
#define SPS30_CMD_CLEAN_INTERVAL
#define SPS30_CMD_STOP_MEAS
void sps30_LogData(char *buf)
log data to buffer
HAL_StatusTypeDef sps30_SetAutoCleanInterval(I2C_HandleTypeDef *hi2c, uint32_t interval_sec)
set interval for auto cleaning
#define SPS30_CMD_READ_MEAS
#define SPS30_CMD_START_MEAS
HAL_StatusTypeDef sps30_IsOnOff(I2C_HandleTypeDef *hi2c, uint8_t *onOff)
helper to check if sensor is on or not
HAL_StatusTypeDef sps30_Off(I2C_HandleTypeDef *hi2c)
Turn off laser and fan to stop measurements.
static const uint8_t _cleaningInterval
HAL_StatusTypeDef sps30_GetAutoCleanInterval(I2C_HandleTypeDef *hi2c, uint32_t *interval_sec)
interval for auto cleaning
#define SPS30_CMD_SOFT_RESET
int8_t sps30_Is(I2C_HandleTypeDef *hi2c, int8_t tryInit)
check if SPS30 sensor is present
int8_t sps30_Service(I2C_HandleTypeDef *hi2c)
the sensor need to be cleaning
HAL_StatusTypeDef sps30_Init(I2C_HandleTypeDef *hi2c)
initialization of sensor sps30
HAL_StatusTypeDef sps30_IsDataReady(I2C_HandleTypeDef *hi2c)
Check if data is available.
static clearing_t _isClearing
HAL_StatusTypeDef sps30_On(I2C_HandleTypeDef *hi2c)
Turn on laser and fan to allow measurements.
#define SPS30_CMD_READ_DRDY
sps30_t _bck_sps30Data
Snapshot copy of the last completed SPS30 measurement; used for LoRaWAN transmission.
AQI_Level_t
Air Quality Index (AQI) level based on PM2.5 mass concentration. Follows US EPA / WHO PM2....
@ AQI_UNHEALTHY_SENSITIVE
sps30_t _sps30Data
Live measurement data from the SPS30 sensor; updated by sps30_Read().
Non-blocking timer utility – similar to HAL_Delay but without CPU blocking.
Measurement data produced by the SPS30 particulate matter sensor. Populated by sps30_Read(); check Is...
void HAL_Delay(__IO uint32_t Delay)
void sleeper_Init(sleeper_t *v, uint32_t sleepMS)
Initialise the sleeper and start timing from now.
int sleeper_IsElapsed(const sleeper_t *v)
Check whether the configured time interval has elapsed.