红外遥控风扇改手机APP远程控制杂记

news/2024/11/29 9:43:20/

前记

最近老是找不到风扇遥控,搞得想整个手机APP远程控制风扇。说搞就搞,远程控制流程稍微一思考就定下来了。首先是信号转发设备通过WiFi模块连接服务器端,手机端再通过APP向服务器端发送控制指令,服务器端将控制指令下发到信号转发设备上,信号转发设备将控制指令翻译成红外信号发送给红外设备。制作这样一个产品需要几个技术栈:

  1. 服务端程序开发
  2. APP端/Web端应用开发
  3. 硬件相关知识及嵌入式开发

作为一个互联网民工,前两样技能都不是问题。唯独第三样技能接触得比较少。最终虽然把产品做出来了,但是对硬件和嵌入式开发的理解还只是半知半解。此文会重点记录开发过程中碰到的硬件和嵌入式开发的相关知识,权当是给自己做个笔记吧。

硬件选型

产品涉及到的硬件有WiFi模块和红外收发模块及MCU。WiFi模块功能就不用说了,红外接收功能用于解码遥控的信号,MCU用于接收WiFi信号并翻译控制红外发射器发送信号。
咨询做硬件的朋友后经过一番搜索筛选,最终选用ESP8266模块。ESP8266既有WiFi功能且有MCU可以烧写程序,这样一来就可以不用单独买一个MCU模块了。最终在某宝买了个带NodeMCU开发板很红外收发器的ESP8285模块(8285和8266的主要区别是flash大了1mb)。买到的模块是这样的:
在这里插入图片描述在这里插入图片描述

USB转TTL模块

USB转TTL基本是嵌入式开发必备的,用来烧写或者调试嵌入式程序经常需要用到。具体功能我也不太懂,大概就是将USB接口转为类似RS232的串口信号。
TTL接口和ESP8266的接线如下:
5v – 5v
rx – tx
tx – rx
GND – GND

开发调试

驱动

ESP8266和USB转TTL模块接好线之后插上电脑,需要安装驱动才能识别,驱动下载链接:https://sparks.gogo.co.nz/ch340.html。

调试工具

驱动安装好之后,下载一个串口调试软件,配置参数如下,然后打开串口。ESP8266自带的固件支持AT命令,支持的所有AT命令可以参考官方PDF文档。这里我们只需要用到AT+RST命令来测试我们前面的步骤是否都成功了。输入AT+RST命令之后,ESP8266会重启并且输出一系列信息,如果能在调试工具上看到串口输出的信息,就证明我们前面的操作都成功了。
在这里插入图片描述

引脚电平

这里需要注意的是ESP8266的IO0引脚。IO0引脚在短接GND的情况下是烧写模式,这个模式下进行调试是不会有任何反应的,需要去掉短接才能进行调试。

波特率

不管是ESP8266还是ESP8285,串口波特率都是115200,不用尝试其他的值。由于前期我没有足够的经验和知识,在调试这个步骤尝试换波特率进行连接,浪费了不少时间。

烧写固件

由于平时也有写一些Python代码,然后发现这个模块可以烧写Python运行环境–MicroPython,所以模块拿到手就立即烧了个MicroPyton环境。固件可以从MicroPython官网找到。MicroPython官方是推荐使用esptool烧写固件的。为了节省学习成本,我还是下载了个桌面客户端烧写程序。烧写时的配置:
在这里插入图片描述
如果是8266,选1MByte就好。如果烧写没反应,试一下拔插USB。且需要注意在拉低IO0引脚电平的情况下才能将固件烧写进去。

恢复固件

由于python的内存垃圾回收机制会导致程序短暂中断,而红外信号又是对频率比较敏感的,所以用python来进行红外信号收发可能不太合适。然后我又尝试刷回原来的固件。ESP8266的固件可以在官方网站找到。我下载的是ESP8266 NonOS AT Bin V1.7.4,下载下来是个压缩包,里面是有刷写说明的。打开压缩包at文件夹下的readme.md文件,可以看到如下内容:

### Flash size 8Mbit: 512KB+512KB
boot_v1.2+.bin 0x00000
user1.1024.new.2.bin 0x01000
esp_init_data_default.bin 0xfc000
blank.bin 0x7e000 & 0xfe000

我们只需要安装这个列表配置烧写工具就行了。由于我们使用了NodeMCU开发板,所以不能使用官方的下载工具,要使用NodeMCU的下载工具,记得下载是需要短接IO0和GND引脚的。我的成功烧写配置如下:
在这里插入图片描述

Arduino配置

下载安装Arduino IDE之后还需要安装相关的插件才能对esp8266进行烧写程序,插件的安装过程可以参考这篇文章。大家配置好之后可以尝试烧写个简单的串口文字打印程序调试一下,我这里就不再详解代码相关的知识了。要注意烧写完程序之后重新上电才会运行,并且要断开IO0和GND引脚的短接。

IR库

从零手写代码完成红外信号的编解码是相当麻烦的,最好是找一个轮子支持一下。幸好github上有个好轮子https://github.com/crankyoldgit/IRremoteESP8266。可以按照这个IR库的说明安装并运行实例程序。

程序实现

我最终实现了我的想法:ESP8266上电连接WiFi并建立TCP连接到服务器,服务器接收App的HTTP请求并转发控制请求给ESP8266的TCP连接,下面贴上ESP8266的示例代码。由于我家的风扇品牌没有在IR支持的列表里,且不是NEC协议,所以只能用官方的示例代码接收遥控发出的红外信号打印并且记录下来,将每一个按键对应的信息都写死在程序里:


#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ESP8266WiFi.h>const uint16_t kIrLed = 4;  // ESP8266 GPIO pin to use. Recommended: 4 (D2).IRsend irsend(kIrLed);  // Set the GPIO to be used to sending the message.uint16_t power[107] = {2432, 3254,  430, 1240,  1232, 422,  1228, 390,  428, 1210,  1262, 390,  1262, 388,  1262, 390,  1262, 390,  1262, 420,  398, 1210,  432, 1208,  430, 1208,  430, 1208,  430, 1210,  430, 1208,  1266, 414,  398, 6898,  2464, 3254,  430, 1210,  1262, 390,  1262, 388,  430, 1206,  1264, 388,  1262, 422,  1232, 388,  1262, 422,  1230, 420,  398, 1208,  430, 1208,  430, 1208,  430, 1208,  432, 1208,  430, 1208,  1266, 414,  400, 6896,  2464, 3252,  432, 1208,  1264, 388,  1266, 420,  398, 1240,  1232, 420,  1230, 422,  1230, 388,  1262, 420,  1236, 386,  432, 1208,  430, 1210,  430, 1208,  430, 1210,  430, 1210,  430, 1210,  1264, 418,  398};  
uint16_t plus[107] = {2462, 3258,  400, 1238,  1260, 392,  1236, 416,  402, 1236,  1262, 392,  1234, 418,  1262, 388,  1260, 392,  1264, 388,  1244, 410,  400, 1238,  402, 1238,  402, 1238,  402, 1238,  1236, 446,  1206, 412,  402, 6928,  2464, 3256,  402, 1236,  1264, 390,  1262, 392,  402, 1236,  1262, 392,  1260, 390,  1262, 390,  1260, 390,  1262, 390,  1262, 390,  402, 1238,  402, 1238,  400, 1238,  402, 1236,  1264, 390,  1250, 398,  400, 6930,  2464, 3254,  402, 1268,  1206, 416,  1264, 390,  402, 1236,  1262, 392,  1260, 390,  1262, 390,  1262, 390,  1236, 416,  1260, 390,  404, 1236,  400, 1240,  402, 1238,  400, 1238,  1262, 392,  1236, 412,  402};
uint16_t subtract[107] = {2462, 3256,  430, 1210,  1262, 390,  1260, 392,  428, 1212,  1262, 390,  1260, 392,  1260, 390,  1262, 390,  1262, 390,  1260, 392,  428, 1212,  430, 1242,  396, 1210,  1264, 390,  1260, 392,  428, 1208,  430, 6900,  2460, 3258,  430, 1210,  1262, 390,  1260, 392,  428, 1210,  1262, 392,  1262, 388,  1262, 392,  1260, 390,  1262, 390,  1262, 390,  428, 1210,  430, 1210,  430, 1208,  1262, 392,  1260, 392,  426, 1208,  428, 6932,  2432, 3256,  430, 1210,  1262, 390,  1262, 388,  430, 1210,  1264, 388,  1262, 388,  1264, 388,  1264, 420,  1230, 390,  1262, 422,  396, 1210,  430, 1210,  430, 1240,  1232, 390,  1262, 390,  428, 1208,  430};
uint16_t updown[107] = {2464, 3256,  406, 1234,  1262, 392,  1236, 416,  402, 1236,  1264, 388,  1264, 390,  1238, 446,  1204, 416,  1238, 416,  402, 1236,  1236, 416,  402, 1236,  402, 1236,  402, 1238,  402, 1236,  402, 1234,  402, 6954,  2434, 3258,  404, 1236,  1262, 390,  1262, 424,  368, 1238,  1236, 416,  1236, 416,  1260, 392,  1260, 392,  1236, 448,  370, 1236,  1236, 416,  402, 1236,  404, 1236,  402, 1238,  402, 1238,  404, 1234,  402, 6928,  2464, 3256,  402, 1236,  1238, 416,  1260, 392,  402, 1236,  1260, 392,  1260, 392,  1262, 390,  1238, 416,  1260, 390,  402, 1270,  1204, 416,  402, 1236,  402, 1238,  400, 1238,  402, 1238,  402, 1234,  402};
uint16_t leftright[107] = {2460, 3258,  428, 1210,  1264, 390,  1262, 390,  428, 1212,  1260, 392,  1260, 390,  1260, 392,  1262, 392,  1262, 392,  426, 1212,  428, 1210,  1264, 390,  428, 1212,  428, 1212,  428, 1212,  428, 1208,  428, 6902,  2462, 3258,  428, 1210,  1262, 392,  1260, 392,  426, 1244,  1230, 422,  1228, 392,  1260, 392,  1260, 394,  1258, 394,  428, 1212,  426, 1214,  1258, 424,  396, 1212,  428, 1212,  430, 1210,  428, 1226,  410, 6902,  2460, 3256,  430, 1242,  1230, 392,  1258, 394,  428, 1212,  1260, 394,  1258, 392,  1260, 392,  1258, 394,  1260, 394,  424, 1246,  394, 1212,  1260, 392,  426, 1214,  426, 1214,  426, 1212,  426, 1210,  426};
uint16_t baby[107] = {2434, 3284,  398, 1242,  1234, 418,  1234, 450,  366, 1242,  1232, 452,  1202, 450,  1200, 420,  1232, 420,  1234, 420,  1234, 418,  400, 1240,  400, 1240,  1234, 450,  1202, 450,  366, 1240,  400, 1238,  398, 6932,  2436, 3284,  400, 1272,  1200, 422,  1232, 420,  398, 1240,  1234, 418,  1232, 450,  1202, 452,  1200, 422,  1232, 420,  1232, 420,  398, 1242,  398, 1240,  1234, 420,  1232, 420,  398, 1242,  400, 1236,  398, 6932,  2434, 3284,  400, 1240,  1232, 420,  1234, 450,  368, 1242,  1230, 454,  1198, 420,  1232, 420,  1232, 420,  1232, 418,  1234, 450,  366, 1274,  366, 1240,  1234, 420,  1234, 420,  398, 1240,  398, 1238,  398};
uint16_t timing[107] = {2434, 3282,  398, 1240,  1238, 416,  1234, 418,  404, 1234,  1236, 422,  1230, 416,  1234, 420,  1230, 420,  1234, 418,  400, 1238,  428, 1210,  428, 1246,  1202, 418,  428, 1218,  420, 1210,  428, 1208,  426, 6902,  2436, 3282,  400, 1240,  1236, 416,  1236, 416,  428, 1210,  1236, 416,  1236, 416,  1234, 450,  1202, 450,  1202, 450,  398, 1208,  426, 1212,  400, 1238,  1262, 392,  428, 1208,  402, 1240,  400, 1236,  400, 6930,  2440, 3280,  424, 1216,  1262, 406,  1222, 436,  408, 1208,  1236, 448,  1204, 450,  1202, 450,  1204, 416,  1234, 418,  430, 1208,  402, 1238,  400, 1272,  1206, 450,  394, 1210,  424, 1214,  400, 1236,  400};const char* host = "139.186.70.***";void setup() {irsend.begin();
#if ESP8266Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
#else  // ESP8266Serial.begin(115200, SERIAL_8N1);
#endif  // ESP8266//while (!Serial)  // Wait for the serial connection to be establised.//  delay(50);WiFi.begin("ABCDE", "***");Serial.print("Connecting");while (WiFi.status() != WL_CONNECTED){delay(500);Serial.print(".");}Serial.println();Serial.print("Connected, IP address: ");Serial.println(WiFi.localIP());
}void sendIR(char c) {switch(c){case 'p':irsend.sendRaw(power, 107, 38);break;case 'q':irsend.sendRaw(plus, 107, 38);break;case 's':irsend.sendRaw(subtract, 107, 38);break;case 'u':irsend.sendRaw(updown, 107, 38);break;case 'l':irsend.sendRaw(leftright, 107, 38);break;case 'b':irsend.sendRaw(baby, 107, 38);break;case 't':irsend.sendRaw(timing, 107, 38);break;      default:break;};
}void loop() {WiFiClient client;Serial.printf("\n[Connecting to %s ... ", host);if (client.connect(host, 5000)){Serial.println("connected]");Serial.println("[Sending a request]");client.print(String("from-big-head\n"));Serial.println("[Response:]");while (client.connected() || client.available()){if (client.available()){String line = client.readStringUntil('\n');sendIR(line[0]);}}client.stop();Serial.println("\n[Disconnected]");}else{Serial.println("connection failed!]");client.stop();}delay(1000);
}

引用

  1. https://micropython.org
  2. https://github.com/espressif/esptool/
  3. https://github.com/nodemcu/nodemcu-flasher
  4. https://www.espressif.com/en/support/download/at
  5. https://www.qutaojiao.com/11532.html
  6. https://github.com/crankyoldgit/IRremoteESP8266

http://www.ppmy.cn/news/288784.html

相关文章

离线语音控制系统 唤醒词.命令字

唤醒词&#xff1a; 小虎贝贝 | 小贝小贝 | 你好小贝 音量调节&#xff1a; 增大音量 | 音量增大 减小音量 | 音量调小 控制空调相关的命令字&#xff1a; 打开空调 关闭空调 自动模式 制冷模式 制热模式 升高温度 | 升高一度 降低温度 | 降低一度 十六度 十七度 十八度 十九…

NLP学习笔记四-word embeding

NLP学习笔记四-word embeding word embeding就是一块重头戏了&#xff0c;因为这里做完&#xff0c;我们的数据处理部分也基本上收尾了。 下面我们附上一张图&#xff1a; 如上图&#xff0c;word embeding实在我们one-hot word之后才可以进行的&#xff0c;每一步处理技术都是…

SpringBoot整合Mybatis-Plus+Druid实现多数据源

&#x1f33a;本文主要讲解springboot mybatisplus druid 实现多数据源配置功能 &#x1f33a; 一些必要的准备及代码说明 &#x1f391;多数据源 &#x1f379;1. pom.xml 添加依赖 &#x1f6d1;2. application.yml⏳ 3. 排除默认加载&#x1f6ce; 4. Mybatis-Plus 配置&a…

python-面向对象:三大特性高级特性

文章目录 前言一、面向对象三大特性&#xff1a;封装、继承、多态1.对象和类2.封装3.继承(1)重写父类方法(2)多继承(3)私有属性与私有方法 4.多态 二、三大特性的应用1.链表的封装2.栈的封装3.队列的封装4.二叉树的封装 三、高级特性1.类属性与实例属性2.类方法与静态方法3.pro…

新同居时代

新同居时代【转载】 ID:愤怒的螃蟹 一  偷眼看了看不远处的经理。见他仍全神贯注地继续玩着他那弱智的联众。悄悄的溜回自己的电脑前打开qq。 “嘿&#xff0c;干什么呢&#xff1f;”哥们见我上线和我打招呼。 “上班呢”给他回一句后再偷偷的看经理一眼。 “还在那公司做…

三星s6开机无显示无服务器,三星Galaxy S6手机不能开机怎么办?三星Galaxy S6手机不能开机解决办法...

三星Galaxy S6手机不能开机怎么办呢&#xff1f;可能很多使用三星Galaxy S6的用户会有这样的问题&#xff0c;三星Galaxy S6在入手之后&#xff0c;可能由于一些不恰当的操作或者刷机&#xff0c;导致手机无法开机&#xff0c;那么如果遇到这样的问题&#xff0c;我们可以怎么来…

三星Galaxy Tab S6与Tab S7的任何区别

Samsung’s Galaxy Tab S7 was recently announced at Samsung’s Unpacked event which featured products like the Note20 Ultra, Galaxy Buds Live, and more products! Last year, Samsung released the Galaxy Tab S6, which was a great 2-in-1 device which consumers …

三星S6的Wifi连接上了,却无法上网

三星S6手机的Wifi连接上了&#xff0c;应用却无法上网&#xff01; 如何解&#xff1f; 答&#xff1a; 进入设置——》流量监控——》管理应用程序流量&#xff0c; 数据和WLAN全勾上就OK啦&#xff01; 注意是“全勾上”哟。