前面提到了315Mhz和433Mhz 发送接收模块,淘宝上这种发送+接收模块一套只要3.8。
这次文章研究的目标是:如何让接收模块能够收到自发电无线开关(TEL0146)发送的信号。
首先需要对这种模块的基本原理有了解,根据【参考1】资料,它使用调幅AM,OOK方式。我的理解是这种方式下:用无信号表示当前输出为0;发射433.29Mhz的无线信号表示当前输出为1。
此外与这种方式类似还有一种ASK (“振幅键控”)的调制方式:当需要输出0时,发射幅度较低的433.29Mhz的无线信号(下图A1);当输出1时,发射幅度较高的433.29Mhz的无线信号(下图A2)。
在【参考4】给出的频谱分析的结果中可以更清晰的看到二者区别,左侧是 ASK,右侧是 OOK 方式。
当然,我手上没有频谱仪无法“看”到实际发射的信号,但是我可以使用示波器查看接收模块的输出引脚。接收模块有4个引脚,分别是:GND,DATA,DATA,VCC (中间2个引脚都是用于输出的DATA)。经过实验该接收模块刚好能够接收到手中这个发射器的数据,因此就先用它进行实验。
接下来使用示波器直接观察 DATA引脚,了解一下模块输出的形式。使用的代码是RCSwitch 中的例子:
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
void setup() {
Serial.begin(9600);
mySwitch.enableReceive(2); // Receiver on interrupt 0 => that is pin #2
}
void loop() {
if (mySwitch.available()) {
Serial.print("Received ");
Serial.print( mySwitch.getReceivedValue() );
Serial.print(" / ");
Serial.print( mySwitch.getReceivedBitlength() );
Serial.print("bit ");
Serial.print("Protocol: ");
Serial.println( mySwitch.getReceivedProtocol() );
mySwitch.resetAvailable();
}
}
当按下“开”按钮,模块收到 16529064(0x00FF 36A8);当按下“关”按钮,模块收到 16529060(0x00FF 36A4).
使用示波器查看接收模块的输出引脚,可以看到如下波形。就是说当没有数据的时候,引脚为高,之后会拉低一段时间,然后发送数据,发送完毕再次拉高。
类似的,当我使用自发电无线开关时,接收模块也会输出类似波形。因此,它无法工作的问题是软件解码的问题,而不是硬件的问题。
在 RCSwitch.cpp 有下面一段代码:
/* 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.
*/
#if defined(ESP8266) || defined(ESP32)
static const VAR_ISR_ATTR RCSwitch::Protocol proto[] = {
#else
static const RCSwitch::Protocol PROGMEM proto[] = {
#endif
{ 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1
};
意思是使用高电平和低电平不同的比例来确定当前数值为0还是1.比如:高电平持续350us,然后出现一个1050us的低电平,那就是1:3,在 Protocol 1 中,这个值为0;反之高电平持续1050us,然后出现一个350u的低电平,那就是3:1 ,表示值为1。
接下来我们要首先查看一下正确的抓取值,然后再反推编码方式。我们使用 rf433snif-main 这个代码,这个是专用用来统计时间的分析工具。
抓取如下,左侧是原始数据,右侧是我们标记的结果(标注了前面49个数据,因为第50个数据有跟着一个很长的延时,猜测是在数据传输过程中一笔数据会重复三次):
Signal duration: 1445023 us
N LOW, HIGH
-----BEGIN RF433 LOW HIGH SEQUENCE-----
, 11166
000 1076, 384 1
001 1072, 384 1
002 1072, 392 1
003 1064, 392 1
004 1064, 392 1
005 1064, 396 1
006 328, 1116 0
007 328, 1120 0
008 324, 1120 0
009 320, 1116 0
010 1060, 396 1
011 1064, 400 0
012 324, 1120 0
013 1056, 408 1
014 1052, 408 1
015 316, 1128 0
016 1048, 412 1
017 312, 1128 0
018 1048, 412 1
019 312, 1136 0
020 1044, 416 1
021 308, 1132 0
022 308, 1136 0
023 308, 1136 0
024 308, 11204 0
025 1048, 412 1
026 1048, 416 1
027 1044, 416 1
028 1044, 416 1
029 1044, 420 1
030 1040, 416 1
031 304, 1140 0
032 304, 1140 0
033 304, 1136 0
034 308, 1136 0
035 1044, 420 1
036 1044, 420 1
037 304, 1136 0
038 1044, 416 1
039 1044, 420 1
040 304, 1140 0
041 1040, 424 1
042 300, 1140 0
043 1040, 420 1
044 300, 1140 0
045 1040, 420 1
046 304, 1140 0
047 304, 1140 0
048 304, 1144 0
049 300, 11224
….中间省略…..
-----END RF433 LOW HIGH SEQUENCE-----
Waiting for signal...
看起来这里的猜测需要一些运气,重新写出来是下面这样:
1 | 1111 | 1000 | 0100 | 1101 | 0101 | 0000 | 1111 | 1100 | 0011 | 0110 | 1010 | 1000 |
1 | F | 8 | 4 | D | 5 | 0 | F | C | 3 | 6 | A | 8 |
很明显最后的 36A8 是我们之前抓到的“开”命令。同样的方法再分析 050-073,也可以得到一个序列:FC36A8。资料中也提到了前面的值可能是厂商定义的型号和地址等信息。
有了上述的知识之后,目标非常明确,设定用于接收的GPIO引脚上会出现一个高低电平的的序列,我们需要根据序列的时间间隔来判断无线开关是否有按下。同样的代码抓取(特别注意,下面的序列是通过给自发电开关上电的方法来让其发射,这样更稳定的。具体抓到的原始数据在后面),整理之后可以看到下面的有规律的排列:
3098,104,296,104,296,104,297,104,296,104,296,104,296,104,296,105,296,104,296,104,296,104,296,305,96,304,96,104,296,104,296,305,96,304,96,304,96,304,96,304,97,303,97,103,297,104,296,104,296,104,
3098,104,296,104,297,104,296,104,296,104,296,104,296,105,296,104,296,104,296,104,296,104,296,304,97,304,96,104,296,104,296,304,97,304,96,304,96,304,96,304,97,303,97,104,296,104,296,104,297,103,
3098,104,296,105,296,104,296,104,296,104,296,104,296,105,296,104,296,104,296,104,296,105,296,304,96,304,96,104,296,105,295,305,96,304,96,304,96,304,97,303,97,303,97,104,296,104,296,104,297,104,
3097,105,295,104,297,104,296,104,296,105,295,104,297,103,297,104,296,104,296,104,296,105,296,304,96,304,96,104,296,105,296,304,96,304,96,304,96,304,97,303,97,304,96,104,296,104,297,104,296,104,
就说说,拉低3100us ,然后是 100us 高,300us低….因此,理论上修改前面的Protocol结构体加入这个特征应该是可以实现的,但是不知道什么原因,无法收到。最终,我编写一个简化版的识别代码:
const unsigned long int SelfSwitch[] =
{
100, 300, 100, 300, 100, 300, 100, 300, 100, 300,
100, 300, 100, 300, 100, 300, 100, 300, 100, 300,
100, 300, 300, 100, 300, 100, 100, 300, 100, 300,
300, 100, 300, 100, 300, 100, 300, 100, 300, 100,
300, 100, 100, 300, 100, 300, 100, 300
};
static int receiverPin = 2;
static int interruptPin = 0;
unsigned long lastTime = 0;
unsigned long int timings;
unsigned int pos;
boolean shoot;
void setup() {
Serial.begin(1000000);
pinMode(receiverPin, INPUT_PULLUP);
interruptPin = digitalPinToInterrupt(receiverPin);
lastTime = micros();
attachInterrupt(interruptPin, handleInterrupt, CHANGE);
Serial.println("Waiting INPUT pin HIGH");
Serial.println(sizeof(SelfSwitch) / sizeof(unsigned long int));
while (digitalRead(receiverPin) != HIGH) {}
pos = 0;
shoot=false;
}
int MaxP=0;
void loop() {
if (shoot) {
Serial.println("Fired!");
shoot=false;
}
if (pos>MaxP) {
Serial.println(pos);
MaxP=pos;
}
}
void handleInterrupt() {
if (pos < sizeof(SelfSwitch) / sizeof(unsigned long int)) {
timings = micros() - lastTime;
lastTime = micros();
}
// 对于第一个需要特别处理
if (pos == 0) {
// 如果第一个在[2900,3100]之间,那么开始记录
if ((timings > 2900) && (timings < 3100)) {
pos++;
return ;
}
}
// 如果超出范围
if ((timings>SelfSwitch[pos]+80)||(timings<SelfSwitch[pos]-80)) {
// 超出范围的情况下有可能是新的开始
if ((timings > 2900) && (timings < 3100)) {
pos=1;
return ;
}
pos=0;
} else {
//没有超过范围,满足要求
// 如果到达最后一个,表明发生
if (pos==sizeof(SelfSwitch) / sizeof(unsigned long int)-1) {shoot=true; pos=0;}
else pos++;
}
}
当接收模块收到信号时,GPIO会拉低,首先判断这个是否为 3000us的起始标志(特别注意,从2900到3100us都会被认定为启示标志。同样的,后面判定的信号也有一个容错范围)。起始之后,逐一对照SelfSwitch中定义的序列,如果相同,那么继续下一个,否则重新开始。这样,如果都能匹配上就认为确实收到了无线开关的发送信号。
经过测试,代码勉强能够工作,需要离得非常近(5CM),并且需要多按下几次。我猜测是因为发射端功率比较小,并且接收模块灵敏度不是很高的缘故。当然,如果真正想用,需要接收模块更好的天线,更加灵敏的芯片,不妨尝试数字无线开关接收端(TEL0142)。
参考:
- https://baike.baidu.com/item/433m%E6%97%A0%E7%BA%BF%E6%A8%A1%E5%9D%97?fromModule=lemma_search-box
- http://www.energiazero.org/arduino_sensori/Complete%20Guide%20for%20RF%20433MHz%20Transmitter.pdf
- https://www.rfwireless-world.com/Terminology/OOK-vs-FSK-vs-ASK.html
附录:
1. 抓取的能够正常通讯的遥控器数值:
Signal duration: 1445023 us
N LOW, HIGH
-----BEGIN RF433 LOW HIGH SEQUENCE-----
, 11166
000 1076, 384
001 1072, 384
002 1072, 392
003 1064, 392
004 1064, 392
005 1064, 396
006 328, 1116
007 328, 1120
008 324, 1120
009 320, 1116
010 1060, 396
011 1064, 400
012 324, 1120
013 1056, 408
014 1052, 408
015 316, 1128
016 1048, 412
017 312, 1128
018 1048, 412
019 312, 1136
020 1044, 416
021 308, 1132
022 308, 1136
023 308, 1136
024 308, 11204
025 1048, 412
026 1048, 416
027 1044, 416
028 1044, 416
029 1044, 420
030 1040, 416
031 304, 1140
032 304, 1140
033 304, 1136
034 308, 1136
035 1044, 420
036 1044, 420
037 304, 1136
038 1044, 416
039 1044, 420
040 304, 1140
041 1040, 424
042 300, 1140
043 1040, 420
044 300, 1140
045 1040, 420
046 304, 1140
047 304, 1140
048 304, 1144
049 300, 11224
050 1036, 420
051 1040, 420
052 1040, 420
053 1044, 416
054 1044, 424
055 1036, 424
056 300, 1144
057 304, 1140
058 304, 1140
059 304, 1140
060 1040, 424
061 1036, 424
062 300, 1144
063 1036, 424
064 1040, 424
065 300, 1144
066 1036, 424
067 304, 1140
068 1040, 428
069 296, 1148
070 1036, 424
071 300, 1144
072 304, 1148
073 300, 1144
074 300, 11232
075 1036, 420
076 1040, 424
077 1036, 424
078 1040, 424
079 1036, 424
080 1036, 424
081 300, 1144
082 300, 1144
083 300, 1144
084 300, 1144
085 1036, 424
086 1036, 424
087 300, 1148
088 1032, 428
089 1040, 420
090 300, 1148
091 1036, 424
092 300, 1144
093 1040, 424
094 300, 1148
095 1032, 428
096 296, 1148
097 300, 1148
098 300, 1148
099 300, 11232
100 1036, 424
101 1040, 420
102 1040, 424
103 1036, 424
104 1036, 424
105 1036, 428
106 296, 1148
107 300, 1144
108 300, 1144
109 300, 1148
110 1036, 424
111 1036, 424
112 300, 1144
113 1036, 424
114 1036, 432
115 296, 1152
116 1032, 424
117 300, 1148
118 1036, 428
119 300, 1144
120 1040, 428
121 296, 1148
122 296, 1144
123 300, 1148
124 296, 11232
125 508,175872
126 200, 880
127 676, 160
128 848, 124
129 200000, 0
130 200000, 0
131 200000, 0
132 200000, 0
133 12296, 11176
134 1072, 392
135 1064, 396
136 1064, 396
137 1064, 400
138 1060, 404
139 1056, 404
140 316, 1132
141 312, 1128
142 312, 1128
143 316, 1128
144 1052, 412
145 1048, 412
146 312, 1128
147 1052, 408
148 1048, 412
149 312, 1132
150 1048, 412
151 312, 1132
152 1048, 412
153 312, 1132
154 1048, 412
155 312, 1132
156 312, 1136
157 308, 1136
158 308, 11212
159 1048, 412
160 1048, 412
161 1048, 416
162 1044, 416
163 1044, 412
164 1048, 416
165 308, 1136
166 308, 1136
167 308, 1136
168 308, 1136
169 1048, 416
170 1044, 416
171 308, 1132
172 1048, 416
173 1044, 416
174 308, 1136
175 1044, 416
176 308, 1140
177 1040, 416
178 308, 1140
179 1044, 416
180 308, 1140
181 308, 1140
182 304, 1140
183 304, 11224
184 1044, 416
185 1044, 416
186 1044, 416
187 1044, 416
188 1044, 416
189 1048, 420
190 304, 1144
191 304, 1136
192 308, 1140
193 304, 1140
194 1044, 416
195 1044, 420
196 308, 1140
197 1044, 420
198 1044, 420
199 304, 1140
200 1044, 420
201 304, 1140
202 1044, 420
203 304, 1140
204 1044, 420
205 304, 1140
206 308, 1140
207 304, 1140
208 308, 11228
209 1044, 420
210 1040, 420
211 1040, 420
212 1040, 420
213 1044, 416
214 1044, 416
215 308, 1144
216 304, 1140
217 308, 1144
218 300, 1140
219 1044, 416
220 1044, 420
221 308, 1136
222 1040, 420
223 1040, 424
224 300, 1144
225 1040, 424
226 300, 1144
227 1040, 420
228 304, 1144
229 1040, 420
230 304, 1140
231 304, 1140
232 304, 1140
233 304, 11236
234 1040, 416
235 1044, 420
236 1044, 420
237 1044, 420
238 1044, 420
239 1044, 420
240 304, 1140
241 304, 1148
242 300, 1140
243 308, 1136
244 1044, 420
245 1040, 420
246 304, 1140
247 1040, 420
248 1040, 424
249 304, 1140
-----END RF433 LOW HIGH SEQUENCE-----
Waiting for signal...
2.抓取的自发电开关数据。
⸮⸮)⸮Signal duration: 210193 us
N LOW, HIGH
-----BEGIN RF433 LOW HIGH SEQUENCE-----
, 38599
000 116, 3084
001 112, 284
002 108, 288
003 108, 284
004 112, 284
005 108, 284
006 112, 284
007 112, 284
008 112, 284
009 112, 284
010 108, 284
011 108, 288
012 308, 88
013 308, 88
014 108, 288
015 108, 288
016 308, 92
017 304, 92
018 304, 92
019 304, 92
020 304, 92
021 304, 92
022 104, 292
023 104, 292
024 104, 292
025 104, 3092
026 104, 288
027 104, 292
028 104, 292
029 104, 292
030 104, 292
031 104, 292
032 104, 292
033 104, 292
034 104, 292
035 104, 292
036 104, 292
037 304, 92
038 304, 92
039 104, 292
040 104, 292
041 304, 92
042 304, 92
043 304, 92
044 108, 98916
045 36, 1072
046 40, 2668
047 68, 740
048 64, 3240
049 148, 28
050 36, 2304
051 40, 392
052 32, 600
053 60, 48
054 216, 856
055 20, 588
056 128, 284
057 20, 876
058 48, 392
059 36, 1696
060 72, 988
061 60, 360
062 84, 104
063 24, 1220
064 128, 140
065 64, 216
066 52, 1108
067 52, 96
068 32, 100
069 16, 176
070 44, 760
071 88, 192
072 60, 648
073 100, 720
074 196, 752
075 100, 1136
076 96, 68
077 32, 288
078 52, 284
079 20, 176
080 136, 372
081 24, 60
082 60, 140
083 56, 76
084 352, 492
085 36, 320
086 76, 244
087 100, 144
088 364, 720
089 68, 132
090 204, 336
091 236, 32
092 100, 100
093 232, 380
094 192, 28
095 264, 132
096 28, 28
097 136, 752
098 60, 312
099 88, 360
100 236, 588
101 104, 432
102 92, 156
103 56, 40
104 176, 252
105 72, 456
106 36, 92
107 160, 88
108 112, 336
109 232, 56
110 264, 80
111 56, 160
112 136, 44
113 272, 88
114 136, 40
115 108, 112
116 372, 84
117 56, 532
118 284, 48
119 360, 88
120 36, 164
121 80, 88
122 88, 212
123 64, 12
124 32, 116
125 124, 192
126 376, 260
127 112, 296
128 56, 84
129 128, 328
130 128, 592
131 200, 608
132 380, 172
133 40, 140
134 100, 148
135 56, 480
136 64, 356
137 640, 356
138 120, 12
139 16, 220
140 124, 536
141 320, 84
142 60, 80
143 44, 128
144 120, 52
145 72, 44
146 108, 36
147 204, 76
148 88, 224
149 308, 108
150 8, 52
151 64, 8
152 128, 36
153 80, 428
154 204, 96
155 108, 68
156 88, 180
157 116, 28
158 172, 136
159 76, 40
160 92, 84
161 52, 516
162 472, 472
163 156, 84
164 292, 368
165 180, 120
166 268, 196
167 248, 0
168 188, 236
169 172, 104
170 24, 36
171 140, 180
172 180, 192
173 108, 136
174 112, 140
175 72, 16
176 292, 48
177 164, 136
178 8, 240
179 76, 92
180 156, 32
181 264, 292
182 600, 260
183 88, 76
184 412, 88
185 108, 184
186 60, 52
187 236, 0
188 168, 68
189 76, 80
190 100, 568
191 436, 156
192 108, 72
193 68, 304
194 120, 544
195 4, 20
196 180, 68
197 48, 48
198 188, 244
199 160, 104
200 496, 184
201 148, 276
202 8, 116
203 64, 24
204 168, 520
205 20, 172
206 104, 340
207 108, 72
208 384, 48
209 164, 164
210 176, 76
211 228, 40
212 200, 248
213 188, 132
214 328, 92
215 152, 112
216 176, 64
217 132, 80
218 76, 144
219 196, 228
220 140, 40
221 16, 280
222 272, 100
223 900, 152
224 48, 92
225 572, 52
226 68, 196
227 120, 256
228 156, 128
229 48, 48
230 36, 128
231 772, 232
232 516, 60
233 272, 172
234 164, 92
235 568, 144
236 80, 120
237 16, 8
238 164, 28
239 16, 88
240 304, 180
241 652, 340
242 48, 108
243 116, 32
244 264, 36
245 200, 192
246 448, 68
247 180, 552
248 80, 80
249 80, 76
-----END RF433 LOW HIGH SEQUENCE-----
Waiting for signal...