Asked

Hello ,
I am experiencing inconsistent UART data transfer from the EZ-B v4 to an Arduino Mega 2560. Single-byte transfers are very consistent between these two devices, but when I attempt to transfer 8 bytes, the reliability decreases significantly. I have attached samples of JavaScript and C++ code that I am using. Could you please examine this code and provide recommendations to increase the reliability of the data transfer?
Thank you very much.
Jack
JavaScript Code:
UART.initHardwareUart(0, 9600, 0);
sleep(10);
var pathTotalDistance = getVar("$pathTotalDistance");
var pathEndpointDistance = getVar("$pathEndpointDistance");
var oppositeDistance = getVar("$oppositeDistance");
var actualCourse = getVar("$actualCourse");
var desiredCourse = getVar("$desiredCourse");
var highByte = (pathTotalDistance >> 8) & 0xFF;
var lowByte = pathTotalDistance & 0xFF;
UART.hardwareUartWrite(0, [highByte, lowByte]);
print("Sending pathTotalDistance high byte: " + (pathTotalDistance >> 8));
print("Sending pathTotalDistance low byte: " + (pathTotalDistance & 0xFF));
print("pathTotalDistance: " + pathTotalDistance);
var highByte = (pathEndpointDistance >> 8) & 0xFF;
var lowByte = pathEndpointDistance & 0xFF;
UART.hardwareUartWrite(0, [highByte, lowByte]);
print("Sending pathEndpointDistance high byte: " + (pathEndpointDistance >> 8));
print("Sending pathEndpointDistance low byte: " + (pathEndpointDistance & 0xFF));
print("pathEndpointDistance: " + pathEndpointDistance);
var highByte = (oppositeDistance >> 8) & 0xFF;
var lowByte = oppositeDistance & 0xFF;
UART.hardwareUartWrite(0, [highByte, lowByte]);
print("Sending oppositeDistance high byte: " + (oppositeDistance >> 8));
print("Sending oppositeDistance low byte: " + (oppositeDistance & 0xFF));
print("oppositeDistance: " + oppositeDistance);
UART.hardwareUartWrite(0, [actualCourse]); // Send as one byte
UART.hardwareUartWrite(0, [desiredCourse]); // Send as one byte
print("Sending actualCourse: " + actualCourse);
print("Sending desiredCourse: " + desiredCourse);
setVar("$actualCourse", (Servo.GetPosition(17)));
halt();
C++ Code:
long pathTotalDistance = 0;
long adjacentRemainingDistance = 0;
long pathEndpointDistance = 0;
float oppositeDistance = 0;
float desiredCourse;
long actualCourse;
float diffCourse = 0;
float lastDiff = 100;
int lastIncomingByte;
int run = 0;
void setup() {
Serial3.begin(9600); // Communication with EZ-B
Serial.begin(9600); // Debugging via Serial Monitor
}
void loop() {
if (run == 0) { // State of RUN when the robot has yet to begin movement towards the reflector.
if (Serial3.available() >= 8) {
// Read and store bytes for pathTotalDistance
byte highBytePTD = Serial3.read();
byte lowBytePTD = Serial3.read();
pathTotalDistance = (highBytePTD << 8) | lowBytePTD;
// Read and store bytes for pathEndpointDistance
byte highBytePED = Serial3.read();
byte lowBytePED = Serial3.read();
pathEndpointDistance = (highBytePED << 8) | lowBytePED;
// Read and store bytes for oppositeDistance
byte highByteOD = Serial3.read();
byte lowByteOD = Serial3.read();
oppositeDistance = (highByteOD << 8) | lowByteOD;
actualCourse = Serial3.read(); // Read and store actualCourse
desiredCourse = Serial3.read(); // Read and store desiredCourse
// Print the above received parameters
Serial.print("pathTotalDistance: ");
Serial.println(pathTotalDistance);
Serial.print("pathEndpointDistance: ");
Serial.println(pathEndpointDistance);
Serial.print("oppositeDistance: ");
Serial.println(oppositeDistance);
Serial.print("actualCourse: ");
Serial.println(actualCourse);
Serial.print("desiredCourse: ");
Serial.println(desiredCourse);
delay(10);
// run = 1;
}
}
}
I look forward to your insights on improving the reliability of this data transfer process.
Related Hardware EZ-B v4
Related Controls
User Defined Function Example
ArduinoComs
I can tell you right away what's wrong. This..
You're checking for more than 8 bytes available. So if there's 9, or 10, because the loop is faster than the uart transmission speed, the read will get out of sync. You're wanting to send "packets" it looks like. A packet would normally have a header and a byte length, but at the least, it would need header with a known number of bytes. Now, if that's the only "packet" you're sending, over and over, then you can assume the byte length.
I'd use MOD to ensure there's packets...
That will tell you if there's at least one packet. @athena, what do you think?
Hello Jack,
DJ_Sures has pointed out a crucial aspect of your code that could be causing the inconsistency in your UART data transfer. Let's break it down and see how you can improve the reliability of your data transfer between the EZ-B v4 and the Arduino Mega 2560.
Key Points to Consider:
Packet Structure:
Buffer Management:
if (Serial3.available() % 8 == 0)
to ensure you have a complete packet before reading.Synchronization:
Error Checking:
Timing and Delays:
delay()
in your Arduino code to match the data processing speed.Example Adjustments:
JavaScript Code:
C++ Code:
By implementing these changes, you should see an improvement in the reliability of your UART data transfer. If you have any further questions or need additional assistance, feel free to ask!
I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
Athena's suggestion is more scalable if you're adding more protocol packet types of varying length and data. My suggestion would only work if you're always sending the same packet length of your protocol that you're inventing. So if you wanna scale it, use athena's answer. If you think it would always be the same information and same packet length then you can use mine.
Hello @Athena and @DJ, Thank you so much for your input. I was able to get the following C++ code to work. It became very reliable once I removed the "print" commands out of the "UART.write" sequences.
I've tried your suggestion:
but I am unable to get it to run. Could you please insert your recommended code into the sample above for me? Could you please explain what the following code means?
I know it's late for you, so I'll check back in tomorrow morning. Thank you so much. Jack
Hello Jack,I'm glad to hear that you've made progress with your code! Let's clarify the use of the modulo operator (
%
) in the context of checking for complete packets and integrate it into your existing code.Explanation of the Modulo Operator in This Context:
%
) is used to find the remainder of a division operation.Serial3.available() % 8 == 0
ensures that the number of bytes available in the buffer is a multiple of 8. This means you have a complete packet to read.Integrating the Modulo Check into Your Code:
Here's how you can integrate the modulo check into your existing loop:
Key Points:
if (Serial3.available() >= 9)
ensures that there are at least 9 bytes available before attempting to read a packet.if (Serial3.available() % 8 == 0)
ensures that the number of available bytes is a multiple of 8, indicating a complete packet.By using this approach, you can ensure that your code only processes complete packets, which should improve the reliability of your data transfer. If you have any more questions or need further assistance, feel free to ask!
I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
Hello @Athena, Thank you for your continued support. I was able to get MOD to run, just not reliably. I occasionally have other UART data being sent, and while it is in the buffer, may initiate a rejection for the 8 bytes. So far, the above code runs well, so thanks again @DJ and @Athena! Jack
Hello Jack,Im glad to hear that your code is running well! The occasional rejection you mentioned could be due to other UART data interfering with your packet structure. Here are a few additional tips to help manage this situation:
Additional Tips for Managing UART Data:
Buffer Flushing:
Unique Header:
0xAA
) is unique and unlikely to appear in other data. This helps in correctly identifying the start of a packet.Timeout Mechanism:
Error Handling:
Separate Channels:
Example of Buffer Flushing:
Here's a simple way to flush the buffer before reading a new packet:
By implementing these strategies, you can improve the reliability of your UART communication even when other data is present. If you have any more questions or need further assistance, feel free to ask!
I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
Hello @Athena, So, in the last post you suggest code that flushes the buffer before checking if (Serial3.available() >= 9). As this loops, wouldn't it flush the packet before it could be read? Does Buffer Flush empty the entire buffer? Thanks Jack
Hello Jack,Great question!You're correct in noting that flushing the buffer before checking for available bytes could inadvertently remove data you want to read. Let's clarify how to use buffer flushing effectively.
Understanding Buffer Flushing:
Correct Usage in Your Context:
Example of Proper Buffer Flushing:
Here's how you might incorporate buffer flushing only when necessary:
Key Points:
By using buffer flushing judiciously, you can maintain the integrity of your data while still managing errors effectively. If you have more questions or need further clarification, feel free to ask!
I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.