{"id":170305,"date":"2025-06-19T13:48:55","date_gmt":"2025-06-19T13:48:55","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=170305"},"modified":"2025-06-19T14:30:24","modified_gmt":"2025-06-19T14:30:24","slug":"micropython-esp-now-esp32","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/micropython-esp-now-esp32\/","title":{"rendered":"MicroPython: ESP-NOW with ESP32 (Getting Started)"},"content":{"rendered":"\n<p>Learn how to use ESP-NOW communication protocol with the ESP32 programmed with MicroPython. ESP-NOW is a connectionless communication protocol created by Espressif, designed for short packet transmission. It is one of the easiest ways to communicate between ESP32 boards wirelessly. Currently, the MicroPython firmware for the ESP32 includes two built-in modules, <span class=\"rnthl rntliteral\">espnow<\/span> and <span class=\"rnthl rntliteral\">aioespnow<\/span>, that provide classes and functions for working with ESP-NOW.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-MicroPython-ESP32-Getting-Started.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-NOW with ESP32 Programmed with Micropython\" class=\"wp-image-170341\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-MicroPython-ESP32-Getting-Started.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-MicroPython-ESP32-Getting-Started.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-MicroPython-ESP32-Getting-Started.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-MicroPython-ESP32-Getting-Started.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-MicroPython-ESP32-Getting-Started.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgray\"><strong>Using Arduino IDE?<\/strong> Follow this tutorial instead: <a href=\"https:\/\/randomnerdtutorials.com\/esp-now-esp32-arduino-ide\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Getting Started with ESP-NOW (ESP32 with Arduino IDE)<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites &#8211; MicroPython Firmware<\/h2>\n\n\n\n<p>To follow this tutorial, you need MicroPython firmware installed on your ESP32 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/getting-started-thonny-micropython-python-ide-esp32-esp8266\/\">Installing and getting started with Thonny IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/flashing-micropython-firmware-esptool-py-esp32-esp8266\/\">Flashing MicroPython Firmware with esptool.py<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"rntbox rntclblue\"><strong>New to MicroPython?<\/strong> Check out our eBook: <a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\" title=\"\">MicroPython Programming with ESP32 and ESP8266 eBook (2nd Edition)<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introducing ESP-NOW<\/h2>\n\n\n\n<p>ESP-NOW is a wireless communication protocol developed by Espressif that allows multiple ESP32 or ESP8266 boards to exchange small amounts of data without using Wi-Fi or Bluetooth. ESP-NOW does not require a full Wi-Fi connection (though the Wi-Fi controller must be turned on), making it ideal for low-power and low-latency applications like sensor networks, remote controls, or data exchange between boards.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-medium\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"300\" height=\"75\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/esp-now-logo.png?resize=300%2C75&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-NOW - ESP32 Logo\" class=\"wp-image-93360\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/esp-now-logo.png?resize=300%2C75&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/esp-now-logo.png?resize=1024%2C256&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/esp-now-logo.png?resize=768%2C192&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/esp-now-logo.png?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/figure><\/div>\n\n\n<p>ESP-NOW uses a connectionless communication model, meaning devices can send and receive data without connecting to a router or setting up an access point (unlike HTTP communication between boards). It supports unicast (sending data to a specific device using its MAC address) and broadcast (sending data to all nearby devices using a broadcast MAC address) messaging.<\/p>\n\n\n\n<p>ESP-NOW supports the following features:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Supports both encrypted and unencrypted unicast communication.<\/li>\n\n\n\n<li>Direct communication between up to 20 registered peers or 6 encrypted peers.<\/li>\n\n\n\n<li>Can communicate with a mix of encrypted and unencrypted devices at the same time.<\/li>\n\n\n\n<li>Allows sending data packets of up to 250 bytes.<\/li>\n<\/ul>\n\n\n\n<p>ESP-NOW is very versatile and you can have one-way or two-way communication in different setups. For example:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-tiled-gallery aligncenter is-style-rectangular\"><div class=\"\"><div class=\"tiled-gallery__gallery\"><div class=\"tiled-gallery__row\"><div class=\"tiled-gallery__col\" style=\"flex-basis:51.06558%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_way_communication_two_boards.png?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_way_communication_two_boards.png?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"\" data-height=\"421\" data-id=\"93050\" data-link=\"https:\/\/randomnerdtutorials.com\/esp-now-esp32-arduino-ide\/esp_now_one_way_communication_two_boards\/#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_way_communication_two_boards.png\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_way_communication_two_boards.png?ssl=1\" data-amp-layout=\"responsive\" aria-label=\"Open image 1 of 4 in full-screen\"\/><\/figure><\/div><div class=\"tiled-gallery__col\" style=\"flex-basis:48.93442%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_master_multiple_slaves.png?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_master_multiple_slaves.png?strip=info&#038;w=652&#038;ssl=1 652w\" alt=\"\" data-height=\"382\" data-id=\"93051\" data-link=\"https:\/\/randomnerdtutorials.com\/esp-now-esp32-arduino-ide\/esp_now_one_master_multiple_slaves\/#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_master_multiple_slaves.png\" data-width=\"652\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_master_multiple_slaves.png?ssl=1\" data-amp-layout=\"responsive\" aria-label=\"Open image 2 of 4 in full-screen\"\/><\/figure><\/div><\/div><div class=\"tiled-gallery__row\"><div class=\"tiled-gallery__col\" style=\"flex-basis:48.98262%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_slave_multiple_masters.png?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_slave_multiple_masters.png?strip=info&#038;w=649&#038;ssl=1 649w\" alt=\"\" data-height=\"375\" data-id=\"93052\" data-link=\"https:\/\/randomnerdtutorials.com\/esp-now-esp32-arduino-ide\/esp_now_one_slave_multiple_masters\/#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_slave_multiple_masters.png\" data-width=\"649\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_slave_multiple_masters.png?ssl=1\" data-amp-layout=\"responsive\" aria-label=\"Open image 3 of 4 in full-screen\"\/><\/figure><\/div><div class=\"tiled-gallery__col\" style=\"flex-basis:51.01738%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/02\/ESP8266_ESP_NOW_multiple_boards_two_way_communication.png?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/02\/ESP8266_ESP_NOW_multiple_boards_two_way_communication.png?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"\" data-height=\"416\" data-id=\"93798\" data-link=\"https:\/\/randomnerdtutorials.com\/esp8266_esp_now_multiple_boards_two_way_communication\/\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/02\/ESP8266_ESP_NOW_multiple_boards_two_way_communication.png\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/02\/ESP8266_ESP_NOW_multiple_boards_two_way_communication.png?ssl=1\" data-amp-layout=\"responsive\" aria-label=\"Open image 4 of 4 in full-screen\"\/><\/figure><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>One ESP32 board sending data to another ESP32 board;<\/li>\n\n\n\n<li>ESP-NOW two-way communication between two boards;<\/li>\n\n\n\n<li>One ESP32  receiving data from multiple boards;<\/li>\n\n\n\n<li>One ESP32 board sending data to multiple boards;<\/li>\n\n\n\n<li>Multiple ESP32 boards sending and receiving data from multiple ESP32 boards to create something that looks like a network.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Basic Concepts in ESP-NOW<\/h3>\n\n\n\n<p>There are a few basic concepts you need to understand in ESP-NOW:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Sender<\/strong>: the device that sends data using ESP-NOW.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Receiver<\/strong>: the device that receives the data sent by the sender.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>MAC Address<\/strong>: a unique 6-byte hardware address assigned to each device\u2019s Wi-Fi interface. ESP-NOW uses MAC addresses to identify devices. If you want to send data to a specific board, you need to know its MAC address.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Broadcast MAC Address<\/strong>: a MAC address like this FF:FF:FF:FF:FF:FF is used to send a message to all nearby devices. Any ESP32 or ESP8266 in range can receive it.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Peer<\/strong>: a specific device (identified by its MAC address) that you register on your ESP-NOW device so that it can send or receive data with that device.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Packet<\/strong>: the data sent from one device to another. ESP-NOW packets can carry up to 250 bytes of data.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Requirements for ESP-NOW<\/h3>\n\n\n\n<p>Before using ESP-NOW, there are a few important requirements:<\/p>\n\n\n\n<p><strong>Same Wi-Fi channel<\/strong>: all devices communicating via ESP-NOW must be on the same Wi-Fi channel. If they&#8217;re not, they won&#8217;t be able to receive and send packets to one another. Usually, this is done automatically in the code, unless one of the devices is also connected to a Wi-Fi network.<\/p>\n\n\n\n<p><strong>MAC address<\/strong>: to send messages to a specific device, the sender must know the receiver&#8217;s MAC address in advance.<\/p>\n\n\n\n<p><strong>Registration of peers<\/strong>: you must register a peer before sending data to it, except when using the broadcast MAC address on ESP32 boards.<\/p>\n\n\n\n<p><strong>Wi-Fi<\/strong>: the Wi-Fi interface (station or access point mode) must be active, even if not connected.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32: Getting Board MAC Address<\/h2>\n\n\n\n<p>To communicate via ESP-NOW, you need to know the MAC address of your boards. To get your board\u2019s MAC Address, you can copy the following code to Thonny IDE and run it on your board.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Rui Santos &amp; Sara Santos - Random Nerd Tutorials\r\n# Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-esp-now-esp32\/\r\n \r\nimport network\r\n\r\nwlan = network.WLAN(network.STA_IF)\r\nwlan.active(True)\r\n\r\n# Get MAC address (returns bytes)\r\nmac = wlan.config('mac')\r\n\r\n# Convert to human-readable format\r\nmac_address = ':'.join('%02x' % b for b in mac)\r\n\r\nprint(&quot;MAC Address:&quot;, mac_address)<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/esp32_get_mac_address.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>After running the code, it should print the board&#8217;s MAC address on the shell.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"707\" height=\"298\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/thonny-ide-get-board-mac-address.png?resize=707%2C298&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Thonny IDE - Get ESP32 Board MAC Address - MicroPython\" class=\"wp-image-170329\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/thonny-ide-get-board-mac-address.png?w=707&amp;quality=100&amp;strip=all&amp;ssl=1 707w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/thonny-ide-get-board-mac-address.png?resize=300%2C126&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 707px) 100vw, 707px\" \/><\/figure><\/div>\n\n\n<p>We recommend that you add a label or sticker to each board so that you can clearly identify them.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-ESP-NOW-Micropython-Point-to-Point-Communication-Example.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP-NOW MicroPython Point to Point Communication\" class=\"wp-image-170359\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-ESP-NOW-Micropython-Point-to-Point-Communication-Example.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-ESP-NOW-Micropython-Point-to-Point-Communication-Example.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">ESP-NOW One-way Point to Point Communication (espnow module)<\/h2>\n\n\n\n<p>To get you started with ESP-NOW wireless communication, we\u2019ll build a simple project that shows how to send a message from one ESP32 to another. One ESP32 will be the \u201c<strong>sender<\/strong>\u201d and the other ESP32 will be the \u201c<strong>receiver<\/strong>\u201d.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_way_communication_two_boards.png?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP-NOW One-Way Communication\" class=\"wp-image-93050\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_way_communication_two_boards.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/ESP_NOW_one_way_communication_two_boards.png?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">ESP32 Sender Code (ESP-NOW with MicroPython)<\/h3>\n\n\n\n<p>The following code sends a message every second to an ESP32 receiver board. Copy it to your Thonny IDE and then run it or upload it to the board.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Rui Santos &amp; Sara Santos - Random Nerd Tutorials\r\n# Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-esp-now-esp32\/\r\n\r\nimport network\r\nimport espnow\r\nimport time\r\n\r\n# Stats tracking\r\nlast_stats_time = time.time()\r\nstats_interval = 10  # Print stats every 10 seconds\r\n\r\n# Initialize Wi-Fi in station mode\r\nsta = network.WLAN(network.STA_IF)\r\nsta.active(True)\r\n#sta.config(channel=1)  # Set channel explicitly if packets are not delivered\r\nsta.disconnect()\r\n\r\n# Initialize ESP-NOW\r\ne = espnow.ESPNow()\r\ntry:\r\n    e.active(True)\r\nexcept OSError as err:\r\n    print(&quot;Failed to initialize ESP-NOW:&quot;, err)\r\n    raise\r\n\r\n# Receiver's MAC address\r\nreceiver_mac = b'\\x30\\xae\\xa4\\xf6\\x7d\\x4c'\r\n#receiver_mac = b'\\xff\\xff\\xff\\xff\\xff\\xff' #broadcast\r\n\r\n# Add peer\r\ntry:\r\n    e.add_peer(receiver_mac)\r\nexcept OSError as err:\r\n    print(&quot;Failed to add peer:&quot;, err)\r\n    raise\r\n\r\ndef print_stats():\r\n    stats = e.stats()\r\n    print(&quot;\\nESP-NOW Statistics:&quot;)\r\n    print(f&quot;  Packets Sent: {stats[0]}&quot;)\r\n    print(f&quot;  Packets Delivered: {stats[1]}&quot;)\r\n    print(f&quot;  Packets Dropped (TX): {stats[2]}&quot;)\r\n    print(f&quot;  Packets Received: {stats[3]}&quot;)\r\n    print(f&quot;  Packets Dropped (RX): {stats[4]}&quot;)\r\n    \r\n# Main loop to send messages\r\nmessage_count = 0\r\nwhile True:\r\n    try:\r\n        # Create a sample message with a counter\r\n        message = f&quot;Hello! ESP-NOW message #{message_count}&quot;\r\n        # Send the message with acknowledgment\r\n        try:\r\n            if e.send(receiver_mac, message, True):\r\n                print(f&quot;Sent message: {message}&quot;)\r\n            else:\r\n                print(&quot;Failed to send message (send returned False)&quot;)\r\n        except OSError as err:\r\n            print(f&quot;Failed to send message (OSError: {err})&quot;)\r\n        \r\n        message_count += 1\r\n        \r\n        # Print stats every 10 seconds\r\n        if time.time() - last_stats_time &gt;= stats_interval:\r\n            print_stats()\r\n            last_stats_time = time.time()\r\n        \r\n        time.sleep(1)  # Send every 1 second\r\n        \r\n    except OSError as err:\r\n        print(&quot;Error:&quot;, err)\r\n        time.sleep(5)\r\n        \r\n    except KeyboardInterrupt:\r\n        print(&quot;Stopping sender...&quot;)\r\n        e.active(False)\r\n        sta.active(False)\r\n        break<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/esp32_espnow_sender.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>You need to insert the receiver board&#8217;s MAC address or use the broadcast MAC address. <\/p>\n\n\n\n<p>In my case, the receiver board MAC address is <span class=\"rnthl rntliteral\">30:AE:A4:F6:7D:4C<\/span>. So, I need to convert it to bytes format as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">30:AE:A4:F6:7D:4C<\/span> &gt; <span class=\"rnthl rntliteral\">b&#8217;\\x30\\xae\\xa4\\xf6\\x7d\\x4c&#8217;<\/span><\/li>\n<\/ul>\n\n\n\n<p>Do the same for your receiver board&#8217;s MAC address.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Receiver's MAC address\nreceiver_mac = b'\\x30\\xae\\xa4\\xf6\\x7d\\x4c'<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>Let&#8217;s take a quick look at how the code works and the most relevant ESP-NOW functions.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Importing Modules<\/h4>\n\n\n\n<p>First, import the required modules. For this example, we&#8217;re using the <span class=\"rnthl rntliteral\">espnow<\/span> module to use ESP-NOW functions and classes.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>import network\nimport espnow\nimport time<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Initialize the Wi-Fi Interface<\/h4>\n\n\n\n<p>Then, we need to initialize Wi-Fi (even if we don&#8217;t use it) to use ESP-NOW. We can use station (<span class=\"rnthl rntliteral\">STA_IF<\/span>) or access point mode (<span class=\"rnthl rntliteral\">AP_IF<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Initialize Wi-Fi in station mode\nsta = network.WLAN(network.STA_IF)\nsta.active(True)\n#sta.config(channel=1)  # Set channel explicitly if packets are not delivered\nsta.disconnect()<\/code><\/pre>\n\n\n\n<p>Later, when testing if the packets are not being delivered, you may need to manually explicit which Wi-Fi channel to use. It must be the same on both the receiver and sender boards.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>#sta.config(channel=1)  # Set channel explicitly if packets are not delivered<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Initialize ESP-NOW<\/h4>\n\n\n\n<p>Then, we can initialize ESP-NOW. First, create an <span class=\"rnthl rntliteral\">espnow<\/span> instance called <span class=\"rnthl rntliteral\">e<\/span>. Then activate it using the <span class=\"rnthl rntliteral\">active()<\/span> method and passing the <span class=\"rnthl rntliteral\">True<\/span> value as argument.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Initialize ESP-NOW\ne = espnow.ESPNow()\ntry:\n    e.active(True)\nexcept OSError as err:\n    print(\"Failed to initialize ESP-NOW:\", err)\n    raise<\/code><\/pre>\n\n\n\n<p>To deactivate ESP-NOW, pass <span class=\"rnthl rntliteral\">False<\/span> to the <span class=\"rnthl rntliteral\">active()<\/span> method. If you use the <span class=\"rnthl rntliteral\">active()<\/span> method without any arguments, it will return the current ESP-NOW state.<\/p>\n\n\n\n<p>We activate ESP-NOW inside a <span class=\"rnthl rntliteral\">try<\/span> and <span class=\"rnthl rntliteral\">except<\/span> statements so that we can catch any errors if the initialization fails.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Add ESP-NOW Peer<\/h4>\n\n\n\n<p>Add the receiver MAC address (or use the broadcast MAC address to send the message to all devices within its range):<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Receiver's MAC address\nreceiver_mac = b'\\x30\\xae\\xa4\\xf6\\x7d\\x4c'\n#receiver_mac = b'\\xff\\xff\\xff\\xff\\xff\\xff' #broadcast<\/code><\/pre>\n\n\n\n<p>Then, we can add the receiver&#8217;s MAC address as a peer using the <span class=\"rnthl rntliteral\">add_peer()<\/span> method.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Add peer\ntry:\n    e.add_peer(receiver_mac)\nexcept OSError as err:\n    print(\"Failed to add peer:\", err)\n    raise<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Print ESP-NOW Statistics<\/h4>\n\n\n\n<p>Then, we create a function to call later in the code, called <span class=\"rnthl rntliteral\">print_stats()<\/span> that prints current statistics about the ESP-NOW packets. To get the number of packets sent\/received and lost, we can call the <span class=\"rnthl rntliteral\">stats()<\/span> method on the ESP-NOW <span class=\"rnthl rntliteral\">e<\/span> object.<\/p>\n\n\n\n<p>This returns a 5-tuple containing the number of packets sent\/received\/lost:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>(tx_pkts, tx_responses, tx_failures, rx_packets, rx_dropped_packets)<\/code><\/pre>\n\n\n\n<p>Then, we print each of those results:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>print(\"\\nESP-NOW Statistics:\")\nprint(f\"  Packets Sent: {stats&#091;0]}\")\nprint(f\"  Packets Delivered: {stats&#091;1]}\")\nprint(f\"  Packets Dropped (TX): {stats&#091;2]}\")\nprint(f\"  Packets Received: {stats&#091;3]}\")\nprint(f\"  Packets Dropped (RX): {stats&#091;4]}\")<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Sending ESP-NOW Message<\/h4>\n\n\n\n<p>We create a main loop to send a message with a counter (<span class=\"rnthl rntliteral\">message_count<\/span>) every second.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>message_count = 0\nwhile True:\n    try:\n        # Create a sample message with a counter\n        message = f\"Hello! ESP-NOW message #{message_count}\"<\/code><\/pre>\n\n\n\n<p>We send the message using the <span class=\"rnthl rntliteral\">send()<\/span> method on the ESP-NOW <span class=\"rnthl rntliteral\">e<\/span> object. This function accepts as arguments the receiver board&#8217;s MAC address, the message, and the last parameter is a boolean value (<span class=\"rnthl rntliteral\">True<\/span> to send a message to the peer and wait for a response; or <span class=\"rnthl rntliteral\">False<\/span> to return immediately).<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>try:\n    if e.send(receiver_mac, message, True):\n        print(f\"Sent message: {message}\")\n    else:\n        print(\"Failed to send message (send returned False)\")\nexcept OSError as err:\n    print(f\"Failed to send message (OSError: {err})\")<\/code><\/pre>\n\n\n\n<p>After sending the message, we increment the counter and check if it&#8217;s time to print new statistics.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Print stats every 10 seconds\nif time.time() - last_stats_time &gt;= stats_interval:\n    print_stats()\n    last_stats_time = time.time()\n        \ntime.sleep(1)  # Send every 1 second<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">In summary&#8230;<\/h4>\n\n\n\n<p>In summary, these are the steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Initialize the Wi-Fi interface;<\/li>\n\n\n\n<li>Initialize ESP-NOW;<\/li>\n\n\n\n<li>Add a Peer;<\/li>\n\n\n\n<li>Send a Message.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Running the Code<\/h3>\n\n\n\n<p>After connecting the board to your computer and establishing a communication with Thonny IDE, you can upload the code as <span class=\"rnthl rntliteral\">main.py<\/span> to the board or run it using the green Run button.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"470\" height=\"114\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/12\/thonny-ide-run-button.png?resize=470%2C114&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Thonny IDE run script micropython\" class=\"wp-image-144594\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/12\/thonny-ide-run-button.png?w=470&amp;quality=100&amp;strip=all&amp;ssl=1 470w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/12\/thonny-ide-run-button.png?resize=300%2C73&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 470px) 100vw, 470px\" \/><\/figure><\/div>\n\n\n<p>It will start printing messages in the Shell. It will fail to send the message because we haven&#8217;t prepared the receiver yet.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"729\" height=\"270\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-Sender-ESP32-Micropython-Failed-to-send-packet.png?resize=729%2C270&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32-ESP-NOW Send Packet Failed Micropython\" class=\"wp-image-170334\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-Sender-ESP32-Micropython-Failed-to-send-packet.png?w=729&amp;quality=100&amp;strip=all&amp;ssl=1 729w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-Sender-ESP32-Micropython-Failed-to-send-packet.png?resize=300%2C111&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 729px) 100vw, 729px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">ESP32 Receiver Code (ESP-NOW with MicroPython)<\/h3>\n\n\n\n<p>The following code listens for incoming ESP-NOW packets from its peer (the sender board we programmed previously). Open another window of Thonny IDE (independent of the first one). <\/p>\n\n\n\n<div class=\"wp-block-group rntbox rntclgray\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p><strong>Enabling Two Instances of Thonny IDE<\/strong><\/p>\n\n\n\n<p>Go to <strong>Tools <\/strong>&gt; <strong>Options <\/strong>and untick the option <em>Allow only single Thonny instance<\/em>.<\/p>\n<\/div><\/div>\n\n\n\n<p>Copy the code to your Thonny IDE and then run it or upload it to the board.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Rui Santos &amp; Sara Santos - Random Nerd Tutorials\r\n# Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-esp-now-esp32\/\r\n\r\nimport network\r\nimport espnow\r\nimport time\r\n\r\n# Stats tracking\r\nlast_stats_time = time.time()\r\nstats_interval = 10  # Print stats every 10 seconds\r\n\r\n# Initialize Wi-Fi in station mode\r\nsta = network.WLAN(network.STA_IF)\r\nsta.active(True)\r\nsta.config(channel=1)  # Set channel explicitly if packets are not received\r\nsta.disconnect()\r\n\r\n# Initialize ESP-NOW\r\ne = espnow.ESPNow()\r\ntry:\r\n    e.active(True)\r\nexcept OSError as err:\r\n    print(&quot;Failed to initialize ESP-NOW:&quot;, err)\r\n    raise\r\n\r\n# Sender's MAC address\r\nsender_mac = b'\\x30\\xae\\xa4\\x07\\x0d\\x64'  # Sender MAC\r\n\r\n# Add peer (sender) for unicast reliability\r\n# You don't need to add peer for broadcast\r\n#try:\r\n#    e.add_peer(sender_mac)\r\n#except OSError as err:\r\n#    print(&quot;Failed to add peer:&quot;, err)\r\n#    raise\r\n\r\ndef print_stats():\r\n    stats = e.stats()\r\n    print(&quot;\\nESP-NOW Statistics:&quot;)\r\n    print(f&quot;  Packets Sent: {stats[0]}&quot;)\r\n    print(f&quot;  Packets Delivered: {stats[1]}&quot;)\r\n    print(f&quot;  Packets Dropped (TX): {stats[2]}&quot;)\r\n    print(f&quot;  Packets Received: {stats[3]}&quot;)\r\n    print(f&quot;  Packets Dropped (RX): {stats[4]}&quot;)\r\n\r\nprint(&quot;Listening for ESP-NOW messages...&quot;)\r\nwhile True:\r\n    try:\r\n        # Receive message (host MAC, message, timeout of 10 seconds)\r\n        host, msg = e.recv(10000)\r\n        \r\n        # Print stats every 10 seconds\r\n        if time.time() - last_stats_time &gt;= stats_interval:\r\n            print_stats()\r\n            last_stats_time = time.time()\r\n        \r\n    except OSError as err:\r\n        print(&quot;Error:&quot;, err)\r\n        time.sleep(5)\r\n        \r\n    except KeyboardInterrupt:\r\n        print(&quot;Stopping receiver...&quot;)\r\n        e.active(False)\r\n        sta.active(False)\r\n        break<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/esp32_espnow_receiver.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>The code is similar to the sender board. The only difference is the loop, where we&#8217;ll listen for incoming packets.<\/p>\n\n\n\n<p>Inserting the Sender Board&#8217;s MAC address and add it as a peer is <strong>optional<\/strong>. However, it&#8217;s good to implement it for better reliability, especially if you&#8217;re not receiving the packets.<\/p>\n\n\n\n<p>In my case, the sender board MAC address is <span class=\"rnthl rntliteral\">30:AE:A4:07:0D:64<\/span>. So, I need to convert it to bytes format as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">30:AE:A4:07:0D:64<\/span> &gt; <span class=\"rnthl rntliteral\">b&#8217;\\x30\\xae\\xa4\\x07\\x0d\\x64&#8242;<\/span><\/li>\n<\/ul>\n\n\n\n<p>Do the same for your sender board&#8217;s MAC address.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Sender's MAC address<br>sender_mac = b'\\x30\\xae\\xa4\\x07\\x0d\\x64'  # Sender MAC<\/code><\/pre>\n\n\n\n<p>If you want to add the sender as a peer, uncommend the following part of the code:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>#try:\n#    e.add_peer(sender_mac)\n#except OSError as err:\n#    print(\"Failed to add peer:\", err)\n#    raise<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Receiving ESP-NOW Messages<\/h4>\n\n\n\n<p>To receive messages, we can use the <span class=\"rnthl rntliteral\">recv()<\/span> method on the ESP-NOW <span class=\"rnthl rntliteral\">e<\/span> object. <\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>host, msg = e.recv(10000)<\/code><\/pre>\n\n\n\n<p>This method waits for an incoming message and returns the mac address of the peer (saved in the <span class=\"rnthl rntliteral\">host<\/span> variable) and the message (saved in the <span class=\"rnthl rntliteral\">msg<\/span> variable). It is not necessary to register a peer (using <span class=\"rnthl rntliteral\">add_peer()<\/span>) to receive a message from that peer.<\/p>\n\n\n\n<p>It accepts as arguments the timeout in milliseconds. The timeout refers to the amount of time the function will wait to receive an incoming message before giving up and returning. It can have the following values<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>0: No timeout. Return immediately if no data is available.<\/li>\n\n\n\n<li>&gt; 0: specify a timeout value in milliseconds;<\/li>\n\n\n\n<li>&lt; 0: do not timeout: wait forever for new messages;<\/li>\n\n\n\n<li>None: uses the default timeout value set with <span class=\"rnthl rntliteral\">ESPNOW.config()<\/span><\/li>\n<\/ul>\n\n\n\n<p>When we receive a new message, we print the host MAC address and the message.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>if msg:\n    print(f\"Received from {host.hex()}: {msg.decode()}\")<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Running the Code<\/h3>\n\n\n\n<p>With a new window on Thonny IDE open, establish a connection with this receiver board. Upload and\/or run the receiver code on this new board.<\/p>\n\n\n\n<p>It will start receiving the ESP-NOW packets from the other board.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"471\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-MicroPython-ESP-NOW-Receiver.png?resize=730%2C471&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with MicroPython ESP-NOW Receiver\" class=\"wp-image-170335\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-MicroPython-ESP-NOW-Receiver.png?w=730&amp;quality=100&amp;strip=all&amp;ssl=1 730w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-MicroPython-ESP-NOW-Receiver.png?resize=300%2C194&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 730px) 100vw, 730px\" \/><\/figure><\/div>\n\n\n<p>At the same time, you&#8217;ll see that the sender board will print success messages now.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"729\" height=\"468\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-MicroPython-ESP-NOW-Sender.png?resize=729%2C468&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 MicroPython - ESP-NOW Sender\" class=\"wp-image-170336\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-MicroPython-ESP-NOW-Sender.png?w=729&amp;quality=100&amp;strip=all&amp;ssl=1 729w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP32-MicroPython-ESP-NOW-Sender.png?resize=300%2C193&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 729px) 100vw, 729px\" \/><\/figure><\/div>\n\n\n<p>Every 10 seconds, the sender and receiver print the ESP-NOW statistics on the shell.<\/p>\n\n\n\n<p>You can combine the functions used in both sketches and establish a two-way communication. You can also add more boards to your setup and create a network.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP-NOW One-way Point to Point Communication (aioespnow module)<\/h2>\n\n\n\n<p>There is another module that supports ESP-NOW asynchronously using the <span class=\"rnthl rntliteral\">asyncio<\/span> module\u2014it is the <span class=\"rnthl rntliteral\">aioespnow<\/span> module. In this section, we&#8217;ll create the same example as the previous one, but using the <span class=\"rnthl rntliteral\">aioespnow<\/span> module, which supports asynchronous programming.<\/p>\n\n\n\n<p class=\"rntbox rntclblue\">Before proceeding, we recommend learning about asynchronous programming with MicroPython: <a href=\"https:\/\/randomnerdtutorials.com\/micropython-esp32-esp8266-asynchronous-programming\/\">MicroPython: ESP32\/ESP8266 Asynchronous Programming \u2013 Run Multiple Tasks<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ESP32 Sender Code (ESP-NOW with MicroPython)<\/h3>\n\n\n\n<p>The following code does the same as the one in the previous example, but it uses the <span class=\"rnthl rntliteral\">aioespnow<\/span> module if you want to use asynchronous programming instead.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Rui Santos &amp; Sara Santos - Random Nerd Tutorials\r\n# Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-esp-now-esp32\/\r\n \r\nimport network\r\nimport aioespnow\r\nimport asyncio\r\nimport time\r\n\r\n# Stats tracking\r\nlast_stats_time = time.time()\r\nstats_interval = 10  # Print stats every 10 seconds\r\n\r\n# Initialize Wi-Fi in station mode\r\nsta = network.WLAN(network.STA_IF)\r\nsta.active(True)\r\nsta.disconnect()\r\n\r\n# Initialize AIOESPNow\r\ne = aioespnow.AIOESPNow()\r\ntry:\r\n    e.active(True)\r\nexcept OSError as err:\r\n    print(&quot;Failed to initialize AIOESPNow:&quot;, err)\r\n    raise\r\n\r\n# Receiver's MAC address (broadcast for testing)\r\n#receiver_mac = b'\\x30\\x0e\\xa4\\xf6\\x7d\\x4c'\r\nreceiver_mac = b'\\xff\\xff\\xff\\xff\\xff\\xff'\r\n\r\n# Add peer\r\ntry:\r\n    e.add_peer(receiver_mac)\r\nexcept OSError as err:\r\n    print(&quot;Failed to add peer:&quot;, err)\r\n    raise\r\n\r\ndef print_stats():\r\n    stats = e.stats()\r\n    print(&quot;\\nESP-NOW Statistics:&quot;)\r\n    print(f&quot;  Packets Sent: {stats[0]}&quot;)\r\n    print(f&quot;  Packets Delivered: {stats[1]}&quot;)\r\n    print(f&quot;  Packets Dropped (TX): {stats[2]}&quot;)\r\n    print(f&quot;  Packets Received: {stats[3]}&quot;)\r\n    print(f&quot;  Packets Dropped (RX): {stats[4]}&quot;)\r\n\r\n# Async function to send messages\r\nasync def send_messages(e, peer):\r\n    message_count = 0\r\n    while True:\r\n        try:\r\n            message = f&quot;Hello! AIOESPNow message #{message_count}&quot;\r\n            if await e.asend(peer, message, sync=True):\r\n                print(f&quot;Sent message: {message}&quot;)\r\n            else:\r\n                print(&quot;Failed to send message&quot;)\r\n            \r\n            message_count += 1\r\n            \r\n            # Print stats every 10 seconds\r\n            if time.time() - last_stats_time &gt;= stats_interval:\r\n                print_stats()\r\n            \r\n            await asyncio.sleep(1)  # Send every 1 second\r\n        \r\n        except OSError as err:\r\n            print(&quot;Error:&quot;, err)\r\n            await asyncio.sleep(5)\r\n\r\n# Main async function\r\nasync def main(e, peer):\r\n    await send_messages(e, peer)\r\n\r\n# Run the async program\r\ntry:\r\n    asyncio.run(main(e, receiver_mac))\r\nexcept KeyboardInterrupt:\r\n    print(&quot;Stopping sender...&quot;)\r\n    e.active(False)\r\n    sta.active(False)<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/esp32_espnow_sender_asyncio.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ESP32 Receiver Code (ESP-NOW with MicroPython)<\/h3>\n\n\n\n<p>Similarly, the following code receives incoming ESP-NOW packets from the sender board, but it uses the <span class=\"rnthl rntliteral\">aioespnow<\/span> module for asynchronous programming.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Rui Santos &amp; Sara Santos - Random Nerd Tutorials\r\n# Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-esp-now-esp32\/\r\n\r\nimport network\r\nimport aioespnow\r\nimport asyncio\r\nimport time\r\n\r\n# Initialize Wi-Fi in station mode\r\nsta = network.WLAN(network.STA_IF)\r\nsta.active(True)\r\nsta.config(channel=1)  # Set channel explicitly if packets are not received\r\nsta.disconnect()\r\n\r\n# Initialize AIOESPNow\r\ne = aioespnow.AIOESPNow()\r\ntry:\r\n    e.active(True)\r\nexcept OSError as err:\r\n    print(&quot;Failed to initialize AIOESPNow:&quot;, err)\r\n    raise\r\n\r\n# Sender's MAC address\r\nsender_mac = b'\\x30\\xae\\xa4\\x07\\x0d\\x64'  # Sender MAC for unicast\r\n\r\n# Add peer (sender) for unicast reliability\r\n# You don't need to add peer for broadcast\r\n#try:\r\n#    e.add_peer(sender_mac)\r\n#except OSError as err:\r\n#    print(&quot;Failed to add peer:&quot;, err)\r\n#    raise\r\n\r\n# Async function to receive messages\r\nasync def receive_messages(e):\r\n    while True:\r\n        try:\r\n            async for mac, msg in e:\r\n                print(f&quot;Received from {mac.hex()}: {msg.decode()}&quot;)\r\n        except OSError as err:\r\n            print(&quot;Error:&quot;, err)\r\n            await asyncio.sleep(5)\r\n\r\n# Async function to print stats periodically\r\nasync def print_stats(e):\r\n    global last_stats_time\r\n    last_stats_time = time.time()\r\n    stats_interval = 10  # Print stats every 10 seconds\r\n    while True:\r\n        if time.time() - last_stats_time &gt;= stats_interval:\r\n            stats = e.stats()\r\n            print(&quot;\\nESP-NOW Statistics:&quot;)\r\n            print(f&quot;  Packets Sent: {stats[0]}&quot;)\r\n            print(f&quot;  Packets Delivered: {stats[1]}&quot;)\r\n            print(f&quot;  Packets Dropped (TX): {stats[2]}&quot;)\r\n            print(f&quot;  Packets Received: {stats[3]}&quot;)\r\n            print(f&quot;  Packets Dropped (RX): {stats[4]}&quot;)\r\n            last_stats_time = time.time()\r\n        await asyncio.sleep(1)  # Check every second\r\n\r\n# Main async function\r\nasync def main(e):\r\n    # Run receive and stats tasks concurrently\r\n    await asyncio.gather(receive_messages(e), print_stats(e))\r\n\r\n# Run the async program\r\ntry:\r\n    asyncio.run(main(e))\r\nexcept KeyboardInterrupt:\r\n    print(&quot;Stopping receiver...&quot;)\r\n    e.active(False)\r\n    sta.active(False)<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/esp32_espnow_receiver_asyncio.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>For more information about ESP-NOW modules, functions, and classes for MicroPython, check the <a href=\"https:\/\/docs.micropython.org\/en\/latest\/library\/espnow.html\" target=\"_blank\" rel=\"noopener\" title=\"\">documentation<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, we introduced you to the basics of ESP-NOW communication protocol with the ESP32 programmed with MicroPython.<\/p>\n\n\n\n<p>ESP-NOW is a very versatile protocol that can be useful to transfer data wirelessly between boards, like <a href=\"https:\/\/randomnerdtutorials.com\/esp32-guides-sensors-modules\/\" title=\"\">sensor readings<\/a>, or commands to control outputs. You can add multiple ESP32 boards to your setup and create a network of boards that exchange data between them.<\/p>\n\n\n\n<p>If you&#8217;re interested in this topic, we can create more tutorials about ESP-NOW with MicroPython. Let us know in the comments section.<\/p>\n\n\n\n<p>To learn more about MicroPython, you can check out our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\" title=\"\">MicroPython Programming with ESP32 and ESP8266 eBook (2nd Edition)<\/a><\/li>\n\n\n\n<li><strong><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32-esp8266-micropython\/\" title=\"\">All Our MicroPython Tutorials, Projects, and Guides<\/a><\/strong><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to use ESP-NOW communication protocol with the ESP32 programmed with MicroPython. ESP-NOW is a connectionless communication protocol created by Espressif, designed for short packet transmission. It is one &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"MicroPython: ESP-NOW with ESP32 (Getting Started)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/micropython-esp-now-esp32\/#more-170305\" aria-label=\"Read more about MicroPython: ESP-NOW with ESP32 (Getting Started)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":170341,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[310,309,264],"tags":[],"class_list":["post-170305","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-micropython","category-0-esp32-micropython","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-NOW-MicroPython-ESP32-Getting-Started.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/170305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=170305"}],"version-history":[{"count":15,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/170305\/revisions"}],"predecessor-version":[{"id":171651,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/170305\/revisions\/171651"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/170341"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=170305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=170305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=170305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}