`
今天来写一篇关于使用环境监测板的帖子。主要完成温湿度传感器数据采集和烟雾传感器的数据采集,然后把采集到的数据打印输出。
一、硬件介绍
通过查看环境监测板的原理图,发现该板子主要有三个板子资源:AHT20温湿度传感器、MQ-2烟雾传感器、蜂鸣器。
它们使用主控的GPIO口分别为:AHT20温湿度传感器
SDA --》 GPIO13 可复用为I2C0_SDA
SCL --》 GPIO14 可复用为I2C0_SCL
MQ-2烟雾传感器
ADC --》 GPIO11
可复用为ADC5
蜂鸣器BEEP --》
GPIO9 可复用为PWM0_OUT
二、软件设计
1、新建文件在wifi-iot/app目录下,新建EM文件夹,存放与环境监测板相关的代码。
在EM文件夹分别新建aht20.c、aht20.h、envrionment_demo.c和BUILD.gn文件。
上面c文件和h文件我是从许思维老师demo工程中移植过来的,然后进行了一些修改。
2、aht20.c该c文件主要存放与aht20传感器操作相关的代码
- /*
- * Copyright (c) 2020, HiHope Community.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- #include "aht20.h"
-
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
-
- #include "wifiiot_i2c.h"
- #include "wifiiot_errno.h"
-
- #define AHT20_I2C_IDX WIFI_IOT_I2C_IDX_0
-
- #define AHT20_STARTUP_TIME 20*1000 // 上电启动时间
- #define AHT20_CALIBRATION_TIME 40*1000 // 初始化(校准)时间
- #define AHT20_MEASURE_TIME 75*1000 // 测量时间
-
- #define AHT20_DEVICE_ADDR 0x38
- #define AHT20_READ_ADDR ((0x38<<1)|0x1)
- #define AHT20_WRITE_ADDR ((0x38<<1)|0x0)
-
- #define AHT20_CMD_CALIBRATION 0xBE // 初始化(校准)命令
- #define AHT20_CMD_CALIBRATION_ARG0 0x08
- #define AHT20_CMD_CALIBRATION_ARG1 0x00
-
- /**
- * 传感器在采集时需要时间,主机发出测量指令(0xAC)后,延时75毫秒以上再读取转换后的数据并判断返回的状态位是否正常。
- * 若状态比特位[Bit7]为0代表数据可正常读取,为1时传感器为忙状态,主机需要等待数据处理完成。
- **/
- #define AHT20_CMD_TRIGGER 0xAC // 触发测量命令
- #define AHT20_CMD_TRIGGER_ARG0 0x33
- #define AHT20_CMD_TRIGGER_ARG1 0x00
-
- // 用于在无需关闭和再次打开电源的情况下,重新启动传感器系统,软复位所需时间不超过20 毫秒
- #define AHT20_CMD_RESET 0xBA // 软复位命令
-
- #define AHT20_CMD_STATUS 0x71 // 获取状态命令
-
- /**
- * STATUS 命令回复:
- * 1. 初始化后触发测量之前,STATUS 只回复 1B 状态值;
- * 2. 触发测量之后,STATUS 回复6B: 1B 状态值 + 2B 湿度 + 4b湿度 + 4b温度 + 2B 温度
- * RH = Srh / 2^20 * 100%
- * T = St / 2^20 * 200 - 50
- **/
- #define AHT20_STATUS_BUSY_SHIFT 7 // bit[7] Busy indication
- #define AHT20_STATUS_BUSY_MASK (0x1<<AHT20_STATUS_BUSY_SHIFT)
- #define AHT20_STATUS_BUSY(status) ((status & AHT20_STATUS_BUSY_MASK) >> AHT20_STATUS_BUSY_SHIFT)
-
- #define AHT20_STATUS_MODE_SHIFT 5 // bit[6:5] Mode Status
- #define AHT20_STATUS_MODE_MASK (0x3<<AHT20_STATUS_MODE_SHIFT)
- #define AHT20_STATUS_MODE(status) ((status & AHT20_STATUS_MODE_MASK) >> AHT20_STATUS_MODE_SHIFT)
-
- // bit[4] Reserved
- #define AHT20_STATUS_CALI_SHIFT 3 // bit[3] CAL Enable
- #define AHT20_STATUS_CALI_MASK (0x1<<AHT20_STATUS_CALI_SHIFT)
- #define AHT20_STATUS_CALI(status) ((status & AHT20_STATUS_CALI_MASK) >> AHT20_STATUS_CALI_SHIFT)
- // bit[2:0] Reserved
-
- #define AHT20_STATUS_RESPONSE_MAX 6
-
- #define AHT20_RESLUTION (1<<20) // 2^20
-
- #define AHT20_MAX_RETRY 10
-
- static uint32_t AHT20_Read(uint8_t* buffer, uint32_t buffLen)
- {
- WifiIotI2cData data = { 0 };
- data.receiveBuf = buffer;
- data.receiveLen = buffLen;
- uint32_t retval = I2cRead(AHT20_I2C_IDX, AHT20_READ_ADDR, &data);
- if (retval != WIFI_IOT_SUCCESS) {
- printf("I2cRead() failed, %0X!
- ", retval);
- return retval;
- }
- return WIFI_IOT_SUCCESS;
- }
-
- static uint32_t AHT20_Write(uint8_t* buffer, uint32_t buffLen)
- {
- WifiIotI2cData data = { 0 };
- data.sendBuf = buffer;
- data.sendLen = buffLen;
- uint32_t retval = I2cWrite(AHT20_I2C_IDX, AHT20_WRITE_ADDR, &data);
- if (retval != WIFI_IOT_SUCCESS) {
- printf("I2cWrite(%02X) failed, %0X!
- ", buffer[0], retval);
- return retval;
- }
- return WIFI_IOT_SUCCESS;
- }
-
- // 发送获取状态命令
- static uint32_t AHT20_StatusCommand(void)
- {
- uint8_t statusCmd[] = { AHT20_CMD_STATUS };
- return AHT20_Write(statusCmd, sizeof(statusCmd));
- }
-
- // 发送软复位命令
- static uint32_t AHT20_ResetCommand(void)
- {
- uint8_t resetCmd[] = {AHT20_CMD_RESET};
- return AHT20_Write(resetCmd, sizeof(resetCmd));
- }
-
- // 发送初始化校准命令
- static uint32_t AHT20_CalibrateCommand(void)
- {
- uint8_t clibrateCmd[] = {AHT20_CMD_CALIBRATION, AHT20_CMD_CALIBRATION_ARG0, AHT20_CMD_CALIBRATION_ARG1};
- return AHT20_Write(clibrateCmd, sizeof(clibrateCmd));
- }
-
- // 读取温湿度值之前, 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字),
- // 如果不为1,要发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。
- uint32_t AHT20_Calibrate(void)
- {
- uint32_t retval = 0;
- uint8_t buffer[AHT20_STATUS_RESPONSE_MAX] = { AHT20_CMD_STATUS };
- memset(&buffer, 0x0, sizeof(buffer));
-
- retval = AHT20_StatusCommand();
- if (retval != WIFI_IOT_SUCCESS) {
- return retval;
- }
-
- retval = AHT20_Read(buffer, sizeof(buffer));
- if (retval != WIFI_IOT_SUCCESS) {
- return retval;
- }
-
- if (AHT20_STATUS_BUSY(buffer[0]) || !AHT20_STATUS_CALI(buffer[0])) {
- retval = AHT20_ResetCommand();
- if (retval != WIFI_IOT_SUCCESS) {
- return retval;
- }
- usleep(AHT20_STARTUP_TIME);
- retval = AHT20_CalibrateCommand();
- usleep(AHT20_CALIBRATION_TIME);
- return retval;
- }
-
- return WIFI_IOT_SUCCESS;
- }
-
- // 发送 触发测量 命令,开始测量
- uint32_t AHT20_StartMeasure(void)
- {
- uint8_t triggerCmd[] = {AHT20_CMD_TRIGGER, AHT20_CMD_TRIGGER_ARG0, AHT20_CMD_TRIGGER_ARG1};
- return AHT20_Write(triggerCmd, sizeof(triggerCmd));
- }
-
- // 接收测量结果,拼接转换为标准值
- uint32_t AHT20_GetMeasureResult(float* temp, float* humi)
- {
- uint32_t retval = 0, i = 0;
- if (temp == NULL || humi == NULL) {
- return WIFI_IOT_FAILURE;
- }
-
- uint8_t buffer[AHT20_STATUS_RESPONSE_MAX] = { 0 };
- memset(&buffer, 0x0, sizeof(buffer));
- retval = AHT20_Read(buffer, sizeof(buffer)); // recv status command result
- if (retval != WIFI_IOT_SUCCESS) {
- return retval;
- }
-
- for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) {
- // printf("AHT20 device busy, retry %d/%d!
- ", i, AHT20_MAX_RETRY);
- usleep(AHT20_MEASURE_TIME);
- retval = AHT20_Read(buffer, sizeof(buffer)); // recv status command result
- if (retval != WIFI_IOT_SUCCESS) {
- return retval;
- }
- }
- if (i >= AHT20_MAX_RETRY) {
- printf("AHT20 device always busy!
- ");
- return WIFI_IOT_FAILURE;
- }
-
- uint32_t humiRaw = buffer[1];
- humiRaw = (humiRaw << 8) | buffer[2];
- humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4);
- *humi = humiRaw / (float)AHT20_RESLUTION * 100;
-
- uint32_t tempRaw = buffer[3] & 0x0F;
- tempRaw = (tempRaw << 8) | buffer[4];
- tempRaw = (tempRaw << 8) | buffer[5];
- *temp = tempRaw / (float)AHT20_RESLUTION * 200 - 50;
- // printf("humi = %05X, %f, temp= %05X, %f
- ", humiRaw, *humi, tempRaw, *temp);
- return WIFI_IOT_SUCCESS;
- }
-
- 3.aht20.h
- /*
- * Copyright (c) 2020, HiHope Community.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- #ifndef AHT20_H
- #define AHT20_H
-
- #include <stdint.h>
-
- uint32_t AHT20_Calibrate(void);
-
- uint32_t AHT20_StartMeasure(void);
-
- uint32_t AHT20_GetMeasureResult(float* temp, float* humi);
-
- #endif // AHT20_H
复制代码
4、envrionment_demo.c该c文件是在许思维老师例程代码基础上进行修改,需要I2C功能,需要把IO配置为I2C功能,且前面要加上 GpioInit()函数,才能成功配置IO。
- /*
- * Copyright (c) 2020, HiHope Community.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- #include <stdio.h>
- #include <stdint.h>
- #include <string.h>
- #include <unistd.h>
-
- #include "ohos_init.h"
- #include "cmsis_os2.h"
- #include "wifiiot_i2c.h"
- #include "wifiiot_gpio.h"
- #include "wifiiot_gpio_ex.h"
- #include "wifiiot_pwm.h"
- #include "wifiiot_adc.h"
- #include "wifiiot_errno.h"
-
- #include "aht20.h"
- //#include "oled_ssd1306.h"
-
- #ifndef ARRAY_SIZE
- #define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
- #endif
-
- #define MS_PER_S 1000
-
- #define BEEP_TIMES 3
- #define BEEP_DURATION 100
- #define BEEP_PWM_DUTY 30000
- #define BEEP_PWM_FREQ 60000
- #define BEEP_PIN_NAME WIFI_IOT_IO_NAME_GPIO_9
- #define BEEP_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT
-
- #define GAS_SENSOR_CHAN_NAME WIFI_IOT_ADC_CHANNEL_5
- // #define GAS_SENSOR_PIN_NAME WIFI_IOT_IO_NAME_GPIO_11
-
- #define AHT20_BAUDRATE 400*1000
- #define AHT20_I2C_IDX WIFI_IOT_I2C_IDX_0
-
- #define ADC_RESOLUTION 2048
-
- static float ConvertToVoltage(unsigned short data)
- {
- return (float)data * 1.8 * 4 / 4096;
- }
-
- static void EnvironmentTask(void *arg)
- {
- (void)arg;
- uint32_t retval = 0;
- float humidity = 0.0f;
- float temperature = 0.0f;
- float gasSensorResistance = 0.0f;
-
- /*I2C IO口初始化化*/
- GpioInit();
- IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA);
- IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL);
- I2cInit(AHT20_I2C_IDX, AHT20_BAUDRATE);
-
- while (WIFI_IOT_SUCCESS != AHT20_Calibrate()) {
- printf("AHT20 sensor init failed!
- ");
- usleep(1000);
- }
-
- while(1) {
- retval = AHT20_StartMeasure();
- if (retval != WIFI_IOT_SUCCESS) {
- printf("trigger measure failed!
- ");
- }
-
- retval = AHT20_GetMeasureResult(&temperature, &humidity);
- if (retval != WIFI_IOT_SUCCESS) {
- printf("get humidity data failed!
- ");
- }
-
- unsigned short data = 0;
- if (AdcRead(GAS_SENSOR_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0)
- == WIFI_IOT_SUCCESS) {
- float Vx = ConvertToVoltage(data);
- gasSensorResistance = 5 / Vx - 1;
- }
- printf("temp: %.2f
- ", temperature);
- printf("humi: %.2f
- ", humidity);
- printf("gas: %.2f kom
- ", gasSensorResistance);
- sleep(1);
- }
- }
-
- static void EnvironmentDemo(void)
- {
- osThreadAttr_t attr;
- attr.name = "EnvironmentTask";
- attr.attr_bits = 0U;
- attr.cb_mem = NULL;
- attr.cb_size = 0U;
- attr.stack_mem = NULL;
- attr.stack_size = 4096;
- attr.priority = osPriorityNormal;
-
- if (osThreadNew(EnvironmentTask, NULL, &attr) == NULL) {
- printf("[EnvironmentDemo] Falied to create EnvironmentTask!
- ");
- }
- }
- APP_FEATURE_INIT(EnvironmentDemo);
复制代码
5、BUILD.gnBUILD.gn内容为
- # Copyright (c) 2020, HiHope Community.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions are met:
- #
- # 1. Redistributions of source code must retain the above copyright notice, this
- # list of conditions and the following disclaimer.
- #
- # 2. Redistributions in binary form must reproduce the above copyright notice,
- # this list of conditions and the following disclaimer in the documentation
- # and/or other materials provided with the distribution.
- #
- # 3. Neither the name of the copyright holder nor the names of its
- # contributors may be used to endorse or promote products derived from
- # this software without specific prior written permission.
- #
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- static_library("em_example") {
- sources = [
- "envrionment_demo.c",
- "aht20.c"
- ]
- include_dirs = [
- "//utils/native/lite/include",
- "//kernel/liteos_m/components/cmsis/2.0",
- "//base/iot_hardware/interfaces/kits/wifiiot_lite",
- ]
- }
复制代码
这样还不行,还要修改app文件夹下的BUILD.gn。在features下增加"EM:em_example",
- lite_component("app") {
- features = [
- "startup",
- "SSL:ssl_example",
- "EM:em_example",
- "OLED:oled_example"
- ]
- }
复制代码 6、增加I2C功能在默认情况下,hi3861_sdk中,I2C在CONFIG选项里没有打开,所以I2C无法进行使用我们需要修改vendorhisihi3861hi3861uildconfigusr_config.mk文件中的CONFIG_I2C_SUPPORT行:# CONFIG_I2C_SUPPORT is not set修改为CONFIG_I2C_SUPPORT=y
三、 编译烧录烧录成功后,使用串口组手,查看到已经可以打印输出数据 。
四、总结前一段时间太忙,确实落下很多进度,之后要加快学习速度了。再一次感谢许思维老师,查看许思维老师的例程代码,确实帮助了自己很多。明天我将写一篇关于OLED12864的帖子,主要功能为显示时钟、温湿度,总之要加快进度啦。
`