Introduction
This article is about the very well known RF modules TX433 and RX433 that (or similar) can be found almost in every electronics shop, and a pair of them costs ~15 bucks.
Using the Silabs C8051F321 microcontroller.
I searched the internet for a 'radio remote control' with more than 8 buttons, but found none. So I decided to program one myself. At first, it seemed an easy task as I have programmed microcontrollers before.
See my other articles on Silabs c8051:
Luckily, I got the idea for this task from reading some other examples:
The problem was to find a solution to the UART communication protocol for radio communication. You need to know a way to read and write to UART in C, that is different than Keil and MCU-s like Silabs ones. The problem is finding a solution not to echo back when reading UART signals. To read UART signals, you must use low-level functions (_getkey
) and use interrupts to signal timers that control IO-s.
char _getkey () {
char c;
while (!RI0); c = SBUF0; RI0 = 0; return (c);
}
At first, I got nothing but garbage from the hypertrminal. Then, I decided to use the other USB-to-Serial cable, and it worked. It has reversed polarity (UART signals are inverted compared to the RS232 signals). One solution to this is to use MAX232 or a transistor to the reverse polarity - I chose the last method.
This is the result:
Large pictures are available here: RX1, RX2, TX.
My mission is to use more than 8 buttons, which is the usual count of buttons in modules like thes, for example: Wellmann catalogue (VM118). The buttons count is limited due to the manufactured controllers-encryption/decryption modules chips limitations. This restriction can be overridden by writing receive-transmission codes yourself. To achieve this goal, I used the well-known Silabs MCU-s C8051F321, but with small modifications, it can used with many other Silabs chips as well.
The transmitting-receiving distance can have a range up to ~50m when applying 15cm antennas. In my case, I used a UART 2400 baud rate. The maximum is 4800bps. But as explained in many places in the internet, and from testing the modules, the recommended connection speed would be 2400bps for better noise/distance ratio.
Many modules are sold and used at the maximum baud rate for a small distance ~10 meters or so, and that's even with antennas. I find that insufficient.
So first, I looked at an example code here: Running TX433 and RX433 RF modules with AVR microcontrollers. It explains the radio packets structure basics (protocol) for these modules:
- Sending packet sync - it may be any character
- Sending address
- Sending a control (verification) byte
---------------
- Sending a carriage return character '13' or '\r'
- Waiting for a few ms ~ 10ms
- If a button is pressed: the same procedure is repeated again
Receiver waits for synchronization characters (I made that 'SW' for abbreviation, e.g., switch) because the receiver reads a lot of noise while waiting (and we do not want false triggering). After that:
- Reads address bits (two bits, e.g., '00' or '21')
- Reads a control byte character
- Compares the control byte to the address, and if they match, triggers address port to high level
- Waits ~100ms and switches all ports to low again (port pulse switching)
- If another signal is read before timeout occurs, switches that new port high and old off
Basically, all relays are switched off while no button is pressed.
The purpose of this module is to control the crane movements of the vehicle that moves the garbage containers. (You can't find any of the modified code in modules bought from a shop). In those, you don't need to worry about interferences with other remotes in range.
Background
To read UART pulses with serial port (COM port), you must invert the polarity of signals with transistors or using MAX232. Without reversing the polarity, it is possible to gain connection and also get the device to work, but it will lack the possibility to read signals with the hyperterminal. That means no debug facility. To debug the program, I used a USB-to-Serial adapter like the USB - UART interface in 'Counter based c8051' and read signals with the Silabs debug adapter, for which the firmware was updated. Also, to read, I use my USB terminal 'usbhidio3.exe'.
Hardware schematics:
To update firmware and debug, use Silabs 'Toolstick Base Adapter':
Using the code
The code for the microcontroller is written within Silabs IDE 3.61.00 and compiled with the Keil compiler ver. 8.17. If any button is pressed, a signal like 'SW01b\r' is written to the UART of c8051F321 and the TX433 module sends a code to the receiver RX433. Accordingly, the receiver decodes and lights the LED of that channel (or pulses a relay - if it's connected to the matching port output of the microcontroller).
Here is the basic Tx main module:
void main (void)
{
PCA0MD &= ~0x40; Timer0_Init ();
PORT_Init(); SYSCLK_Init (); UART0_Init();
EA = 1; while (1)
{
if(LED==0)
{
if(SW00==0){
bSwitch=1;
printf ("SW00a%c",13);
}
if(SW01==0){
bSwitch=1;
printf ("SW01b%c",13);
}
if(SW02==0){
bSwitch=1;
printf ("SW02c%c",13);
}
if(SW03==0) {
bSwitch=1;
printf ("SW03d%c",13);
}
if(SW06==0){
bSwitch=1;
printf ("SW06g%c",13);
}
if(SW07==0) {
bSwitch=1;
printf ("SW07h%c",13);
}
if(SW10==0) {
bSwitch=1;
printf ("SW10k%c",13);
}
if(SW11==0) {
bSwitch=1;
printf ("SW11l%c",13);
}
if(SW12==0) {
bSwitch=1;
printf ("SW12m%c",13);
}
if(SW13==0) {
bSwitch=1;
printf ("SW13n%c",13);
}
if(SW14==0) {
bSwitch=1;
printf ("SW14o%c",13);
}
if(SW15==0) {
bSwitch=1;
printf ("SW15p%c",13);
}
if(SW16==0) {
bSwitch=1;
printf ("SW16q%c",13);
}
if(SW17==0) {
bSwitch=1;
printf ("SW17r%c",13);
}
if(SW20==0) {
bSwitch=1;
printf ("SW20u%c",13);
}
if(SW21==0) {
bSwitch=1;
printf ("SW21v%c",13);
}
if(SW23 == 0) {
bSwitch=1;
printf ("SW23x%c",13);
}
if(bSwitch == 1){
bSwitch= 0;
LED = 1;
}
} }}
The receiver tst_gets
module behaves like this:
void tst_gets (void) {
int i = 2; unsigned long temp_amplitude;
unsigned char chksum;
LED = 0;
while( _getkey() != 'S' ); if(_getkey() == 'W')
{
LED = 1;
temp_amplitude = hex2char();
chksum = _getkey();
if(temp_amplitude == chksum-97)
{
if(temp_amplitude==0){
P0=1;
P1=0;
P2=0;
}else{
if (temp_amplitude < 10) {
P0 = SINE_TABLE[temp_amplitude];
P1=0;
P2=0;
} else if (temp_amplitude < 20) {
temp_amplitude -= 10;
P1 = SINE_TABLE[temp_amplitude];
P0=0;
P2=0;
} else if (temp_amplitude < 30) {
temp_amplitude -= 20;
P2 = SINE_TABLE[temp_amplitude];
P0=0;
P1=0;
} } counter = 0;
} }
}
Software links: