AVR goes ESP mit MicroPython - Teil 2 - AZ-Delivery

This article is also available as PDF file for download.

MicroPython on the ESP32 and ESP8266

Today it's party time. The AVRs are getting dressed up to introduce themselves properly to the ESP clan. We are of course exclusive paparazzi, watching the action from the front row. Welcome to

AVR goes ESP8266/32 (part 2)

Figure 1: LDR, nRF24L01 and ATmega328 microcontroller

Image 1: LDR, nRF24L01, and ATmega328 microcontroller

In the previous episode, we spruced up ESP32 and ESP8266 for reception. Today it's the AVRs' turn. All ATmega328 controllers I know of have an SPI bus. This connection can be used to program the chips natively. Before an AVR can be programmed via USB/RS232 from the Arduino IDE, it has to be given a bootloader and this is exactly what is done via the SPI bus. The boards we are going to use today already have this bootloader, so we can program all of them via the Arduino IDE and the USB port and use the serial monitor for control and result display. For the Arduino Pro mini we need a USB-RS232 TTL adapter. We need the SPI bus to dock the nRF24L01 to the microcontroller, as we did with the ESP8266 in the last episode.

Figure 2: ATmega328 microcontroller AZ-Delivery

Image 2: ATmega328 microcontroller AZ-Delivery

Figure 3: NANO V3

Image 3: NANO V3

Figure 4: PRO MINI with ATmega328

Image 4: PRO MINI with ATmega328

Figure 5: USB-RS232 adapter FTDI232RL

Image 5: USB-RS232 adapter FTDI232RL

The hardware

Components from the first episode


ESP8266 Node MCU or


ESP32 Node-MCU or ESP32 D1 mini


FDTI USB RS232 TTL adapter




nRF24L10+ breadboard adapter


LDR with 10kΩ trimpot or


LDR module



Components for the current episode


ATmega328 microcontroller or

Nano V3 or

Pro mini




Jumper cable


suitable USB cables


possibly battery 4,5V or 5V plug-in power supply unit

The pin assignments for the three AVRs can be seen in the following circuit diagrams. Just choose a circuit as you like. Because the chip (ATMega 328P) is the same for all of them, there are no differences in the program.

Figure 6: nRF24L10 on ATmega328 microcontroller

Image 6: nRF24L10 on ATmega328 microcontroller

Figure 7: Circuit with Nano V3 - 5V supply

Image 7: Circuit with Nano V3 - 5V supply

Figure 8: Circuit with Pro mini - 3.3V from FTDI adapter

Image 8: Circuit with Pro mini - 3.3V from FTDI adapter

When powering from the USB port via the FTDI adapter, we need to make sure that the jumper is plugged into the 3.3V position before connecting the nRF24L01. The nRF24L01 board must in no case be directly powered with 5V directly. However, the logic lines are 5V fixed. The circuit in Figure 7 takes advantage of this.

The pin numbers of the SPI bus on the AVR board can also be transferred directly to various other boards of the family. For example, the connections on the "Minis" are each at different positions on the board, but have the same numbers and the same function.

The software

For flashing and programming the ESP32:

Thonny or


For the AVR

Arduino IDE

Library for the nRF24L01+

Sketch for the nRF24L01+

nRF24L01 Sketch

Used firmware for the ESP8266/ESP32:


Please choose a stable version

The MicroPython programs for the project:

nRF24-L01 module for the ESP8266/ESP32

master+slave.py: Demo program for the ESP8266 RX and TX function of the nRF24L01

MicroPython - Language - Modules and programs

For the installation of Thonny, you find here a detailed manual. In it there is also a description of how the MicropythonFirmware (as of 02/03/2022) on the ESP chip. burned is burned.

MicroPython is an interpreter language. The main difference to the Arduino IDE, where you always and only flash whole programs, is that you only have to flash the MicroPython firmware once at the beginning to the ESP32 so that the controller understands MicroPython instructions. You can use Thonny, µPyCraft, or esptool.py to do this. For Thonny, I have described the process here described here.

Once the firmware is flashed, you can casually talk to your controller one-on-one, test individual commands, and immediately see the response without having to compile and transfer an entire program first. In fact, that's what bothers me about the Arduino IDE. You simply save an enormous amount of time if you can do simple tests of the syntax and the hardware up to trying out and refining functions and whole program parts via the command line in advance before you knit a program out of it. For this purpose, I also like to create small test programs from time to time. As a kind of macro, they summarize recurring commands. From such program fragments sometimes whole applications are developed.


If you want the program to start autonomously when the controller is switched on, copy the program text into a newly created blank file. Save this file as boot.py in the workspace and upload it to the ESP chip. The program will start automatically at the next reset or power-on.

Test programs

Manually, programs are started from the current editor window in the Thonny IDE via the F5 key. This is quicker than clicking on the Start button, or via the menu Run. Only the modules used in the program must be in the flash of the ESP32.

In between times Arduino IDE again?

If you want to use the controller together with the Arduino IDE again later, simply flash the program in the usual way. However, the ESP32/ESP8266 will then have forgotten that it ever spoke MicroPython. Conversely, any Espressif chip that contains a compiled program from the Arduino IDE or the AT firmware or LUA or ... can easily be flashed with the MicroPython firmware. The process is always like here described.

Setting up the Arduino IDE

If you have not yet worked with the Arduino IDE and this tool is not yet on your computer, please follow this quick guide.

Start with the Download the installation file via this link.

Figure 9: Download Arduino IDE

Image 9: Download Arduino IDE

Click the version that corresponds to your operating system and save the file in a directory of your choice.

Figure 10: Save installation file

Image 10: Save the installation file

Start the installation file and follow the user guide.

In the next step please load the library file RF24-master.zip directly via this link, or from the GitHub page and save it in a directory of your choice.

Figure 11: Download nRF24 library

Image 11: Download the nRF24 library

Figure 12: Save RF24-master.zip

Image 12: Save RF24-master.zip

Figure 13: Select directory

Image 13: Select the directory

Now start the Arduino IDE to include the new library. In the menu Sketch select the item Include library and then.Add Zip library.

Figure 14: Include library

Image 14: Include the Library

Navigate to the downloaded ZIP file, highlight it, and then click Open.

Figure 15: Select and open library

Image 15: Select and open the library

The sketch for the AVR slave

The AVR variants presented here have the same controller on board, an ATMega328P, but still, each of the three has to be operated with its own setting. Important are the right choice of board, the setting of the processor, and of course the right COM port.

Figure 16: Pro mini - board selection

Image 16: Pro mini-board selection

Figure 17: Pro mini with FTDI adapter

Image 17: Pro mini with FTDI adapter

The interface pins of the Pro mini fit opposite to those of the FTDI adapter, so that the two boards can be plugged directly on top of each other or, like here face to face, on a breadboard. The lines RXD and TXD are already crossed.

That was already the preparation for the Arduino IDE. We now connect the AVR to a free USB port and load the Sketch into the editor.

Let's take a closer look at the program before we start it. It is divided into three main parts.

Includes and declarations
 #include "RF24.h"
 #include "printf.h"
 RF24 radio(9,10); // CE=9; CSN=10
 uint8_t address0[]={0x54, 0x5A, 0x5A, 0x5A, 0x5A};
 uint8_t address1[]={0x52, 0x5A, 0x5A, 0x5A, 0x5A};
 uint8_t channel=50;
 const int PLLength = 8;
 char payload[PLLength];
 bool radioNumber=1; //
 uint16_t ldr=0; //Integer value from LDR
 int ldrPin = A0;

We first import three libraries for the operation of the SPI bus, the control of the nRF24L01+, and for the output of its configuration data.

The constructor call of the class RF24 creates an nRF24L01 instance, which we radio name. In order to address different units, each unit needs two unique addresses, one for sending and one for receiving. It is sufficient if the addresses differ in one byte. Further information about address assignment can be found in the previous episode in more detail. Addresses may contain between three and five bytes. We used an address length of 5 bytes for the ESP8266 and do the same here. However, in the MicroPython program master+slave.py the addresses are defined as 10-digit hexadecimal values, while in the Arduino IDE sketch byte arrays of length 5 are used for this purpose.

In the array, the least significant byte is at position 0, which is also the first to go over the SPI bus when transmitting to the nRF24L01. Channel 50 becomes our message channel. Possible values are between 0 and 125. If there are transmission problems during operation, it may be because the selected channel is also used by other stations, for example, WLAN devices that use the same frequency band of 2.4 GHz. In this case, it is advisable to switch to higher channels. However, the stations involved must use the same channel.

As payload, we are allowed to transmit up to 32 characters. We set the number here to 8 and create a char array of this length as buffer memory. The AVR works as a slave. It receives orders from the ESP8266 and sends back measured values as the response. We have connected the LDR to A0 connected. Its converter values are taken by the 16-bit variable LDR takes up.

Configuration of the AVR
 void setup() {
   while (!Serial) {
     Serial.println(F("nRF24 not found"));
     while(1){}  // Halt on error
   Serial.println(F("nRF24 started in Slave mode on channel:"));

And we are already in the setup department. The serial port for the monitor is set up. We try to start the nRF24L01+. If this worked, we get the start message in the serial monitor. Otherwise, the program gets stuck in the while loop.

Then the working parameters are sent to the nRF24L01+, the channel number, the number of address bytes, and the number of bytes for the payload, we always send and receive 8 characters. A master can maintain up to six connections to slaves on one channel. These connections are called pipes. We set we transmit line to address 1 and the receiving line Pipe 1 to address 0. Thus we have crossed the addresses to the master on the ESP8266. The ESP8266 sends on address 0, so the AVR must listen on one of its receive pipes, here pipe 1, on this address. The AVR transmits on address 1 because the ESP8266 also listens on address 1 on input pipe 1. We throttle the transmit power to the lowest level because our two stations are very close to each other during the tests and too much transmit power can overdrive the receive section, which leads to interference.

After instructing the nRF24L01+ to listen on the radio, we set up the output unit, set the lowest transmission rate (for best receiver sensitivity) to 250kBit/s, and display the entire configuration on the serial monitor.

The main loop does the job
 void loop() {
   uint8_t pipe;
   if (radio.available(&pipe)){
     Serial.print(F(" Bytes on Pipe: "));
     Serial.print(F(": "));
     for (int i=0; i<8;i++){
     String recv=(String((char *)payload));
     int colonAt=recv.indexOf(":");
     String command=recv.substring(0,colonAt);
     String rest=recv.substring(colonAt+1);
     // int val=rest.toInt();
     if (command=="send"){
       String value = rest+":"+string(ldr);
       char reply[PLLength]={0,0,0,0,0,0,0,0};
       bool report = radio.write(&reply, PLLength);

The main loop checks if a packet with data has arrived. If so, the payload is written to the char array payload is read. We get some messages with the received data. The following print commands and the for loop are only for evaluation during development and can be omitted in the later production system.

We now convert the char array into a string, remove non-printable characters and check for the text of the arrived command. For this we look for the position of the ":", because it separates the command from the following serial number. Everything before is the command, and everything after is the serial number. If necessary, we can also convert the serial number to an integer to generate a check digit or encryption from it to secure the transfer.

If the command "send", then we stop listening, read the analog value at A0, and reshape it into a string. Into the deleted char array reply[] we let the serial number and, separated by a ":", the content of the LDR value string be transferred to send the data to the master in the following command. If the content of the report equals 1, then the transmission has worked and we go back to eavesdropping. How or if the answer is processed at the master (ESP8266), I like to leave it up to you. Ideas would be for example sending to the net or writing to a log file.

Is everything set up and connected at the AVR? Are the correct USB port to the AVR set and the correct board selected? Then we can compile and upload the sketch. The AVR runs as a slave and should be able to receive and answer requests from the master.

The ESP8266 is master

For the AVR to be able to do this, we need the master program to run on the ESP8266. There are two possibilities for this. Either an ESP8266 is already prepared and ready to go according to the information given in the previous episode of the blog, or a station must be created according to the explanations given in this episode. For the latter case, a short tutorial follows.

The circuit for the master is shown in Image 16. In case the master is to do other things besides operating the nRF24L01, an ESP32 might be better suited instead of the ESP8266. Program and Driver module are identical to big brother.

Figure 18: nRF24L10 on ESP8266

Image 18: nRF24L10 on the ESP8266

By means of Thonny, the ESP8266/ESP32 is connected to the MicroPython firmware with the MicroPython firmware. Instructions for this can be found in the chapter MicroPython - Language - Modules and programs further up in this article or you can simply follow this link.

Once that is done, we load the file nrf24simple.py to the ESP8266 and open the program master+slave.py in an editor window of Thonny. After it has been started with F5, five requests are sent to the Arduino. Then it returns control to the MicroPython prompt ">>>" in the terminal area of Thonny. As long as the AVR is not yet running, we will receive timeout messages that we can safely ignore for the moment.

Figure 19: First start of the ESP8266 as master

Image 19: First start of the ESP8266 as master

In the Arduino IDE, we now start the serial monitor. It receives the outputs of our program on 115200 baud.

Figure 20: Starting the serial monitor in the Arduino IDE

Image 20: Starting the serial monitor in the Arduino IDE

After a few seconds, we get the startup messages from our sketch.

Figure 21: Start messages of the AVR slave

Image 21: Start messages of the AVR slave

The slave is now ready to receive. So let us start the master's program in Thonny with F5.

In the serial monitor, the queries of the ESP8266 appear in 2-second intervals in a broken-down form with the LDR value in the penultimate line. The 1 tells us that the feedback to the master has successfully left the slave.

Figure 22: Output in the serial monitor of the slave

Image 22: Output in the serial monitor of the slave

The values also appear in Thonny's terminal without any noticeable delay.

Figure 23: Shell output in Thonny

Image 23: Shell output in Thonny

In individual cases, the request is sent by the master, but does not arrive at the slave or arrives in a garbled form, so that subsequently no response is sent. This is then expressed at the master by a timeout. The program can then take care of the error accordingly, for example by immediately sending another request.

This brings us to the end of the two-part post on the nRF24L01, let's summarize.

  • The nRF24L01 provides a radio link between the AVR and ESP8266/32 that is off the usual WLAN frequencies.
  • Due to the SPI interface the nRF24L01 can be used for both controller families.
  • The SPI interface on the ESP32/ESP8266 is also conveniently programmable in MicroPython.
  • Existing Arduino IDE projects can be easily extended with WLAN functionality via ESP32 and ESP8266.
  • An ESP32 or ESP8266 can manage up to 6 logical connections to AVR projects or nRF24L01 units in conjunction with other controllers.

For us, this provides further foundations for exciting new projects. Maybe you already find something in the Overview already available on AZ-Delivery articles about MicroPyton and ESP32/ESP8266.

Esp-32Esp-8266Für arduinoProjekte für anfängerSensoren

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery