无线通信433
在实现一个无线门铃产品时,不得不接触一下433。空研究了好几天,终于有一些眉目,这里记录一些研究感想。门铃协议中的专业术语比较多,比如OOK
、Manchester code
、433的模组又有很多型号,随便钻入某个专业词不得几天爬不出来,这期间还借助claude、ChatGPT、Gemini的帮助下来了解,这个AI工具就像汽车,如果不会使用提示词,也是和搜索引擎差不多,所以还得自身的驾驶技术过硬才可以。
了解一个新技术,我喜欢先找靠山,对于433我因为手上有PulseView
逻辑分析仪,就以它为靠山。它抓取的信号可以使用内置的协议解析,比较找到两个相关的一个是OOK
和RC encode
,我在OOK
中陷入了很久出不来,不过最终在后者RC encode
的帮助下理解这种协议了。
实现官网例子
开源逻辑分析仪协议解析官网有RC encode
的介绍,其中还给出一个例子,以应试教育的心态,如果自己造出和该参考答案
一致的图形,那么说明算对433有了初步的了解。
sigrok官网RC encode 例子 |
使用Arduino生产波形
参考《使用 Arduino 和 RC Switch 逆向遥控器》写出如下Arduino代码:
/*
Example for different sending methods
https://github.com/sui77/rc-switch/
*/
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
void setup() {
Serial.begin(9600);
// Transmitter is connected to Arduino Pin #10
mySwitch.enableTransmit(10);
// Optional set pulse length.
// mySwitch.setPulseLength(320);
// Optional set protocol (default is 1, will work for most outlets)
// mySwitch.setProtocol(2);
// Optional set number of transmission repetitions.
// mySwitch.setRepeatTransmit(15);
}
void loop() {
/* Same switch as above, but using decimal code */
mySwitch.send(5393, 24); // 5393 表示发送的信号代码, 24 表示数据长度。
delay(1000); // 暂停 1000 毫秒后再执行下一行代码。
mySwitch.send(5396, 24);
delay(1000);
delay(20000);
}
逻辑分析仪接上之后读取的波形如下所示:
生成Button D信号 |
经过参考答案是A,我们自己能生产相近的D,至于为了PulseView为何认为是这两字母,是ASCII还是HID或者UNICODE暂时不清楚,继续生产了数字1、2的波形如下,开始了解到规律,RC encode
中出现U
不必惊慌,自动读波形才更加准确,窄波形是0、宽波形是1,正好24位。
数字1 | 数字2 |
生成参考答案
通过查询参考答案
对应的数值,使用计算器转换为16进制后是0x111154
,将其写入代码支持并抓取波形,如右图所示,生成了 Button A的波形。
查询参考答案 对应的数值 |
生成 Button A |
代码如下:
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
void setup() {
Serial.begin(115200);
// Transmitter is connected to Arduino Pin #10
mySwitch.enableTransmit(10);
}
void loop() {
/* Same switch as above, but using decimal code */
mySwitch.send(0x111154, 24); // 0x111154 表示发送的信号代码, 24 表示数据长度。
delay(1000); // 暂停 1000 毫秒
}
RCSwitch参数与PulseView图示对照
以上算是快速理解,本小节对比一下参数。RCSwitch可以很容易生产波形,并被PulseView抓取显示。如果先有了PulseView抓取的波形,想来匹配使用RCSwitch来接收解析和发送,则需要能根据波形总结出参数的能力。库代码中有这么一段注释来说明:
/* Format for protocol definitions:
* {pulselength, Sync bit, "0" bit, "1" bit, invertedSignal}
*
* pulselength: pulse length in microseconds, e.g. 350
* Sync bit: {1, 31} means 1 high pulse and 31 low pulses
* (perceived as a 31*pulselength long pulse, total length of sync bit is
* 32*pulselength microseconds), i.e:
* _
* | |_______________________________ (don't count the vertical bars)
* "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse
* and 3 low pulses, total length (1+3)*pulselength, i.e:
* _
* | |___
* "1" bit: waveform for a data bit of value "1", e.g. {3,1}:
* ___
* | |_
*
* These are combined to form Tri-State bits when sending or receiving codes.
*/
static const RCSwitch::Protocol PROGMEM proto[] = {
{ 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1
我来将这些参数直接标注在波形图上
如何读信号 |
pulselength(350)
注意这个参数不是周期,而是高电平的宽度
pulselength(350) |
Sync bit{ 1, 31 }
两段波形中间低电平的宽度
Sync bit{ 1, 31 } |
“0” bit and “1” bit
0和1分别的占空比
“0” bit and “1” bit |
nSeparationLimit
这个参数在库中被固定的设置为了4300
,根据其注释应该是和Sync bit
,比如pulselength * 30 = 10500
,只要小于该10500即可。比如我测试的波形是pulselength
是34us,合适的值是34 * 30 = 1020
,如果还使用默认的4300
则就抓取不到正确信号。这个是重点。
总结
了解的时候应该避免上来就去选择433发射接收模组
,也尽可能不要在自定义的数据中徘徊,找到公认的靠山,死磕就能磕明白。按照现在的总结, PulseView
的解析也不是十分的精准,如果不准确的东西太多,那就没有办法有策略的来熟悉这种协议。我其实到现在也不清楚会何PulseView
在解析bits(第一行)的时候会把两位当成1位,这样的话就没有办法正确读取。