commit 0b57fc0a3cf05c64f2d360cf3c28307029fc6580 Author: Jan Mrna Date: Sun Jun 12 22:49:01 2022 +0200 Added files (not yet modified) diff --git a/scd4x.c b/scd4x.c new file mode 100644 index 0000000..330d74d --- /dev/null +++ b/scd4x.c @@ -0,0 +1,129 @@ +/* + * sht4x.c + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#include "scd4x.h" +#include "main.h" /* for uart_disable_interrupts() */ + +int8_t scd4x_send_cmd(scd4x_cmd_t cmd) +{ + uint8_t buffer[32]; + int result; + + // start measurement + buffer[0] = cmd >> 8; + buffer[1] = cmd & 0x00ff; + result = i2c_transmit(SCD4X_I2C_ADDRESS<<1, buffer, 2); + if (result == I2C_ERROR_TX_INCOMPLETE) { + return SCD4X_ERROR; + } + + /* Sensirion sensors return NACK after last byte (so NACK at the end is ok) */ + return SCD4X_OK; +} + +int8_t scd4x_get_serial(uint8_t serial[6]) +{ + uint8_t buffer[16]; + int result; + + scd4x_send_cmd(SCD4X_GET_SERIAL_NUMBER); + result = i2c_receive(SCD4X_I2C_ADDRESS << 1, buffer, 9); + if (result != I2C_OK) { + return SCD4X_ERROR; + } + return SCD4X_OK; +} + +int8_t scd4x_read_data(uint8_t *buffer, int len) +{ + return SCD4X_OK; +} + +int8_t scd4x_start_periodic_measurement( void ) +{ + return scd4x_send_cmd(SCD4X_START_PERIODIC_MEASUREMENT); +} + +int8_t scd4x_stop_periodic_measurement( void ) +{ + return scd4x_send_cmd(SCD4X_STOP_PERIODIC_MEASUREMENT); +} + +int8_t scd4x_perform_factory_reset( void ) +{ + return scd4x_send_cmd(SCD4X_PERFORM_FACTORY_RESET); +} + +int8_t scd4x_read_measurement(uint16_t *co2, int16_t *temperature, uint16_t *relative_humidity) +{ + uint8_t buffer[32]; + int result; + + // start measurement + // TODO: Check for data ready + /* + buffer[0] = GET_DATA_READY_STATUS >> 8; + buffer[1] = GET_DATA_READY_STATUS & 0x00ff; + result = i2c_transmit(SCD4X_I2C_ADDRESS<<1, buffer, 2); + if (result != I2C_OK) { + return SCD4X_ERROR; + } + LL_mDelay(100); // 10 ms should be enough + // read out + result = i2c_receive(SCD4X_I2C_ADDRESS<<1, buffer, 6); + if (result != I2C_OK) { + return SCD4X_ERROR; + }*/ + + // start measurement + buffer[0] = SCD4X_READ_MEASUREMENT >> 8; + buffer[1] = SCD4X_READ_MEASUREMENT & 0x00ff; + // disable interrupts to prevent MODBUS/I2C conflict + uart_disable_interrupts(); + result = i2c_transmit(SCD4X_I2C_ADDRESS<<1, buffer, 2); + uart_enable_interrupts(); + if (result != I2C_OK) { + return SCD4X_ERROR; + } + LL_mDelay(1); // 10 ms should be enough + // read out + uart_disable_interrupts(); + result = i2c_receive(SCD4X_I2C_ADDRESS<<1, buffer, 9); + uart_enable_interrupts(); + if (result != I2C_OK) + { + return SCD4X_ERROR; + } + /* Convert to T and RH; taken directly from pseudocode in SHT4x datasheet, page 3 */ + uint32_t co2_ticks = (buffer[0] << 8) + buffer[1]; + uint8_t co2_crc = buffer[2]; + uint32_t t_ticks = (buffer[3] << 8) + buffer[4]; + uint8_t t_crc = buffer[5]; + uint32_t rh_ticks = (buffer[6] << 8) + buffer[7]; + uint8_t rh_crc = buffer[8]; + /* check CRC-8 checksum */ + uint8_t crc_correct = crc8_calculate(buffer, 2) == co2_crc; + crc_correct &= crc8_calculate(buffer + 3, 2) == t_crc; + crc_correct &= crc8_calculate(buffer + 6, 2) == rh_crc; + if (!crc_correct) { + return SCD4X_CRC8_ERROR; + } + /* copy to output variables */ + int t_degC = -450 + 10 * 175 * t_ticks / 65535; + int rh_pRH = 100 * rh_ticks / 65535; + if (rh_pRH > 100) { + rh_pRH = 100; + } + if (rh_pRH < 0) { + rh_pRH = 0; + } + *co2 = co2_ticks; + *temperature = t_degC; + *relative_humidity = rh_pRH; + + return SCD4X_OK; +} diff --git a/scd4x.h b/scd4x.h new file mode 100644 index 0000000..426ff74 --- /dev/null +++ b/scd4x.h @@ -0,0 +1,58 @@ +/* + * sht4x.h + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#ifndef INC_SCD4X_H_ +#define INC_SCD4X_H_ + +#include "stdint.h" +#include "stm32l0xx_ll_i2c.h" +#include "stm32l0xx_ll_utils.h" +#include "i2c.h" +#include "crc8.h" + +/* + * Defines & macros + */ + +#define SCD4X_I2C_ADDRESS 0x62 + +/* + * Return values + */ + +#define SCD4X_OK 0 +#define SCD4X_ERROR -1 // generic error +#define SCD4X_CRC8_ERROR -2 // checksum failed + +/* + * Data types + */ + +typedef enum { + SCD4X_START_PERIODIC_MEASUREMENT = 0x21B1, + SCD4X_READ_MEASUREMENT = 0xEC05, + SCD4X_STOP_PERIODIC_MEASUREMENT = 0x3F86, + SCD4X_GET_DATA_READY_STATUS = 0xE4B8, + SCD4X_PERFORM_FACTORY_RESET = 0x3632, + SCD4X_GET_SERIAL_NUMBER = 0x3682 +} scd4x_cmd_t; + +/* + * Function prototypes + */ + +int8_t scd4x_send_cmd(scd4x_cmd_t cmd); +int8_t scd4x_read_data(uint8_t *buffer, int len); + +int8_t scd4x_start_periodic_measurement( void ); +int8_t scd4x_stop_periodic_measurement( void ); + +int8_t scd4x_perform_factory_reset( void ); + +int8_t scd4x_read_measurement(uint16_t * co2, int16_t *temperature, uint16_t *relative_humidity); + +#endif /* INC_SCD4X_H_ */