[Necromant] wrote a library to flash his microcontroller over an RF link using an NRF24L01 wireless communication module. The NRF24L01 is a cheap RF module that can be easily integrated into many microcontroller projects. Though there are Arduino libraries for driving the NRF24L01, [Necromat] decided to make a port of one with no Arduino dependencies.
The resulting bootloader fits into 4K of
RAM flash with packet loss and recovery along with user-configurable hardware or software SPI. Programming speeds are not the highest, but [ NecromatNecromant] believes this to be a property of the VUSB rather than the transfer rate from the NRF24L01 or the target microcontroller.
To program the target AVR chip, [
NecromatNecromant] used another NRF24L01 module connected to his uISP dongle over USB. Using a custom tool to interface with the uISP, the target board can be programmed in a similar fashion as avrdude. Check out the code for the ISP dongle and the AVR bootloader on his GitHub page.
16 thoughts on “Using An NRF24L01 For Air Bootloading”
My love for HackADay just +1(ed). I started a project like this literally last night. Now I don’t have to do the dirty work myself. :D HUGE thanks to Necromant for this!
This came just a little too late for me – I just completed a similar project with the NRF24L01+ not two months ago. Nice work!
Whoah, I did a similar project too, which I’m using for my home automation boards like Necromant does.
It is optiboot — the 512-byte arduino bootloader — modified to support flashing over the nRF24L01+ (it grows to 1.5kB when this option is enabled). The nice thing is that the underlying protocol remains the same as with serial flashing, so you still use avrdude on the PC to send the radio commands, so you can upload skecthes from the Arduino IDE with no configuration changes.
For those who don’t realise how cheap those modules are, they can be had for $1 from aliexpress, along with arduino mini’s for $2.5.
I was trying to use your bootloader for OTA programming, but i could not find the schematic of connections from the module to the ‘mega328 chip. Could you link me to that?
Hi Sarang, I don’t have a pretty schematic but basically: CE by default connects to A1 (analog 1), CSN to A0.
The rest of the connections have the same names on atmega vs. module:
SCK to SCK, MOSI to MOSI, MISO to MISO, GND to GND, 3.3V to a 3.3V source.
Hi Andrew – I was not able to make this work -I am not sure about the avrdude commands:
It seems when I try to set the eeprom address for the flasher – I am just overrding it or damagin it
avrdude -C “C:\Users\Ben\Downloads\avrdude\etc\avrdude.conf” -F -p atmega328p -P COM5 -c arduino -b 115200 -U eeprom:w:0x30,0x30,0x31,0x30,0x30,0x30:m
also I am not sure what it the right commad to run against the flasher – it also seems just to overwrite it:
I am using:
avrdude -C “C:\Users\Ben\Downloads\avrdude\etc\avrdude.conf” -V -p atmega328p -c stk500v1 -P COM5 -b 115200 -U flash:w:text.ino.standard.hex -vvvv
where :text.ino.standard.hex is exported from arduino IDE.
My flasher is on COM5 and the target is connected (and the flasher) to the RF modules.
tryied the traget on A0 and A1 pins and A1 and D10
still does not work
I think the problem is my avrdude commands….
>The resulting bootloader fits into 4K of RAM with packet loss and recovery along with user-configurable hardware or software SPI.
That’s 4k of FLASH. You can’t exactly boot from RAM in AVR as it is Harvard architecture, so there is a distinction & limitation of Code space vs Data Space. i.e. can’t run from RAM as is for DATA!
As for VUSB speed, here are some of the numbers I had from an earlier version of a (parallel) FLASH/EPROM programmer I built. An updated hardware moved the VUSB pins to PortB, freed up Port D, overclocked and I hit 20kB/s read/write speed.
USB 1.1 8 bytes control message (block Size# Speed)
Speed: 8# 7.8kB/s, 16# 7.8kB/s, 32#10.4kB/s, 64#12.5kB/s 128#3.9kB/s 256#14.7kB/s, 512#15.2kB/s
(Had to report my last post under moderation as I used the at sign and the forum thought they were email addresses. Please remove that post)
The bad thing is, that the current implementation just relays all the rf24 library API via usb with no buffering. So when you send a control transfer with 32 bytes of the payload you want to send, you’ll have to wait till the nrf24 transmits that, before you can send the next chunk. Proper buffering and async operation would certainly speed things up a lot.
I know that this is quite dumb, but since I don’t like the current hardware implementation anyway (easy to fry nrf24l01 with just one jumper that selects Vcc between 3.3, 3.6 and 5.0v) and an stm32-based dongle is on my todo list – this is just a temporary solution.
But feel free to patch/improve it and send your merge request!
These kinds of over the air flashers based on nrf24l01 can be had on ebay, pretty cheap. If you don’t want to make your own.
I got excited that this was about a bootloader that resides in your actual board.
It’s still a cool project but I think most people have a laptop, rPi and the automations are not so embedded as they become immovable.
Still waiting for a bootloader via nrf24l+, I am not able to write one myself. Actually a scripting language that can be uploaded can also do the trick, I suspect most of these home automation ideas do not required more than this.
Wow, thanks for the frontpage. Just replace Necromat with Necromant. That’s double a typo!
Just a side note. an avr-only bootloader can possibly be fitted in 2K. However I decided to bloat it a little. That’s our price for readability and portability. So basically you can easily run it on anything that is supported by antares (stm32 is the next target). Other targets might have a smaller footprint – looks like avr-gcc totally doesn’t like pointers that bloat the code.
Thanks fixed and thanks for the awesome hack!
i’m doing some guesswork about the interface to the uISP, and scrolling through the code i hit ./src/avr/kcnf. So now I’m wondering why “CE_PORT” and “CSN_PORT” both are “D” and “CE_PIN” and “CSN_PIN” both are “0”. Looking at the pics and uISP schematics, one of these two pins is PB0…
I’m guessing the “CSN_PORT” should be “B”
Here is my solution for Arduino OTA over rf24, video post about
Please be kind and respectful to help make the comments section excellent. (Comment Policy)