I'm trying to stream sensor data from my Arduino (server), over my network, to my computer (client) in real-time.
While sensor data is coming in at a consistent rate per second, the time between messages is highly irregular.
I tested both UDP and TCP connections with both one directional and bidirectional communication on minimal examples to isolate this behavior.
I also tried adding delays, using different settings (SOCK_STREAM vs TCP_NO_DELAY), decreasing the message size, and adding headers to the message in attempt to synchronize the connection, if that was the issue.
In every case, the messages come in consistent, but in inconsistent burst like this:
*message is always "test", frame number printed instead for illustration
Why is this happening and how can I make time between messages more consistent/stable?
Below are the bare minimum examples I tested on:
One Directional (server -> client)
TCP Client
import time
import socket
ADDRESS = "xxx.xxx.xxx.xxx"
PORT = 80
SIZE = 4
sock = socket.socket(socket.AF_INET, socket.TCP_NODELAY)
sock.connect((ADDRESS, PORT))
print("Waiting for connection...")
sock.recv(SIZE)
print("Connected")
t0 = 0
f = 0
while True:
data = sock.recv(SIZE).decode()
if f == 0:
t0 = time.time()
time.sleep(.0001)
f += 1
fps = int(f / (time.time() - t0))
print(f"\r{f} FPS: {fps} data: {data} ", end='')
TCP Server
#include <WiFiNINA.h>
WiFiServer server(80);
void setup() {
Serial.begin(115200);
int status = WL_IDLE_STATUS;
while (status != WL_CONNECTED) {
status = WiFi.begin("ssid", "password");
delay(1000);
}
server.begin();
Serial.println("connected");
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.println(ip);
}
void loop() {
server.write("test");
delay(16);
}
UDP Client
import socket
import time
ADDRESS = "xxx.xxx.xxx.xxx"
PORT = 2390
SIZE = 4
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(b"s", (ADDRESS, PORT))
print("Waiting for connection...")
sock.recvfrom(SIZE)
print("Connected")
t0 = 0
f = 0
while True:
data, addr = sock.recvfrom(SIZE)
data = data.decode()
if f == 0:
t0 = time.time()
time.sleep(.0001)
f += 1
fps = int(f / (time.time() - t0))
print(f"\r{f} FPS: {fps} data: {data} ", end='')
UDP Server
#include <WiFiNINA.h>
#include <WiFiUdp.h>
WiFiUDP Udp;
void setup() {
Serial.begin(115200);
int status = WL_IDLE_STATUS;
while (status != WL_CONNECTED) {
status = WiFi.begin("ssid", "password");
delay(1000);
}
Udp.begin(2390);
Serial.println("connected");
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.println(ip);
}
void loop() {
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write("test");
Udp.endPacket();
delay(16);
}
Bi Directional (server <> client)
TCP Client
import time
import socket
ADDRESS = "xxx.xxx.xxx.xxx"
PORT = 80
SIZE = 4
sock = socket.socket(socket.AF_INET, socket.TCP_NODELAY)
sock.connect((ADDRESS, PORT))
print("Waiting for connection...")
sock.send(b's')
sock.recv(SIZE)
print("Connected")
t0 = 0
f = 0
while True:
sock.send(b's')
data = sock.recv(SIZE).decode()
if f == 0:
t0 = time.time()
time.sleep(.0001)
f += 1
fps = int(f / (time.time() - t0))
print(f"\r{f} FPS: {fps} data: {data} ", end='')
TCP Server
#include <SPI.h>
#include <WiFiNINA.h>
WiFiServer server(80);
boolean alreadyConnected = false;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.print("Connecting to Wifi... ");
int status = WL_IDLE_STATUS;
while (status != WL_CONNECTED) {
status = WiFi.begin("ssid", "password");
delay(500);
}
Serial.println("connected.");
server.begin();
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.println(ip);
}
void loop() {
WiFiClient client = server.available();
if (client) {
if (!alreadyConnected) {
client.flush();
alreadyConnected = true;
}
if (client.available() > 0) {
char thisChar = client.read();
client.write("test");
}
}
}
UDP Client
import socket
import time
ADDRESS = "xxx.xxx.xxx.xxx"
PORT = 2390
SIZE = 4
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(b"s", (ADDRESS, PORT))
print("Waiting for connection...")
sock.recvfrom(SIZE)
print("Connected")
t0 = 0
f = 0
while True:
sock.sendto(b"s", (ADDRESS, PORT))
data, addr = sock.recvfrom(SIZE)
data = data.decode()
if f == 0:
t0 = time.time()
time.sleep(.0001)
f += 1
fps = int(f / (time.time() - t0))
print(f"\r{f} FPS: {fps} data: {data} ", end='')
UDP Server
#include <WiFiNINA.h>
#include <WiFiUdp.h>
WiFiUDP Udp;
void setup() {
Serial.begin(115200);
while (!Serial);
Serial.print("Connecting to Wifi... ");
int status = WL_IDLE_STATUS;
while (status != WL_CONNECTED) {
status = WiFi.begin("wifi", "password");
delay(500);
}
Serial.println("connnected.");
Udp.begin(2390);
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.println(ip);
}
void loop() {
if (!Udp.parsePacket()) {
return;
}
while (Udp.read() != -1);
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write("test");
Udp.endPacket();
}