Network Protocol Usage For Time-sensitive Lighting

I'm working on a project where a main Raspberry Pi server sends out data packets over a wifi network which tells different ESP8266s with neopixel strips what to do (turn on, turn off, play a specific animation, etc.)

The Pi contains a file with an animation script, so by changing that one file I can change what all of the lights do. The network data transfer is time-sensitive, as I want each ESP to work in sync at the same time.

Right now, to transfer the data, the Pi sends out UDP broadcast packets which contain all of the data for each ESP, and the ESPs parse the data to know what each individual one should do.

This works pretty well, and the effect of having all of the lights sync up is really cool, but there are some issues with reliability and timing. Sometimes, a light will miss a packet and not be in time, causing it to not do anything until the next packet arrives. Also, sometimes a single light will start to lag behind on the animation, which I think I can fix by programming the ESPs to run the new command right as it arrives and not wait to finish the one it is currently running.,

I was curious if anyone had any insight on possible conceptual networking fixes. I know TCP packets would be more reliable, but I know it is also slower. Could TCP packets be implemented for something so time-sensitive? Are there other options with the UDP packets that could increase the reliability?

TCP has some setup and overhead cost, but once you have a socket established, unless your network is highly unreliable, I don't see why you couldn't use it instead of UDP.

There are some complicated ways to solve the problem. But, a simple solution would be for the Pi to retransmit multiple times leading up to the start time. You would have to alter the protocol and add some state to the lights.

Make sense?

One caveat is scalability. At some N lights the delay between sending to the first and sending to the last would be detectable by a human.

Unless multicast is used.

UDP generally is going to simplify your life. You may wish to consider a roaming scheme with multiple rPi sending the exact same information; each rPi will have the same SSID, encoding, and passcode.

802.11 AccessPoints work in this roaming scenario (tested) but I have not applied the roaming to rPi or devices like the ESP32/Arduino.

In theory, the client should latch onto the stronger signal and a better RSSI should help with lost packets.

clearly if you require reliable data transfer you either use TCP or use UDP with acknowledgements.
if using TCP is the number of lighting units greater than the maximum number of TCP sockets
NO - if not you can set up a TCP connection to every unit and transfer data as required
YES - if greater you have the overhead of setting up and closing virtual circuits for every data transfer

if using UDP you send a datagram to each unit in turn
if a unit receives the datagram it sends and acknologement UDP datagram back to the server
if the server fails to receive an acknologement from a unit it assumes a failure and resends the appropriate datagram
it is a good idea to sequence number datagrams so you can check for lost datagrams/multiple datagrams, etc

how many lighting units do you have?
how often do you send new data to the units?

probably the Raspberry pi code will need to be multithreaded
what langauge do you use for the Raspberry pi? I tend to use Java

Right now my system only has 14 nodes. It was actually originally made for a Christmas parade this past year, and everything worked well enough and it was really cool, but I want to improve on it and possibly expand this to other home-wide lighting projects with many more nodes.

I think the TCP connection is a good idea, and that would also allow for the pi to identify every device on the network and keep track of them.

My code right now is written in python, and it just reads a text file with the animation script and sends out the broadcast packets, but I might look into writing it in Java or even C for better speed.

Perhaps a different approach is needed.
Rather than trying to do reliable real-time communication, instead have the remote units synchonized in time and broadcast your data stream several seconds in advance with a time stamp and sequence number indicating when each block of data should be played. If a receiving unit sees a gap in the sequence numbers then it has time to request retransmission of the missing information.

The receiving units buffer the data and execute the instructions according to the time stamps and their own internal clocks. GPS clocks give the highest accuracy but there are cheaper options.

This is an interesting idea, but I also would like it to work as fast as possible so I can do live control and maybe sync it up with music or something. I've thought about using RF modules for higher reliability, but I would also like them to be as cheap and as simple as possible.

The fundamental problem with all RF communication systems is that the more reliable you want it to be the higher the latency you are likely to experience because time is needed to retransmit lost packets. Even so called 'reliable' protocols such as 802.15.4 only make a limited number of attempts to retransmit data before giving up and declaring the transmission failed.

I think your dream of having a lossless low latency system is not achievable using the ISM band in an urban environment as you are sharing the spectrum with other people and therefore interference and data loss will occur.

Perhaps the solution is to not use RF. Do your devices have line of site with each other?
If indoors or at night, perhaps a modulated Infra-red system using hacked high power security floodlights would do it. You could pulse them at 50w. Mobile phone cameras will see them but the audience won't.

how often do you update the device settings?

rather than sending individual settings to each device in turn as individual datagrams you could use UDP multicast and send the new settings for every device in a single datagram - every device receives the information and extracts the settings for itself ignoring all the others - they could then reply with acknowledgements

May be your WiFi is not stable enough and some of your (moving?) nodes lose connectivity for a fraction of time. So you might consider to improve your Wifi coverage.

Protocollwise I assume you should stick to UDP broadcast to send one message to all all nodes.
But I would change the concept: not only send when lights should change but a constant "stream" of data several times per second - so it wouldn't matter to much if a node looses on message as the next message will either contain the same information (or an updated information).
can you tell more about what data you transmit e.g. how many "ports" / colors / dimlevels .. per Node and how a sample message looks like

Each node has preset "animations" that they can run. They include things like just set the color, wipe the color through the strip, a sparkle animation, rainbow animation, etc.

The packet is structured as follows

03 255 255 255 010 (with no spaces)

03 - animation (color wipe)
255 - red value
255 - green value
255 - blue value
010 - time value (how long to take to wipe the color through the strip)

The main packet is sent out the data to control every node, so a packet that would wipe every node in a 4-node system to red would look like this being sent out by the pi:

03255000000010032550000000100325500000001003255000000010

Each node has a preset identifier value (in this scenario from 0-3). Since the command for each node is 14 bytes long, each node just reads the data from the packet corresponding to its own 14-byte long segment, meaning each node can do different things.

The reason that I use this method over just broadcast packets with an identifier value to send data specific to each node is that when I was testing I had issues where if multiple packets for multiple different nodes are sent out at the same time the ESP8266s would receive the first packet and not be able to receive the next packets since it is still trying to identify if that first packet was intended for that ESP8266.

Also, a lot of my light animation code is blocking, so I need to try to change that as well.

This is essentially what I do without the acknoledgements.

This is also a really cool idea which I want to explore, but I would like to stick to wifi because I might want to expand this project to smart home type things and keep it as cheap as possible with the built in wifi of ESP8266s.

I basically just want to try to make it as reliable as possible mainly through software or hardware on the transmission side only.

Also this is very true. The whole system was running off of a Raspberry Pi Zero 2 W, and the pi sends out the data and creates the wifi network using RaspAP. This could very much be an issue with the wifi network. Perhaps I could do something with broadcast packets without association? Basically, using the ESP8266s in monitor mode as just dumb tx/rx pairs?

One issue I also found is that during the parade, in extremely crowded areas, the lights would just stop working completely, maybe update once ever 5-10s until I got to a less crowded area. I assumed this was some sort of wifi interfearence with how many devices were around us. Any ideas on that?

Tell us about all the antennas being used by your equipment. The last comments point to fundamental overload of your receiving equipment from the RF emitted by cell phones in the nearby area.

The built-in Raspberry Pi and ESP8266 antennas. Nothing fancy, just pcb trace antennas. I might try to use an external usb wifi module on the Raspberry Pi to increase the gain there.

the range of the Raspberry pi is very limited
I have found using a D-LINK CPE210 and similar devices as a range extender for outdoor applications improves range significantly

That could definitely help, and the higher power output could also improve accurate data reception

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.