Trouble getting 433mhz transmission/receiving setup properly

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using avr-gcc with an ATMega328p as the receiver, and an ATTiny2313a as the transmitter.  Using RXB12 (http://eeant.com/datasheet/et-rxb-12.pdf) receiver module and H34A (http://www.icstation.com/h34a-31...) 433mhz transmitter module.  The receiver breadboard circuit transmits anything it receives to a USART-to-USB module connected to my desktop, which I'm viewing with a serial console (TeraTerm).  I have set up my serial console to the correct baud rate that both the transmitter and receiver are running on (250,000 bps).

 

I can't seem to properly send anything from the transmitter breadboard circuit (ATTiny2313a) to the receiver breadboard circuit (with the ATMega328p).  Even without the transmitter powered on, the receiver circuit picks up and outputs lots of noise data (which I guess makes sense - probably lots of 433mhz signals bouncing around).  Whenever I power the transmitter on, I know that it's actually transmitting things, because the output to my terminal greatly, greatly speeds up - but it's not the data that I expect to see, just faster garbled chars.  I have the transmitter programmed to constantly output the char 't', but as you can see here there is no 't' to be found.

 

 

Here's the code.  What am I doing wrong here?

 

Transmitter:

 

#define F_CPU 16000000UL
#define BAUD_RATE 250000
#define CALCULATED_BAUD ((F_CPU / 16 / BAUD_RATE) - 1)

#include <avr/io.h>

void usart_transmit(unsigned char data);

int main(void)
{
    /*
     UBRR is a 16-bit register, but only the 4 least significant bits of UBBRH are valid.
     Let's put our calculated baud rate into these registers.
    */
    UBRRH = (CALCULATED_BAUD >> 8);
    UBRRL = CALCULATED_BAUD;

    /*
      Set the TXEN bit in the USART control register B to enable transmission off the TX pin.
    */
    UCSRB = (1 << TXEN);

    /*
      Set these bits to set 8-bits in the USART control register C to set a character size of 8.
    */
    UCSRC = (1 << UCSZ0) | (1 << UCSZ1);

    while (1)
    {
        usart_transmit('t');
    }
}

void usart_transmit(unsigned char data)
{
    // Wait for transmit buffer to be empty
    while ( !(UCSRA & (1 << UDRE)) );

    UDR = data;
}

 

Receiver:

 

#define F_CPU 16000000UL
#define BAUD_RATE 250000
#define CALCULATED_BAUD ((F_CPU / 16 / BAUD_RATE) - 1)

#include <avr/io.h>

void usart_transmit(unsigned char data);
unsigned char usart_receive();

int main(void)
{
    /*
     UBRR is a 16-bit register, but only the 4 least significant bits of UBBR0H are valid.
     Let's put our calculated baud rate into these registers.
    */
    UBRR0H = (CALCULATED_BAUD >> 8);
    UBRR0L = CALCULATED_BAUD;

    /*
      Set the RXEN0 bit in the USART control register B to enable receiving data off the RX pin.
    */
    UCSR0B = (1 << RXEN0) | (1 << TXEN0);

    /*
      Set these bits to set 8-bits in the USART control register C to set a character size of 8.
    */
    UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);

    while (1)
    {
        unsigned char data = usart_receive();
        usart_transmit(data);
    }
}

void usart_transmit(unsigned char data)
{
    // Wait for transmit buffer to be empty
    while ( !(UCSR0A & (1 << UDRE0)) );

    UDR0 = data;
}

unsigned char usart_receive()
{
    /* Wait for data to be received */
    while ( !(UCSR0A & (1<<RXC0)) )
    ;
    /* Get and return received data from buffer */
    return UDR0;
}

 

This topic has a solution.

Last Edited: Sun. Oct 29, 2017 - 05:24 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It looks an awful lot like baud rate mismatch. How are you clocking the two MCUs, particularly the receiving one that sends to the terminal? Are they both actually clocked at 16MHz? Are those modules designed to handle data at 250Kbaud (some require a specific limited range of baud rates).

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sun. Oct 29, 2017 - 04:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think that was it - bumping them down to 4800 baud works.  Thanks!

Last Edited: Sun. Oct 29, 2017 - 05:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You do realise these modules don't like working with async data? You want to use a library like 'virtualwire' that is specifically designed for these modules.

You are pushing your luck even at 4800 baud, you'll be lucky to get reasonable range on anything much past 1200 baud.

Last Edited: Sun. Oct 29, 2017 - 05:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting.  The lowest baud rate that the datasheet specifies is 2400 - will my #define work fine to calculate these lower bauds, such as 1200?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The little, inexpensive, 433 MHz modules are great to tinker with.

 

They can be a little frustrating, also, until you understand a little bit about how they work.

 

First, for your Receiver's communications with the PC it is easiest if you use a crystal to control the micro's clock frequency.  The data sheet likely has a section on baud rate error as a function of clock frequency, select one with less than 2% error.

 

Next, to have the two micro's communicate you will want the transmitter's baud rate to match the receiver's baud rate.  So, once again use a crystal on the transmitter micro.

 

The baud rate for the RF modules depends on the modules, look at their data sheet, but 2400 baud is common for many of them.

 

You will want to use a crystal that gives a < 2% error, as a general rule.  So select a crystal that works for 2400 baud, and then either use 2400 baud for the PC link, also, or select another baud rate that still has a low error for 2400 and for the PC link's baud rate.

 

If you Google AVRCalc you can download to your (Win) PC a small program which can tell you the baud rate error for various clock frequencies.  There was an updated version by another Doc, whose name I'm blanking on... 

Your original post shows a 16 MHz clock.  That's tough, I think, to set up for 2400 baud.  If the micro you are using has a divide by 8 "Fuse", then you could run the micro at 2 MHz.  2400 baud is then doable with a 0.16% baud rate error.  9600 baud rate for the PC would also have the same, small error.

 

Next know that if you use a Bluetooth or XBee module, the modules do much of the RF noise elimination  and data error correction for you.  With the 433 modules it is all up to you!  The receiver will likely receive a continuous stream of RF noise, which it will interpret as data.  Your receiver code has to sort out the real data from the continuous data stream.

 

There are certainly some data link protocols out there that can be used, but to get up and running for starters, a simple data link protocol can be used.  An example would be:

_ _ _ < A B C D X

 

For viewing on the PC terminal in ASCII mode, (not Hex mode), it will be easiest if your data is all ASCII characters, not binary data.

 

The string above starts with a few garbage characters, a "Space" or dash or "*" or anything you like.

 

The very cheap 433 modules do not have a crystal controlled transmitter / receiver, they use a (cheap and less accurate) surface acoustic wave oscillator...  Which doesn't matter to you except to know that transmitting a few junk characters helps to "warm up" the transmitter and "synch up" the receiver. 

How many junk characters doesn't really matter, start with 3.

 

The "<" is a Start of Packet character. 

 

Your receiver software will read each incoming data character and watch for the "<" character.  If it sees the "<" character it will, for now, assume that it has found a data packet.  It will then read in the next 5 bytes, (for this example).

 

The "X" character, the last byte in the packet, is a Check Sum byte.  There are lots of ways to generate the Check Sum, but for now just add up each of the four preceding data byte, as 8-bit values, and ignore any carry out.  e.g. X = A + B + C + D, and is itself an 8 bit value.

 

Your transmitter software, which generates the packet to send, calculates the Check Sum based upon the four data bytes, and sends the Check Sum as the fifth byte in the packet, after the Start of Character.

Your receiver software, having spotted an incoming "<" Start of Packet Character, and having captured the next 5 characters received, adds up the four data bytes, (A+B+C+D), ands sees if the sum matches the received Check Sum byte. 

 

If the received data packet's calculated Check Sum matches the transmitted Check Sum, then you assume you have received a valid data packet, and life is good!

 

If the Check Sum the receiver calculates doesn't match the transmitted Check Sum byte, then you assume that either that wasn't really a data packet, or that there was an error in receiving the packet, so for now just ignore it and start watching the incoming data stream, watching for another Start of Packet character, and try again.

 

If your transmitter program transmits the packets at a rate of once per second, for starters, then the receiver should receive a stream of noise and a data packet, a stream of noise and then a data packet...

Occasionally, the noise will be received as whatever character you selected for the Start of Packet, "<" in this case.  If the noise is evenly distributed, then on average once every 255 characters of random noise will be detected as the Start of Packet character.

 

The Check Sum is what allows you to determine that the Start of Packet was a valid Start of Packet character, and that the following characters were valid data.

By using ASCII characters for the data, the receiver can send only valid packets to the PC, followed by a CR LF. 

 

The screen should then look like this:

<ABCD

<ABCD

<ABCD...

 

Don't send the Check Sum byte, don't send the precursor junk bytes, just upload the valid data packets.

 

Next, once that works you can develop the "protocol" further, or switch to a canned Protocol.  For example, once you can recognize an incoming packet and capture it, you can then switch to binary data that isn't easily readable on the PC screen.  Characters A and B, for example could be a 16-bit data value.

 

If you have several transmitter modules, the first character in the packet, (The "A" character), could be a transmitter I.D. byte.

 

The second character in the packet, (The "B" character), could tell you how many data characters there are in the packet, if you aren't using a fixed length packet.

 

RF data links are inherently "noisy", and with the cheap modules not all packets will get through, especially when you put the transmitter in one room, and the receiver in another room, instead of having them a few feet apart on the bench.

 

When you switch to data, instead of a test packet with ABCD as the data load, you may find it helpful to send each packet three times.  This increase the probability of one of the three packets getting through.

You could add a byte that sequentially increases, (0,  1, 2, 3...), and know if you are receiving the a copy of the same packet, or a new packet.

 

The Check Sum is a simple Error Detecting technique.  It will detect one error in the transmitted packet.  But it is statistically possible to have two errors in the packet now and then, and possible for the data byte error and the Check Sum byte error to cancel each other out, so that the packet appears to be a valid packet when it fact it isn't.  There are, therefore, more sophisticated error detection schemes available, followed by error detection and single error correction schemes, etc...

 

But, for a 433 MHz cheapo module RF data link, that level of complexity is rarely required.

 

One can set up bi-directional communications and have the receiver send an acknowledge back to the transmitter, which the transmitter recognizes or automatically retransmits the last packet, etc., if needed.

Next, some Threads recommend that the data transmission be Manchester Encoded, which means that the transmitted data won't have a long string of 1's or 0's in a row.  For getting the modules to communicate, as a start anyway, I think this is an unneeded level of complexity. 

 

Finally, when I set up a network of little 433 modules know that I had one module out of 8, (or however many it was...), that was off frequency and just didn't work well with the others.  Having a couple modules to work with, therefore, might be a good idea.

 

For the 433 cheap modules I'd keep your data packets to <= 16 bytes.  You don't want to send long packets, they will likely be corrupted.

 

Good luck with your project!

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow, that was incredibly helpful.  I can't thank you enough!  While that all mostly makes sense, I have a few questions:

 

1.  You mention setting up 2400 baud with a 16mhz clock might be difficult.  The datasheet seems to show support for 2400 baud at 16mhz, but I've heard 1200 baud will give me better range.  However, the lowest baud the datasheet shows is 2400 for any clock speed.  Am I out of luck in setting up 1200 baud?

 

2.  You suggested sending a few junk characters to "warm up" the link between the sender and receiver.  Where can I read more about this?  That's very interesting.  That being said, my RXB12 receiver module does have a crystal oscillator on it - is that what you were referring to when you mentioned "surface acoustic wave oscillator"?  My H34a transmitter does not have a crystal onboard, however.

 

3.  Isn't it likely that noise will interrupt one of my packets?  So if my transmitter is sending _ _ _ < ABCDX, what if it gets to C and then some noise data is picked up (so it becomes _ _ _ < ABC NOISE CHAR DX)?  Is this the sort of thing that our checksum and multiple packet sending approach prevents?  Is it likely that if I send a packet three times, that they all be corrupted?  I was picking up quite a bit of noise in my earlier tests.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seems just about everyone who tries these modules runs into the same problems. That’s why there’s plenty written about them on the interwebs.
If you care to search you’ll find that using uart framed data is far from ideal - sure ‘it works’ but is has pattern sensitivities. Some data might work fine, other data might be full of errors. This is due to the simple techniques used for these modules. The receiver has a data slicer that needs to be ‘trained’ - this is why a preamble is required - if you REALLY want to us uart data, then you send a few U s as this gives a nice square wave signal for the dataslicer to adjust itself.
Radio comms is unreliable by nature - expect errors. Can your three packets get corrupted? Most likely. Especially on the 315/433MHz band as the neighbour’s door bell can ruin your day. Or someone unlocking their car and so on.
The virtualwire library attempts to solve all these problems. If anything, reading the doc will explain the challenges these cheapy radio modules present and how to overcome them.
Note that virtualwire does not use the uart nor does any commercial application I’ve seen. There is a good reason for this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 The receiver has a data slicer that needs to be ‘trained’ - this is why a preamble is required - if you REALLY want to us uart data, then you send a few U s as this gives a nice square wave signal for the dataslicer to adjust itself.

Yes, and additionally, at least for some of the modules, the non-Xtal receivers need to lock onto the transmitter's frequency, and adjust their RF front end sensitivity, (RF gain), and all that can best happen with a few junk characters.

 

Tyler, you can certainly use the VirtualWire approach, but with the above suggestions you should also be up and running quickly, at least to get started.

Then try both approaches and see which gives the best range and the least data corruption.

 

You will have to look at the data sheet for the specific micro you are using and see what it says about setting the baud rate divisor for various baud rates.

It should have an equation.

Plug in a couple of known values that are already provided, and then plug in 2400 or 1200 baud.

Current day systems rarely use such slow transmission rates, so perhaps the data sheet simply omitted them.

 

Yes, once the transmitter and the receiver are in the middle of sending a packet a burst of noise could easily trash the received data, corrupting the data.

The CheckSum allows you to tell if the data packet got through correctly, without any data errors.

 

Ideally, and very dependent upon the complexity of the receiver and the modulation mode, (On/Off keying, AM, FM, etc.), your signal level at the receiver will be well above the ambient noise level, and the receiver will lock on to the incoming data packet's signal.  This helps to improve the data integrity when you have good hardware and a strong signal.  Neither of those typically apply when dealing with the 433 cheap-o modules.  Hence there is lots more software work for you to do to decode the transmitted signal.

 

Obviously you can use your smart phone to send data, (e.g. a text message), from just about anywhere, to just about anywhere, with a high degree of reliability.

That's the difference between an $800 USD smart phone and a $2 USD 433 module.

You get what you pay for!

 

JC  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
the challenges these cheapy radio modules present 

This is exactly why they are cheap - because it's all left to you to do all the clever stuff to get around the limitations.

 

Now, if you're skilled & experienced in this stuff, that's not a problem - but it's why these things are not really suitable for beginners.

 

See: http://www.avrfreaks.net/comment...

 

IF you want something that'll connect straight to a UART and "just work", then you have to pay a little extra to have that functionality built in

 

See: http://www.avrfreaks.net/comment...

 

EDIT

 

See also: http://www.avrfreaks.net/comment...

 

#CheapRF

Last Edited: Thu. Nov 2, 2017 - 09:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Use RFM12B or nrf2401
.
MG

I don't know why I'm still doing this hobby

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Poor rf signal. nrf24l01+ is better.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ashbrlmd wrote:

Poor rf signal. nrf24l01+ is better.


Thank you
.
MG

I don't know why I'm still doing this hobby

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but not a direct UART connection?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for those suggestions!  In your guys' experience, what is the range on each of these modules?  I see that the RFM12B is 915mhz and the nrf2401l+ is 2.4ghz - what are the advantages and disadvantages of these higher frequencies?  I believe I read somewhere that a higher frequency generally means a lower range, but that's where my understanding stops.

 

In general, what makes these modules better than the ones that I'm using (RXB12 and H34a), or other cheap modules?  I don't doubt at all that they are better, but I'd like to actually understand what makes these modules stand out.

 

Also, I don't mind if the modules don't use UART - as long as the protocol the module uses is supported by my chip(s), I'm happy!

Last Edited: Wed. Nov 1, 2017 - 02:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Range is almost entirely down to how well (or badly) you design the RF part, and your choice of antenna.

 

But sub-GHz is bound to go further than 2.4GHz - especially through walls, etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Range at UHF and higher (line of sight) is mostly a function of antenna height at both ends, due to earth curvature, there are other factors as well depending on frequency, such as reflections (buildings, ground, water, etc), other transmitters on or near the operating frequency used, Absorption (walls, trees, humidity, rain, etc), bandwidth (generally, the wider the signal the shorter the range).  I'm sure I left some out.  

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tylerlee12 wrote:
I see that the RFM12B is 915mhz

No.
There's 433MHz also. And other freq.
The distance depends on the antenna choice. With about 7cm wire as antenna it will be about 7-10 meters. Depends on obstacle also.
There's also high power type. Like RFM64W. If you want long distance.

Tylerlee12 wrote:
what makes these modules better than the ones that I'm using

It's tranceiver so it can transmit and receive in single module. Half duplex mode.
.
MG

I don't know why I'm still doing this hobby