The following sketch prints a message to the serial output when it detects the doorbell signal.
/* DoorbellReceiver.ino - Detects signal from Grundig wireless doorbell (model QH-831A). Modified sketch (unknown licence) from Riva, to be found at http://forum.arduino.cc/index.php?topic=110662.msg1094167#msg1094167 DBAD Public Licence (http://www.dbad-license.org/) crutzen.eu - July 2013 Connect data pin of RF receiver to digital pin 2 of the Arduino. The signal exists of 24 bits. 1 means: long ON followed by short OFF 0 means: short ON followed by long OFF __ _____________ _____ __ | | | | | | |_____________________| |_____| |____________| | 19760us | 1480 | 464 | 464 | 1480 | | | | | | | |<--------Sync------->|<--------1------->|<--------0------->| To detect the delay values for your device, use the DeurbelSniffer.ino sketch and read the instructions at http://blog.crutzen.eu */ #define SHORT_DELAY 464 #define SHORT_DEV 12 #define SHORT_MIN (SHORT_DELAY - SHORT_DEV) #define SHORT_MAX (SHORT_DELAY + SHORT_DEV) #define LONG_DELAY 1480 #define LONG_DEV 12 #define LONG_MIN (LONG_DELAY - LONG_DEV) #define LONG_MAX (LONG_DELAY + LONG_DEV) #define SYNC_DELAY 19788 #define SYNC_DEV 8 #define SYNC_MIN (SYNC_DELAY - SYNC_DEV) #define SYNC_MAX (SYNC_DELAY + SYNC_DEV) #define F_WAITING 1 // 1 = waiting for sync 0 = receiving data #define F_SIGNAL 2 // 1 = a signal found 0 = no signal found #define F_RIGHT_SIGNAL 3 // 1 = right signal found 0 = incorrect signal #define RF_DATA_PIN 2 const unsigned long glitch_length = 150; // Anything below this value is a glitch and will be ignored. unsigned long fall_time = 0; // Microsecond time when last falling edge occured. unsigned long rise_time = 0; // Microsecond time when last rising edge occured. unsigned long length_low = 0; unsigned long length_high = 0; unsigned long length_sync = 0; unsigned long buffer = 0; byte bitCount = 0; const unsigned long signal = 0b01011111011000100000100; // The doorbell signal to look for: 0101 1111 0110 0010 0000 100 const byte nBits = 23; volatile byte flags = 0; void change() { unsigned long time = micros(); if (bitRead(flags,F_WAITING)) { // waiting for sync if (digitalRead(RF_DATA_PIN) == LOW) { // falling if (time > (rise_time + glitch_length)) { // no glitch fall_time = time; } } else { // Rising - digitalRead(2) == HIGH if (time > (fall_time + glitch_length)) { // no glitch rise_time = time; length_low = rise_time - fall_time; if ((length_low >= SYNC_MIN) && (length_low <= SYNC_MAX)) { // found sync, start receiving data length_sync = length_low; bitClear(flags, F_WAITING); } } } } else { //receiving data if (digitalRead(RF_DATA_PIN) == LOW) { // falling if (time > (rise_time + glitch_length)) { // no glitch fall_time = time; length_high = fall_time - rise_time; if ((length_high >= SHORT_MIN) && (length_high <= SHORT_MAX)) { // found short high = 0 bitCount++; buffer = buffer << 1; } else if ((length_high >= LONG_MIN) && (length_high <= LONG_MAX)) { // found long high = 1 bitCount++; buffer = buffer << 1; bitSet(buffer,0); // set rightmost bit to 1 } else { // found nothing - start waiting for sync again bitClear(flags, F_SIGNAL); bitClear(flags, F_RIGHT_SIGNAL); buffer = 0; bitCount = 0; bitSet(flags, F_WAITING); } if (bitCount == nBits) { bitSet(flags, F_SIGNAL); if (buffer == signal) { bitSet(flags, F_RIGHT_SIGNAL); } } } } else { // Rising - digitalRead(2) == HIGH if (time > (fall_time + glitch_length)) { // no glitch rise_time = time; } } } } void setup() { pinMode(13, OUTPUT); // for debugging pinMode(RF_DATA_PIN, INPUT); bitSet(flags, F_WAITING); // waiting for sync bitClear(flags, F_SIGNAL); // no signal found yet bitClear(flags, F_RIGHT_SIGNAL); // right signal not found yet attachInterrupt(0, change, CHANGE); Serial.begin(9600); } void loop() { if (bitRead(flags, F_SIGNAL) == 1) { Serial.println(buffer); if (bitRead(flags, F_RIGHT_SIGNAL) == 1) { Serial.println("Ding dong!"); } bitClear(flags, F_SIGNAL); bitClear(flags, F_RIGHT_SIGNAL); buffer = 0; bitCount = 0; bitSet(flags, F_WAITING); } }
As you might have noticed, I used other delay values than those I found with Audacity and used in the sketch to activate the doorbell. That's because it turned out that those values did not work for detecting the doorbell signal. I'm not exactly sure what the reason for this strange behaviour is, but I guess it has to do with the way the RF receiver component with the Arduino detects the signal in a different kind of way than the "Audacity-circuit" does.
My solution to this problem was to make a "sniffer" program for the RF receiver on the Arduino. This program writes the received values to the serial output window:
/* DoorbellSniffer.ino - Prints lengths of received RF values. Modified sketch (unknown licence) from Riva, to be found at http://forum.arduino.cc/index.php?topic=110662.msg1094167#msg1094167 DBAD Public Licence (http://www.dbad-license.org/) crutzen.eu - July 2013 Connect data pin of RF receiver to digital pin 2 of the Arduino. Usage: This sketch prints the lengths of the periods of time of which the RF receiver picks up a signal. The sketch can either pick up high signals OR low signals. See the comments in the code to select the kind of signal you want to pick up. Copy the output of the serial monitor to a spreadsheet to analyse which durations are most commom. Use those durations in the DeurbelOntvanger.ino sketch. Detailed instructions at http://blog.crutzen.eu */ #define RF_DATA_PIN 2 const unsigned long glitch_length = 150; // Anything below this value is a glitch and will be ignored. unsigned long fall_time = 0; // Microsecond time when last falling edge occured. unsigned long rise_time = 0; // Microsecond time when last rising edge occured. unsigned long length_low = 0; unsigned long length_high = 0; void change() { unsigned long time = micros(); if (digitalRead(2) == LOW) { // falling if (time > (rise_time + glitch_length)) { // no glitch fall_time = time; //length_high = fall_time - rise_time; // comment out to measure length_low } } else { // Rising - digitalRead(2) == HIGH if (time > (fall_time + glitch_length)) { // no glitch rise_time = time; length_low = rise_time - fall_time; // comment out to measure length_high } } } void setup() { pinMode(RF_DATA_PIN, INPUT); attachInterrupt(0, change, CHANGE); Serial.begin(9600); } void loop() { Serial.println(length_low); // comment out to measure length_high //Serial.println(length_high); // comment out to measure length_low }
After letting this program run for approximately 30 second while pressing the doorbell button continuously, I copied the numbers in the serial window to a text file and imported this file into a spreadsheet. I used the spreadsheet to analyse which values were the most frequent. I my case, these were 464, 1480 and 19788, or slightly more or less. This way I figured out that the short delay had to be 464 microseconds, the long delay had to be 1480 microseconds and the sync delay (between to signals) had to be 19788 microseconds.
When you also want to use the sniffer program, bear in mind:
- to measure the long and the short delays: comment out the right lines so you detect the length of the high signals;
- to measure the sync delay: comment out the right lines so you detect the length of the low signals.
Source:
- Arduino Forum: "Re: Help me decode this 434mhz signal...?" (Create an account and log in to download the code from Riva's post.)
Hello!
This is a great article about receiving/transmitting 433Mhz.
I've tried your sniffer but I didn't manage to capture the correct signal as the receiver I have gets a lot of noise (it's the same you used).
Could you give me a hand? The sensor I'm trying to play with it's a water leak detector. I've sniffed the signal it broadcasts when the TEST button is pressed: http://www.ciproconsulting.it/pdf/Soundcard_TEST.wav (using a soundcard).
I'd practically want to use Arduino listening to this sensor and, in case of water leak detected to send me an email or something.
Thanks in advance!
Hi,
I noticed that the pattern in the wav file doesn't really consist of straight lines like the signal of my doorbell has, but curved ones. Maybe the signal of your detector is of a different type? I'm sorry, but I'm no expert and all I know is what I learned myself from the links in the articles.
When I use the sniffer program, I also get a lot of noise. But some numbers in the serial monitor appear much more often than others. You have to use the sniffer sketch and then copy a list of approximately 5000 numbers to Excel to determine which ones appear the most. Did you do that?
Sorry for my late and short reply, but I'm having trouble with my internet connection so I'm typing this on my phone and haven't got the patience to to elaborate on my explanation.
Good luck!
Thanks Ralph!
I've already analysed the numbers but there are too many sequences tat could match. I'm trying to figure it using Protocol Analyzer and, in case I'll succeed, I'll use then your "listener" for the Arduino part.
very interesting series. sadly the sniffer program didnt prove of much use: right from the start there is a tremendous output of what i presume to be noise