Pelajari cara menggunakan protokol komunikasi ESP-NOW pada ESP32 yang diprogram menggunakan MicroPython. ESP-NOW adalah protokol komunikasi tanpa koneksi (connectionless) yang dikembangkan oleh Espressif, dirancang untuk transmisi paket data singkat. Protokol ini menjadi salah satu cara termudah untuk melakukan komunikasi nirkabel antar papan ESP32. Saat ini, firmware MicroPython untuk ESP32 sudah menyertakan dua modul bawaan, yaitu espnow dan aioespnow, yang menyediakan kelas dan fungsi khusus untuk bekerja dengan ESP-NOW.
Memperkenalkan ESP-NOW
ESP-NOW adalah protokol komunikasi nirkabel yang dikembangkan oleh Espressif, memungkinkan beberapa papan ESP32 atau ESP8266 bertukar data dalam jumlah kecil tanpa memerlukan koneksi Wi-Fi penuh atau Bluetooth. Meskipun pengendali Wi-Fi harus aktif, ESP-NOW tidak memerlukan koneksi Wi-Fi penuh, sehingga sangat ideal untuk aplikasi berdaya rendah dan latensi rendah, seperti jaringan sensor, remote control, atau pertukaran data antar papan.
ESP-NOW menggunakan model komunikasi tanpa koneksi (connectionless), artinya perangkat dapat mengirim dan menerima data tanpa terhubung ke router atau membuat access point (tidak seperti komunikasi HTTP antar papan). Protokol ini mendukung unicast (mengirim data ke perangkat tertentu menggunakan alamat MAC) dan broadcast (mengirim data ke semua perangkat terdekat menggunakan alamat MAC broadcast).
Fitur utama ESP-NOW antara lain:
- Mendukung komunikasi unicast terenkripsi maupun tidak terenkripsi.
- Komunikasi langsung dengan hingga 20 peer terdaftar atau 6 peer terenkripsi.
- Bisa berkomunikasi dengan perangkat terenkripsi dan tidak terenkripsi secara bersamaan.
- Mengizinkan pengiriman paket data hingga 250 byte.
ESP-NOW sangat fleksibel dan memungkinkan komunikasi satu arah maupun dua arah dalam berbagai konfigurasi. Contohnya:
- Satu papan ESP32 mengirim data ke papan ESP32 lain
- Komunikasi dua arah ESP-NOW antara dua papan
- Satu papan ESP32 menerima data dari beberapa papan
- Satu papan ESP32 mengirim data ke beberapa papan
- Beberapa papan ESP32 saling mengirim dan menerima data antar papan, membentuk semacam jaringan sederhana.
Konsep Dasar dalam ESP-NOW
Beberapa konsep dasar yang perlu dipahami dalam ESP-NOW antara lain:
- Sender (Pengirim): perangkat yang mengirim data menggunakan ESP-NOW.
- Receiver (Penerima): perangkat yang menerima data yang dikirim oleh pengirim.
- MAC Address: alamat hardware unik 6-byte yang diberikan pada setiap antarmuka Wi-Fi perangkat. ESP-NOW menggunakan MAC address untuk mengidentifikasi perangkat. Jika ingin mengirim data ke papan tertentu, Anda perlu mengetahui MAC address papan tersebut.
- Broadcast MAC Address: alamat MAC seperti `FF:FF:FF:FF:FF:FF` digunakan untuk mengirim pesan ke semua perangkat di sekitarnya. Semua ESP32 atau ESP8266 dalam jangkauan dapat menerimanya.
- Peer: perangkat tertentu (diidentifikasi melalui MAC address) yang didaftarkan pada perangkat ESP-NOW Anda agar bisa mengirim atau menerima data.
- Packet (Paket): data yang dikirim dari satu perangkat ke perangkat lain. Paket ESP-NOW dapat membawa data hingga 250 byte.
Persyaratan untuk ESP-NOW
Sebelum menggunakan ESP-NOW, ada beberapa persyaratan penting yang perlu diperhatikan:
- Saluran Wi-Fi yang sama: semua perangkat yang berkomunikasi melalui ESP-NOW harus berada pada saluran Wi-Fi yang sama. Jika tidak, perangkat tidak akan dapat mengirim atau menerima paket data. Biasanya pengaturan ini dilakukan otomatis melalui kode, kecuali salah satu perangkat juga terhubung ke jaringan Wi-Fi.
- MAC Address: untuk mengirim pesan ke perangkat tertentu, pengirim harus mengetahui MAC address penerima sebelumnya.
- Pendaftaran peer: Anda harus mendaftarkan peer sebelum mengirim data ke perangkat tersebut, kecuali saat menggunakan broadcast MAC address pada papan ESP32.
- Wi-Fi aktif: antarmuka Wi-Fi (mode station atau access point) harus aktif, meskipun perangkat tidak terhubung ke jaringan Wi-Fi.
ESP32: Mendapatkan MAC Address Papan
Untuk berkomunikasi menggunakan ESP-NOW, Anda perlu mengetahui MAC address setiap papan ESP32. Untuk mendapatkan MAC address papan Anda, salin kode berikut ke Thonny IDE dan jalankan pada papan ESP32 tersebut.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/micropython-esp-now-esp32/
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Get MAC address (returns bytes)
mac = wlan.config('mac')
# Convert to human-readable format
mac_address = ':'.join('%02x' % b for b in mac)
print("MAC Address:", mac_address)
Setelah menjalankan kode, MAC address papan akan ditampilkan di jendela shell.
Kami menyarankan untuk menambahkan label atau stiker pada setiap papan agar Anda dapat mengidentifikasi masing-masing papan dengan jelas.
Komunikasi Satu Arah Point-to-Point dengan ESP-NOW (modul `espnow`)
Untuk memulai komunikasi nirkabel menggunakan ESP-NOW, kita akan membuat proyek sederhana yang menunjukkan cara mengirim pesan dari satu ESP32 ke ESP32 lainnya. Satu papan ESP32 akan berperan sebagai “pengirim” (sender), dan papan ESP32 lainnya akan menjadi “penerima” (receiver).
Kode ESP32 Pengirim (ESP-NOW dengan MicroPython)
Kode berikut akan mengirim pesan setiap satu detik ke papan ESP32 penerima. Salin kode ini ke Thonny IDE, lalu jalankan atau unggah ke papan ESP32 Anda.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/micropython-esp-now-esp32/
import network
import espnow
import time
# Stats tracking
last_stats_time = time.time()
stats_interval = 10 # Print stats every 10 seconds
# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
#sta.config(channel=1) # Set channel explicitly if packets are not delivered
sta.disconnect()
# Initialize ESP-NOW
e = espnow.ESPNow()
try:
e.active(True)
except OSError as err:
print("Failed to initialize ESP-NOW:", err)
raise
# Receiver's MAC address
receiver_mac = b'\x30\xae\xa4\xf6\x7d\x4c'
#receiver_mac = b'\xff\xff\xff\xff\xff\xff' #broadcast
# Add peer
try:
e.add_peer(receiver_mac)
except OSError as err:
print("Failed to add peer:", err)
raise
def print_stats():
stats = e.stats()
print("\nESP-NOW Statistics:")
print(f" Packets Sent: {stats[0]}")
print(f" Packets Delivered: {stats[1]}")
print(f" Packets Dropped (TX): {stats[2]}")
print(f" Packets Received: {stats[3]}")
print(f" Packets Dropped (RX): {stats[4]}")
# Main loop to send messages
message_count = 0
while True:
try:
# Create a sample message with a counter
message = f"Hello! ESP-NOW message #{message_count}"
# Send the message with acknowledgment
try:
if e.send(receiver_mac, message, True):
print(f"Sent message: {message}")
else:
print("Failed to send message (send returned False)")
except OSError as err:
print(f"Failed to send message (OSError: {err})")
message_count += 1
# Print stats every 10 seconds
if time.time() - last_stats_time >= stats_interval:
print_stats()
last_stats_time = time.time()
time.sleep(1) # Send every 1 second
except OSError as err:
print("Error:", err)
time.sleep(5)
except KeyboardInterrupt:
print("Stopping sender...")
e.active(False)
sta.active(False)
break
Anda perlu memasukkan MAC address papan penerima atau menggunakan broadcast MAC address.
Dalam contoh ini, MAC address papan penerima adalah `30:AE:A4:F6:7D:4C`. MAC address ini perlu dikonversi ke format bytes seperti berikut:
- 30:AE:A4:F6:7D:4C → b'\x30\xae\xa4\xf6\x7d\x4c'
Lakukan hal yang sama untuk MAC address papan penerima Anda sendiri.
# Receiver's MAC address
receiver_mac = b'\x30\xae\xa4\xf6\x7d\x4c'
Bagaimana Kode Bekerja?
Mari kita lihat secara singkat cara kerja kode dan fungsi-fungsi ESP-NOW yang paling relevan.
Mengimpor Modul
Pertama, impor modul yang diperlukan. Dalam contoh ini, kita menggunakan modul `espnow` untuk mengakses fungsi dan kelas ESP-NOW.
import network
import espnow
import time
Inisialisasi Antarmuka Wi-Fi
Selanjutnya, kita perlu menginisialisasi Wi-Fi (meskipun tidak digunakan untuk koneksi) agar ESP-NOW dapat berjalan. Anda bisa menggunakan mode station (STA_IF) atau mode access point (AP_IF).
# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
#sta.config(channel=1) # Set channel explicitly if packets are not delivered
sta.disconnect()
Nantinya, jika terjadi paket tidak terkirim saat pengujian, Anda mungkin perlu menentukan secara manual saluran Wi-Fi yang digunakan. Saluran ini harus sama pada papan pengirim dan penerima.
#sta.config(channel=1) # Set channel explicitly if packets are not delivered
Inisialisasi ESP-NOW
Selanjutnya, kita dapat menginisialisasi ESP-NOW. Pertama, buat sebuah instance `espnow` dengan nama `e`. Kemudian, aktifkan instance tersebut menggunakan metode `active()` dengan nilai `True` sebagai argumennya.
# Initialize ESP-NOW
e = espnow.ESPNow()
try:
e.active(True)
except OSError as err:
print("Failed to initialize ESP-NOW:", err)
raise
Untuk menonaktifkan ESP-NOW, berikan nilai `False` pada metode `active()`. Jika metode `active()` dipanggil tanpa argumen, ia akan mengembalikan status ESP-NOW saat ini.
Kita mengaktifkan ESP-NOW di dalam blok `try` dan `except` agar bisa menangkap kesalahan jika inisialisasi gagal.
Menambahkan Peer ESP-NOW
Tambahkan MAC address penerima (atau gunakan broadcast MAC address untuk mengirim pesan ke semua perangkat dalam jangkauan):
# Receiver's MAC address
receiver_mac = b'\x30\xae\xa4\xf6\x7d\x4c'
#receiver_mac = b'\xff\xff\xff\xff\xff\xff' #broadcast
Selanjutnya, kita dapat menambahkan MAC address penerima sebagai peer menggunakan metode `add_peer()`.
# Add peer
try:
e.add_peer(receiver_mac)
except OSError as err:
print("Failed to add peer:", err)
raise
Menampilkan Statistik ESP-NOW
Selanjutnya, kita buat sebuah fungsi yang dapat dipanggil nanti dalam kode, bernama `print_stats()`, untuk menampilkan statistik terkini paket ESP-NOW.
Untuk mendapatkan jumlah paket yang dikirim, diterima, dan hilang, kita dapat memanggil metode `stats()` pada objek ESP-NOW `e`.
Metode ini akan mengembalikan sebuah 5-tuple yang berisi jumlah paket yang dikirim, diterima, dan hilang:
(tx_pkts, tx_responses, tx_failures, rx_packets, rx_dropped_packets)
Selanjutnya, kita menampilkan masing-masing hasil tersebut:
print("\nESP-NOW Statistics:")
print(f" Packets Sent: {stats[0]}")
print(f" Packets Delivered: {stats[1]}")
print(f" Packets Dropped (TX): {stats[2]}")
print(f" Packets Received: {stats[3]}")
print(f" Packets Dropped (RX): {stats[4]}")
Mengirim Pesan ESP-NOW
Kita membuat loop utama untuk mengirim pesan beserta counter (`message_count`) setiap satu detik.
message_count = 0
while True:
try:
# Create a sample message with a counter
message = f"Hello! ESP-NOW message #{message_count}"
Kita mengirim pesan menggunakan metode `send()` pada objek ESP-NOW `e`. Fungsi ini menerima beberapa argumen, seperti MAC address papan penerima, pesan, dan parameter terakhir berupa nilai boolean (`True` untuk mengirim pesan ke peer dan menunggu respons, atau `False` untuk langsung kembali tanpa menunggu`).
try:
if e.send(receiver_mac, message, True):
print(f"Sent message: {message}")
else:
print("Failed to send message (send returned False)")
except OSError as err:
print(f"Failed to send message (OSError: {err})")
Setelah mengirim pesan, kita meningkatkan nilai counter dan memeriksa apakah sudah waktunya menampilkan statistik terbaru.
# Print stats every 10 seconds
if time.time() - last_stats_time >= stats_interval:
print_stats()
last_stats_time = time.time()
time.sleep(1) # Send every 1 second
Ringkasan
Secara ringkas, langkah-langkahnya adalah:
1. Inisialisasi antarmuka Wi-Fi
2. Inisialisasi ESP-NOW
3. Menambahkan Peer
4. Mengirim Pesan
Menjalankan Kode
Setelah menghubungkan papan ke komputer dan memastikan komunikasi dengan Thonny IDE, Anda dapat mengunggah kode sebagai `main.py` ke papan atau menjalankannya langsung menggunakan tombol hijau Run.
Kode akan mulai menampilkan pesan di jendela Shell. Namun, pengiriman pesan akan gagal karena papan penerima belum disiapkan.
Kode ESP32 Penerima (ESP-NOW dengan MicroPython)
Kode berikut mendengarkan paket ESP-NOW yang masuk dari peer-nya (papan pengirim yang sudah kita program sebelumnya). Buka jendela Thonny IDE lain agar independen dari jendela pertama.
Mengaktifkan Dua Instance Thonny IDE
Masuk ke Tools > Options dan hilangkan centang pada opsi Allow only single Thonny instance.
Salin kode ini ke Thonny IDE, lalu jalankan atau unggah ke papan ESP32 Anda.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/micropython-esp-now-esp32/
import network
import espnow
import time
# Stats tracking
last_stats_time = time.time()
stats_interval = 10 # Print stats every 10 seconds
# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.config(channel=1) # Set channel explicitly if packets are not received
sta.disconnect()
# Initialize ESP-NOW
e = espnow.ESPNow()
try:
e.active(True)
except OSError as err:
print("Failed to initialize ESP-NOW:", err)
raise
# Sender's MAC address
sender_mac = b'\x30\xae\xa4\x07\x0d\x64' # Sender MAC
# Add peer (sender) for unicast reliability
# You don't need to add peer for broadcast
#try:
# e.add_peer(sender_mac)
#except OSError as err:
# print("Failed to add peer:", err)
# raise
def print_stats():
stats = e.stats()
print("\nESP-NOW Statistics:")
print(f" Packets Sent: {stats[0]}")
print(f" Packets Delivered: {stats[1]}")
print(f" Packets Dropped (TX): {stats[2]}")
print(f" Packets Received: {stats[3]}")
print(f" Packets Dropped (RX): {stats[4]}")
print("Listening for ESP-NOW messages...")
while True:
try:
# Receive message (host MAC, message, timeout of 10 seconds)
host, msg = e.recv(10000)
# Print stats every 10 seconds
if time.time() - last_stats_time >= stats_interval:
print_stats()
last_stats_time = time.time()
except OSError as err:
print("Error:", err)
time.sleep(5)
except KeyboardInterrupt:
print("Stopping receiver...")
e.active(False)
sta.active(False)
break
Bagaimana Kode Bekerja?
Kode penerima mirip dengan kode papan pengirim. Perbedaannya hanya pada loop utama, di mana kita akan mendengarkan paket yang masuk.
Memasukkan MAC address papan pengirim dan menambahkannya sebagai peer bersifat opsional, namun disarankan untuk meningkatkan keandalan, terutama jika paket tidak diterima dengan baik.
Dalam contoh ini, MAC address papan pengirim adalah `30:AE:A4:07:0D:64`. MAC address ini perlu dikonversi ke format bytes seperti berikut:
- 30:AE:A4:07:0D:64 → b'\x30\xae\xa4\x07\x0d\x64'
Lakukan hal yang sama untuk MAC address papan pengirim Anda sendiri.
# Sender's MAC addresssender_mac = b'\x30\xae\xa4\x07\x0d\x64' # Sender MAC
Jika Anda ingin menambahkan papan pengirim sebagai peer, hapus komentar pada bagian kode berikut:
#try:
# e.add_peer(sender_mac)
#except OSError as err:
# print("Failed to add peer:", err)
# raise
Menerima Pesan ESP-NOW
Untuk menerima pesan, kita dapat menggunakan metode `recv()` pada objek ESP-NOW `e`.
host, msg = e.recv(10000)
Metode ini menunggu pesan masuk dan mengembalikan MAC address peer (disimpan di variabel `host`) serta pesan itu sendiri (disimpan di variabel `msg`). Tidak perlu mendaftarkan peer (menggunakan `add_peer()`) untuk menerima pesan dari peer tersebut.
Metode ini menerima argumen timeout dalam milidetik. Timeout menentukan berapa lama fungsi akan menunggu pesan masuk sebelum berhenti dan mengembalikan kontrol. Nilai yang dapat digunakan:
- `0`: Tanpa timeout, langsung kembali jika tidak ada data.
- `> 0`: menentukannilai timeout dalam milidetik.
- `< 0`: tidak ada timeout, tunggu selamanya hingga ada pesan baru.
- `None`: menggunakan nilai timeout default yang disetel dengan `ESPNOW.config()`.
Saat menerima pesan baru, kita akan menampilkan MAC address host dan pesan yang diterima.
if msg:
print(f"Received from {host.hex()}: {msg.decode()}")
Menjalankan Kode
Buka jendela baru di Thonny IDE dan pastikan terhubung dengan papan penerima. Unggah dan/atau jalankan kode penerim pada papan ini.
Papan akan mulai menerima paket ESP-NOW dari papan pengirim.
Pada saat yang sama, papan pengirim akan mulai menampilkan pesan keberhasilan (success messages).
Setiap 10 detik, papan pengirim dan penerima akan menampilkan statistik ESP-NOW di jendela Shell.
Anda dapat menggabungkan fungsi-fungsi yang digunakan di kedua sketch untuk membangun komunikasi dua arah. Selain itu, Anda juga bisa menambahkan lebih banyak papan untuk membuat jaringan ESP-NOW.
Komunikasi Satu Arah Point-to-Point dengan ESP-NOW (modul `aioespnow`)
Ada modul lain yang mendukung ESP-NOW secara asinkron menggunakan modul `asyncio`, yaitu modul `aioespnow`. Pada bagian ini, kita akan membuat contoh yang sama seperti sebelumnya, tetapi menggunakan `aioespnow`, yang mendukung pemrograman asinkron.
Kode ESP32 Pengirim (ESP-NOW dengan MicroPython)
Kode berikut melakukan hal yang sama seperti contoh sebelumnya, tetapi menggunakan modul `aioespnow`, jika Anda ingin menerapkan pemrograman asinkron.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/micropython-esp-now-esp32/
import network
import aioespnow
import asyncio
import time
# Stats tracking
last_stats_time = time.time()
stats_interval = 10 # Print stats every 10 seconds
# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect()
# Initialize AIOESPNow
e = aioespnow.AIOESPNow()
try:
e.active(True)
except OSError as err:
print("Failed to initialize AIOESPNow:", err)
raise
# Receiver's MAC address (broadcast for testing)
#receiver_mac = b'\x30\x0e\xa4\xf6\x7d\x4c'
receiver_mac = b'\xff\xff\xff\xff\xff\xff'
# Add peer
try:
e.add_peer(receiver_mac)
except OSError as err:
print("Failed to add peer:", err)
raise
def print_stats():
stats = e.stats()
print("\nESP-NOW Statistics:")
print(f" Packets Sent: {stats[0]}")
print(f" Packets Delivered: {stats[1]}")
print(f" Packets Dropped (TX): {stats[2]}")
print(f" Packets Received: {stats[3]}")
print(f" Packets Dropped (RX): {stats[4]}")
# Async function to send messages
async def send_messages(e, peer):
message_count = 0
while True:
try:
message = f"Hello! AIOESPNow message #{message_count}"
if await e.asend(peer, message, sync=True):
print(f"Sent message: {message}")
else:
print("Failed to send message")
message_count += 1
# Print stats every 10 seconds
if time.time() - last_stats_time >= stats_interval:
print_stats()
await asyncio.sleep(1) # Send every 1 second
except OSError as err:
print("Error:", err)
await asyncio.sleep(5)
# Main async function
async def main(e, peer):
await send_messages(e, peer)
# Run the async program
try:
asyncio.run(main(e, receiver_mac))
except KeyboardInterrupt:
print("Stopping sender...")
e.active(False)
sta.active(False)
Kode ESP32 Penerima (ESP-NOW dengan MicroPython)
Demikian pula, kode berikut menerima paket ESP-NOW yang masuk dari papan pengirim, tetapi menggunakan modul `aioespnow` untuk pemrograman asinkron.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/micropython-esp-now-esp32/
import network
import aioespnow
import asyncio
import time
# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.config(channel=1) # Set channel explicitly if packets are not received
sta.disconnect()
# Initialize AIOESPNow
e = aioespnow.AIOESPNow()
try:
e.active(True)
except OSError as err:
print("Failed to initialize AIOESPNow:", err)
raise
# Sender's MAC address
sender_mac = b'\x30\xae\xa4\x07\x0d\x64' # Sender MAC for unicast
# Add peer (sender) for unicast reliability
# You don't need to add peer for broadcast
#try:
# e.add_peer(sender_mac)
#except OSError as err:
# print("Failed to add peer:", err)
# raise
# Async function to receive messages
async def receive_messages(e):
while True:
try:
async for mac, msg in e:
print(f"Received from {mac.hex()}: {msg.decode()}")
except OSError as err:
print("Error:", err)
await asyncio.sleep(5)
# Async function to print stats periodically
async def print_stats(e):
global last_stats_time
last_stats_time = time.time()
stats_interval = 10 # Print stats every 10 seconds
while True:
if time.time() - last_stats_time >= stats_interval:
stats = e.stats()
print("\nESP-NOW Statistics:")
print(f" Packets Sent: {stats[0]}")
print(f" Packets Delivered: {stats[1]}")
print(f" Packets Dropped (TX): {stats[2]}")
print(f" Packets Received: {stats[3]}")
print(f" Packets Dropped (RX): {stats[4]}")
last_stats_time = time.time()
await asyncio.sleep(1) # Check every second
# Main async function
async def main(e):
# Run receive and stats tasks concurrently
await asyncio.gather(receive_messages(e), print_stats(e))
# Run the async program
try:
asyncio.run(main(e))
except KeyboardInterrupt:
print("Stopping receiver...")
e.active(False)
sta.active(False)
Siap Untuk Membuat Proyek Impianmu Menjadi Kenyataan?
Klik di sini untuk chat langsung via WhatsApp dan dapatkan dukungan langsung dari tim ahli kami!








0 on: "Panduan Dasar ESP-NOW di ESP32 Menggunakan MicroPython untuk Pemula"