Following the previous article, I will continue to explain how our lost RC beacon works, especially the firmware of the receiver module. At the end of the post, a video shows how to find a lost RC model in real conditions.
Filtering noise on receiver module
Let’s recap the main design of the receiver module first. We use a DRA886RX that receives the signal transmitted by the TX beacon. The output of this chip is a digital signal that can for example be used to drive a buzzer through a transistor. But doing this is a punishment for our ears because if there is no radio signal, the receiver output can randomly be 0 or 1... as a result it will output an high level noise.
The first (bad) idea to avoid this is: “hmm let’s add a band-pass filter between the receiver and the buzzer calibrated on TX beacon frequency, so I will only ear the signal when we receive this frequency”. Wrong. By definition, noise contains all frequencies, and if we add a perfect band-pass filter, we will hear only one frequency instead of a noise. Worst, we may not be able to distinguish the signal.
The second idea is to do a FFT on the received signal. The RX beacon is designed with a microcontroler between the radio receiver module and the buzzer, so we can do some processing on the received signal. Unfortunately a precise FFT is not really possible on a 8-bit microcontroler because it would consume a lot of resources, but we can do something quite similar.
To detect a 500 Hz square signal (this is what the TX beacon sends), we use 3 filters (FIR) running in parallel on specific frequencies. We know from its Fourier decomposition that a square signal is composed of odd-integer harmonic frequencies (of the form 2π(2k-1)f). The power of the first harmonic (n=3) is one third of the power of the fundamental frequency.
If the signal is a noise, the output of the 3 filters will have the same mean power. If the signal is the 500Hz square signal, The power of the fundamental filter will be high, the power of the harmonic filter will be lower, and the power of the last filter (1000Hz) should be very low as this frequency should not be included in the signal.
Generation of filter parameters
To generate the filter parameters, we use a python script and the pylab module. This module contains a function to generate the parameters of a simple low pass FIR from its cutoff frequency and its order. We added some code done by Matti Pastell found on the Internet to calculate the parameters of a bandpass filter.
The script fir.py generates a graph of the filters. It assumes Fe=5Khz, Ffond=500hz (blue), Fharm1=1500hz (green), Fother=850hz (red) but this can be modified in the source. The order of the filter is 32. The filter is displayed in normalized frequencies: for instance, 0.2 means “0.2 * Fe/2”.
Run the script as following:
python fir.py [filename]
The script also generates the code of a C function to be copied in the AVR program. People used to program on AVR may be surprised that the device has enough power to apply 3 different filters (order = 32) on a signal sampled at 5Khz. Indeed, this is usually a work for a DSP!
The trick here is that the input signal is 0 or 1. So we can completely remove the need of multiplication to apply the FIR filter:
out(n) = a0 * in(n) + a1 * in(n-1) + ... + ak(n-k)
We store the 32 previous sampled inputs in a 32bit integer, so the code is:
if (bitfield & (1 << 0)) out += a0 if (bitfield & (1 << 1)) out += a1 if (bitfield & (1 << 2)) out += a2 ... Moreover, we use some more optimizations in the code:
- the loop is fully unrolled and all the filter parameters are directly in the code as constant to enhance speed and RAM consumption. The price is a large code in flash, but we don’t care.
- the 3 filters are applied at the same time (the same “if” is used for the 3 filters)
- the calculation is done on 16 bits without overflow or saturation because we know that the filter gain never exceed 1.
We will see later in the article that the simulator shows that we have enough CPU power.
Listen and view the result
The same code can be compiled for AVR but also for a linux host. Thanks to this, we can test the effect of the filter on a real audio input. Four WAV files have been generated. They are sampled at 5Khz 16 bits, and each sample is either -32768 or 32767, simulating a 1 bit sampling (like the output of the DRA886RX):
- tone.wav: the perfect square tone at 500 hz
- tone-lownoise.wav: the tone plus some noise
- tone-highnoise.wav: the tone plus a lot of noise
- noise.wav: only noise
These files are our reference test inputs.
Depending on how the code is compiled, it will use one of these files:
make H=1 WAV=WAV_TONE make H=1 WAV=WAV_TONE_LOWNOISE make H=1 WAV=WAV_TONE_HIGHNOISE make H=1 WAV=WAV_NOISE
A script output_to_audio.py is used to display the result, and save the output of each filter (fond, harm1 and other) in a separate WAV file.
In the figures below, the top graph represents the output power of each filter. In blue “fond1”, in green “harm1” and in red “other”. The bottom graph displays the output of the “signal detector”. When the green line is 500, the signal is detected.
To generate the images, start gen-img.sh.
The code that decides if the signal is detected is a bit empirical. We first filter the mean power of each filter. Then we compare their values as in the code below. When the variable cpt_filter is above a threshold, we consider that the signal is detected.
if ((pow_fond/3) > (pow_harm1/2) && (pow_fond/2) > pow_other && cpt_filter < MAX_CPT_FILTER) cpt_filter += 2; else if (cpt_filter > 0) cpt_filter--;
We can check that the program will run correctly on an AVR by using a simulator. We simulates an ATmega128 because the ATtiny45 is not supported by simulavr:
make simulavr -g -p 1234 -d atmega128 -F binary main.bin
Then launch gdb:
avr-gdb main.elf (gdb) target remote 127.0.0.1:1234 Remote debugging using 127.0.0.1:1234 0x00000000 in __vectors () (gdb) b main (gdb) c Continuing. Breakpoint 1, main () at /home/zer0/projects/zavr/projects/fir/main.c:371 371 if ((pow_fond/3) > (pow_harm1/2) &&
Then we add a breakpoint somewhere in the loop, and do several “cont”. The simulator displays the cycle value each time we go in a breakpoint.
We measure between 450 and 750 cycles for one loop iteration, so it’s large enough to have Fe=5Khz! Indeed, the AVR runs at 8Mhz, so the loop frequency is 10Khz in the worst case.
The receiver in action
The receiver can work in 2 modes:
- bypass mode: in this case, the input (from the radio receiver) is copied on the output (the buzzer) by the microcontroler, there is no filtering.
- filter mode: the microcontroler will apply the filters described above on the input signal and detect the square signal sent by the TX beacon. If it is detected, a pure square signal is transmitted on the output, else the output port stays to 0.
In both modes, the LED is switched on when the signal is detected.
See the real-life video.
Thanks to serpilliere and will who helped me on this project.
With some friends, we play with RC planes, especially FPV (First Person Viewer): the RC model has a camera that transmits the video over radio, received and displayed in goggles, as if we were in the plane! But this hobby can be risky, we sometimes crash the plane, and unfortunately it can be crashed far, at an unknown location. So the question is: how can we find it easily?
To solve this issue, there are several solutions. The easiest one is to put an audio beeper on the plane (we already do that), but it doesn’t help if the plane is too far. Another common solution is to embed a GPS on the plane and transmit the position to the ground station. This is probably a good solution but it requires some quite complex electronics: the GPS board, a microcontroler to decode data, and a radio transmitter. Moreover, you need another GPS device that to get your current position and determine the relative position of the RC plane.
Although this solution is probably a good one, we wanted to design the simplest board with the following constraints:
- cheap: no GPS, small uC
- long autonomy: embeds its own battery
- reliable: implies simple, board is protected by a box, embeds its own battery (again)
- “long” range (500m)
- fun ;) ...it is probably not the best design, but at least it is a not so bad one that works
Our system is composed of 2 boards: a transmitter and a receiver. The transmitter sends beeps over radio (433 Mhz), and the receiver module is connected to a buzzer that emits sound when the signal is received. To detect the direction of the transmitter, we use a directional antenna (yagi).
Here are the final version of the boards:
We decided to use the Dorji DRA886RX (receiver) and the Dorji DRA887TX (transmitter) as they are referenced by two (interesting) documents:
The datasheets of these modules are very poor, but they are easy to use. The radio power depends on the voltage. When using the maximum voltage, the range of these modules can be quite high, but we should take care to conform to legal constraints.
We were able to build a simple prototype in a couple of hours:
Description of the transmitter
The transmitter board contains:
- the radio TX (DRA887TX)
- an audio buzzer to find the RC plane when distance is < 50m
- a push button, for user interaction
- a LED
- a microcontroler (AVR ATtiny13) that will generate the radio and audio signals, and handle the button
- an adjustable power for the TX, that can be switched off by the microcontroler
Here is the schematic:
Here is the PCB:
Eagle files (including part list) are available on our git: http://git.droids-corp.org/?p=protos/xbee-elec.git;a=tree;f=beacon-tx;h=35ff6facfb31ee73fdde580f25aca327b1a5446d;hb=HEAD
The program in the ATtiny13 is very basic. It transmits a beep on the radio every second, and an audio beep every 2 seconds. If the button is pressed, the audio is mutted during one minute. A future evolution could be to add a servo input and monitor activity on it to mute the audio or radio, as it is done by this guy.
The program is available on our git: http://git.droids-corp.org/?p=beacon-tx-433.git;a=summary
Description of the receiver
The receiver board contains:
- the radio RX (DRA886RX)
- an audio buzzer to hear the output of the receiver and a trimmer to modify the volume
- a push button, for user interaction
- 2 LEDs (one for power, one for status)
- a microcontroler (AVR ATtiny45) that will filter the received signal
Here is the schematic:
Here is the PCB:
Eagle files (including part list) are available on our git:
In the next article, I will talk about the filter code of the receiver, and I will post a demo video to show that it works well !
A small post to talk about my heavy metal band Marker Beacon: we just released our first album today called “Dead Frequencies”, and it is licenced under the Creative Commons licence (BY-SA 3.0).
Feel free to download it and drop us a message on the guestbook if you like it !