Seperated AHT10 driver.

This commit is contained in:
imi415 2022-07-01 23:44:15 +08:00
parent 0114304002
commit 108549e5ee
Signed by: imi415
GPG Key ID: 885EC2B5A8A6F8A7
5 changed files with 221 additions and 80 deletions

View File

@ -3,6 +3,7 @@ IndentWidth: 4
AlignConsecutiveMacros: Consecutive
AlignConsecutiveDeclarations: true
AlignConsecutiveAssignments: true
AllowShortFunctionsOnASingleLine: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: false

View File

@ -3,8 +3,14 @@ cmake_minimum_required(VERSION 3.10)
project(usbsio_dhtsensor)
set(USBSIO_DHT_SRCS
"src/aht10.c"
"src/main.c"
)
set(USBSIO_DHT_INCLUDES
"include"
)
add_executable(${PROJECT_NAME} ${USBSIO_DHT_SRCS})
target_include_directories(${PROJECT_NAME} PRIVATE ${USBSIO_DHT_INCLUDES})
target_link_libraries(${PROJECT_NAME} PRIVATE "usbsio")

View File

@ -0,0 +1,42 @@
#ifndef AHT10_H
#define AHT10_H
#include <stdint.h>
#define AHT10_SKIP_BUSY_CHECK
typedef enum {
AHT10_OK,
AHT10_FAIL,
} aht10_ret_t;
typedef struct {
uint8_t *tx_data;
uint8_t *rx_data;
uint16_t tx_size;
uint16_t rx_size;
} aht10_xfer_desc_t;
typedef aht10_ret_t (*aht10_i2c_xfer_t)(void *pdev, aht10_xfer_desc_t *xfer);
typedef aht10_ret_t (*aht10_delay_t)(void *pdev, uint32_t delay_msec);
typedef struct {
double temperature;
double humidity;
} aht10_result_t;
typedef struct {
aht10_i2c_xfer_t xfer;
aht10_delay_t delay;
} aht10_cb_t;
typedef struct {
aht10_cb_t cb;
void *user_data;
} aht10_t;
aht10_ret_t aht10_init(aht10_t *aht);
aht10_ret_t aht10_measure(aht10_t *aht, aht10_result_t *result);
#endif

View File

@ -0,0 +1,132 @@
#include <stddef.h>
/* Private header */
#include "aht10.h"
#define AHT10_STATUS_CALIBRATED_MASK (1U << 3U)
#define AHT10_STATUS_BUSY_MASK (1U << 7U)
#define AHT10_ERROR_CHECK(x) \
if (x != AHT10_OK) return AHT10_FAIL
typedef struct {
uint8_t status;
uint32_t temperature;
uint32_t humidity;
} aht10_raw_t;
static aht10_ret_t aht10_software_reset(aht10_t *aht) {
/* Reset and initialize device */
uint8_t tx_data[3] = {0xBA};
aht10_xfer_desc_t xfer = {
.tx_data = tx_data,
.tx_size = 1U,
.rx_data = NULL,
.rx_size = 0U,
};
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 20));
tx_data[0] = 0xE1;
tx_data[1] = 0x08;
tx_data[2] = 0x00;
xfer.tx_size = 3U;
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
}
static aht10_ret_t aht10_start_measurement(aht10_t *aht) {
/* Start measurement */
uint8_t tx_data[3] = {0xAC, 0x33, 0x00};
aht10_xfer_desc_t xfer = {
.tx_data = tx_data,
.tx_size = 3U,
.rx_data = NULL,
.rx_size = 0U,
};
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
return AHT10_OK;
}
static aht10_ret_t aht10_read_result(aht10_t *aht, aht10_raw_t *raw) {
/* Read conversion result */
uint8_t tx_data[] = {0x71};
uint8_t rx_data[6];
aht10_xfer_desc_t xfer = {
.tx_data = tx_data,
.tx_size = 1U,
.rx_data = rx_data,
.rx_size = 6U,
};
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
raw->humidity = rx_data[1] << 12U;
raw->humidity |= rx_data[2] << 4U;
raw->humidity |= rx_data[3] >> 4U;
raw->temperature = (rx_data[3] & 0x0FU) << 16U;
raw->temperature |= rx_data[4] << 8U;
raw->temperature |= rx_data[5];
raw->status = rx_data[0];
return AHT10_OK;
}
aht10_ret_t aht10_init(aht10_t *aht) {
/* Check if we need initialization */
/* Delay 40ms after POR */
AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 40));
aht10_raw_t raw;
/* Check 0x71 status byte, if uncalibrated then reset and calibrate it. */
AHT10_ERROR_CHECK(aht10_read_result(aht, &raw));
if ((raw.status & AHT10_STATUS_CALIBRATED_MASK) == 0) {
AHT10_ERROR_CHECK(aht10_software_reset(aht));
}
return AHT10_OK;
}
aht10_ret_t aht10_measure(aht10_t *aht, aht10_result_t *result) {
/* Start a measurement and read back result... */
AHT10_ERROR_CHECK(aht10_start_measurement(aht));
AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 80));
aht10_raw_t raw;
uint8_t max_retries = 5U;
do {
AHT10_ERROR_CHECK(aht10_read_result(aht, &raw));
max_retries--;
if (max_retries == 0) {
return AHT10_FAIL;
}
#ifndef AHT10_SKIP_BUSY_CHECK
} while (raw.status & AHT10_STATUS_BUSY_MASK);
#else
} while (0);
#endif
result->temperature = ((double)raw.temperature * 200.0 / 1048576.0) - 50.0;
result->humidity = (double)raw.humidity * 100.0 / 1048576.0;
return AHT10_OK;
}

View File

@ -7,14 +7,17 @@
/* USBSIO header */
#include <lpcusbsio.h>
/* AHT10 */
#include "aht10.h"
#define NXP_VID 0x1FC9
#define MCULINK_PID 0x0143
static bool s_running = true;
static int aht10_measure(LPC_HANDLE handle, uint8_t slave_addr, double *temp, double *hum);
static void signal_handler(int sig);
static aht10_ret_t aht_impl_xfer(void *pdev, aht10_xfer_desc_t *xfer);
static aht10_ret_t aht_impl_delay(void *pdev, uint32_t msec);
static void signal_handler(int sig);
int main(int argc, const char *argv) {
int ret;
@ -49,98 +52,55 @@ int main(int argc, const char *argv) {
i2c_handle = I2C_Open(dev_handle, &i2c_cfg, 0);
double temperature = 0.00;
double humidity = 0.00;
aht10_t aht = {
.user_data = i2c_handle,
.cb =
{
.delay = aht_impl_delay,
.xfer = aht_impl_xfer,
},
};
aht10_init(&aht);
aht10_result_t result;
while (s_running) {
int ret = aht10_measure(i2c_handle, 0x38, &temperature, &humidity);
if(ret < 0) {
if (aht10_measure(&aht, &result) != AHT10_OK) {
fprintf(stderr, "Sensor communication error.\n");
}
else {
fprintf(stdout, "Temperature: %.2fC, humidity: %.2f%%\n", temperature, humidity);
} else {
fprintf(stdout, "Temperature: %.3fC, humidity: %.3f%%\n", result.temperature, result.humidity);
}
usleep(100 * 1000);
}
}
static int aht10_measure(LPC_HANDLE handle, uint8_t slave_addr, double *temp, double *hum) {
uint8_t tx_buffer[3] = {0x71, 0x00, 0x00};
uint8_t rx_buffer[6];
static aht10_ret_t aht_impl_xfer(void *pdev, aht10_xfer_desc_t *xfer) {
LPC_HANDLE i2c_handle = pdev;
I2C_FAST_XFER_T xfer = {
.slaveAddr = slave_addr,
.txSz = 1U,
.txBuff = tx_buffer,
.rxSz = 1U,
.rxBuff = rx_buffer,
I2C_FAST_XFER_T i2c_xfer = {
.options = 0U,
.slaveAddr = 0x38,
.rxBuff = xfer->rx_data,
.rxSz = xfer->rx_size,
.txBuff = xfer->tx_data,
.txSz = xfer->tx_size,
};
usleep(40 * 1000);
int ret = I2C_FastXfer(handle, &xfer);
int ret = I2C_FastXfer(i2c_handle, &i2c_xfer);
if (ret < 0) {
I2C_Reset(handle);
return ret;
return AHT10_FAIL;
}
if ((rx_buffer[0] & 0x08) == 0U) {
/* BIT3 indicates AHT10 not calibrated, send initialization command */
tx_buffer[0] = 0xE1;
tx_buffer[1] = 0x08;
tx_buffer[2] = 0x00;
xfer.txSz = 0x03;
xfer.rxSz = 0x00;
ret = I2C_FastXfer(handle, &xfer);
if (ret < 0) {
I2C_Reset(handle);
return ret;
}
usleep(40 * 1000);
}
tx_buffer[0] = 0xAC;
tx_buffer[1] = 0x33;
tx_buffer[2] = 0x00;
xfer.txSz = 0x03;
xfer.rxSz = 0x00;
ret = I2C_FastXfer(handle, &xfer);
if (ret < 0) {
I2C_Reset(handle);
return ret;
}
usleep(80 * 1000);
tx_buffer[0] = 0x71;
xfer.txSz = 0x01;
xfer.rxSz = 0x06;
ret = I2C_FastXfer(handle, &xfer);
if (ret < 0) {
I2C_Reset(handle);
return ret;
}
uint32_t humid_raw = rx_buffer[1] << 12U;
humid_raw |= rx_buffer[2] << 4U;
humid_raw |= rx_buffer[3] >> 4U;
uint32_t temp_raw = (rx_buffer[3] & 0x0FU) << 16U;
temp_raw |= rx_buffer[4] << 8U;
temp_raw |= rx_buffer[5];
*hum = (double)humid_raw * 100.0 / 1048576.0;
*temp = ((double)temp_raw * 200.0 / 1048576.0) - 50.0;
return ret;
return AHT10_OK;
}
static void signal_handler(int sig) { s_running = false; }
static aht10_ret_t aht_impl_delay(void *pdev, uint32_t msec) {
usleep(msec * 1000);
return AHT10_OK;
}
static void signal_handler(int sig) {
s_running = false;
}