提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、实习内容
- 二、实习方法
- 2.1搭建开发环境并完成编译
- 2.1.1 正常完成编译的标志
- 2.1.2 编写实例烧录程序,并完成烧录
- 2.2按键实现流水灯
- 2.2.1 HaaS EDU K1开发版原理图。如图2- 2- 1。
- 2.2.2 GPIO中各个接口函数的作用,如图2- 2- 2。
- 2.2.3 led初始化函数的结构体
- 2.2.4 流水灯具体实现流程
- 2.3按键控制led闪烁代码
- 2.3.1 按键分类
- 2.3.2 按键原理图
- 2.3.3按键消抖原理图
- 2.3.4 按键对应的CPU引脚
- 2.3.5实现按键控制led灯亮灭代码及思路如下图。
- 2.3.1蜂鸣器分类
- 2.3.2 PWM
- 2.3.3分析hal库接口函数
- 2.3.4蜂鸣器报警
- 2.4 OLED屏幕打印图形
- 2.4.2 OLED屏幕扫描方式
- 2.4.3分析hal库的接口函数
- 2.4.4 取模软件的注册
- 2.4.5 编写打印图像的代码。
- 2.5 温湿度传感器
- 2.5.1 温湿度传感器概述
- 2.5.2转换公式
- 2.5.3IIC 总线通信协议,示意图如图2- 5 -1。
- 2.5.4 温湿度传感器原理图
- 2.5.5分析hal库中接口函数
- 2.5.6测量温度和湿度代码
- 2.6 ADC转换器
- 2.6.1概述
- 2.6.2分析hal库的接口函数
- 2.6.3 ADC转换代码
- 2.7光照传感器
- 2.7.1光照传感器概述
- 2.7.3分析hal库中的接口函数
- 2.7.3编写代码
- 2.8使用阿里云平台调试程序
- 三、实习成果
- 3.1 按键控灯
- 3.1.1 代码如下
- 3.2PWM 控制蜂鸣器
- 3.2.1程序
- 3.2.2结果
- 3.3OLED打印图形
- 3.3.1程序
- 3.3.2 结果
- 3.4 检测温湿度
- 3.4.1 程序
- 3.4.2 结果
- 3.5ADC 转换
- 3.5.1 代码
- 3.5.2结果
- 3.6光照传感器
- 3.6.1代码
- 3.6.2结果
- 四、总结
前言
基于AliO Things智能环境监控系统。可以通过连接阿里云实现远程计算机对周围环境进行监控。依托开发板上的环境监测传感器采集环境信息并显示,并进行异常报警。通过上云,实现监测系统的远端控制和查询。
提示:以下是本篇文章正文内容,下面案例可供参考
一、实习内容
1.1 通过按键可以控制系统的LED灯,表示系统状态;
1.2 通过屏幕显示传感器的采集数据;
1.3 控制蜂鸣器进行监测异常报警;
1.4 借助ADC转换器采集电压值并显示;
1.5 借助光强传感器、红外距离传感器、温湿度传感器采集环境数据,并显示;
1.6 通过云端控制系统,并实现系统状态的查询。
二、实习方法
2.1搭建开发环境并完成编译
2.1.1 正常完成编译的标志
当使用vscode软件编译之后,如果出现如图2- 1- 1即可表示创建的项目已完成了正常编译。
2.1.2 编写实例烧录程序,并完成烧录
实例程序如图2- 1- 2。编写完成之后,先点击编译,再点击烧录。点击烧录之后,当出现图2- 1- 3之后,说明程序已经正常完成了烧录。
2.2按键实现流水灯
2.2.1 HaaS EDU K1开发版原理图。如图2- 2- 1。
2.2.2 GPIO中各个接口函数的作用,如图2- 2- 2。
HaaS EDUk1板载了三个可编程LED,分别是L1, L2, L3, 分别为红、绿、蓝三个单色灯。
2.2.3 led初始化函数的结构体
typedef struct {
uint8_t port; /*gpio的引脚号/端口号*/
gpio_config_t config; /*gpio的配置信息*/
void *priv; /*私有数据*/
} gpio_dev_t;
2.2.4 流水灯具体实现流程
流水灯具体分为两步,第一步是对led灯进行初始化,第二步就是在循环当中按照顺序依次点亮和熄灭对应的led灯。
第一步:我们使用结构体pio_dev_t分别定义led1,led2,led3这三个变量。随后通过查询开发版手册查询到端口号和配置信息,我们对定义的变量进行初始化操作。初始化操作后使用hal_gpio_init(&变量名)保存操作。保存完成之后,我们的led初始化就已经完成了。如图2- 2- 3。
第二步:项目中hal_gpio_output_high(&变量名)hal_gpio_output_low(&变量名)函数分别控制的led灯亮和灭。我们在while(1)循环中按照依次对不同led灯进行点亮或者熄灭,两个灯亮灭之间要使用延时函数aos_msleep(延时时间)使得人眼可以观察到(防止余晖效应)。最后无限循环下去就可以实现本次的流水灯实验。如图2- 2- 4。
2.3按键控制led闪烁代码
2.3.1 按键分类
编码按键:由专门的硬件进行驱动,生成了键码值或者是键值对。
非编码按键:由软件编程进行控制。
2.3.2 按键原理图
分析原理图:
当按键被按下时,检测到引脚是一个低电平
当按键未被按下时,检测到引脚是一个高电平
电容:去滤波、充放电的作用
电阻:当按键未按下时,检测到是一个高电平
此实验中采用中断的方式
2.3.3按键消抖原理图
2.3.4 按键对应的CPU引脚
HaaS EDU k1板载了四个可编程按键,分别是K1, k2, K3, K4四个按键对应的GPIO如图2- 3- 1。
2.3.5实现按键控制led灯亮灭代码及思路如下图。
2.3.1蜂鸣器分类
蜂鸣器是一种非常简单的发声器件,播放使用的扬声器不同,蜂鸣器只能播放较为简单的频率。
从驱动原理上区分,蜂鸣器可以分为无源蜂鸣器和有源蜂鸣器。这里的“源”,指的就是有无驱动源。
有源蜂鸣器:内部有rc震荡电路,只需要给控制引脚一个高电平即可,内部的rc震荡电路就会产生方波.这个方波控制线圈是否吸合薄片,从而决定是否发声。
无源蜂鸣器:内部没有rc震荡电路,需要给控制引脚一个方波,它就可以发声了。
2.3.2 PWM
PWM定义: 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,通过调节占空比,就可以调节脉冲宽度(脉宽时间) ,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
PWM频率: 是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期);也就是说一秒钟PWM有多少个周期。其脉冲示意图如
单位: Hz
表示方式: 50Hz 100Hz
如果频率为50Hz ,也就是说一个周期是20ms 那么一秒钟就有 50次PWM周期
占空比:是一个脉冲周期内,高电平的时间与整个周期时间的比例
单位: % (0%-100%)
表示方式:20%
2.3.3分析hal库接口函数
2.3.4蜂鸣器报警
首先对蜂鸣器进行初始化,初始化函数如图2- 3- 2。初始化之后我们调用hal库里面的函数hal_pwm_start()和hal_pwm_stop(),如图2- 3- 3。当程序烧录成功之后,我们可以听到蜂鸣器实现了报警功能。
2.4 OLED屏幕打印图形
1、HaaS EDU K1 自带了一块1.3寸132*64的OLED屏幕,黑底白字.芯片采用SH1106,使用SPI驱动。
2、OLED,即有机发光二极管(Organic Light-Emitting Diode)。OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板等优异之特性。
与LCD相比,LCD需要背光,同样的显示,OLED 效果要来得好一些,OLED分辨率可以做到很高。
2.4.2 OLED屏幕扫描方式
四种扫描方式:逐行扫描、逐列扫描、列行式扫描、行列式扫描。此屏幕采用的是列行式的扫描方式。四种扫描方式如图2- 4- 1。本屏幕采用方式示意图,如图2- 4- 2。
2.4.3分析hal库的接口函数
2.4.4 取模软件的注册
将取模软件进行解压并注册。注册完成之后,我们可以看到如图2- 4 -3,我们使用取模软件,对自己想要生成图片进行取模。
2.4.5 编写打印图像的代码。
我们使用取模软件得到自己想要的图像数组。随后我们调用初始化函数sh1106_init()和屏幕清理函数OLED_Clear(),对屏幕进行预处理。最后我们使用void OLED_Show_Uimge(uint8_t *Name,int leftx,int lefty,int rightx,int righty)函数,我们进行编译和烧录就可以在屏幕上看到取模后的图片。
2.5 温湿度传感器
2.5.1 温湿度传感器概述
2.5.2转换公式
2.5.3IIC 总线通信协议,示意图如图2- 5 -1。
2.5.4 温湿度传感器原理图
2.5.5分析hal库中接口函数
2.5.6测量温度和湿度代码
#include "aos/init.h"
#include "board.h"
#include <aos/errno.h>
#include <aos/kernel.h>
#include <k_api.h>
#include <stdio.h>
#include <stdlib.h>
//按ctrl+s进行保存或者是跳转到其他界面
//将此头文件选中之后按f12键进行跳转,或者是
//选中头文件点击右键选择跳转到定义
#include <aos/hal/gpio.h> //gpio的头文件
#include <hal_iomux_haas1000.h> //引脚号
#include <aos/hal/pwm.h> //pwm的头文件
#include <sh1106.h> //sh1106芯片的头文件
#include <aos/hal/i2c.h> //iic总线通信协议
#include <aos/hal/adc.h> //adc转换器
#define PORT 1
#define DEVADDR 0x40
#define DATA 0x00
//定义一个全局结构体变量
i2c_dev_t IIC1;
//采用主模式获取温湿度函数
void temphumi_data(float *TTmp,float *HHui){
//为结构体变量进行赋值
IIC1.port = PORT;
IIC1.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT; //寻址模式7位
IIC1.config.dev_addr = DEVADDR; //设备地址
IIC1.config.freq = I2C_BUS_BIT_RATES_400K; //通信速度
IIC1.config.mode = I2C_MODE_MASTER; //主模式
IIC1.priv = NULL; //无私有数据
//保存初始化
hal_i2c_init(&IIC1);
//iic主模式发送数据
uint8_t data = DATA;
uint8_t buf[4] = {0};
//保存温湿度的临时变量
int temp = 0;
int humi = 0;
hal_i2c_master_send(&IIC1,DEVADDR,&data,1,1000);
aos_msleep(1000); //保证数据完整性
//iic主模式接收数据
hal_i2c_master_recv(&IIC1,DEVADDR,buf,4,1000);
//将数据进行拼接保存到临时变量中
temp = (buf[0] <<8)+ buf[1];
humi = (buf[2] <<8)+ buf[3];
//将数据进行转换
*TTmp = ((165.0f * (float)temp) / 65535.0f) - 40.0f;
*HHui = (100.0f * (float)humi) / 65535.0f;
}
//相对于是main函数,是应用程序入口函数
int application_start(int argc, char *argv[])
{
float tempp,humii;
//防止程序跑飞
while (1) {
temphumi_data(&tempp,&humii);
//%.2f和%0.2f等价的,保留两位小数
printf("temp:%.2f humi:%.2f\n",tempp,humii);
aos_msleep(1000);
};
}
2.6 ADC转换器
2.6.1概述
ADC转换器将模拟量转换成数据量,模拟量是连续的,数字量是离散的。如图2- 6- 1。
2.6.2分析hal库的接口函数
int32_t hal_adc_init(adc_dev_t *adc);
功能:adc硬件初始化接口
参数:
adc:adc的设备
返回值:
0:成功 非0:失败
typedef struct {
uint8_t port; /*adc的端口号*/
adc_config_t config; /*adc的配置信息 */
void *priv; /*私有数据*/
} adc_dev_t;
typedef struct {
uint32_t sampling_cycle; /*adc的采样周期*/
} adc_config_t;
int32_t hal_adc_value_get(adc_dev_t *adc, uint32_t *output,
uint32_t timeout);
功能:获取adc的采样数据
参数:
adc:adc的设备
output:采样数据
timeout:超时时间(毫秒)
#define HAL_WAIT_FOREVER 0xFFFFFFFFU
返回值:
0:成功 非0:失败
int32_t hal_adc_finalize(adc_dev_t *adc);
功能:取消ADC硬件接口初始化
参数:
adc:adc的设备
返回值:
0:成功 非0:失败
2.6.3 ADC转换代码
我们先对ADC模块初始化,如图2- 6- 2。初始化之后,直接调用int32_t hal_adc_value_get(adc_dev_t *adc, uint32_t *output,uint32_t timeout);函数就可以在终端上看到打印的电压信息。
2.7光照传感器
2.7.1光照传感器概述
本实验的主要结果是通过I2C总线控制光强度传感器AP3216C对环境光强度及物体接近情况进行测量并获取环境光强度及是否有物体靠近,然后通过OLED显示屏将读取到的光强度、接近程度、红外信息显示在HaaS EDU K1的屏幕上。
AP3216C工作模式介绍
根据AP32 16C的datasheet说明,在正常工作时,它共有3种工作模式:
ALS模式
在这种模式下,AP3216C只对光强度进行量测
PS+IR模式
在这种模式下,AP3216C只对接近程度进行量测
AL S+PS+IR模式
在这种模式下,AP3216C会同时对光强度及接近程度进行测量
2.7.3分析hal库中的接口函数
void ap3216c_init(void);
功能:光照传感器的初始化函数
参数:无参数
返回值:无返回值
uint16_t ap3216c_read_ambient_light(void);
功能:获取光照值
参数:无参数
返回值:光照的数据
uint16_t ap3216c_read_ps_data(void);
功能:获取距离值
参数:无参数
返回值:距离的数据
uint16_t ap3216c_read_ir_data(void);
功能:获取红外值
参数:无参数
返回值:红外的数据
2.7.3编写代码
#include "aos/init.h"
#include "board.h"
#include <aos/errno.h>
#include <aos/kernel.h>
#include <k_api.h>
#include <stdio.h>
#include <stdlib.h>
//按ctrl+s进行保存或者是跳转到其他界面
//将此头文件选中之后按f12键进行跳转,或者是
//选中头文件点击右键选择跳转到定义
#include <aos/hal/gpio.h> //gpio的头文件
#include <hal_iomux_haas1000.h> //引脚号
#include <aos/hal/pwm.h> //pwm的头文件
#include <sh1106.h> //sh1106芯片的头文件
#include <aos/hal/i2c.h> //iic总线通信协议
#include <aos/hal/adc.h> //adc转换器
//相对于是main函数,是应用程序入口函数
int application_start(int argc, char *argv[])
{
int data[3] = {0};
uint8_t light[50] = {0};
uint8_t ps[50] = {0};
uint8_t ir[50] = {0};
//调用初始化函数
ap3216c_init();
sh1106_init();
//防止程序跑飞
while (1) {
//获取光照值
data[0] = ap3216c_read_ambient_light();
//获取距离值
data[1] = ap3216c_read_ps_data();
//获取红外值
data[2] = ap3216c_read_ir_data();
sprintf(light,"light:%d",data[0]);
sprintf(ps,"ps:%d",data[1]);
sprintf(ir,"ir:%d",data[2]);
OLED_Clear();
OLED_Show_String(5,5,light,12,1);
OLED_Show_String(5,25,ps,12,1);
OLED_Show_String(5,45,ir,12,1);
OLED_Refresh_GRAM();
aos_msleep(1000);
};
}
2.8使用阿里云平台调试程序
第一步:新建项目,如图2- 8 -1;
第二步:创建项目,如图2- 8 - 2;
第三步:创建物模型,如图2- 8 - 3;
最后,调试程序,如图2- 8 - 4。
三、实习成果
3.1 按键控灯
3.1.1 代码如下
#include "aos/init.h"
#include "board.h"
#include <aos/errno.h>
#include <aos/kernel.h>
#include <k_api.h>
#include <stdio.h>
#include <stdlib.h>
//按ctrl+s进行保存或者是跳转到其他界面
//将此头文件选中之后按f12键进行跳转,或者是
//选中头文件点击右键选择跳转到定义
#include <aos/hal/gpio.h> //gpio的头文件
#include <hal_iomux_haas1000.h> //引脚号
#include <aos/hal/pwm.h> //pwm的头文件
#include <sh1106.h> //sh1106芯片的头文件
#include <aos/hal/i2c.h> //iic总线通信协议
#include <aos/hal/adc.h> //adc转换器
//相对于是main函数,是应用程序入口函数
int application_start(int argc, char *argv[]) {
int data[3] = {0}; uint8_t ps[50] = {0};
uint8_t ir[50] = {0}; uint8_t light[50] = {0};
//调用初始化函数
ap3216c_init();
sh1106_init();
//防止程序跑飞
while (1) {
//获取光照值
data[0] = ap3216c_read_ambient_light();
//获取距离值
data[1] = ap3216c_read_ps_data();
//获取红外值
data[2] = ap3216c_read_ir_data();
sprintf(light,"light:%d",data[0]);
sprintf(ps,"ps:%d",data[1]);
sprintf(ir,"ir:%d",data[2]);
OLED_Clear();
OLED_Show_String(5,5,light,12,1);
OLED_Show_String(5,25,ps,12,1);
OLED_Show_String(5,45,ir,12,1);
OLED_Refresh_GRAM();
aos_msleep(1000);
};
}
3.2PWM 控制蜂鸣器
3.2.1程序
#include "aos/init.h"
#include "board.h"
#include <aos/errno.h>
#include <aos/kernel.h>
#include <k_api.h>
#include <stdio.h>
#include <stdlib.h>
#include <aos/hal/gpio.h>
#include <hal_iomux_haas1000.h>
#include <aos/hal/pwm.h>
#define PORT 0 //pwm的端口号
//定义结构体变量
pwm_dev_t buz;
void buz_init () {
buz.port = PORT; //端口号
buz.config.duty_cycle = 0.1; //占空比10%
buz.config.freq = 1000; //频率 1000
buz.priv = NULL;
hal_pwm_init(&buz); //保存初始化
}
int application_start (int argc, char *argv[])
{
buz_init (); //蜂鸣器初始化
while(1)
{
//实现蜂鸣器功能
hal_pwm_start(&buz);
aos_msleep(500);
hal_pwm_stop(&buz);
aos_msleep(500);
}//防止程序跑飞
}
3.2.2结果
蜂鸣器发出间断的声音。
3.3OLED打印图形
3.3.1程序
3.3.2 结果
3.4 检测温湿度
3.4.1 程序
void temphumi_data(float *TEMP, float *HUMI) {
IIC1.port = PORT;
IIC1.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT;
IIC1.config.dev_addr = DEVADDR;
IIC1.config.freq = I2C_BUS_BIT_RATES_400K;
IIC1.config.mode = I2C_MODE_MASTER;
IIC1.priv = NULL;
hal_i2c_init(&IIC1);
aos_msleep (1000); //保存数据完整性
uint8_t data = DATA;
uint8_t buf[4] = { 0 };
int temp = 0; //温度
int humi = 0; //湿度
hal_i2c_master_send(&IIC1, DEVADDR, &data, 1, 1000);
aos_msleep (1000); //保存数据完整性
hal_i2c_master_recv(&IIC1, DEVADDR, buf, 4, 1000);
temp = (buf[0] << 8) | buf[1];
humi = (buf[2] << 8) | buf[3];
*TEMP = ((165.0f * (float)temp) / 65535.0f) - 40.0f;
*HUMI = (100.0f * (float)humi) / 65535.0f;
}
3.4.2 结果
3.5ADC 转换
3.5.1 代码
int application_start (int argc, char *argv[])
{
int data = 0; //采样数据
adc_dev_t adc1;
adc1.port = PORT; //端口号
adc1.config.sampling_cycle = 100; //采样周期
adc1.priv = NULL;
hal_adc_init(&adc1); //保存数据
while(1)
{
hal_adc_value_get(&adc1, &data, HAL_WAIT_FOREVER);
data = data * 3;
printf("data = %.2f\n", (float)data / 1000);
aos_msleep(1000);
} //防止程序跑飞
}
3.5.2结果
3.6光照传感器
3.6.1代码
int application_start (int argc, char *argv[])
{
int data[3] = { 0 };
uint8_t data_0[20], data_1[20], data_2[20];
get_led1_init();
ap3216c_init();
sh1106_init();
while(1)
{
data[0] = ap3216c_read_ambient_light();
data[1] = ap3216c_read_ps_data();
data[2] = ap3216c_read_ir_data();
sprintf(data_0, "light:%d\n", data[0]);
sprintf(data_1, "ps:%d\n", data[1]);
sprintf(data_2, "ir:%d\n", data[2]);
if (data[0] > 1000) {
hal_gpio_output_high(&led1);
} else {
hal_gpio_output_low(&led1);
}
OLED_Clear();
sh1106_show_string(5, 5, data_0, 12, 1);
sh1106_show_string(5, 25, data_1, 12, 1);
sh1106_show_string(5, 45, data_2, 12, 1);
printf("light:%d, ps:%d, ir:%d\n", data[0], data[1], data[2]);
OLED_Refresh_GRAM();
aos_msleep(1000);
}//防止程序跑飞
}
3.6.2结果
四、总结
在完成这个项目的过程中,我学习到了许多与嵌入式开发和物联网相关的知识和技能。以下是我在整个项目中所学到的主要内容:
刚开始,通过学习整个项目的构架,我了解了各个模块的功能和彼此间的关系。通过使用VSCode软件,我学会了如何搭建开发环境,并成功地创建了示例项目并进行了正常的编译操作。这为我更好地理解项目的需求和目标提供了基础。
在搭建好开发环境之后,老师带领我们复习了与项目相关的C语言基础知识,包括语法、函数和指针等。这些知识对我理解项目代码和进行开发工作非常有帮助。我还通过连接开发版成功实现了程序的烧录,加深了对硬件与软件之间交互的理解。
接着,通过了解GPIO和项目中各个接口函数的作用,我成功地实现了LED流水灯以及通过按键控制LED闪烁的功能;通过利用PWM来控制蜂鸣器,我实现了警报功能。通过调用#include <sh1106.h>中的函数和使用取模软件,我逐步实现了在开发版屏幕上显示字符、字符串和图片的功能;通过按键和显示屏的组合使用,我实现了按键控制图片显示和消失的功能;通过学习温度传感器和通信协议后,我成功地利用硬件设备测量了教室的温度和湿度,并将其显示在终端上;通过ADC模块,我成功的在串口中打印出了开发版的电压值信息;通过运用之前学到的LED模块、蜂鸣器模块、湿度传感器模块和液晶显示模块,我成功地开发了一个湿度检测报警程序;通过调用光照传感器内部自带的函数,我实现了测量光强、距离和获取红外值数据的功能;通过使用WiFi模块,我将手机热点连接上VSCode上,再结合之前学过的OLED屏幕,最后成功的将网络IP地址显示在液晶显示屏上;通过学习Netmgr相关知识之后,结合之前学过的WIFI模块,我成功的使用阿里云平台,实现了网络控制的功能。最后,将以上所学结合之后,我终于成功完成本次项目的开发,完成了预期目标。
在项目的过程中也不是一帆风顺的,我也遇到了一些挑战和问题。例如,在配置VSCode时,由于环境变量的问题导致程序一直无法正常编译。通过老师的指导,我最终解决了编译问题;另外,刚开始使用显示屏时,遇到了图片无法完全显示的问题,最后通过正确设置取模软件的参数,我成功地解决了这个问题;在调用中断函数时,遇到了无法正常调用的情况。最后发现是函数体内的参数设定有误,修改后问题得以解决。
通过本次项目开发提高了我对硬件模块和接口的应用能力,我不仅解决了具体的问题,还在实践中获得了宝贵的经验和教训。我学会了更加仔细地检查和分析代码,排除错误的可能性。同时,我也提高了解决问题的能力和自信心,明白了遇到困难时要积极主动地寻求帮助,并且善于与他人合作共同解决问题。这些经验将对我的未来学习和工作具有持久的影响。