WifiEsp (esp8266) partial UDP packets

I am write you because I am running out of ideas to fix it..

I have a java server controling a car robot by UDP. Basicly the robot send its sensor values and server is then sending movement direction and speed.

  • Using a ESP8266-ESP01 with firmware 1.5.4 at 115200 baud.
  • Using arduino mega at 115200 on Serial and 115200 on Serial1 connected to the ESP.

100% working :
Robot --> to Server

Half working :
Server -->to Robot

For testing purpose, the complet packet should look like the following :

ROORD|{"motor":{"direction":"neutral","speed":0,"time":0},"ip":"192.168.0.100"}

Wireshark prove that the server packets are full and correct. Ex:

0000 84 0d 8e 84 18 c5 00 22 4d 49 3b 7b 08 00 45 00 .....Å."MI;{..E.
0010 00 6b 3e 5b 00 00 80 11 00 00 c0 a8 00 64 c0 a8 .k>[......ˬ.dˬ
0020 00 77 11 5d 11 5f 00 57 82 94 52 4f 4f 52 44 7c .w.]._.W..ROORD|
0030 7b 22 6d 6f 74 6f 72 22 3a 7b 22 64 69 72 65 63 {"motor":{"direc
0040 74 69 6f 6e 22 3a 22 6e 65 75 74 72 61 6c 22 2c tion":"neutral",
0050 22 73 70 65 65 64 22 3a 30 2c 22 74 69 6d 65 22 "speed":0,"time"
0060 3a 30 7d 2c 22 69 70 22 3a 22 31 39 32 2e 31 36 :0},"ip":"192.16
0070 38 2e 30 2e 31 30 30 22 7d 8.0.100"}

I am reading packets at approximatly 10 packets / seconds. (but from test, the number of packets do not modify the accuracy)

Here is the code that read the packets :

bool haveUdpData() {

// if there's data available, read a packet
int packetSize = Udp.parsePacket(); //take 4 milliseconds maximum
if (packetSize) {

// read the packet into packetBufffer
int len = Udp.read(packetBuffer, 512);
if (len > 0) {
packetBuffer[len] = 0;
}

String dataReceived = String(packetBuffer);
Serial.println(dataReceived);

if (dataReceived.length() != packetSize) {
////Serial.print("Incorrect data received :");
}
else {
lastServerCommand = dataReceived;
////Serial.print("Last correct server command :");
}
return true;
}

return false;
}

If you check the image attached you will see that what is printed in the console is random. I am going from almost 100% accuracy to bad accuracy (like the attached image) where only one read is complet.

I think the first 32 chars are always accurate (ROORD|{"motor":{"direction":"neu) then it get random..

Any suggestion?

Also why am I geting sometimes:
1 - blank line
2 - +IPD,3,79,192.168.0.100,4445
3 - +IPD,3,79,192.168.0.100,4445:ROORD|{"motor":{

Rather than just the data?

Other specs :

  • Running a 1000 capacitor close to the esp.
  • Running a 700 milli_amp power supply for the arduino/esp8266/servo/distance sensor/proximity sensor; powered by a 12 volts lipo battery
  • Dropping the voltage from the Arduino serial pin to 3.3v with resistor.
  • Car motors are running from another battery.

For my test, the Arduino is connected directly to the computer, not the powersupply.

Libraries used :
#include <Servo.h>
#include <WiFiEsp.h>
#include <WiFiEspUdp.h>
#include <Metro.h>
#include <ArduinoJson.h>

Thank you very much!

Please use code tags (</> button on the toolbar) when you post code or warning/error messages. The reason is the forum software can interpret parts of your code as markup, leading to confusion, wasted time, and a reduced chance for you to get help with your problem. This will also make it easier to read your code and to copy it to the IDE or editor. If your browser doesn't show the posting toolbar, then you can just manually add the code tags:
[code]``[color=blue]// your code is here[/color]``[/code]
Using code tags and other important information is explained in the How to use this forum post. Please read it.

Please post your full sketch. If possible, you should always post code directly in the forum thread as text using code tags (</> button on the toolbar). This will make it easy for anyone to look at it, which will increase the likelihood of you getting help. If the sketch is longer than the forum will allow then it's OK to add it as an attachment. After clicking the "Reply" button, you will see an "Attachments and other settings" link.

When your code requires a library that's not included with the Arduino IDE please post a link (using the chain links icon on the toolbar to make it clickable) to where you downloaded that library from or if you installed it using Library Manger (Sketch > Include Library > Manage Libraries in the Arduino IDE or Libraries > Library Manager in the Arduino Web Editor) then say so and state the full name of the library.

Are you sure packetBuffer is large enough to hold the packet? Assuming it's a string, you also need to make it one larger than the maximum number of characters for the null terminator.

justicex:

		String dataReceived = String(packetBuffer);
	Serial.println(dataReceived);

I very much doubt it's necessary to do that. I recommend against using String ever.

justicex:

		if (dataReceived.length() != packetSize) {

You should be able to do this instead:

		if (strlen(packetBuffer) != packetSize) {

justicex:

			////Serial.print("Incorrect data received :");

Why did you comment out the useful debug output that could help you with your problem?

Here is the full sketch! (In attachment since too long)

Bare in mind that I am a java programmer..so the C and C++ are not my strength:)

The success rate/count is kind of incorrect, I there is a lot of info printed to improve it.

From manual log count, there is 134 / 159 correct direction (neutral written in full). But the success rate seems random. Can be very high, to low.. which isn't nice when controling robot with the computer keyboard..

<WiFiEsp.h> WiFiEsp library
<WiFiEspUdp.h> WiFiEsp library

Modified with the fork to define a max read timeout of 100ms
WiFiEsp library - unhardcoded timeout

<Metro.h> Metro library
"MotorDriverController.h" homemade
"ProximitySensorModule.h" homemade
"UltrasonicDistance.h" homemade
<ArduinoJson.h> ArduinoJson

Are you sure packetBuffer is large enough to hold the packet? Assuming it's a string, you also need to make it one larger than the maximum number of characters for the null terminator.

The buffer was indeed missing one char for the null terminator. (fixed) While I don't think it was a problem for this command since it's around 79 chars long.

You should be able to do this instead:if (strlen(packetBuffer) != packetSize) {

Changed the code.

Why did you comment out the useful debug output that could help you with your problem?

I commented just to make the output shorter, but I reactivated many prints.

Dudeba.ino (13.4 KB)

log.txt (61.2 KB)

MotorDriverController.cpp (4.77 KB)

MotorDriverController.h (1.61 KB)

ProximitySensorModule.cpp (2.82 KB)

ProximitySensorModule.h (1.15 KB)

UltrasonicDistance.cpp (1.08 KB)

UltrasonicDistance.h (735 Bytes)

String can cause memory fragmentation and there is not a lot of memory to work with on a microcontroller. This is a significant difference between programming a computer and programming a microcontroller. I know the ArduinoJson library does tend to be used with String, and there are likely safe ways to use String (I'm not an expert since I have never used them) but they are one of the culprits we tend to blame first when there are mysterious bugs like this. Nothing else jumps out at me from your code, though I haven't looked at it super closely.

This "+IPD,3,79,192.168.0.100,4445:" thing is added to the start of the received network data by the ESP8266's AT firmware. I'd expect the WiFiEsp library to strip that before filling packetBuffer, and it does seem to do that most of the time.

Have you for sure captured one of the problematic packets with WireShark and verified it's no different from the non-problematic packet? It might be good to look at the packet before the problematic packet also.

The possible causes I can think of are: Memory corruption, bug in the WiFiEsp library, bad network data. The WireShark could eliminate the third possibility at least.

I actually found something interesting, but I have no explanation or solutions :frowning:

I found out that if the Ultrasonic sensor (HC-SR04) is returning an invalid answer (distance higher than 4 meters), I get a 100% incorrect value on the esp8266 reading !!! But if it reads below 4 meters then the reading return around 85% complete and correct reading.

IE 100% failures :
Incorrect data received :ROORD|{"motor":{"direction":"neuOORD|{"motor":{

Correct string
ROORD|{"motor":{"direction":"neutral","speed":0,"time":0},"ip":"192.168.0.100"}

Board : Arduino Mega 2560

Ultrasonic : HC-SR04
Trigger -> A0
Echo -> A1

Esp8266
TX1 / RX1

For the test, the Arduino Mega is not connected to the powersupply, but is connected directly to the computer usb.

Power supply is Smraza 700ma.

Both connected on same powersupply but HC-SR04 on 5v and Esp8266 on 3.3volts.

Is there a conflict between either the pins or timers? Is ultrasonic delayMicroseconds causing a problem?

After further testing I get other interesting data :

If I desactivate all ultrasonic coding, I get about 100% accurate reading (on over 500 readings).

If I do one/many collisions on my (4 channels obstacle avoidance) with tone/140ms delay on collision.. I get some incorrect reading (+- 3%).

If I do collisions without tone/delay (tone(speaker, 140, 100);delay(140);), then I get a 100% accurate reading...

Are delay()/delayMicroseconds() messing with the RX1/TX1 pin of the Arduino Mega or reading with the Esp8266?