Friday, March 15, 2019

UDP Communication part III ESP to Raspberry

For an index of all my stories click this text

This is the third installment about UDP Communication between wifi enabled devices.

In the first two stories I showed you how to send data using UDP between two ESP's. Re-read that story here: http://lucstechblog.blogspot.com/2019/03/udp-communication-part-1.html
The second story showed you how to send data between multiple ESP's. Re-read that story here: http://lucstechblog.blogspot.com/2019/03/udp-communication-part-ii.html
Both stories showed you also a way to check wether the data was really received. And in both stories the communication was direct between the ESP's without a server or a cloud service for the communication.

It is easy to imagine that you need something more powerfull to process all data that is send between ESP's. Suppose that you want to build a home automation system with a central computer that processes all data. An ESP would probably not be sufficient to control all processes.

In comes the Raspberry Pi.






You could even use the humble Pi Zero for this purpose. The Pi Zero itself is dead-cheap (around 5 euro / 5 USD) and a complete setup with an SD card, powersupply and USB-Ethernet adapter will set you back below 25 euro/USD with some carefull sourcing. This means that for about 25 euro/dollar you can have a full blown Linux computer that controlls your automation processes.

If you want more processing power the Raspberry Pi 3 or 3B offers that for around 35 Euro / USD and offers the advantage that you do not need an USB ethernet adapter due to its build in Ethernet.

Besides that the Pi is easily programmable with Python and loads of drivers and documentation are readily available.

ESP-hardware

For the testing purpose you can use the setup from the previous stories. I am just using a plain ESP-8266 (NodeMCU) with no attached hardware. The test software puts two buttons on a web-page and a slider. That is all.

You can modify the software easily to send all kinds of data like button readings, temperature, motion etc etc etc.

Finding IP adresses.

To get this to work you will need to know the IP adresses for the Raspberry and the ESP8266. The Raspberry's IP adress can be looked up in the Raspberry itself as I'll show you later on in this story.

The IP adress of the ESP8266 is a bit trickier to find. You will have to get into your router to find it.

In my router there is a page that looks like this:
 

In the lower section you can see all the wired devices. And hey there is the Raspberry. So you can also use this to find the Raspberry's IP adress.
In the upper section you can see two devices. The first is my ESP's thermometer and the second is the ESP we are looking for.


The ESP side of the software.

I am using almost the same software as I used in the first and second story. I just added a slider. The program is written in ESP-Basic my favorite rapid devellopment environment.



 ' UDP send data with feedback demo  
 ' written by Luc Volders  
 ' http://lucstechblog.blogspot.nl/  
   
 wprint |<h1 style="text-align:center;">Luc Volders</br>UDP-Sender</h1>|  
 wprint "<br/><br/>"  
 olddimmer = 0  
 udpbegin 5001  
   
 button "on", [on]  
 wprint "<br>"  
 button "off", [off]  
 wprint "<br>"  
 wprint "<br>"  
 slider dimmer ,0,255  
 wprint "<br>"  
 wprint "<br>"  
 textbox rec  
 timer 1000, [sendslider]  
   
 udpbranch [udp.received]  
   
 wait  
   
 [on]  
 udpwrite "192.168.1.78", 5001, "on"  
 wait  
   
 [off]  
 udpwrite "192.168.1.78", 5001, "off"  
 wait  
   
 [udp.received]  
 rec = udpread()  
 return  
   
 [sendslider]  
 if dimmer <> olddimmer then  
 udpwrite "192.168.1.78", 5001, "slider " & "00" & str(dimmer)  
 olddimmer = dimmer  
 endif  
 wait  
   


Let's have a brief look at the program.

The program starts with the declaration of the variables and the building of the webpage with 2 buttons and a slider.

timer 1000, [sendslider]

udpbranch [udp.received]

These two statements are important in this section. The first (timer) jumps to a routine that makes sure that every second (timer 1000) there is a test wether the slider has changed.
The second statement makes sure that a routine is called that updates the textbox on the screen which is a check wether the UDP command is actually received by the Raspberry.

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

This simply sends the "on" command to the Raspberry. You will need to alter the IP adress in the IP adress of the Raspberry.
Almost the same routine is made for the "off" command.

[sendslider]
if dimmer <> olddimmer then
udpwrite "192.168.1.78", 5001, "slider " & "00" & str(dimmer)
olddimmer = dimmer
endif
wait

This routine sends the slider value to the Raspberry. Again exchange the IP adress for the adress of your own Raspberry.

if dimmer <> olddimmer then
olddimmer = dimmer

This is a clever mechanism in this routine that checks wether the value of the dimmer has altered. When it has been altered the new value is send to the Raspberry. There is no need to send the value if it is not altered.

This is just a framework. Adjust it to your own needs for sending the values you want to send to your Raspberry.


And this is how it looks on your screen. 

As you can see the textbox shows the information (slider 00104) that has been send to the Raspberry and which the Raspberry has send back as a check.


The Raspberry side of the software.

First point your mouse at the top-right side off the Raspberry screen. There is the Panel item for Ehernet.




Click on it and it will reveal the Raspberry's IP adress. Like described earlier you can also find the IP adress in your router. You can fill that in, in the ESP-Basic program described above.

On the following web-page you can find all documentation for UDP communication with Python.
https://wiki.python.org/moin/UdpCommunication#Receiving



I am still using the Geany editor instead of the Thonny editor. Thonny is preferred by the Raspberry Organisation so I should switch. However Geany still accepts Python 2 code which Thonny refuses.

 

import socket

UDP_IP = "192.168.1.78" # Pi's own IP-Adres
UDP_RETURN = "192.168.1.79" # IP adres from sender
UDP_PORT = 5001

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    print "received message:", data
    sock.sendto(data, (UDP_RETURN, UDP_PORT))

I just copied the UDP receive program from that page and made some alterations.

import socket

This line speaks for itself. It just imports the UDP library.

UDP_IP = "192.168.1.78" # Pi's own IP-Adres
UDP_RETURN = "192.168.1.79" # IP adres from sender
UDP_PORT = 5001

UDP_IP is the Raspberry's own IP adress which you just found.
UDP_RETURN is the IP adress of the ESP8266. You can find that in your router as described before.

while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    print "received message:", data
    sock.sendto(data, (UDP_RETURN, UDP_PORT))

This is where all the magic happens.

while True:

This simple line makes sure that the program keeps running indefinitely

data, addr = sock.recvfrom(1024)

This line sets the variable data to the information that is received over UDP.

sock.sendto(data, (UDP_RETURN, UDP_PORT))

And this line sends the confirmation back to the ESP so we know for sure that the data has been received.

The program is written in Python 2. If you want to use Python 3 you will have to change this line:

    print "received message:", data

Into this:

    print ("received message:", data)



Here you can see the output. I have changed the slider a few times and pushed the ON and OFF buttons on the screen. The information is received by the Raspberry and on the ESP webpage you can check that the information indeed has been send back as a confirmation.


Expansion

Like I said this is just a framework. To make this usefull you would need to expand the ESPBasic program as well as the Raspberry's Python program.

On the ESP side there should be some action when the command is not received back, or mutilated. You could send it again. In any case you should take action.
You could also send an identification with the data so the Raspberry woud know from which ESP the data is coming.

On the Raspberry side we should make a nice graphical page with all the received information.

sock.sendto(data, (UDP_RETURN, UDP_PORT))

This line can easily be altered to send all kinds of information to multiple ESP's. Just alter the data and the UDP_RETURN in the right ESP's IP adress and that's it.

Well that sums it up. It was easier to get the two platforms to talk to eachother as I had expected. My setup worked immediately.

Rests only one thing: Getting my Android Phone to talk over UDP to the ESP and to the Raspberry.

For now a good setup to get things starting.

Till next time
Have fun

Luc Volders