Friday, March 1, 2019

UDP Communication part 1

For a complete index of all my stories click this text

There are times / circumstances that you want to have two (or more) ESP8266's communicating with eachother. For example you put an alarm on a door or window attached to an ESP8266. When the door or window is opened it will send a message.

Another example is an ESP8266 attached to a Dallas DS18B20 thermometer that sends an alarm-message when a critical temperature is reached in a server room.
Or you just want a simple alarm when someone in the kitchen puts his hand in the cookie jar. Attach a vibration sensor to an ESP8266 and have it send a message.

That message can be send into the cloud to IFTTT, Thingspeak or Dweet or whatever. For you to see the alarm you will need to have access to a PC or at least a smart phone. Now suppose you do not have that always at hand and you want just a led to blink or a buzzer to alarm you. Wouldn't it just be nice to have the alarm-esp send directly a message to another ESP that blinks a led or sounds a buzzer when it receives the alarm message.

And actually you can. You can have two or more ESP-8266's communicate with eachother without the need of a server or cloud-based service. The communication method is called UDP.

UDP communication

UDP stands for User Datagram Protocol. It is one of the basic communication protocols of the internet. UDP is designed for fast communication between two devices. The reason why it is not always used is that there is no guarantee that the receving device actually has received the message. Another protocol called TCP actually waits till the package is received. And when it is not it will re-send the package until it is acknowledged that the packet is received. UDP just sends the package and that's it.

The good part is that we can actually write or own safety protocol to make sure the packages have been send and received. I'll show you how to do that later on in the story.

The first hardware setup

I'll start easy with 2 ESP8266's. I use the NodeMCU version as that has a connection for USB programming and power supply. You can use the Wemos version to and you could even use the ESP-01.



The first ESP is just powered and nothing further. The seond ESP has a led attached to D7

The first program

My apologies for the diehard c-coders and Arduino afficionado's I am going to do this in my favoritie rapid devellopment environment: ESP-Basic. If you are not familiar with ESP-Basic I urge you to read this introduction story which will help you setup your ESP and help you start programming in no-time:
http://lucstechblog.blogspot.nl/2017/03/back-to-basic-basic-language-on-esp8266.html

Let us start with sending an UDP message.

The first thing to do in ESP-Basic is to tell the interpreter on which wifi-port the UDP communication is going to take place. Port 80 is normally used for HTML communication. UDP is generally done on port 5001. However feel free to use another port.

The second thing is to actually send the message. However you need to know to which IP adress you are going to send the message.



So open your router and look for the two ESP's. As you can see in my Zyxell router they are found with the names ESP_XXXXX. Clicking on these icons reveals their IP'adresses.

So now we have the information compleet we have the basic information to send UDP messages. In ESP-BASIC we just need two lines to send a message:

udpbegin 5100

udpwrite "192.168.1.78", 5001, "on"


This will send the message "on" over port 5001 to IP-adress 192.18.1.78.
You will need to replace the IP adress with your own.

Receiving the message on the other ESP-8266 is a bit more complicated.

First we need to start udp communication by defining a port over which the messages are send. We can use the same port or another one. The used port is for this particular ESP. I used the same portnumber:

udpbegin 5001

Now we need to tell the ESP what to do when a message is received. We need to do that by making a udpbranch which is basically a jump to a subroutine. You can name that routine anything you like. I called it udp.received

udpbranch [udp.received]

Now we need to build the actual routine that acts when a message is received:

[udp.received]
rec = udpread()

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

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

return


This is straightforward.
We declare a variable called rec (abbrevated from received) and put whatever is received over udp in it.

Next we test if the message received was "on" or "off" and accordingly set IO port d7 on or off, resulting in the led getting on or off.


' 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/>"

udpbegin 5100

button "on", [ledon]
wprint "<br>"
button "off", [ledoff]
wprint "<br>"
wprint "<br>"

wait

[ledon]
udpwrite "192.168.1.78", 5001, "on"
wait

[ledoff]
udpwrite "192.168.1.78", 5001, "off"
wait

So here is the complete listing for the Sending ESP


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

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

udpbegin 5001
udpbranch [udp.received]
wait

[udp.received]
rec = udpread()

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

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

return


And here the complete listing for the receiving ESP


This is how it will look on your screen when you open two browser windows each pointing to the IP number of one of the ESP's.


And this is how it looks in real life. On the right side is the sending NodeMCU and left the receiving one.

Just push the "on" button on the screen and on the receiving ESP the led will go on. Push the "off" button and on the receiving ESP the led will go off.
It's that easy to have a complete communication between two ESP8266's.

Experiment with this a bit before we go on to the next step.

Checking communication

As you have seen in the previous example the UDP message is send and we can only hope that it is received on the other side. So let's build a check into our receiving program.

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

To check what is received we can put a textboxes on our screen that will be filled with the information. I put 2 textboxes on the screen. The first displays what IP adress the information was received from, and the second displays what information was received.

Further there is a build-in option that just resends the received information back to the original sender. So in the receiver program we just have to put the following lines:

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

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

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

udpreply rec

return

The variable rec is filled with the information that is received. The variable remote gets the IP adres from the sender. And the variable whatreceived is copied from the variable rec so the textbox gets filled.

The critical line here is:

udpreply rec

This simple line sends the information received back to the original sender !!!

Now we only have to alter the UDP-send program in such a way that it receives the information back as a check that everything went ok.

Basically this is the same as the lines in the receiver software. So in the UDP-send program we start with a test wether information was received over UDP (the reply from the receiver) :

udpbranch [udp.received]

That information will be displayed in a textbox:

wprint "information returned "
textbox repl

And we need to make the routine where the information which is send back is put into a variable:

[udp.received]
repl = udpread()
return

And that completes our UDP-send program with a feedback that checks if the send information is really received and processed.

' 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/>"

udpbegin 5100
udpbranch [udp.received]

button "on", [ledon]
wprint "<br>"
button "off", [ledoff]
wprint "<br>"
wprint "<br>"
wprint "information returned "
textbox repl

wait

[ledon]
udpwrite "192.168.1.78", 5001, "on"
wait

[ledoff]
udpwrite "192.168.1.78", 5001, "off"
wait

[udp.received]
repl = udpread()
return

So above is the complete UDP-send program


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

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

udpbegin 5001
udpbranch [udp.received]
wait

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

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

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

udpreply rec

return

And here is the complete UDP-receive program.



And this is what it looks on your screen.

Just open a separate browser window for each ESP and you can see what is happening.

There you have it.
A basic setup for you to play with and enough information to send data between two ESP's without the need for a cloud service or dedicated server.

Next time things get a bit more complicated as I am going to use 3 ESP's. One as a controller and two to switch lamps locally and remote.

Till next time
have fun

Luc Volders