Friday, March 8, 2019

UDP Communication Part II

For a complete index of all my stories click this text

This is the second installment on UDP communication with the ESP8266

In the first story you can read how to send information between two ESP's without using a cloud service or a dedicated local server (like MQTTT). You can read that story here: https://lucstechblog.blogspot.com/2019/03/udp-communication-part-1.html

In this story I am going to show you how to communicate between multiple ESP's. I am setting up 2 ESP's with a switch and 2 led's. And one ESP as the master controller with 4 leds and 2 switches.

The goal is that when you push a button on the master ESP a led will go on at one of the 'slave' ESP's. That ESP will send feedback which will set the control led on the master on. Each of the two 'slave' ESP's has a button. When that one is pressed the other led on the slave will go on and the other control led will go on at the master. This way you can locally see on the slave which led is ON and you can see on the master which leds on all the slaves are ON.

The hardware


The hardware setup is easy. A nodeMCU with two buttons and 4 led's as the master and two NodeMCU's each with 2 leds and a button as the slaves. The two slaves have identical hardware setups.




And this is how it looks in real life.

The software.





' UDP send data demo
' written by Luc Volders
' http://lucstechblog.blogspot.nl/

wprint |<h1 style="text-align:center;">Luc Volders</br>UDP-Sender</h1>|
wprint "<br/><br/>"

io(po,d5,0)
io(po,d6,0)
io(po,d7,0)
io(po,d8,0)

press = 0
press2 = 0

interrupt d3, [butpress]
interrupt d4, [butpress2]

udpbegin 5001
udpbranch [udp.received]

button "on1", [ledon1]
wprint "<br>"
button "off1", [ledoff1]
wprint "<br>"
button "on2", [ledon2]
wprint "<br>"
button "off2", [ledoff2]
wprint "<br>"
wprint "<br>"
wprint "information returned "
textbox repl

wait

[ledon1]
udpwrite "192.168.1.78", 5001, "on 1"
wait

[ledoff1]
udpwrite "192.168.1.78", 5001, "off 1"
wait

[ledon2]
udpwrite "192.168.1.77", 5001, "on 2"
wait

[ledoff2]
udpwrite "192.168.1.77", 5001, "off 2"
wait

[udp.received]
repl = udpread()

if repl = "on 1" then
io(po,d5,1)
endif
if repl = "off 1" then
io(po,d5,0)
endif

if repl = "on 1a" then
io(po,d6,1)
endif
if repl = "off 1a" then
io(po,d6,0)
endif

if repl = "on 2" then
io(po,d7,1)
endif
if repl = "off 2" then
io(po,d7,0)
endif

if repl = "on 2a" then
io(po,d8,1)
endif
if repl = "off 2a" then
io(po,d8,0)
endif

return

[butpress]
press = 1 - press
if press = 1 then
  udpwrite "192.168.1.78", 5001, "on 1"
else
  udpwrite "192.168.1.78", 5001, "off 1"
endif
delay 200
interrupt d3,[butpress]
wait

[butpress2]
press2 = 1 - press2
if press2 = 1 then
  udpwrite "192.168.1.77", 5001, "on 2"
else
  udpwrite "192.168.1.77", 5001, "off 2"
endif
delay 200
interrupt d4,[butpress2]
wait


First let's have a look at the sending software for the master ESP.

io(po,d5,0)
io(po,d6,0)
io(po,d7,0)
io(po,d8,0)

I start with setting the led's off by writing 0 to the io ports.

interrupt d3, [butpress]
interrupt d4, [butpress2]

Next 2 interrupts are attached to the two buttons. The buttons are connected to D3 and D4 and I attached a 10k pull up resistor to them to make sure the level is HIGH when the button is not pressed.

udpbegin 5001
udpbranch [udp.received]

UDP is started on port 5001 and a branch is created that checks wether any information is coming from one of the 'slave' ESP's.

The last part of the setup draws 4 buttons on the screen and a textbox.

When one of the buttons on the screen is pressed an ON or OFF command is send to one of the 'slave' ESP's in the [ledon] and [ledoff] routines.

When one of the real buttons is pressed the interrupt is triggered.

[butpress]
press = 1 - press
if press = 1 then
  udpwrite "192.168.1.75", 5001, "on 1"
else
  udpwrite "192.168.1.75", 5001, "off 1"
endif
delay 200
interrupt d3,[butpress]
wait

If the interrupt is triggered like in the above snippet the variable press is inverted. When it is 1 it will become 0 and visa versa. that is what the line press = 1 - press does. Simply said the line makes the button a toggle button.



Make sure you replace the IP numbers with the IP numbers of your slave unnits.

The udpwrite line sends the information to the selected 'slave' and a small delay is initiated to make sure we wait till the information has been send. And then the interrupt is re-initiated.

When the information has been send the receiving ESP will send a confirmation back. That is received by the [udp.receive] routine. In this routine the incoming information is checked and as a visible feedback a led is set ON or OFF as confirmation.



' udp receiver demo
' written by Luc Volders
' http://lucstechblog.blogspot.nl/

io(po,d6,0)
io(po,d7,0)
press = 0

wprint |<h1 style="text-align:center;">Luc Volders</br>UDP-Receiver</h1>|
wprint "<br/><br/>"

wprint "who send information "
textbox remote
wprint "<br>"
wprint "what was received"
textbox whatreceived

interrupt d3, [butpress]

udpbegin 5001
udpbranch [udp.received]
wait

[udp.received]
rec = udpread()
remote = udpremote()
whatreceived = rec

if rec = "on 1" then
  io(po,d7,1)
endif

if rec = "off 1" then
  io(po,d7,0)
endif

udpreply rec

return

[butpress]
press = 1 - press
if press = 1 then
  io(po,d6,1)
  udpwrite "192.168.1.79", 5001, "on 1a"
else
  io(po,d6,0)
  udpwrite "192.168.1.79", 5001, "off 1a"
endif
delay 200
interrupt d3,[butpress]
wait


The software for the 'slave' ESP's is almost identical although there is a bit less hardware: just 2 leds and one button.


[butpress]
press = 1 - press
if press = 1 then
  io(po,d6,1)
  udpwrite "192.168.1.77", 5001, "on 2a"
else
  io(po,d6,0)
  udpwrite "192.168.1.77", 5001, "off 2a"
endif
delay 200
interrupt d3,[butpress]
wait

The button press routine is the same one as the one on the 'master' ESP

The button works as a toggle button and sets the led on the breadboard on or off and sends the ON or OFF information to the 'master' ESP. The delay makes sure that nothing happens until the info is send and the interrupt is re-initiated.


And also note here that you have to replace the IP number with the IP number of your master ESP.

[udp.received]
rec = udpread()
remote = udpremote()
whatreceived = rec

if rec = "on 2" then
  io(po,d7,1)
endif

if rec = "off 2" then
  io(po,d7,0)
endif

udpreply rec

return

The [udp.received] routine listens for information coming from the 'master' ESP and accordingly sets the other led ON or OFF.


Summarising:

On the master ESP we have two buttons that send information to the slave ESP's which activates a led on the choosen slave. That is confirmed by a control led on the master. When the on the slave itself the button is pressed a signal is send to the master that sets the other led for that slave ON or OFF.

On the slave ESP we have two leds. One is controlled by the local button and when that is pressed a signal is send to the master which there triggers a control led. The second led on the slave is controlled by the master.

This way we have 2 led's on each slave. One is controlled locally and the other is controlled by the master ESP.

Ideas and sidenotes.

UDP communication is easy and you can have one master sending commands to lot's of slaves. A simple home automation controller can be build with this. That is practical But how about devellopping a game with this. Or replace your easter eggs with ESP's. Or build an intruder alarm with several slaves each with a PIR or radar module that can locate the intruder. A remote controlled car in which a master with some buttons sends speed and directions to a slave that controls the motor is another possibillity. Use your imagination.

The UDP communucation works with strings. So do not forget to covert your sensor values to strings when sending them over UDP.

I bet you can build a project with this which I did not think off.

Till next time
Have fun

Luc Volders