Cheap radio channel for AVR

Good day. I recently wondered to organize radio communications between microcontrollers AVR. The budget was very limited, and therefore as a controller for the test i selected two Atmega8 which have  long idle lying . When i start search of experimental transceiver I was unpleasantly surprised by the prices of  radio modules, so on that money that I expected in Ukraine could only buy a “pair receiver – transmitter board” at 433 MHz  . But I wanted a full duplex link so I started looking in an Internet suitable option. It was a 2.4 GHz radio module. NRF24L01 drew the attention certainly of its price.

In the basic version without amplifier and the antenna on the printed circuit board. At the time of this writing a article couple of these modules on ebay can be bought for $ 3.23

There are more expensive version with amplifier and the output of 10dBm and the declared range of 260 meters.

But this miracle are more expensive and one pc. now costs $ 13.89
I stopped on the first version. And so let’s look  inside him .

Taransiver designed as a single chip.
Transfer mode ShockBurst ™ (effective fast data transfer mode).
AUTO ACK (acknowledgment of receipt of the package) and setting retransmission if someone is in the network is not get a packet.
Automatic control of CRC.
RF transmission on 125 channels.
Interface (SPI) at speeds of 0-8 Mbps.
Fast switching possible mode of frequency hopping
5V tolerant inputs.
Profiles Standby Modes and Power Down Mode.
Output interrupt events (you can adjust in spec. Register)

And the tablet from datasheet in case i missed something.

Back in the the process of digging in the chip info I was found an interesting feature
The receiver NRF24L01 can simultaneously receive data on six channels. So it can take data from six different transmitters in same time.

The trick six channels that carry a unique 40 bit address so being in one frequency channel. Receiver accepts packets, automatically recognizes the address and put data in the buffer of addressed channel. Each channel has its own set of buffer size, the confirmation ACK, etc … Actually, I did not have get everything .

Okay back to Atmega8. Development of the device began searching existing solutions. I found a project overseas colleague Davide Gironi

Overall it corresponded my project plan. So I took the basis of his scheme and code . Slightly modifying the scheme got next.

Schematics.

Board

Device

And principle of work is in the video. When link is appeared is yellow LED blinking by pressing a button  transmittion begin and green light blinking.

Tested at a distance and came out the following results. In premises of the office communication holds three foam blocks walls, the house of red brick penetrated one bearing brick wall and the connection is 2 meters from it. Outdoors when the transmitter is placed close to a window on the fourth floor, the link is in the line of sight at 85 meters through the crossroads with the trolleybus wires and lamps of street lighting.

Actually I liked the radio module, ordered a further two it will be temperature sensors network .

Davide Gironi nRF24L01 atmega library and development board
Everything You Need to Know about the nRF24L01
AVRLib/nRF24L01

Code of my progect.
 [member]
Code 4mhz NRF24L01
[/member]
Board Eagle PCB
 [member]
Board NRF24L01
[/member]

7 Comments to Cheap radio channel for AVR

  1. szeretemafaszod says:

    HI!

    Your code is unavailable.
    (The link is not working)

    Can you upload again?

    Thank You!

    Your Friend:
    szeretemafaszod

  2. dexter says:

    I`ve just download it now. Everything is fine. You must be logged to see the link.

  3. rishabhcv says:

    Hey Dexter!

    I have a few questions about your project.
    “if(sendpipe == 0) {
    //set tx address for pipe 0
    nrf24l01_settxaddr(addrtx0);
    } else if(sendpipe == 1) {
    //set tx address for pipe 1
    nrf24l01_settxaddr(addrtx1);
    } else if(sendpipe == 2) {
    //set tx address for pipe 2
    nrf24l01_settxaddr(addrtx2);
    } else if(sendpipe == 3) {
    //set tx address for pipe 3
    nrf24l01_settxaddr(addrtx3);
    } else if(sendpipe == 4) {
    //set tx address for pipe 4
    nrf24l01_settxaddr(addrtx4);
    } else if(sendpipe == 5) {
    //set tx address for pipe 5
    nrf24l01_settxaddr(addrtx5);
    } ”

    Is this required only for the transmitting end?

    • dexter says:

      It is settin adresses for tx pipes. It was long time ago I need to check datasheet on nrf.

      • rishabhcv says:

        I have written the code for Transmission and Reception. But it’s not working. Can you please scrutinize it? I can send you the folders containing the codes but I am posting them here for quick reference.

        Transmission:

        #define F_CPU 12000000UL
        #include
        #include
        #include
        #include
        #include
        #include

        //include nrf24l01
        #include “nrf24l01.h”

        uint8_t txpipe = 1;
        uint8_t addrtx0[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP0;
        uint8_t addrtx1[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP1;
        uint8_t addrtx2[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP2;
        uint8_t addrtx3[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP3;
        uint8_t addrtx4[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP4;
        uint8_t addrtx5[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP5;

        //nrf24l01 variables
        uint8_t bufferout[NRF24L01_PAYLOAD];
        uint8_t bufferin[NRF24L01_PAYLOAD];
        uint8_t i = 0;

        uint8_t txrxrole = 1; // 1 transmitter 0 receiver

        void send_packet(uint8_t *buffer, unsigned char sendpipe)

        {
        //tx

        if(sendpipe == 0) {
        //set tx address for pipe 0
        nrf24l01_settxaddr(addrtx0);
        } else if(sendpipe == 1) {
        //set tx address for pipe 1
        nrf24l01_settxaddr(addrtx1);
        } else if(sendpipe == 2) {
        //set tx address for pipe 2
        nrf24l01_settxaddr(addrtx2);
        } else if(sendpipe == 3) {
        //set tx address for pipe 3
        nrf24l01_settxaddr(addrtx3);
        } else if(sendpipe == 4) {
        //set tx address for pipe 4
        nrf24l01_settxaddr(addrtx4);
        } else if(sendpipe == 5) {
        //set tx address for pipe 5
        nrf24l01_settxaddr(addrtx5);
        }
        //write buffer
        uint8_t writeret = nrf24l01_write(buffer);

        if(writeret == 1)
        {
        PORTC=0x0F;
        _delay_ms(100);
        PORTC=0x00;
        _delay_ms(100);
        PORTC=0x0F;
        _delay_ms(100);
        PORTC=0x00;
        _delay_ms(100);

        }
        sendpipe++;
        sendpipe%=6;

        _delay_ms(500);

        }

        //main here
        int main(void)
        {
        DDRC=0x0F;
        PORTC=0x0F;
        _delay_ms(50);
        PORTC=0x00;
        _delay_ms(50);
        PORTC=0x0F;
        _delay_ms(50);
        PORTC=0x00;
        _delay_ms(50);

        //init nrf24l01
        nrf24l01_init();

        //init interrupt
        sei();

        //setup buffer
        for(i=0; i<sizeof(bufferout); i++)
        bufferout[i] = i+'a';
        for(i=0; i<sizeof(bufferin); i++)
        bufferin[i] = 0;

        //main loop
        for(;;)
        {

        send_packet(bufferout,0);

        }
        }

        Receiver side:

        #define F_CPU 12000000UL
        #include
        #include
        #include
        #include
        #include
        #include

        //include nrf24l01
        #include “nrf24l01.h”

        uint8_t txrxrole = 0; // 1 transmitter 0 receiver

        //sending buffer addresses
        uint8_t txpipe = 1;
        uint8_t addrtx0[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP0;
        uint8_t addrtx1[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP1;
        uint8_t addrtx2[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP2;
        uint8_t addrtx3[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP3;
        uint8_t addrtx4[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP4;
        uint8_t addrtx5[NRF24L01_ADDRSIZE] = NRF24L01_ADDRP5;

        //nrf24l01 variables
        uint8_t bufferout[NRF24L01_PAYLOAD];
        uint8_t bufferin[NRF24L01_PAYLOAD];
        uint8_t i = 0;

        void recieve_packet(void)
        {
        //rx
        uint8_t i = 0;
        uint8_t pipe = 0;
        if(nrf24l01_readready(&pipe))
        { //if data is ready
        PORTC=0x0F;
        _delay_ms(100);
        PORTC=0x00;
        _delay_ms(100);
        PORTC=0x0F;
        _delay_ms(100);
        PORTC=0x00;
        _delay_ms(100);

        //read buffer
        nrf24l01_read(bufferin);

        uint8_t samecheck = 1;
        for(i=0; i<sizeof(bufferin); i++) {
        if(bufferin[i] != bufferout[i])
        samecheck = 0;
        }

        if(samecheck)

        {
        PORTC=0x0F;
        _delay_ms(3000);
        PORTC=0x00;
        _delay_ms(100);
        }

        }
        _delay_ms(10);
        }

        //main here
        int main(void)
        {

        DDRC=0x0F;
        PORTC=0x0F;
        _delay_ms(50);
        PORTC=0x00;
        _delay_ms(50);
        PORTC=0x0F;
        _delay_ms(50);
        PORTC=0x00;
        _delay_ms(50);

        //init nrf24l01
        nrf24l01_init();

        //init interrupt
        sei();

        //setup buffer
        for(i=0; i<sizeof(bufferout); i++)
        bufferout[i] = i+'a';
        for(i=0; i<sizeof(bufferin); i++)
        bufferin[i] = 0;

        //main loop
        for(;;)
        {

        recieve_packet();

        }

        }

  4. rishabhcv says:

    This is a test code and hence it isn’t modular. Excuse my coding skills. Here, I am trying to blink an LED on port C, if transmission/reception is successful. I am blinking the LED initially in main, just to check if the code is working.

Leave a Reply