Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated sht driver + header #172

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 32 additions & 25 deletions general/include/sht30.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
#ifndef sht30_h
#define sht30_h
#ifndef SHT30_H
#define SHT30_H

#include "stm32xx_hal.h"
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>

/**
* https://www.mouser.com/datasheet/2/682/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital-971521.pdf
* --Datasheet
*
*/
#define SHT30_I2C_ADDR 0x44 << 1u /* If ADDR (pin2) is connected to VDD, 0x45 \
*/
*/
#define SHT30_I2C_ADDR (0x44u << 1u) /* If ADDR (pin2) is connected to VDD, 0x45 */

typedef enum {
SHT3X_COMMAND_MEASURE_HIGHREP_STRETCH = 0x2c06,
SHT3X_COMMAND_CLEAR_STATUS = 0x3041,
SHT3X_COMMAND_SOFT_RESET = 0x30A2,
SHT3X_COMMAND_HEATER_ENABLE = 0x306d,
SHT3X_COMMAND_HEATER_DISABLE = 0x3066,
SHT3X_COMMAND_READ_STATUS = 0xf32d,
SHT3X_COMMAND_FETCH_DATA = 0xe000,
SHT3X_COMMAND_MEASURE_HIGHREP_10HZ = 0x2737,
SHT3X_COMMAND_MEASURE_LOWREP_10HZ = 0x272a
SHT3X_COMMAND_MEASURE_HIGHREP_STRETCH = 0x2c06u,
SHT3X_COMMAND_CLEAR_STATUS = 0x3041u,
SHT3X_COMMAND_SOFT_RESET = 0x30A2u,
SHT3X_COMMAND_HEATER_ENABLE = 0x306du,
SHT3X_COMMAND_HEATER_DISABLE = 0x3066u,
SHT3X_COMMAND_READ_STATUS = 0xf32du,
SHT3X_COMMAND_FETCH_DATA = 0xe000u,
SHT3X_COMMAND_MEASURE_HIGHREP_10HZ = 0x2737u,
SHT3X_COMMAND_MEASURE_LOWREP_10HZ = 0x272au
} sht3x_command_t;

/*
Expand All @@ -36,37 +35,45 @@ typedef enum {
* repeatability */
#define SHT30_START_CMD_NCS 0x2400

// Function pointer types
typedef int (*I2C_TransmitFunc)(uint8_t addr, const uint8_t *data, size_t len, uint32_t timeout);
typedef int (*I2C_ReceiveFunc)(uint8_t addr, uint8_t *data, size_t len, uint32_t timeout);
typedef int (*I2C_MemReadFunc)(uint8_t addr, uint16_t mem_addr, uint16_t mem_addr_size, uint8_t *data, size_t len, uint32_t timeout);
typedef void (*DelayFunc)(uint32_t ms);


typedef struct {
I2C_HandleTypeDef *i2c_handle;
uint16_t status_reg;
I2C_TransmitFunc i2c_transmit;
I2C_ReceiveFunc i2c_receive;
I2C_MemReadFunc i2c_mem_read;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick but can we change the naming here :

I2C_TransmitFunc --> Write_ptr
I2C_ReceieveFunc --> Read_Ptr
I2C_MemReadFunc --> Mem_Read_Ptr

then the instances to "read', "write"m "mem_read"

DelayFunc delay;
uint16_t temp;
uint16_t humidity;
bool is_heater_enabled;
} sht30_t;

/**
* @brief Initializes an SHT30 Driver
*
* @param sht30 - SHT30 driver
* @return HAL_StatusTypeDef
* @return int - 0 on success, negative value on error
*/
HAL_StatusTypeDef sht30_init(sht30_t *sht30);
int sht30_init(sht30_t *sht30);

/**
* @brief Toggles the status of the internal heater
*
* @param sht30 - SHT30 driver
* @param enable - true to enable, false to disable
* @return HAL_StatusTypeDef
* @return int - 0 on success, negative value on error
*/
HAL_StatusTypeDef sht30_toggle_heater(sht30_t *sht30, bool enable);
int sht30_toggle_heater(sht30_t *sht30, bool enable);

/**
* @brief Retrieves the temperature and humidity
*
* @param sht30 - SHT30 driver
* @return HAL_StatusTypeDef
* @return int - 0 on success, negative value on error
*/
HAL_StatusTypeDef sht30_get_temp_humid(sht30_t *sht30);
int sht30_get_temp_humid(sht30_t *sht30);

#endif
#endif
107 changes: 44 additions & 63 deletions general/src/sht30.c
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
#include "sht30.h"
#include <stdbool.h>
#include <stdio.h>

static HAL_StatusTypeDef sht30_write_reg(sht30_t *sht30, uint16_t command) {
uint8_t command_buffer[2] = {(command & 0xff00u) >> 8u, command & 0xffu};

if (HAL_I2C_Master_Transmit(sht30->i2c_handle, SHT30_I2C_ADDR, command_buffer,
sizeof(command_buffer), 30) != HAL_OK) {
return false;
}

return true;
static int sht30_write_reg(const sht30_t *sht30, uint16_t command) {
uint8_t command_buffer[2] = {(uint8_t)((command & 0xff00u) >> 8u), (uint8_t)(command & 0xffu)};
return sht30->i2c_transmit(SHT30_I2C_ADDR, command_buffer, sizeof(command_buffer), 30u);
}

/**
* @brief Calculates the CRC by using the polynomial x^8 + x^5 + x^4 + 1
* @param data: the data to use to calculate the CRC
*/
static uint8_t calculate_crc(const uint8_t *data, size_t length) {
uint8_t crc = 0xff;
for (size_t i = 0; i < length; i++) {
uint8_t crc = 0xffu;
for (size_t i = 0u; i < length; i++) {
crc ^= data[i];
for (size_t j = 0; j < 8; j++) {
if ((crc & 0x80u) != 0) {
for (uint8_t j = 0u; j < 8u; j++) {
if ((crc & 0x80u) != 0u) {
crc = (uint8_t)((uint8_t)(crc << 1u) ^ 0x31u);
} else {
crc <<= 1u;
crc = (uint8_t)(crc << 1u);
}
}
}
Expand All @@ -36,78 +28,67 @@ static uint16_t uint8_to_uint16(uint8_t msb, uint8_t lsb) {
return (uint16_t)((uint16_t)msb << 8u) | lsb;
}

HAL_StatusTypeDef sht30_init(sht30_t *sht30) {
HAL_StatusTypeDef status = HAL_OK;

int sht30_init(sht30_t *sht30) {
uint8_t status_reg_and_checksum[3];
if (HAL_I2C_Mem_Read(sht30->i2c_handle, SHT30_I2C_ADDR,
SHT3X_COMMAND_READ_STATUS, 2,
(uint8_t *)&status_reg_and_checksum,
sizeof(status_reg_and_checksum), 30) != HAL_OK) {
return false;
int status = sht30->i2c_mem_read(SHT30_I2C_ADDR, SHT3X_COMMAND_READ_STATUS, 2u,
status_reg_and_checksum, sizeof(status_reg_and_checksum), 30u);
if (status != 0) {
return status;
}

uint8_t calculated_crc = calculate_crc(status_reg_and_checksum, 2);

uint8_t calculated_crc = calculate_crc(status_reg_and_checksum, 2u);
if (calculated_crc != status_reg_and_checksum[2]) {
return false;
return -1;
}

return status;
return 0;
}

HAL_StatusTypeDef sht30_toggle_heater(sht30_t *sht30, bool enable) {
if (enable) {
return sht30_write_reg(sht30, SHT3X_COMMAND_HEATER_ENABLE);
} else {
return sht30_write_reg(sht30, SHT3X_COMMAND_HEATER_DISABLE);
}
int sht30_toggle_heater(sht30_t *sht30, bool enable) {
if (enable) {
return sht30_write_reg(sht30, SHT3X_COMMAND_HEATER_ENABLE);
} else {
return sht30_write_reg(sht30, SHT3X_COMMAND_HEATER_DISABLE);
}
}

HAL_StatusTypeDef sht30_get_temp_humid(sht30_t *sht30) {
HAL_StatusTypeDef status;

int sht30_get_temp_humid(sht30_t *sht30) {
union {
struct __attribute__((packed)) {
uint16_t
temp; // The packed attribute does not correctly arrange the bytes
uint16_t temp;
uint8_t temp_crc;
uint16_t
humidity; // The packed attribute does not correctly arrange the bytes
uint16_t humidity;
uint8_t humidity_crc;
} raw_data;
uint8_t databuf[6];
} data;

uint16_t temp, humidity;

sht30_write_reg(sht30, (SHT30_START_CMD_WCS));

HAL_Delay(1);

status = HAL_I2C_Master_Receive(sht30->i2c_handle, SHT30_I2C_ADDR,
data.databuf, sizeof(data.databuf), 30);
if (status != HAL_OK) {
return false;
int status = sht30_write_reg(sht30, SHT30_START_CMD_WCS);
if (status != 0) {
return status;
}

temp = uint8_to_uint16(data.databuf[0], data.databuf[1]);
sht30->delay(1u);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair, but lets simplify and not put a delay here, it shouldnt actually be needed. alllows us to remove the delay func ptr entirely


if (data.raw_data.temp_crc != calculate_crc(data.databuf, 2)) {
return HAL_ERROR;
status = sht30->i2c_receive(SHT30_I2C_ADDR, data.databuf, sizeof(data.databuf), 30u);
if (status != 0) {
return status;
}

float val = -45.0f + 175.0f * (float)temp / 65535.0f;
uint16_t temp = uint8_to_uint16(data.databuf[0], data.databuf[1]);
if (data.raw_data.temp_crc != calculate_crc(data.databuf, 2u)) {
return -1;
}

sht30->temp = (uint16_t)val;
uint32_t temp_val = (uint32_t)(175000u * (uint32_t)temp / 65535u - 45000u);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these calcs were changed; thats not in scope of this ticket and i dont feel like checking chatgpts math so can we revert

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we weren't supposed to use floats directly as per the style guide?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, I guess I should be more clear in that bc that's a good catch. That part of the style guide refers to data storage. In this case, it's just use as an intermediary value- the final value that's being stored is an int.

It's okay that values along the way are floats.

Either way, we def try to keep tickets to the scope that they are listed as. If you spot anything u think should be addressed otherwise, you can make another ticket to address that

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sound good, i'll update the PR after I fix everything up

sht30->temp = (uint16_t)(temp_val / 1000u);

humidity = uint8_to_uint16(data.databuf[3], data.databuf[4]);
if (data.raw_data.humidity_crc != calculate_crc(data.databuf + 3, 2)) {
return HAL_ERROR;
uint16_t humidity = uint8_to_uint16(data.databuf[3], data.databuf[4]);
if (data.raw_data.humidity_crc != calculate_crc(data.databuf + 3, 2u)) {
return -1;
}

humidity = (uint16_t)(100.0f * (float)humidity / 65535.0f);
sht30->humidity = humidity;
sht30->humidity = (uint16_t)((100000u * (uint32_t)humidity) / 65535u);

return HAL_OK;
}
return 0;
}
Loading