基于stm32单片机和rt-thread操作系统的智能灯

  • 总体概况

本次测试技术与信号处理课程作业,我利用了stm32单片机和rt-thread实时操作系统进行实践。做出一个集声控、光敏和超声的智能灯,可以实现的功能是遇到声音并检测到环境较暗的时候智能灯光亮起,同时如果超声检测到20cm范围之内有物体移动时,智能灯亮起。模拟的是声控灯和用于楼梯的感控等。

硬件实物整体图

本文所用到的编译器是一款国产编译器RT-Thread Studio,使用的编程语言是C语言。用到了stm32f4开发板进行控制,RT-Thread实时操作系统负责对于麦克风模块、光敏模块、超声波模块进行调度,完成多线程的操作。

  • 各部分介绍

2.1  STM32F4开发板

本文使用的开发板是stm32f4系列里面的stm32f4VET6板载。

STM32F407VET6是基于STM32F407/417高性能ARM®Cortex?M4的微控制器集成创新外设,168 MHz工作频率,此外,还具有以太网MAC和用于CMOS传感器的照相机接口。STM32F407VET6具有32位闪存MCU具有浮点单元(FPU),带数字信号处理(DSP)说明和存储器保护装置(MPU),提高了应用安全性。STM32F407VET6微控制器带有一个crypto/hash处理器,为AES 128、192、256、Triple DES和hash(MD5,SHA-1)提供硬件加速。

STM32F407实物图

STM32F407VET6 高性能和工业标准芯体系,随附增强外设和连接的输入/输出。它们包括ADC、DAC、RTC、16位计时器(包括两个用于电动机控制的PWM计时器)、32位计时器。还有真随机编号发生器(RNG)。此外,省电模式套件具有低功耗应用设计。将涵盖多种应用,包括电动机驱动器和应用控制、工业应用:反相器、PLC、扫描仪、HVAC、视频对讲机、家用音频设备和医疗设备。

 STM32F407VET6参数与配置

系列名称

STM32F

最低工作温度

-40°C

封装类型

LQFP

以太网通道的最大数量

1

安装类型

表面贴装

I2C通道数目

3

引脚数目

100

计时器数目

14

装置核芯

ARM Cortex M4F

以太网通道数目

1

数据总线宽度

32Bit

UART通道数目

2

程序存储器大小

512 kB

程序存储器类型

闪存

最大频率

168MHz

最高工作温度

+85 °C

内存大小

4 kB、192 kB

模数转换器单元数目

3

USB通道

1 x 设备,1 x 主机,1 x OTG

指令集结构

RISC

PWM单元数目

1

脉冲宽度调制

2 x 16 位

模数转换器通道

16

宽度

14.2mm

SPI通道数目

3

PWM通道

2

典型工作电源电压

1.8 → 3.6 V

模数转换器

3(16 x 12 位)

模数转换器分辨率

12Bit

长度

14.2mm

CAN通道数目

2

尺寸

14.2 x 14.2 x 1.45mm

高度

1.45mm

计时器

12 x 16位,2 x 32位

计时器分辨率

16 bit, 32 bit

USART 通道数量

4

PWM分辨率

16Bit

LIN 通道数量

1

本文使用stm32f4VET6进行控制可以满足需要,对于开发板的使用和操作系统的配置及各模块的协调做出了探索,为以后的深入研究打下了坚实的基础。

本文采用Jlink进行代码的下载。J-Link是SEGGER公司为支持仿真ARM内核芯片推出的JTAG仿真器。配合IAR EWAR,ADS,KEIL,WINARM,RealView等集成开发环境支持所有ARM7/ARM9/ARM11,CortexM0/M1/M3/M4, Cortex A5/A8/A9等内核芯片的仿真,与IAR,Keil等编译环境无缝连接,操作方便、连接方便、简单易学,是学习开发ARM最好最实用的开发工具。产品规格:电源USB供电,整机电流 <50mA 支持的目标板电压 1.2 ~ 3.3V,5V兼容 目标板供电电压 4.5 ~ 5V (由USB提供5V) 目标板供电电流 最大300mA,具有过流保护功能 工作环境温度 +5℃~ +60℃ 存储温度 -20℃ ~ +65℃ 湿度 <90%尺寸(不含电缆) 100mm x 53mm x 27mm 重量(不含电缆)70g 电磁兼容 EN 55022, EN 5502 。

Jlink软件下载器

2.2  光敏模块

光敏传感器是利用光敏元件将光信号转换为电信号的传感器,它的敏感波长在可见光波长附近,包括红外线波长和紫外线波长。光传感器不只局限于对光的探测,它还可以作为探测元件组成其他传感器,对许多非电量进行检测,只要将这些非电量转换为光信号的变化即可。

光敏传感器是最常见的传感器之一,它的种类繁多,主要有:光电管、光电倍增管、光敏电阻、光敏三极管、太阳能电池、红外线传感器、紫外线传感器、光纤式光电传感器、色彩传感器、CCD和CMOS图像传感器等。国内主要厂商有OTRON品牌等。光传感器是产量最多、应用最广的传感器之一,它在自动控制和非电量电测技术中占有非常重要的地位。最简单的光敏传感器是光敏电阻,当光子冲击接合处就会产生电流。

光敏传感器中最简单的电子器件是光敏电阻,它能感应光线的明暗变化,输出微弱的电信号,通过简单电子线路放大处理,可以控制LED灯具的自动开关。因此在自动控制、家用电器中得到广泛的应用,对于远程的照明灯具,例如:在电视机中作亮度自动调节,照相机中作自动曝光;另外,在路灯、航标等自动控制电路、卷带自停装置及防盗报警装置中等。

传感器实物图

光敏传感器的组成:

(1)敏感元件:它能直接感受被测非电量,并按一定规律将其转换成与被测非电量有确定对应关系的其他物理量。

(2)转换器件(又称变换器、传感器件):将敏感元件输出的非电物理量(如光强等)转换成电路参量。

(3)信号调节(转换)电路:将转换器件输出的电信号进行放大、运算、处理等,以获得便于显示、记录、处理和控制的有用电信号。

(4)辅助电源:它的作用是提供能源。有的传感器需要外部电源供电;有的传感器则不需要外部电源供电,如压电传感器。

2.3  麦克风模块

声音传感器的作用相当于一个话筒(麦克风),它用来接收声波。

该传感器是内置一个对声音敏感的电容式驻极体话筒。驻极体话筒主要由两部分组成——声电转换部分和阻抗部分。声电转换的关键元件是驻极体振动膜。它是一片极薄的塑料膜片,在其中一面蒸发上一层纯金薄膜。然后再经过高压电场驻极后,两面分别驻有异性电荷。膜片的蒸金面向外,与金属外壳相连通。

膜片的另一面与金属极板之间用薄的绝缘衬圈隔离开。这样,蒸金膜与金属极板之间就形成一个电容。当驻极体膜片遇到声波振动时,引起电容两端的电场发生变化,从而产生了随声波变化而变化的交变电压。驻极体膜片与金属极板之间的电容量比较小。因而它的输出阻抗值很高,约几十兆欧以上。这样高的阻抗是不能直接与音频放大器相匹配的。所以在话筒内接入一只结型场效应晶体三极管来进行阻抗变换。

麦克风模块原理图

场效应管的特点是输入阻抗极高、噪声系数低。普通场效应管有源极(S)、栅极(G)和漏极(D)三个极。这里使用的是在内部源极和栅极间再复合一只二极管的专用场效应管。接二极管的目的是在场效应管受强信号冲击时起保护作用。场效应管的栅极接金属极板。这样,驻极体话筒的输出线便有两根。即源极 S,一般用蓝色塑线,漏极 D,一般用红色塑料线和连接金属外壳的编织屏蔽线。

麦克风模块实物图

2.4  超声波模块

超声波传感器是利用压电效应的原理,压电效应有逆效应和顺效应,超声波传感器是可逆元件,超声波发送器就是利用压电逆效应的原理。所谓压电逆 是在压电元件上施加电压,元件就变形,即称应变。 外部正电荷与压电陶瓷的极化正电荷相斥,同时,外部负电荷与极化负电荷相斥。由于相斥的作用,压电陶瓷在厚度方向上缩短,在长度方向上伸长。若外部施加的极性变反,压电陶瓷在厚度方向上伸长,在长度方向上缩短。超声波传感器采用双晶振子,即把双压电陶瓷片以相反极化方向粘在一起,在长度方向上,一片伸长,另一片就缩短。在双晶振子的两面涂敷薄膜电极,其上面用引线通过金属板(振动板)接到一个电极端,下面用引线直接接到另一个电极端。双晶振子为正方形,正方形的左右两边由圆弧形凸起部分支撑着。这两处的支点就成为振子振动的节点。金属板的中心有圆锥形振子。发送超声波时,圆锥形振子有较强的方向性,因而能高效率地发送超声波;接收超声波时,超声波的振动集中于振子的中心,所以,能产生高效率的高频电压。采用双晶振子的超声波传感器,若在发送器的双晶振子(谐振频率为40kHz)上施加40kHz的高频电压,压电陶瓷片就根据所加的高频电压极性伸长与缩短,于是就能发送40kHz频率的超声波。超声波以疏密波形式传播,传送给超声波接收器。超声波接收器是利用压电效应的原理,即在压电元件的特定方向上施加压力,元件就发生应变,则产生一面为正极,另一面为负极的电压。若接收到发送器发送的超声波,振子就以发送超声波的频率进行振动,于是,就产生与超声波频率相同的高频电压,当然这种电压是非常小的,必须采用放大器放大。

对于我们使用的模块具有性能稳定,测度距离精确,模块高精度,盲区小等特点。产品主要的应用领域在机器人避障、物体测距、液位检测、公共安防、停车场检测等。

超声波模块实物图

接线方式:VCC、trig(控制端)、 echo(接收端)、 GND

基本工作原理:

  1. 采用IO口TRIG触发测距,给至少10us的高电平信号;
  2. 模块自动发送8个40khz的方波,自动检测是否有信号返回;
  3. 有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出.一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离.如此不断的周期测,即可以达到你移动测量的值

操作方法:初始化时将trig和echo端口都置低,首先向给trig 发送至少10 us的高电平脉冲(模块自动向外发送8个40K的方波),然后等待,捕捉 echo 端输出上升沿,捕捉到上升沿的同时,打开定时器开始计时,再次等待捕捉echo的下降沿,当捕捉到下降沿,读出计时器的时间,这就是超声波在空气中运行的时间,按照 测试距离=(高电平时间*声速(340M/S))/2 就可以算出超声波到障碍物的距离。

  • RT-Thread介绍

RT-Thread,全称是 Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。事实上,一个处理器核心在某一时刻只能运行一个任务,由于每次对一个任务的执行时间很短、任务与任务之间通过任务调度器进行非常快速地切换(调度器根据优先级决定此刻该执行的任务),给人造成多个任务在一个时刻同时运行的错觉。在 RT-Thread 系统中,任务通过线程实现的,RT-Thread 中的线程调度器也就是以上提到的任务调度器。

RT-Thread 主要采用 C 语言编写,浅显易懂,方便移植。它把面向对象的设计方法应用到实时系统设计中,使得代码风格优雅、架构清晰、系统模块化并且可裁剪性非常好。针对资源受限的微控制器(MCU)系统,可通过方便易用的工具,裁剪出仅需要 3KB Flash、1.2KB RAM 内存资源的 NANO 版本(NANO 是 RT-Thread 官方于 2017 年 7 月份发布的一个极简版内核);而对于资源丰富的物联网设备,RT-Thread 又能使用在线的软件包管理工具,配合系统配置工具实现直观快速的模块化裁剪,无缝地导入丰富的软件功能包,实现类似 Android 的图形界面及触摸滑动效果、智能语音交互效果等复杂功能。

相较于 Linux 操作系统,RT-Thread 体积小,成本低,功耗低、启动快速,除此以外 RT-Thread 还具有实时性高、占用资源小等特点,非常适用于各种资源受限(如成本、功耗限制等)的场合。虽然 32 位 MCU 是它的主要运行平台,实际上很多带有 MMU、基于 ARM9、ARM11 甚至 Cortex-A 系列级别 CPU 的应用处理器在特定应用场合也适合使用 RT-Thread。面向物联网设备,其中设备端和云端一体化设计,轻松接入各类主流物联网设备云平台。

RT_Thread的优点简略图

RT-Thread 与其他很多 RTOS 如 FreeRTOS、uC/OS 的主要区别之一是,它不仅仅是一个实时内核,还具备丰富的中间层组件,如下图所示。

RT_Thread架构

  • 开发过程

本文主要使用RT-Thread Studio进行编译。Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。Studio内设cubemx,可以跳转到cubemx进行引脚时钟等的配置,非常的方便快捷。

先进行硬件的连接,硬件引脚连接如下:

引脚使用情况表

引脚

功能

引脚

功能

PA6

LED1

PC0

SR04_TRIG_PIN

PA7

LED2

PC1

SR04_ECHO_PIN

PE2

声音传感器输入

PE3

光敏输入

并编写代码,声控灯的部分代码展示如下:

#define DBG_TAG "main"  
#define DBG_LVL DBG_LOG  
#include <rtdbg.h>  
#include <rtthread.h>  
#include <rtdevice.h>  
  
#include <sys/time.h>  
#define LED     6//  GET_PIN(A, 6)  
#define sound   66//   GET_PIN(E, 2)  
#define guang   67//   GET_PIN(E, 2)  
#define LED2   7  
int status,status2;  
int main(void)  
{  
     rt_pin_mode(LED, PIN_MODE_OUTPUT);  
     rt_pin_mode(LED2, PIN_MODE_OUTPUT);  
     rt_pin_mode(sound, PIN_MODE_INPUT);  
     rt_pin_mode(guang, PIN_MODE_INPUT);  
       while (1)  
       {  
         rt_pin_write(LED, PIN_HIGH);//灯灭  
        // rt_pin_write(LED2, PIN_HIGH);//灯灭  
          status = rt_pin_read(sound);  
          status2=rt_pin_read(guang);  
           if (status==1&&status2==1) {  
            rt_pin_write(LED, PIN_LOW);//灯亮  
               rt_thread_mdelay(1000);  
           }  
  
           rt_thread_mdelay(10);  
       }  
    return RT_EOK;  
} 

此实验用到的引脚较少,没有用到cubemx进行引脚配置,直接利用操作系统的函数(rt_pin_mode(xxx, PIN_MODE_xxxx))进行引脚设置,led灯引脚为输出格式,其它引脚例如光敏和麦克风模块的引脚为输入格式。rt_pin_read()和rt_pin_write()负责对引脚进行读写操作,并读取或改变引脚的高低电平状态。

将光敏的引脚读入到status2,将麦克风的引脚读入到status中,并判断两个状态是否同时为1,同时为1则表示环境中光线较暗并且有声音输入,此时应该亮起led灯光。起到了声控灯基本功能。

接下来是实现超声波测量感应物体实现智能灯的亮灭,主要由以下几个场景适用:

  • 每一阶楼梯安装一个小灯,感应到有物体经过时亮起一段时间,方便人夜里上下楼梯。
  • 公园路中间的地灯或者水上桥石需要灯光的地方,以此来感应有无人经过而亮起,起到了非常美观宜人的作用。
  • 智能感应路灯,提前预判人的到来,将灯亮起。起到节能环保的作用,同时对人来说更叫适宜。

本文超声波模块的使用用到了RT-Thread Studio的组件功能,可以直接进行调用,将"sensor_hc_sr04.c"和"sensor_hc_sr04.h"文件添加到工程中,并在代码中导入"sensor_hc_sr04.h"头文件,便可以调用集成化的初始化函数int rt_hw_sr04_init(const char *name, struct rt_sensor_config *cfg),并可以利用定义好的一些结构体,非常之方便。

HC-SR04软件包

Sr04软件包的作者同时也给出了示例代码,因此我们可以在该代码的基础上进行一些拓展,得到我们想要的结果。

HC-SR04初始化示例

我选取的定时器是time3,需要进行定义并开启。Trig和Echo输入输出引脚分别为C0和C1。下面是具体的代码展示,定义了一个sr04_thread的线程,并在sr04_read_distance_entry函数里面进行具体的编码实现,最后使用INIT_APP_EXPORT()使函数自动调用和自启动,而不用经过主函数的编码。这样工程开始运行之后,sr04_thread线程就直接挂靠运行,并实时监测是否有物体在20cm之内,并实现亮灭灯的一个命令操作。

#include <stdlib.h>  
#include <rtthread.h>  
#include <rtdevice.h>  
  
#include "board.h"  
#include "sensor.h"  
#include "sensor_hc_sr04.h"  
  
/* Modify this pin according to the actual wiring situation */  
#define SR04_TRIG_PIN GET_PIN(C, 0)  
#define SR04_ECHO_PIN GET_PIN(C, 1)  
#define LED2   7//GET_PIN(A, 7)//  7//  GET_PIN(A, 6)  
  
int sr04_read_distance_sample(void);  
int rt_hw_sr04_port(void);  
  
  
static void sr04_read_distance_entry(void *parameter)  
{  
    rt_device_t dev = RT_NULL;  
    struct rt_sensor_data sensor_data;  
    rt_size_t res;  
    rt_pin_mode(LED2, PIN_MODE_OUTPUT);  
  
  
    dev = rt_device_find(parameter);  
    if (dev == RT_NULL) {  
        rt_kprintf("Can't find device:%s\n", parameter);  
        return;  
    }  
  
    if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) {  
        rt_kprintf("open device failed!\n");  
        return;  
    }  
    rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100);  
  
    while (1) {  
        rt_pin_write(LED2, PIN_HIGH);  
        res = rt_device_read(dev, 0, &sensor_data, 1);  
        if (res != 1) {  
            rt_kprintf("read data failed!size is %d\n", res);  
            rt_device_close(dev);  
            return;  
        }  
        else {  
            rt_kprintf("distance:%3d.%dcm, timestamp:%5d\n", sensor_data.data.proximity / 10, sensor_data.data.proximity % 10, sensor_data.timestamp);  
            //如果距离小于20cm,表示有人经过,将会亮灯操作  
           if(sensor_data.data.proximity/10<20)  
            {  
                 rt_pin_write(LED2, PIN_LOW);  
                 rt_thread_mdelay(1000);  
                 rt_pin_write(LED2, PIN_HIGH);  
                 rt_thread_mdelay(100);  
           }  
        }  
        //rt_thread_mdelay(200);  
    }  
}  
  
int sr04_read_distance_sample(void)  
{  
    rt_thread_t sr04_thread;  
  
    sr04_thread = rt_thread_create("sr04",  
                                   sr04_read_distance_entry,  
                                   "pr_sr04",  
                                   1024,  
                                   RT_THREAD_PRIORITY_MAX / 2,  
                                   20);  
    if (sr04_thread != RT_NULL) {  
        rt_thread_startup(sr04_thread);  
    }  
  
    return RT_EOK;  
}  
INIT_APP_EXPORT(sr04_read_distance_sample);  
  
int rt_hw_sr04_port(void)  
{  
    struct rt_sensor_config cfg;  
    rt_base_t pins[2] = {SR04_TRIG_PIN, SR04_ECHO_PIN};  
  
    cfg.intf.dev_name = "timer3";  
    cfg.intf.user_data = (void *)pins;  
    rt_hw_sr04_init("sr04", &cfg);  
  
    return RT_EOK;  
}  
INIT_COMPONENT_EXPORT(rt_hw_sr04_port); 

同时main函数也是一个线程,它的优先级比sr04_thread的优先级高,这样就实现了多线程实时操作,一边监测声音,一边监测物体距离,而不互相干扰。相比于顺序执行代码,先检测声音,再监测物体,我使用的方法更加优良,可以兼顾快速性和准确性的要求。

设计实物图

  • 未来设想

本文所探索的智能灯功能单一,无法满足人们现代化的精细化的高标准的要求,因此需要了解人们更真实的需要,完成真正地智能化网络化绿色化的灯光要求。

  • 利用传感器收集人发出的声音信息,并进行智能识别,了解人的声音命令,并对灯光系统进行相应的调节。
  • 可以利用摄像头传感器对人进行监测,并编写人工智能代码,对人的心情与身体状态进行计算和求解,根据人的状态实时调好智能灯的颜色和亮暗。
  • 在汽车行业,也可以实现利用车身上的传感器判断车子的运行状态和当前的环境状态,进行相应灯的方向的移动以及灯远近大小的调整,达到辅助司机和提醒行人的目的。
  • 对于养殖行业,可以实时监测作物或者动物的生长状况,并据此对于灯光进行调整,达到节能绿色和高效产出的目的。

要注重去中心化和边缘计算,实现单个灯的智能化。同时又要兼顾网络化,使灯与灯之间互联互通,形成灯光系统,整体去协同动作,实现系统的智能化。

除了对于照明的场景进行改进外,对于照明的广源的研究也是一个不可忽视的部分。除传统照明外,半导体照明技术具有低功耗、高光效、高稳定性、超长使用寿命、无频闪、无环境污染等优点,是一种符合节能环保的绿色照明光源。半导体照明作为21世纪最具发展前景的高新技术领域之一,正在引发世界范围内照明电光源的一场革命,同时,也实现了节省能源,促进社会可持续发展,形成具有重大经济价值与社会意义的高新技术产业。所以,应该聚焦半导体照明,实现传统照明与新兴照明技术的过渡。

  • 开发心得

本次实验由对于声控灯的思考出发,进行了智能灯的进行了探索和实践。虽然,本文实现功能单一,但是思路方法完整,可扩展性强。测试了多个传感器,并进行了实际的编码操作。使用了RT-Thread实时操作系统进行多传感器的调度,达到了实时性和快速性的要求。

这为之后更深刻的研究开发奠定了深厚的基础,也锻炼的自己的实际动手操作能力。同时,之前学习了C语言和单片机等课程,这次实践加深了我对于它们的理解。重要的是,本次实践环节,我对于测试技术与信号处理的过程与方法有了更加直观的理解,与课堂内肖老师讲解的知识形成了互补。测试技术是控制中必要的一环,也可以说是最重要的一环,没有测试就如同没有了眼睛。信息失去了流通的路径,那么再高深的控制算法也便没有了用武之地。测试需要向智能化微型化的方向发展,同时在材质上也要向柔性化的方向迈进,而且精准化快速化的要求也应该达到满足。以上是我动手使用了这些传感器后的体会,通过这么课程和这次作业,我收获很多。

源文档,
可带价私聊,有小偿。

赞赏作者icon-default.png?t=N2N8https://nyzhhd.github.io/zsm 

猜你喜欢

转载自blog.csdn.net/m0_51738372/article/details/130168164