项目经历(一)— 基于Arduino的红外遥控

​ 这是笔者大学时着手的第一个项目,从选题和解决方案上都比较菜,仅仅为记录而用。(PS:空调红外信号较为复杂,此次算是一个失败的案例,也希望有大佬在评论中指点一二)
​ 话不多说,进入正题:

1. 系统方案

1.1 目标

​ 通过 Arduino UNO 板与其他模块的配合,实现对家用红外控制电器的控制;
​ 功能分为两大部分,一是实现对外部温度的实时监控并根据此来选择打开空调或者关闭空调,二是对预先写入程序的遥控代码以及语音进行匹配,从而进行语音控制。

1.2 思路

​ Arduino UNO 板连接红外接收模块,红外发射模块,语音控制模块,温湿度检测模块分别达到接收并解析红外信号,模拟红外 信号的发射,识别语音,实时检测环境温度的功能。根据外界条件进行判断,达到控制目的。在这里插入图片描述

2. 具体实现

2.1 模块简介

Arduino模块大多需要库文件的驱动,之前大部分库文件均靠github寻找,而新版本Arduino IDE中库文件管理可以极大方便这种操作,最新版IDE下载地址库管理操作教程

2.1.1 红外发射模块与红外接收模块

红外信号的解码和模仿
​ 红外遥控器发出的信号是一连串的二进制脉冲码,而红外接收模块可以根据你选定的协议方式将接收到的信号转换为二进制内容显示在串口,而红外发射模块可以根据给定数组进行二进制信号的输出。

硬件图与连接方式
红外接收模块:VCC--------5V GND--------GND DAT--------PIN11
红外接收模块:VCC--------5V GND--------GND DAT--------PIN8 红外发射和接收模块

代码部分

//此段为破译并将二进制信号赋值入数组single1中
void dump1(decode_results *results) {
	count = results->rawlen; 
	for (int i = 1; i < count; i++) { 
		if (i & 1) { 
			single1[i-1]=(results->rawbuf[i]*USECPERTICK); 
		}
		else {
			single1[i-1]=((unsigned long) results->rawbuf[i]*USECPERTICK); 
		}
		Serial.print(" "); 
	}
	Serial.println(); 
	for(int j=0;j<count-1;j++){ 
		Serial.print(single1[j]); 
		Serial.print(", "); 
	} 
}
//此句为以38KHz发送single1
	irsend.sendRaw(single1,sizeof(single1) / sizeof(single1[0]),38);

红外遥控要用的话需要安装其库文件IRremote.h,下载地址

2.1.2 温湿度检测模块

温湿度检测

​ DHT11温湿度传感器,内部有一个电阻式感湿元件和有关NTC测温元件,元件信号经过存储在OPT内存中的校准系数处理后,以单一总线通信的形式发送给单片机IO口,数据帧格式为:8bit湿度整数值,8bit湿度小数值,8Bit温度整数值,8bit温度小数值,8bit校验和。
​ 一段完整的通信过程如下:
​ ①单片机将驱动总线的IO配置为输出模式。准备向DHT11发送数据。
​ ②单片机将总线拉低至少18ms,以此来发送起始信号。再将总线拉高并延时20~40us,以此来代表起始信号结 束。
​ ③单片机将驱动总线的IO配置为输入模式,准备接收DHT11回传的数据。
​ ④当DHT11检测倒单片机发送的起始信号后,就开始应答,回传采集到的传感器数据。

硬件图与连接方式

DHT11:VCC--------5V GND--------GND
DATA--------PIN8 NC---------not connect

DHT11
代码部分

调用DHT11库中的DHT11.temperature即可,此处附上DHT11库文件下载地址,或者自己写一个DHT11库

2.1.2 语音识别模块

语音识别

​ LD3320是一颗基于非特定人语音识别计数的一款芯片,工作过程简单来说就是把用户说出的语音内容,通过频谱转换为语音特征和之前设定好的关键词进行对比,选出最优的匹配结果。
硬件图与连接方式
LD3320 : 3.3V ----- VCC GND ------ GND MISO ----- PIN12
MOSI ----- PIN11 SCK ----- PIN13 NSS ----- PIN4 RST ----- PIN9
IRQ ----- PIN2 WR ----- GND LD3320
注意:LD3320必须由3.3V供电,否则会影响识别精度,如果Arduino板上无3.3V引脚,建议购买一块5V转3.3V的转换模块

代码部分

Voice.init(); //初始化 VoiceRecognition 模块 
Voice.addCommand("gao",0); //添加指令,参数(指令内容,指令标签(可重复))
                           //指令内容为识别内容,指令标签为返回值

需要调用LD3320库,此处附上LD3320资料的百度网盘地址,密码: v55g

2.2 程序流程

因为当时指令设置较多,所以需要用的信号也随之增多,导致一块Arduino板内存不足,无法同时实现两个功能,故选择了拆开进行

2.2.1 学习功能及自动控制

程序流程
学习功能
自动控制
代码部分

#include <IRremote.h> 
#include <LiquidCrystal.h> 
#include <dht11.h> 
#define DHT11PIN 8 dht11 DHT11; 
int RECV_PIN = 11,LED=7; 
int sg1,sg2,sg3; 
IRsend irsend; 
int count; 
unsigned int signle1[100],signle2[100],signle3[100]; 
IRrecv irrecv(RECV_PIN); 
decode_results results;
void setup() { 
	Serial.begin(9600); 
	pinMode(LED, OUTPUT); 
	pinMode(DHT11PIN,OUTPUT); 
	irrecv.enableIRIn(); // Start the receiver 
}
//此处省略上述过的将信号赋值部分
void loop() { 
	int TEM; 
	int chk = DHT11.read(DHT11PIN); 
	TEM=(float)DHT11.temperature; 
	digitalWrite(LED, HIGH); 
	delay(5000); 
	digitalWrite(LED, LOW); 
	delay(300); 
	digitalWrite(LED, HIGH); 
	delay(100); 
	if (irrecv.decode(&results)) { 
	sg1=results.value; 
	dump1(&results); 
	irrecv.resume(); 
	delay(300); 
	//当时采用了多重循环将信号分别赋值入singl1,singl2,singl3,过于冗杂不再列出
	digitalWrite(LED, LOW); 
	if(TEM>20&&TEM<28){ 
		irsend.sendRaw(single1,sizeof(single1) / sizeof(single1[0]),38); 
		delay(1000); 
	}
	else if(TEM>=28){ 
		irsend.sendRaw(single2,sizeof(single2) / sizeof(single2[0]),38); 
	delay(1000); 
	}
	else{ 
		irsend.sendRaw(single3,sizeof(single3) / sizeof(single3[0]),38); 
		delay(1000);
	} 
}

2.2.2 语音控制

程序流程
语音声明
语音循环
代码部分

#include <ld3320.h> 
#include <IRremote.h> 
VoiceRecognition Voice; //声明一个语音识别对象 
IRsend irsend; 
unsigned int signle1[100]={9000, 4350, 650, 450, 600, 1600, 650, 450, 650, 450, 650, 450, 600, 1600, 600, 500, 650, 450, 600, 1600, 600, 500, 600, 1600, 650, 1550, 650, 1600, 600, 500, 600, 1600, 650, 1550, 650, 450, 650, 450, 600, 500, 600, 500, 650, 450, 650, 450, 650, 400, 650, 1600, 650, 1550, 650, 1550, 650, 1600, 650, 1550, 650, 1550, 650, 1600, 600, 1600, 650, 450, 600}, signle2[100]={9000, 4300, 650, 450, 650, 1600, 650, 450, 650, 400, 650, 450, 650, 1600, 650, 450, 650, 400, 650, 1600, 600, 500, 650, 1550, 650, 1550, 650, 1550, 650, 450, 650, 1600, 650, 1550, 650, 450, 600, 1600, 650, 450, 650, 1550, 650, 450, 650, 450, 650, 1550, 650, 1600, 600, 1600, 650, 450, 650, 1550, 650, 450, 650, 1550, 650, 1600, 650, 450, 650, 400, 700},signle3[100]={}........; //  此处省略其他的信号声明
#define Led 7 //定义 LED 控制引脚 
void setup() {
	pinMode(Led,OUTPUT); //初始化 LED 引脚为输出模式 
	digitalWrite(Led,LOW); //LED 引脚低电平 
	Voice.init(); //初始化 VoiceRecognition 模块 
	Voice.addCommand("gao",0); //添加指令,参数(指令内容,指 令标签(可重复)) 
	Voice.addCommand("di",1); //省略其他语音的声明
	Voice.start(); //开始识别 
}
void loop() { 
	switch(Voice.read()) { //判断识别
		case 0: irsend.sendRaw(xinhao1,sizeof(xinhao1) / sizeof(xinhao1[0]),38); 
			digitalWrite(Led,HIGH); 
			delay(1000); 
			break; //省略其他信号的判断
	}
	digitalWrite(Led,LOW); 
}

3.测试结果

​ 笔者当时家中没有空调,思考电视与空调都采用了红外信号控制,并且都满足 NEC 协议(红外通信协议), 所以采用了电视控制作为代替,而回到学校才发现空调红外信号的复杂(泪目www)
​ 自控功能:检测到外部温度,每隔 10 秒发射一次开启信号,在电视中表现为音量提高
​ 声控功能:在各个模式中表现正常,温度上调信号的发射,表现在电视中为选择框向上移动

4.总结

​ 在控制电视方面表现良好,方案是可行的,但是对于空调的复杂红外信号破解仍需要思考。不过总的来说,作为第一个独立完成的项目,还算满意。

发布了2 篇原创文章 · 获赞 0 · 访问量 55

猜你喜欢

转载自blog.csdn.net/baidu_40605776/article/details/104718416
今日推荐