Seperated AHT10 driver.
This commit is contained in:
parent
0114304002
commit
108549e5ee
|
@ -3,6 +3,7 @@ IndentWidth: 4
|
|||
AlignConsecutiveMacros: Consecutive
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignConsecutiveAssignments: true
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterEnum: false
|
||||
|
|
|
@ -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")
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue