[Mod] AHT10驱动 优化AHT10源码
1. 参考 devctl 使用方法; 2. 参考 QNX 文档,确认:i2c_send_t 后附加发送数据;
This commit is contained in:
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@ -0,0 +1,16 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
||||
|
||||
[*.c]
|
||||
indent_size = 8
|
||||
indent_style = tab
|
||||
@ -7,10 +7,6 @@
|
||||
#include <stdbool.h>
|
||||
#include "aht10_util.h"
|
||||
|
||||
int fd_i2c1 = -1;
|
||||
|
||||
extern bool aht1x_getEvent(sensors_event_t *humidity, sensors_event_t *temp);
|
||||
|
||||
int main() {
|
||||
int ret = 0, fd_i2c_s = 0;
|
||||
i2c_driver_info_t info = {0};
|
||||
@ -22,39 +18,25 @@ int main() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(fd_i2c_s, DCMD_I2C_DRIVER_INFO, &info);
|
||||
ret = aht1x_begin(fd_i2c_s, AHTX0_I2CADDR_DEFAULT);
|
||||
if (ret < 0) {
|
||||
printf("ErrNo(%d) %s, failed to read from I2C device\n", errno, strerror(errno));
|
||||
printf("[%12s|%4u] ErrNo(%d), failed to init AHT1x\n", __FILE_NAME__, __LINE__, ret);
|
||||
close(fd_i2c_s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("I2C Driver Info:\n");
|
||||
printf(" Speed : %#X\n", info.speed_mode); /* supported speeds: I2C_SPEED_* */
|
||||
printf(" Mode-Addr: %#X\n", info.addr_mode); /* supported address fmts: I2C_ADDRFMT_* */
|
||||
printf(" Verbosity: %#X\n", info.verbosity); /* Driver verbosity level */
|
||||
|
||||
|
||||
Adafruit_AHTX0 aht;
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println("Adafruit AHT10/AHT20 demo!");
|
||||
|
||||
if (! aht.begin()) {
|
||||
Serial.println("Could not find AHT? Check wiring");
|
||||
while (1) delay(10);
|
||||
}
|
||||
|
||||
Serial.println("AHT10 or AHT20 found");
|
||||
|
||||
while(1) {
|
||||
sensors_event_t humidity, temp;
|
||||
aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
|
||||
Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
|
||||
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
|
||||
float humidity, temp;
|
||||
ret = aht1x_getEvent(fd_i2c_s, AHTX0_I2CADDR_DEFAULT, &humidity, &temp);
|
||||
if (ret < 0) {
|
||||
printf("[%12s|%4u] ErrNo(%d), failed to read data from AHT1x\n", __FILE_NAME__, __LINE__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
delay(500);
|
||||
printf("Temperature: %2.3f degrees C\n", temp);
|
||||
printf("Humidity : %2.3f %% rH\n", humidity);
|
||||
|
||||
usleep(500000); // wait 500ms before next read
|
||||
}
|
||||
|
||||
close(fd_i2c_s);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <hw/i2c.h>
|
||||
@ -7,9 +8,90 @@
|
||||
#include <stdbool.h>
|
||||
#include "aht10_util.h"
|
||||
|
||||
float _humidity = 0, _temperature = 0;
|
||||
static int fd_i2c;
|
||||
|
||||
extern int fd_i2c1;
|
||||
static int _i2c_read(uint8_t address, uint8_t *data, size_t length, uint8_t stop)
|
||||
{
|
||||
int ret = 0;
|
||||
char *data_recv = NULL;
|
||||
unsigned int recv_lent = sizeof(i2c_recv_t) + length;
|
||||
i2c_recv_t *data_msg = NULL, *data_buf = NULL;
|
||||
|
||||
data_recv = malloc(recv_lent);
|
||||
if (data_recv == NULL) {
|
||||
printf("Failed to allocate memory for I2C read\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(data_recv, 0, recv_lent);
|
||||
|
||||
data_msg = (i2c_recv_t *)data_recv;
|
||||
data_buf = (char *)data_recv + sizeof(*data_msg);
|
||||
|
||||
data_msg->slave.addr = address;
|
||||
data_msg->slave.fmt = I2C_ADDRFMT_7BIT;
|
||||
data_msg->len = length;
|
||||
data_msg->stop = stop;
|
||||
|
||||
ret = devctl(fd_i2c, DCMD_I2C_RECV, data_msg, recv_lent, NULL);
|
||||
if (ret < 0) {
|
||||
printf("[%s|%u] ErrNo(%d) %s, failed to read I2C data\n", __FILE__, __LINE__, errno, strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _i2c_write(uint8_t address, const uint8_t *data, size_t length, uint8_t stop)
|
||||
{
|
||||
int ret = 0;
|
||||
char *data_send = NULL;
|
||||
i2c_send_t *data_msg = NULL;
|
||||
unsigned int send_lent = sizeof(i2c_send_t) + length;
|
||||
|
||||
data_send = malloc (send_lent);
|
||||
if (data_send == NULL) {
|
||||
printf("Failed to allocate memory for I2C write\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(data_send, 0, send_lent);
|
||||
|
||||
data_msg = (i2c_send_t *)data_send;
|
||||
data_msg->slave.addr = address;
|
||||
data_msg->slave.fmt = I2C_ADDRFMT_7BIT;
|
||||
data_msg->len = length;
|
||||
data_msg->stop = stop;
|
||||
|
||||
memcpy ((char *)data_send + sizeof(*data_msg), data, length);
|
||||
|
||||
ret = devctl(fd_i2c, DCMD_I2C_SEND, data_send, send_lent, NULL);
|
||||
if (ret < 0) {
|
||||
printf("[%12s|%4u] ErrNo(%d) %s, failed to write I2C data\n", __FILE_NAME__, __LINE__, errno, strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the status (first byte) from AHT10/AHT20
|
||||
*
|
||||
* @returns 8 bits of status data, or 0xFF if failed
|
||||
*/
|
||||
static int aht1x_getStatus(uint8_t address)
|
||||
{
|
||||
int ret;
|
||||
uint8_t recv_data[1] = {0};
|
||||
|
||||
ret = _i2c_read(address, recv_data, 1, 1);
|
||||
if (ret < 0) {
|
||||
printf("[%s|%4u] ErrNo(%d) %s, failed to read date from I2C Address[%#X]\n", __FILE_NAME__, __LINE__, ret, address);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return recv_data[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets up the hardware and initializes I2C
|
||||
@ -21,63 +103,47 @@ extern int fd_i2c1;
|
||||
* The I2C address used to communicate with the sensor
|
||||
* @return True if initialization was successful, otherwise false.
|
||||
*/
|
||||
bool aht1x_begin(TwoWire *wire, int32_t sensor_id, uint8_t i2c_address)
|
||||
int aht1x_begin(int i2c_dev, uint8_t i2c_address)
|
||||
{
|
||||
delay(20); // 20 ms to power up
|
||||
int ret = 0;
|
||||
uint8_t cmd[3] = {0};
|
||||
|
||||
if (i2c_dev) {
|
||||
delete i2c_dev; // remove old interface
|
||||
if (i2c_dev < 0) {
|
||||
printf("Error, invalid I2C device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2c_dev = new Adafruit_I2CDevice(i2c_address, wire);
|
||||
|
||||
if (!i2c_dev->begin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t cmd[3];
|
||||
fd_i2c = i2c_dev;
|
||||
|
||||
cmd[0] = AHTX0_CMD_SOFTRESET;
|
||||
if (!i2c_dev->write(cmd, 1)) {
|
||||
return false;
|
||||
ret = _i2c_write(i2c_address, cmd, 1, 0);
|
||||
if (ret < 0) {
|
||||
printf("[%12s|%4u] ErrNo(%d), failed to write SOFTRESET command\n", __FILE_NAME__, __LINE__, ret);
|
||||
return ret;
|
||||
}
|
||||
delay(20);
|
||||
|
||||
while (getStatus() & AHTX0_STATUS_BUSY) {
|
||||
delay(10);
|
||||
usleep(20000); // 20ms delay
|
||||
|
||||
while (aht1x_getStatus(i2c_address) & AHTX0_STATUS_BUSY) {
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
cmd[0] = AHTX0_CMD_CALIBRATE;
|
||||
cmd[1] = 0x08;
|
||||
cmd[2] = 0x00;
|
||||
i2c_dev->write(cmd, 3); // may not 'succeed' on newer AHT20s
|
||||
|
||||
while (getStatus() & AHTX0_STATUS_BUSY) {
|
||||
delay(10);
|
||||
}
|
||||
if (!(getStatus() & AHTX0_STATUS_CALIBRATED)) {
|
||||
ret = _i2c_write(i2c_address, cmd, 3, 1);
|
||||
if (ret < 0) {
|
||||
printf("ErrNo(%d) %s, failed to write CALIBRATE command\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
delete humidity_sensor;
|
||||
|
||||
|
||||
temp_sensor = new Adafruit_AHTX0_Temp(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the status (first byte) from AHT10/AHT20
|
||||
*
|
||||
* @returns 8 bits of status data, or 0xFF if failed
|
||||
*/
|
||||
uint8_t aht1x_getStatus(void)
|
||||
{
|
||||
uint8_t ret;
|
||||
if (!i2c_dev->read(&ret, 1)) {
|
||||
return 0xFF;
|
||||
while (aht1x_getStatus(i2c_address) & AHTX0_STATUS_BUSY) {
|
||||
delay(10);
|
||||
}
|
||||
return ret;
|
||||
if (!(aht1x_getStatus(i2c_address) & AHTX0_STATUS_CALIBRATED)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@ -89,42 +155,42 @@ uint8_t aht1x_getStatus(void)
|
||||
@returns true if the event data was read successfully
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool aht1x_getEvent(sensors_event_t *humidity, sensors_event_t *temp)
|
||||
int aht1x_getEvent(int i2c_dev, uint8_t i2c_address, float *_humidity, float *_temperature)
|
||||
{
|
||||
uint32_t t = millis();
|
||||
int ret = 0;
|
||||
|
||||
// read the data and store it!
|
||||
uint8_t cmd[3] = {AHTX0_CMD_TRIGGER, 0x33, 0};
|
||||
if (!i2c_dev->write(cmd, 3)) {
|
||||
return false;
|
||||
ret = _i2c_write(i2c_address, cmd, 3, 1);
|
||||
if (ret < 0) {
|
||||
printf("[%s|%4u] ErrNo(%d) %s, failed to write TRIGGER command\n", __FILE_NAME__, __LINE__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (getStatus() & AHTX0_STATUS_BUSY) {
|
||||
while (aht1x_getStatus(i2c_address) & AHTX0_STATUS_BUSY) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
uint8_t data[6];
|
||||
if (!i2c_dev->read(data, 6)) {
|
||||
return false;
|
||||
ret = _i2c_read(i2c_address, data, 6, 1);
|
||||
if (ret < 0) {
|
||||
printf("[%s|%4u] ErrNo(%d) %s, failed to read date from I2C Address[%#X]\n", __FILE_NAME__, __LINE__, ret, i2c_address);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t h = data[1];
|
||||
h <<= 8;
|
||||
h |= data[2];
|
||||
h <<= 4;
|
||||
h |= data[3] >> 4;
|
||||
_humidity = ((float)h * 100) / 0x100000;
|
||||
*_humidity = ((float)h * 100) / 0x100000;
|
||||
|
||||
uint32_t tdata = data[3] & 0x0F;
|
||||
tdata <<= 8;
|
||||
tdata |= data[4];
|
||||
tdata <<= 8;
|
||||
tdata |= data[5];
|
||||
_temperature = ((float)tdata * 200 / 0x100000) - 50;
|
||||
*_temperature = ((float)tdata * 200 / 0x100000) - 50;
|
||||
|
||||
// use helpers to fill in the events
|
||||
if (temp)
|
||||
fillTempEvent(temp, t);
|
||||
if (humidity)
|
||||
fillHumidityEvent(humidity, t);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#define AHTX0_STATUS_BUSY 0x80 ///< Status bit for busy
|
||||
#define AHTX0_STATUS_CALIBRATED 0x08 ///< Status bit for calibrated
|
||||
|
||||
bool aht1x_getEvent(sensors_event_t *humidity, sensors_event_t *temp);
|
||||
int aht1x_begin(int i2c_dev, uint8_t i2c_address);
|
||||
int aht1x_getEvent(int i2c_dev, uint8_t i2c_address, float *_humidity, float *_temperature);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user