Initial import. master
authorNot Zed <notzed@gmail.com>
Sat, 9 Nov 2024 23:46:58 +0000 (10:16 +1030)
committerNot Zed <notzed@gmail.com>
Sat, 9 Nov 2024 23:46:58 +0000 (10:16 +1030)
CMakeLists.txt [new file with mode: 0644]
README [new file with mode: 0644]
esp-aht30.c [new file with mode: 0644]
include/esp-aht30.h [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8648526
--- /dev/null
@@ -0,0 +1,3 @@
+idf_component_register(SRCS "esp-aht30.c"
+                    INCLUDE_DIRS "include"
+                   REQUIRES esp_driver_i2c)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..fec426e
--- /dev/null
+++ b/README
@@ -0,0 +1,57 @@
+
+Copyright (C) 2024 Michael Zucchi
+
+See the section LICENSE for details.
+
+Introduction
+------------
+
+esp-aht30 is an i2c driver for the ASAIR AHT30 temperature and
+humidity sensor.
+
+Compile
+-------
+
+This is an esp-idf component which needs to be copied to the
+components directory of your project or otherwise referenced by the
+esp-idf build system for your project.
+
+Then add REQUIRES esp-aht30 to idf_component_register() for the
+project.
+
+Usage
+-----
+
+See the header.
+
+Links
+-----
+
+* browse source  <https://code.zedzone.au/cvs?p=esp-aht30&a=tree>
+  source code    <https://code.zedzone.au/git/esp-aht30>
+
+* esp-idf        <https://github.com/espressif/esp-idf>
+
+* AHT30          <https://asairsensors.com/product/aht30-integrated-temperature-and-humidity-sensor/>
+
+LICENSE
+-------
+
+This code is licensed under GNU General Public License version
+3, see COPYING for the full details.
+
+    Copyright (C) 2024 Michael Zucchi
+
+    This program is free software: you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation, either version 3 of the
+    License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see
+    <http://www.gnu.org/licenses/>.
diff --git a/esp-aht30.c b/esp-aht30.c
new file mode 100644 (file)
index 0000000..a8c95f7
--- /dev/null
@@ -0,0 +1,60 @@
+#include <stdio.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "esp-aht30.h"
+
+static const uint8_t aht30_update_seq[] = { 0xac, 0x33, 0x00 };
+
+static uint8_t crc8(uint8_t *msg, size_t n) {
+       uint8_t crc = 0xff;
+       uint8_t *end = msg + n;
+
+       while (msg < end) {
+               crc ^= *msg++;
+               for (int i=0;i<8;i++) {
+                       if (crc & 0x80)
+                               crc = (crc << 1) ^ 0x31;
+                       else
+                               crc = (crc << 1);
+               }
+       }
+
+       return crc;
+}
+
+esp_err_t aht30_init(i2c_master_bus_handle_t bus, const aht30_config_t *config, aht30_handle_t *aht) {
+       i2c_device_config_t i2c_dev_conf = {
+               .dev_addr_length = I2C_ADDR_BIT_LEN_7,
+               .device_address = AHT30_ADDR,
+               .scl_speed_hz = config ? config->scl_speed_hz : 400000,
+               .scl_wait_us = config ? config->scl_wait_us : 20000,
+       };
+
+       return i2c_master_bus_add_device(bus, &i2c_dev_conf, &aht->dev);
+}
+
+esp_err_t aht30_delete(aht30_handle_t *aht) {
+       return i2c_master_bus_rm_device(aht->dev);
+}
+
+esp_err_t aht30_read(aht30_handle_t *aht, aht30_reading_t *res) {
+       uint8_t data[7];
+
+       // request sensor update
+       ESP_ERROR_CHECK(i2c_master_transmit(aht->dev, aht30_update_seq, sizeof(aht30_update_seq), 500));
+
+       // delay required 80ms
+       vTaskDelay(80 / portTICK_PERIOD_MS);
+
+       // poll result
+       ESP_ERROR_CHECK(i2c_master_receive(aht->dev, data, 7, 500));
+
+       res->status = data[0];
+       res->valid = crc8(data, 6) == data[6];
+       res->humidity = (data[1] << 12 | data[2] << 4 | data[3] >> 4) * 100;
+       res->temperature = ((data[3] << 16 | data[4] << 8 | data[5]) & 0xfffff) * 200 - (50 << 20);
+
+       return 0;
+}
diff --git a/include/esp-aht30.h b/include/esp-aht30.h
new file mode 100644 (file)
index 0000000..7f8331f
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef ESP_AHT30_H
+#define ESP_AHT30_H
+
+#include "driver/i2c_master.h"
+
+struct aht30_reading {
+       uint8_t status;
+       uint8_t valid;          /* if crc check passed */
+       int32_t temperature;    /* deg C, fixed point 12.20 */
+       uint32_t humidity;      /* RH%, fixed point 12.20 */
+};
+
+typedef struct aht30_reading aht30_reading_t;
+
+#define AHT30_ADDR (0x38)
+#define AHT30_STATUS_BUSY 0x80
+#define AHT30_STATUS_CRC_PASSED 0x10
+#define AHT30_STATUS_CALIBRATED 0x08
+
+struct aht30_config {
+       uint32_t scl_speed_hz;
+       uint32_t scl_wait_us;
+};
+
+typedef struct aht30_config aht30_config_t;
+
+struct aht30_handle {
+       i2c_master_dev_handle_t dev;
+};
+
+typedef struct aht30_handle aht30_handle_t;
+
+esp_err_t aht30_init(i2c_master_bus_handle_t bus, const aht30_config_t *config, aht30_handle_t *handle);
+esp_err_t aht30_delete(aht30_handle_t *aht);
+
+esp_err_t aht30_read(aht30_handle_t *aht, aht30_reading_t *res);
+
+#endif