Decodarea sonerie wireless
În articolul de azi o să vă prezint o metodă foarte simplă pentru decodificarea soneriilor wireless de la Lidl , Hornbach sau LM. Practic se folosește o placă ardunio uno, un receptor 433Mhz și câteva fire de legătură. Scopul acestei decodări este posibilitatea aflării codului de activare și folosirea lui cu alt dispozitiv DIY. Sketch-ul de mai jos se bazează pe biblioteca RCSwitch.
Conexiuni:
- VCC receptor se leagă la 5V Arduino
- GND receptor se leagă la GND Arduino
- Pinul de date al receptorului (cel de lângă VCC) se conectează la PIN 2 de la Arduino
Schema electronica/sistem:
- Compilează și încarcă sketch-ul de mai jos
- În Arduino IDE Tools>Serial monitor , setează viteaza de comunicare la 9600 și o să se afișeze meniul :
- 433MHz Sniffer - Select Mode:
- 1 - mode RCSwitch
- 2 - mode RAW Sniffer
- 0 - home
- Selectează 1 pentru citirea codului soneriei
- Apasă butonul soneriei în apropierea receptorului 433Mhz
- Decodificarea transmisiei (dacă este compatibilă cu protocolul 433Mhz) ar trebui să arate așa:
- Decimal: 12xxxxxx (24Bit) Binary: 1100000bbbbbbbbbbbbbbbb Tri-State: not applicable PulseLength: 250 microseconds Protocol: 1
Raw data: ddd, ddd, ddd, .....
Sketch-ul de test:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "rcswitch.h"
RCSwitch mySwitch = RCSwitch();
unsigned char snifferMode = 0;
#define SAMPLESIZE 500
static unsigned int timings[SAMPLESIZE];
static unsigned int pos = 0;
static unsigned long lastTime = 0;
static int receiverPin = 2;
static int interruptPin = 0;
void setup() {
Serial.begin(9600);
//mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2
//interruptPin = digitalPinToInterrupt(receiverPin);
//attachInterrupt(interruptPin, handleInterrupt, CHANGE);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Serial.println(F("433MHz Sniffer - Select Mode:"));
Serial.println(F("1 - mode RCSwitch"));
Serial.println(F("2 - mode RAW Sniffer"));
Serial.println(F("0 - home"));
}
void loop() {
handleSerial();
//Serial.println(snifferMode);
// Everything else loop() does…
switch (snifferMode) {
case 1:
//Serial.println(snifferMode);
handleRCSwitch();
break;
case 2:
handleRAW();
snifferMode = 0;
break;
case 0:
//Serial.println("Start-up. Set Mode:");
snifferMode = 0;
break;
}
}
void handleSerial() {
if (Serial.available() > 0) {
char incomingCharacter = Serial.read();
switch (incomingCharacter) {
case '1':
Serial.println(F("mode RCSwitch"));
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2
snifferMode = 1;
break;
case '2':
Serial.println(F("mode RAW Sniffer - send 2 to trigger receiver"));
interruptPin = digitalPinToInterrupt(receiverPin);
attachInterrupt(interruptPin, handleInterrupt, CHANGE);
snifferMode = 2;
break;
case '0':
snifferMode = 0;
break;
}
}
}
static const char* bin2tristate(const char* bin);
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength);
void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) {
const char* b = dec2binWzerofill(decimal, length);
Serial.print("Decimal: ");
Serial.print(decimal);
Serial.print(" (");
Serial.print( length );
Serial.print("Bit) Binary: ");
Serial.print( b );
Serial.print(" Tri-State: ");
Serial.print( bin2tristate( b) );
Serial.print(" PulseLength: ");
Serial.print(delay);
Serial.print(" microseconds");
Serial.print(" Protocol: ");
Serial.println(protocol);
Serial.print("Raw data: ");
for (unsigned int i=0; i<= length*2; i++) {
Serial.print(raw[i]);
Serial.print(",");
}
Serial.println();
Serial.println();
}
void handleRCSwitch()
{
if (mySwitch.available()) {
output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol());
mySwitch.resetAvailable();
}
}
static const char* bin2tristate(const char* bin) {
static char returnValue[50];
int pos = 0;
int pos2 = 0;
while (bin[pos]!='\0' && bin[pos+1]!='\0') {
if (bin[pos]=='0' && bin[pos+1]=='0') {
returnValue[pos2] = '0';
} else if (bin[pos]=='1' && bin[pos+1]=='1') {
returnValue[pos2] = '1';
} else if (bin[pos]=='0' && bin[pos+1]=='1') {
returnValue[pos2] = 'F';
} else {
return "not applicable";
}
pos = pos+2;
pos2++;
}
returnValue[pos2] = '\0';
return returnValue;
}
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) {
static char bin[64];
unsigned int i=0;
while (Dec > 0) {
bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0';
Dec = Dec >> 1;
}
for (unsigned int j = 0; j< bitLength; j++) {
if (j >= bitLength - i) {
bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
} else {
bin[j] = '0';
}
}
bin[bitLength] = '\0';
return bin;
}
void handleRAW() {
for (int i = 5; i>0; i--) {
Serial.print(i);
Serial.print("... ");
delay(900);
digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
}
Serial.println();
detachInterrupt(interruptPin);
int finalstate = digitalRead(receiverPin);
char s = Serial.read();
for (unsigned int i = pos + finalstate; i< SAMPLESIZE; i++) {
Serial.print( timings[i] );
Serial.print(",");
}
for (unsigned int i = 0; i < pos; i++) {
Serial.print( timings[i] );
Serial.print(",");
}
Serial.println("");
Serial.println("Send 2 to scan again...");
//while(true) {}
}
void handleInterrupt() {
const long time = micros();
timings[pos] = time - lastTime;
lastTime = time;
if (++pos > SAMPLESIZE-1) {
pos = 0;
}
}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "rcswitch.h" | |
RCSwitch mySwitch = RCSwitch(); | |
unsigned char snifferMode = 0; | |
#define SAMPLESIZE 500 | |
static unsigned int timings[SAMPLESIZE]; | |
static unsigned int pos = 0; | |
static unsigned long lastTime = 0; | |
static int receiverPin = 2; | |
static int interruptPin = 0; | |
void setup() { | |
Serial.begin(9600); | |
//mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 | |
//interruptPin = digitalPinToInterrupt(receiverPin); | |
//attachInterrupt(interruptPin, handleInterrupt, CHANGE); | |
pinMode(13, OUTPUT); | |
digitalWrite(13, LOW); | |
Serial.println(F("433MHz Sniffer - Select Mode:")); | |
Serial.println(F("1 - mode RCSwitch")); | |
Serial.println(F("2 - mode RAW Sniffer")); | |
Serial.println(F("0 - home")); | |
} | |
void loop() { | |
handleSerial(); | |
//Serial.println(snifferMode); | |
// Everything else loop() does… | |
switch (snifferMode) { | |
case 1: | |
//Serial.println(snifferMode); | |
handleRCSwitch(); | |
break; | |
case 2: | |
handleRAW(); | |
snifferMode = 0; | |
break; | |
case 0: | |
//Serial.println("Start-up. Set Mode:"); | |
snifferMode = 0; | |
break; | |
} | |
} | |
void handleSerial() { | |
if (Serial.available() > 0) { | |
char incomingCharacter = Serial.read(); | |
switch (incomingCharacter) { | |
case '1': | |
Serial.println(F("mode RCSwitch")); | |
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 | |
snifferMode = 1; | |
break; | |
case '2': | |
Serial.println(F("mode RAW Sniffer - send 2 to trigger receiver")); | |
interruptPin = digitalPinToInterrupt(receiverPin); | |
attachInterrupt(interruptPin, handleInterrupt, CHANGE); | |
snifferMode = 2; | |
break; | |
case '0': | |
snifferMode = 0; | |
break; | |
} | |
} | |
} | |
static const char* bin2tristate(const char* bin); | |
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength); | |
void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) { | |
const char* b = dec2binWzerofill(decimal, length); | |
Serial.print("Decimal: "); | |
Serial.print(decimal); | |
Serial.print(" ("); | |
Serial.print( length ); | |
Serial.print("Bit) Binary: "); | |
Serial.print( b ); | |
Serial.print(" Tri-State: "); | |
Serial.print( bin2tristate( b) ); | |
Serial.print(" PulseLength: "); | |
Serial.print(delay); | |
Serial.print(" microseconds"); | |
Serial.print(" Protocol: "); | |
Serial.println(protocol); | |
Serial.print("Raw data: "); | |
for (unsigned int i=0; i<= length*2; i++) { | |
Serial.print(raw[i]); | |
Serial.print(","); | |
} | |
Serial.println(); | |
Serial.println(); | |
} | |
void handleRCSwitch() | |
{ | |
if (mySwitch.available()) { | |
output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); | |
mySwitch.resetAvailable(); | |
} | |
} | |
static const char* bin2tristate(const char* bin) { | |
static char returnValue[50]; | |
int pos = 0; | |
int pos2 = 0; | |
while (bin[pos]!='\0' && bin[pos+1]!='\0') { | |
if (bin[pos]=='0' && bin[pos+1]=='0') { | |
returnValue[pos2] = '0'; | |
} else if (bin[pos]=='1' && bin[pos+1]=='1') { | |
returnValue[pos2] = '1'; | |
} else if (bin[pos]=='0' && bin[pos+1]=='1') { | |
returnValue[pos2] = 'F'; | |
} else { | |
return "not applicable"; | |
} | |
pos = pos+2; | |
pos2++; | |
} | |
returnValue[pos2] = '\0'; | |
return returnValue; | |
} | |
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) { | |
static char bin[64]; | |
unsigned int i=0; | |
while (Dec > 0) { | |
bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0'; | |
Dec = Dec >> 1; | |
} | |
for (unsigned int j = 0; j< bitLength; j++) { | |
if (j >= bitLength - i) { | |
bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; | |
} else { | |
bin[j] = '0'; | |
} | |
} | |
bin[bitLength] = '\0'; | |
return bin; | |
} | |
void handleRAW() { | |
for (int i = 5; i>0; i--) { | |
Serial.print(i); | |
Serial.print("... "); | |
delay(900); | |
digitalWrite(13, HIGH); | |
delay(100); | |
digitalWrite(13, LOW); | |
} | |
Serial.println(); | |
detachInterrupt(interruptPin); | |
int finalstate = digitalRead(receiverPin); | |
char s = Serial.read(); | |
for (unsigned int i = pos + finalstate; i< SAMPLESIZE; i++) { | |
Serial.print( timings[i] ); | |
Serial.print(","); | |
} | |
for (unsigned int i = 0; i < pos; i++) { | |
Serial.print( timings[i] ); | |
Serial.print(","); | |
} | |
Serial.println(""); | |
Serial.println("Send 2 to scan again..."); | |
//while(true) {} | |
} | |
void handleInterrupt() { | |
const long time = micros(); | |
timings[pos] = time - lastTime; | |
lastTime = time; | |
if (++pos > SAMPLESIZE-1) { | |
pos = 0; | |
} | |
} |
Documentatie proiect:
- https://www.electroschematics.com/433mhz-rf-sniffer/
- https://www.codrey.com/electronic-circuits/433mhz-rf-sniffer/
- https://tinkerman.cat/post/decoding-433mhz-rf-data-from-wireless-switches
- https://github.com/sui77/rc-switch
- https://os.mbed.com/users/TheChrisyd/code/RCSwitch/docs/tip/classRCSwitch.html
Pentru întrebari și/sau consultanță tehnică vă stau la dispozitie pe blog sau pe email simedruflorin@automatic-house.ro.
O seară/zi plăcută tuturor !