红外遥控风扇改手机APP远程控制杂记
前记
最近老是找不到风扇遥控,搞得想整个手机APP远程控制风扇。说搞就搞,远程控制流程稍微一思考就定下来了。首先是信号转发设备通过WiFi模块连接服务器端,手机端再通过APP向服务器端发送控制指令,服务器端将控制指令下发到信号转发设备上,信号转发设备将控制指令翻译成红外信号发送给红外设备。制作这样一个产品需要几个技术栈:
- 服务端程序开发
- APP端/Web端应用开发
- 硬件相关知识及嵌入式开发
作为一个互联网民工,前两样技能都不是问题。唯独第三样技能接触得比较少。最终虽然把产品做出来了,但是对硬件和嵌入式开发的理解还只是半知半解。此文会重点记录开发过程中碰到的硬件和嵌入式开发的相关知识,权当是给自己做个笔记吧。
硬件选型
产品涉及到的硬件有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);
}
引用
- https://micropython.org
- https://github.com/espressif/esptool/
- https://github.com/nodemcu/nodemcu-flasher
- https://www.espressif.com/en/support/download/at
- https://www.qutaojiao.com/11532.html
- https://github.com/crankyoldgit/IRremoteESP8266
红外遥控风扇改手机APP远程控制杂记相关推荐
- 毕业设计——基于STM32的智能家具控制系统(ESP-01S(8266)、手机app远程控制、远程显示温度)
智能家具系统分为两个不同版本系列: ①系列一:手机app远程控制.远程检测温湿度显示在app,(云平台) ---------本文章 ②系列二:语音识别控制 http ...
- 手机APP远程控制树莓派
手机APP远程控制三步快速连接树莓派 www.marsiot.com 请确认树莓派可以访问互联网 目前支持树莓派官方镜像Raspbian 硬件目前支持Raspberry Pi 2/3 Model B ...
- 一种典型的手机APP远程控制PLC解决方案
一种低成本的手机APP远程控制PLC解决方案 对于很多用户来说,通过手机APP远程控制设备,是一种非常便利的事情.在物联网技术快速发展的时代,当前有几种方式可以实现手机APP远程控制PLC的解决方案, ...
- 红外遥控及Android手机红外遥控器开发
一.红外遥控 红外遥控技术是通过红外技术.红外通信技术和遥控技术的结合实现的一种无线控制技术.由于红外线的波长较短,对障碍物的衍射能力较差,无法穿透墙壁,所以红外遥控术更适合应用在短距离直线控制的场合 ...
- 如何通过手机APP远程控制PLC
随着工业自动化的发展,PLC作为一种可靠的.高效的智能控制器在工业领域得到了广泛运用.同时在日常工作中,智能手机作为一台越来越强大的多媒体平台,应用于远程监控PLC的需求越来越高,现在已经十分成熟并得 ...
- 使用手机APP远程控制51单片机
前言: 这个算是51单片机上传数据到手机APP续集,添加了远程控制的功能,不懂的小伙伴可以看看之前的文章. 功能介绍: 1.采集温度数据到手机APP 2.通过APP控制单片机上的LED灯 APP操作: ...
- 搭建人工智能云服务器,搭建人工智能云连接,实现手机APP远程控制
STC89C52驱动ESP8266-01搭建实现云连接,支持手机APP远程控制程序 单片机与wifi模块接线 单片机 wifi模块 TX--------RX RX--------TX GND----- ...
- (开源)ESP8266改装小风扇,手机app远程控制+天猫精灵控制
ESP8266改装小风扇,app远程控制+天猫精灵控制 材料准备 拆解风扇 第一 下载ESP8266示例(arduino ide 编程开发) 第二 修改demo例程 关于主题topic 第三 app ...
- 实现微信小程序和手机app远程控制51单片机控制L298N电机驱动器控制马达(ESP8266 AT89S52 http请求转串口通信系统 mqtt )
首先你有这样的8266 这种8266自身带2个按键和烧录芯片方便调试,综合性价比较高. 还有就是你需要有一个51单片机或者其他芯片都行.有了这2个芯片我们开始吧! 1.先看一段视频效果演示,再来介绍实 ...
- ESP8266改装小风扇,手机app远程控制+天猫精灵控制
材料准备 拆解风扇 ESP8266一块 3)3.3继电器一块 主要步骤 1) 下载ESP8266示例(arduino ide 编程开发) 下载地址 2) 修改demo例程 关于主题topic 3) a ...
最新文章
- Visual Studio调试时遇到的问题:生成下面模块时,启用了优化或没有调试信息
- phpstorm8 license key
- 【Git】Git使用记录: 撤回已经commit到本地的提交记录
- 系统学Android从零开始,搞懂这些直接来阿里入职
- 避坑指南:通过expdp/impdp迁移数据的7个坑
- mysql执行文件脚本文件_MySQL执行外部sql脚本文件的命令
- python3 学习日志 Microsoft Office 编程
- JAVA md5加盐加密解密_md5加密,md5加盐加密和解密
- 阿铭Linux_公有云学习笔记20190117
- 3D建模的几种常用建模方法
- 以太坊分片Sharding FAQ
- [蓝桥杯][算法提高VIP]盾神与砝码称重
- PDF提取页面方法,如何从PDF文件中提取页面
- 前端笔记1 HTML基础
- PMP报考一定要报培训班吗?
- CSS中四分之一圆的写法
- 网间进程的标识和端口分配机制
- Virus.Win32.Ramnit.X,Virus.Win32.Ramnit.a病毒
- UI设计薪酬范围是多少 如何快速掌握UI技能
- mac apache自带 ab 测试工具安装及使用
热门文章
- 根据报告数据,2021 年 Q1,全球小说 App 推广榜 Top20 里面,有 11 个 App 来自中国厂商。最新版本已经上线
- (已解决)网页不显示数学公式||只显示源码
- 九宫格摆法_九宫格婚纱照摆法图片与技巧
- Fallback class must implement the interface annotated by @FeignClient
- [学点经济]什么是SDR [the IMF's Special Drawing Rights (SDR) basket of currencies]
- 自定义组件使用v-modle
- 【译】eBPF 概述:第 4 部分:在嵌入式系统运行
- hdu 2044 一只小蜜蜂...
- skip gram模型的实现
- 《崩坏3》评测:游戏设计中整体性和利用率分析(下)