ESP-NOW 사용하기 4 – 1:N (1:복수) 양방향 통신

ESP-NOW 사용하기 4 – 1:N (1:복수) 양방향 통신

앞선 글들에서 ESP-NOW 통신으로 ESP32/esp8266 보드에서 1:1양방향 통신을 소개한 바 있었다.

https://blog.naver.com/mythee1/223291266342

그런데 이를 발전시켜 복수의 ESP 보드들과 ESP-NOW 방식으로 양방향 통신을 시도하기 위해, 다음과 같이 회로를 구성했다.

즉, 오른쪽 ESP32(=sender)에서 버튼을 누르면 ESP-NOW 메시지를 송신하는 의미의 백색 LED를 켜고,

왼쪽에 위치한 별도의 ESP32(Receiver 1) 및 ESP8266(Receiver 2) 보드에서 이 통신 메시지를 수신한 후, 잘 수신했다는 의미로 각각에 연결된 LED를(Receiver 1 – 백색, Receiver 2 – 청색) 켜게 된다.

그리고, 각각의 보드들은 메시지를 잘 수신했다는 내용의 메시지를 오른쪽에 위치한 ESP 보드(=Sender)에게 송신하데 되는데, Sender가 이를 수신하면, 전체적인 양방향 통신이 잘 이루어졌음을 확인해 주는 의미로 각기 Receiver 1의 확인용과, Receiver 2의 확인용에 할당된 노란색 및 녹색 LED를 각각 켜게 된다.

만일 Sender에서 버튼스위치가 떨어지면, 동일한 순서대로 통신이 이루어지면서 LED들이 꺼지게 된다.

이를 위하여 Sender 쪽 코드에서 달라지는 것은

먼저 Receiver ESP 보드들의 MAC 주소를 기재하고, 각각 add_peer 해주는 게 필요하다.

그리고, 버튼의 동작 이후, 반송되어 오는 확인 메시지를 수신하기 위해 메시지 수신 및 수신 메시지에 따른 동작을 선택하는 다음 문구 이하 부분의 추가가 필요하다. 수신확인 메시지를 보내는 receiver 보드들의 숫자만큼 이 동작이 필요하다.

_, msg = esp.recv()

최종적으로 Sender 쪽에서 사용한 최종 Code는 다음과 같다.

import network
from machine import Pin
import espnow
import utime

sta = network.WLAN(network.STA_IF)  
sta.active(True)
sta.disconnect()      
esp = espnow.ESPNow()
esp.active(True)

Noofreceiver=2
peer32 = b'$bxabxff(xdc'
peer8266 = b'xb4xe6-pDn'

esp.add_peer(peer32)
esp.add_peer(peer8266)

button = Pin(23, Pin.IN, Pin.PULL_DOWN)
led = Pin(22, Pin.OUT)
ledA = Pin(21, Pin.OUT)
ledB = Pin(18, Pin.OUT)
buttonwas = 0
while True:
    buttonnow = button.value()
if buttonnow != buttonwas:
if buttonnow == 1:
           
           message = "SWOn"
           led.value(1)
else:
           
           message = "SWOff"
           led.value(0)
print("Sending command : ", message)
        esp.send(peer32, message)
        esp.send(peer8266, message)
for i in range(Noofreceiver):
            _, msg = esp.recv()
if msg:
if msg == b'AOn':
                  utime.sleep(0.2)
                  ledA.value(1)
print("Rcvd message from A :  AOn")
               elif msg == b'AOff':
                  utime.sleep(0.2)
                  ledA.value(0)
print("Rcvd message from A :  AOff")
               elif msg == b'BOn':
                  utime.sleep(0.2)
                  ledB.value(1)
print("Rcvd message from B :  BOn")
               elif msg == b'BOff':
                  utime.sleep(0.2)
                  ledB.value(0)
print("Rcvd message from B :  BOff")
else:
print("Unknown")
        
        buttonwas = buttonnow

한편 Receiver 쪽에서 최종적으로 사용한 Code는 다음과 같은데, 과거 1:1 양방향 통신에서와 기본적으로 동일하나, 각 Receiver 보드들을 구분하기 위해 반송하는 메시지를 “AOn” “BOn” “AOff” “BOff” 등의 방식으로 다르게 지정해 주었다.

import network
import espnow
import utime
from machine import Pin

sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect()
esp = espnow.ESPNow()
esp.active(True)

peer = b'xe4exb8rTxf4'   #E4:65:B8:0D:54:F4
esp.add_peer(peer)

led = Pin(22, Pin.OUT)
while True:
    _, msg = esp.recv()
if msg:
if msg == b'SWOn':
            utime.sleep(0.2)
print("Turn on SW")
            led.on()
            msgback="AOn"
            esp.send(peer, msgback)
                        
        elif msg == b'SWOff':
            utime.sleep(0.2)
print("Turn off SW")
            led.off()
            msgback="AOff"
            esp.send(peer, msgback)
else:
print("Unknown")

정상적으로 동작하면 각 보드별 출력 결과는 다음과 같으며,

실제 동작 모습은 다음과 같다.

코딩 시 한 가지 주의할 것은 Sender Code에서 상대측 확인 메시지를 받는 부분을 Receiver들의 수만큼 반복해 주어야 한다는 점이다.

위의 Sender 측 코드에서는 다음과 같이 for 문을 이용하여 해결하였다. range( ) 안에는 미리 지정해둔 Receiver들의 수값에 해당되는 변수를 지정했다.

만일 이 부분을 Receiver 수만큼 반복하지 않는 경우에는, 각각의 Receiver에서 보내온 확인 메시지들 중이 입력버퍼에 남아 오동작을 유발하기 때문으로, 실제 오동작 모습은 다음과 같다.