What Am I Trying To Do?
Hello guys. Im building an outdoor laser tag game. I want to send 504 byte data as fast as possible.
What Did I Do So Far?
Currently I send 24 byte packets. Every packet contains player information. I have 20 players.
Plus packet for general game commands. There are 21 packets in total.
Im sending one packet every 50ms from PC Server to Arduino Clients.
Im sending "here is my information" packet every 50ms from Arduino client to PC Server.
I can send all the packets in 1000ms succesfully(!) now.
What is the problem?
Problem is 1000ms latency itself.
If I try to lower 50ms sending cycle, Esp8266 or Arduino Mega freezes and fails to read packets.
So Im stuck with 1 second latency.
Equipment Used
Esp8266 (4mbit/s) Black Version by AI Thinker. 2016 Firmware came by default with it. Havent flashed
Arduino Mega 2560
100mbit Wi-Fi AP Router
115200 baud rate to communicate with Esp8266.
Video
My Code
My Visual Basic.Net Server Does These :
- We have 20 Players, We send a packet like <PlayerNo#DesiredHealthValue#CommandTrigger>
- Arduino checks if PlayerNo is equal to its own Player No.
- If they match, then it means this packet is for him.
- Then Arduino checks if HealthChangeCommand is different from local value.
- If its different, then it means server has sent a "new" command to be obeyed ( Change his health )
- This way, I wanted to implement a communication without ACK between PC Server and Arduino clients.
Visual Basic .Net Application Code ( converted to Arduino code )
// Send the packet for next player every 50ms.
int WhichPlayerNow = 1;
unsigned long LastTimeWeSent= 0;
void loop()
{
if ( ( LastTimeWeSent - millis() ) >= 50 ) // Every 20ms, Send Broadcast Udp message
{
if ( WhichPlayerNow <= 20 )
{
int id = WhichPlayerNow;
Udp.SendBroadcast(<id#DesiredHealthValue[id]#HealthChangeCommand[id]>");
LastTimeWeSent = millis();
WhichPlayerNow++;
}
else
{
WhichPlayerNow = 1;
}
}
}
void onButtonClick()
{
DesiredHealthValue[1] = 75; //We want to change player1's value
HealthChangeCommand++; //We change his trigger number so player1 knows it is fresh update
}
UDP broadcast messages look like this :
<1#100#0>
<2#100#0>
<3#100#0>
..
..
<20#100#0>
<1#100#0> // Start again
<2#100#0>
After button click :
..
<19#100#0>
<20#100#0>
<1#75#1>
<2#100#0>
..
..
..
Arduino Client Code :
#include <WiFiEsp.h>
#include <WiFiEspUdp.h>
char ssid[] = "Home";
char pass[] = "mypassword";
int status = WL_IDLE_STATUS;
unsigned int localPort = 3333;
unsigned long Sendinterval = 50; // any value lower than this causes lags in Esp8266 for me
unsigned long lastSent = 0;
int order = 1;
int myID = 1;
int myHealth = 75;
int myLastAttacker = 0;
int mySetHealthTrg = 0;
char packetBuffer[24];
char validBuffer[24];
char dataArray[8][8];
WiFiEspUDP Udp;
void setup() {
Serial.begin(115200);
Serial2.begin(115200);
WiFi.init(&Serial2);
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("ESP8266 Not Connected");
while (true);
}
while ( status != WL_CONNECTED) {
Serial.println("Connecting..");
status = WiFi.begin(ssid, pass);
}
Serial.println("Connection established..!");
Serial.println("Udp is beginning...");
Udp.begin(localPort);
Serial.println("Port ready!");
}
void loop()
{
if ( order == 1 ) // We split Sending and Receiving into turns
{
//// PACKET RECEIVING ////
int packetsize = Udp.parsePacket();
if (packetsize)
{
memset(packetBuffer, 0, sizeof(packetBuffer)); //Clear the packet buffer
int len = Udp.read(packetBuffer, 24); //Read into packet buffer
if (len > 0) {
packetBuffer[len] = 0;
}
int validPacketStartPoint= -1;
for (int i = 0; i <= 23 ; i++)
{
if ( packetBuffer[i] == '<' )
{
validPacketStartPoint = i + 1; // next character after '<' is our starting point
}
else if ( packetBuffer[i] == '>' && validPacketStartPoint != -1 )
{
memset(validBuffer, 0, 24); // clear the valid buffer
strncpy(validBuffer, packetBuffer + validPacketStarted, i - validPacketStarted);
// So far, we scanned the packetbuffer we got from Udp.read()
// We copied the part between '<' and '>' into validPacket[24]
// Now we can parse the validPacket
char *token;
for (int i = 0; i <= 8; i++) // Im expecting a 8 different data in same packet at maximum
{
if (i == 0) {
token = strtok(validBuffer, "#"); // parse data with # character
}
else {
token = strtok(NULL, "#");
}
if (token != NULL) {
memcpy(dataArray[i], token, 8); // copy every data into dataArray
}
}
PaketReceived(dataArray); // pass the whole data array to another function
}
}
}
////////////END OF PACKET RECEIVING///////////
order = 2;
}
else
{
/// START OF SENDING///
if ((millis() - lastSent) >= Sendinterval)
{
char tosend[15];
sprintf(tosend, "<%d#%d#%d>", myID, myHealth, myLastAttacker); // This is for the server
Udp.beginPacket("10.10.10.1", 27015);
Udp.write(tosend);
Udp.endPacket();
lastSent = millis();
}
/// END OF SENDING ///
order = 1;
}
}
void PaketReceived(char data[8][8])
{
if ( fast_atoi(data[0]) == myID )
{
// Data is For Me
if (mySetHealthTrg != fast_atoi(data[2])) // Local Trigger value and incoming value are different
{
myHealth = fast_atoi(data[1]); // Change our health
mySetHealthTrg = fast_atoi(data[2]); // Change our trigger, the command is old now.
}
}
}
int fast_atoi( const char * str )
{
int val = 0;
while ( *str ) {
val = val * 10 + (*str++ - '0');
}
return val;
}
How can I speed this up? How do these people even fly their quadcopters with wireless then?