Is it possible to send OTA updates to Arduino via nRF24L01+ module?

Here are my findings:

Here is an instructable explaining how to program Arduino wirelessly but this thing uses a BT module which shows up on PC as a COM port.

Here is something similar using Xbees.

However, these use another arduino attached to a PC on the other end. In my case, I am planning to use rPi hooked to another nRF24L01+ rather than PC.

This is an excerpt from the datasheet of Atmega chip:

In ATmega88A/88PA/168A/168PA/328/328P the Boot LoaderSupport provides a real Read-While-Write SelfProgramming mechanism for downloading and uploading program code by the MCU itself. This feature allows flexible application software updates controlled by the MCU using a Flash-resident Boot Loader program. The Boot Loader program can use any available data interface and associated protocol to read code and write (program) that code into the Flash memory, or readthe code from the program memory.

Here is what I planned as a strategy.

Master programmer = Raspberry Pi + nRF module.

Slave arduino = Arduino + nRF24L01 + external EEPROM

Once I have to upload a new code, I can transmit the compiled code to the arduino (I can do that, right?) and Arduino will save it in the external EEPROM for the time being.

When the transfer is complete, I will send a signal which will make the arduino reset and copy the code from EEPROM to its flash memory.

My questions:

Is the strategy correct and feasible?

How should I proceed to achieve it?

Any other suggestions which you might have are welcome.

  • Using external EEPROM would make your bootloader a lot simpler to write, and would make things more robust. Sound feasible to me.
    – Gerben
    May 10, 2015 at 16:00
  • 1
    Not sure what protocol you're using on top of ESB, but you should be aware that the 16 bit CRC provided by the nRF24L01 is not sufficient to protect a firmware upload. Your algorithm should have a stronger test (e.g. a CRC over the entire FW) before it accepts the new image. May 10, 2015 at 19:06
  • @Ben - I was skeptical about the data integrity. That's why I am planning to verify it first and store it in an external EEPROM first. Once the data is checked, then only the stored code will be applied to micro-controller. May 10, 2015 at 21:51
  • Perhaps forum.arduino.cc/index.php?topic=332191.0 can lead to examples how to reprogram the flash from an own sketch...
    – gone
    Nov 7, 2015 at 13:37
  • You can investigate how MySensor does it. I'm fairly certain it'd help you.
    – Avamander
    Jan 30, 2016 at 16:32

5 Answers 5


Your best strategy would be to write your own bootloader.

The existing bootloader receives data through the serial port and writes it, a page at a time, to the flash. Your custom bootloader, instead, would receive the data through the nRF module and write it to flash, a page at a time.

You could use the source code for the existing bootloader (maybe use optiboot?) as a starting point and remove the UART code, replacing it with nRF code.

Of course, you still need a way to enter the bootloader when you want to program it - the easiest way is to ensure that is added into any sketch you upload so you can send an instruction to that sketch to enter the bootloader.

You would also need to create a program on the Pi to do the programming over the air - or modify an existing one like avrdude.

It may, in the long run, be simpler to have a pair of other Arduinos (maybe something small like an ATTiny based board) to act as bridges between UART and the nRF modules so they become a transparent wireless serial link.


There is an Arduino optiboot fork for this now, which seems to handle what you want.

You would use a PC, RPi or whatever that could run avrdude to send the update to an Arduino acting as the update server, which transmits the code to the client.

The instructions on the page seem quite comprehensive.

  • Thanks Kurt for answering. I will look into it. Hopefully a modified version of this might help in my future projects. However I have moved to esp8266 now following the terrible range of nRFs. Esp has added benefit of pre-defined data transfer protocols and recently OTA updates for ESP have been released in ESP arduino library. Seems like esps are better choice as compared to nRFs due to good range and better data transfer reliability. Moreover, for simple work, I don't even need another arduino hooked to esp. Jan 30, 2016 at 18:27
  • Did anyone was able to make this work? I have used github.com/nicolas-schurando/optiboot-nrf24l01-flasher and github.com/nicolas-schurando/optiboot-nrf24l01 was able to burn the bootloader and the flasher (remote has bootloader and local has flasher) but I am not sure which avrdude command to use in order to burn the remote station - it seems to always overwrite my local arduino and remove the flasher sketch from it - instead of forwarding it... Apr 27, 2017 at 19:38

If you're working with remote sensor nodes, perhaps consider the MySensors library.

It's got support for two methods of delivering OTA updates - one using a node.js controller running on a rPi; and another third-party solution with a .NET front-end.

Failing that, you could borrow the bootloader code from the library and customise to your own needs.


It's definitely feasible and it's been done. Look at Low Power Labs site where Felix did the same thing, but with a RF69 radio and an external flash chip. You do need a modified bootloader as he uses, one that would detect the new sketch in the external flash and will upload it to the Arduino on reset. Radio difference aside this should work well for your purposes.

Given the flaky nature of the radio communication I think it's a good idea to store the program separately rather than create a highly modified bootloader which will read the radio stream - it might be that for programming you need a constant stream of bytes which the radio can't always provide (though I'm not 100% sure about this); another reason being that the extra code you would need to access the radio will make for a larger bootloader.

  • I was skeptical about the data integrity. That's why I am planning to verify it first and store it in an external EEPROM first. Once the data is checked, then only the stored code will be applied to micro-controller. Thanks for that article. I will go through it. May 10, 2015 at 21:52

As per @Majenko and @Kurt suggestions:

Please check out me blog post, it is exactly about that!


I have made a complete tutorial about this issue and also modified the suggested code above so debugging will be easier.

The basic idea is to have a local station which forwards the new sketch from the computer->uart->spi->rf24 to a remote Arduino running a custom bootloader which listens on the rf24->spi instead of the UART. This bootloader does everything as usual (expecting protocol commands as part of the stk500 protocol and so on) but, instead of getting them over UART the packets arrive from the RF24 module through SPI.

During boot, the bootloader will have to initialize the RF module registers and then parse the incoming bytes if any; after a timeout, it will quit and run the sketch currently there in a loog as usual

In my blog you will see some notes about the Hardware configuration for the local station: you need a 10uF capacitor between the RESET and GND pins to avoid flashing the local station while trying to flash the remote station.

That post also incldues the commands needed to use AVRdude to flash the bootloader and then to flash the remote station (which has the new bootlaoder) through the local station running the "flasher" sketch (station with the capacitor).

Basic commands are:

avrdude -C "C:\Users\Ben\Downloads\avrdude\etc\avrdude.conf" -b 19200 -c usbtiny -p m328p -v -e -U efuse:w:0xFD:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m -F
avrdude -C "C:\Users\Ben\Downloads\avrdude\etc\avrdude.conf" -b 19200 -c usbtiny -p m328p -v -e -U flash:w:optiboot_atmega328_new_bootlader.hex -U lock:w:0x0F:m

You can find the code on my blog and links to other sources and tools needed (such as an AVR programmer).

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
    – jfpoilpret
    Jan 7, 2018 at 1:24
  • @jfpoilpret added description, feels like anything is missing? Jan 7, 2018 at 11:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.