Goal: continuously send UDP packets from an Arduino Nano 33 IoT to a Raspberry Pi 4 to understand the reliability of this solution.
It’s not important at the moment: software or networking performance, throughput, etc. This is a first test to check the basics, there is a lot of room for improvements in the code, protocol, approach, which will be done in future iterations and based on the discoveries done in this test.
The experiment
From the Arduino, an UDP packet is sent to the Raspberry Pi. The packet contains a string with the value of an incremental counter, and the value of micros().
Contents of the first 3 packets were (one per line):
1,33726393
2,33728539
3,33730495
On the Raspberry Pi, netcat is listening for those UDP packets:
$ netcat -u -s 0.0.0.0 -p 4545 -l > netcat-output.txt
Once finished, the last lines of netcat-output.txt were:
$ tail netcat-output.txt
1799991,3579137145
1799992,3579139114
1799993,3579141112
1799994,3579143035
1799995,3579144985
1799996,3579146918
1799997,3579148832
1799998,3579150780
1799999,3579152790
1800000,3579154958
and the output see on the Arduino console shows partial stats and the final stat:
(...)
stats | iter=1797000 | err=9285 | msg/sec=507
stats | iter=1798000 | err=9285 | msg/sec=507
stats | iter=1799000 | err=9285 | msg/sec=507
stats | iter=1800000 | err=9285 | msg/sec=507
ENDED | Sent 1800001 UDP packets in 3545431 ms. with 9285 errors
Errors
How the errors are counted? The return value of WiFiUDP.endPacket() is used: that method returns 0 if there was some error. See WiFiNINAUDPEndPacket for mor information.
On the Raspberry Pi, we can easilly check how many packets were actually received:
$ wc -l netcat-output.txt
1790712 netcat-output.txt
Results
Generated packets (Arduino): 1,800,000
Errors reported by WiFiUDP.endPacket(): 9,285
Successfully sent packets (measured from Arduino): 1,790,715
Received packets (at Raspberry Pi): 1,790,712
Errors in percentages:
errors reported by WiFiUDP.endPacket(): 9,285 of 1,800,000 = 0.5158%
lost packets: 3 of 1,790,715 = 0.000167531%
Next steps
Refactor Arduino code
Send data in binary format instead of strings
Experiment with retries
Experiment buffering data and send multiple data points per UDP message
Experiment with different WiFi configuration
Appendix: snippet of Arduino code
void floodUdp(int iters) {
int ret;
int ratio;
counter = 1;
errors = 0;
Serial.println("Flooding... :D");
udpStart = millis();
for (; iters == -1 || counter <= iters; counter++) {
if (counter % 1000 == 0) {
ratio = (counter) / ((millis() - udpStart) / 1000);
Serial.println(str + "stats | iter=" + counter + " | err=" + errors + " | msg/sec=" + ratio);
}
if (sendUdpToServer(serverHostname) != 1) {
errors++;
};
}
udpEnd = millis();
Serial.println(str + "ENDED | Sent " + counter + " UDP packets in " + (millis() - udpStart) + " ms. with " + errors + " errors");
}
int sendUdpToServer(char* ip) {
if (Udp.beginPacket(ip, 4545) != 1) {
Serial.println("[UDP] Udp.beginPacket() failed");
return -1;
}
String(counter).toCharArray(buf, 100);
Udp.write(buf);
Udp.write(sep);
String(micros()).toCharArray(buf, 100);
Udp.write(buf);
Udp.write(nl);
if (Udp.endPacket() != 1) {
Serial.print("e");
return -1;
}
return 1;
}
Appendix: Wifi configuration
Configuration of hostapd running in Raspberry Pi:
# --------------------------------------------------------------------
# 2 Ghz (Arduino Nano 33 IoT)
# --------------------------------------------------------------------
interface=wlanrpi0
hw_mode=g
channel=10
ieee80211d=1
country_code=US
ieee80211n=1
wmm_enabled=1
ssid=********
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
wpa_passphrase=********
macaddr_acl=1
accept_mac_file=/etc/hostapd/accept_mac.txt
abdulmuqeet
Sending data from Arduino Nano 33 IoT to Raspberry Pi 4 using UDP