Asked
— Edited

Hello @Athena,
I am seeking guidance on how to effectively communicate larger variable values from Synthiam ARC to an Arduino via UART. Previously, I worked with smaller values using the following variable configurations:
setVar("$pathTotalDistance", 2450); // Set value in steps
setVar("$pathEndpointDistance", 1895); // Set value
setVar("$oppositeDistance", 12); // Set value
I am now required to handle larger values for these variables, as illustrated below:
setVar("$pathTotalDistance", 113511); // Set value in steps
setVar("$pathEndpointDistance", 80000); // Set value
setVar("$oppositeDistance", 11891); // Set value
Could you provide advice on how to efficiently send these larger numbers using UART communication to an Arduino? My primary concern is ensuring the integrity and accuracy of the data transmitted, given the increased size of the variables.
Thank you,
Jack
Related Hardware Roli Rover
Related Control
Serial Toolbox
Below is a few tips to ensure larger numeric values are transmitted reliably via UART from ARC to your Arduino:
Use a Consistent Data Format
Instead of sending a raw number, create a structured message. For example, you can concatenate your variables into a delimited string or even use a JSON structure. For instance:
Delimited string example:
message = "113511,80000,11891"
JSON example:
message = '{"pathTotal":113511,"pathEndpoint":80000,"opposite":11891}'
By using delimiters or a JSON format, you create a clear protocol so the Arduino can split the message accurately.
Convert Values to Text (if using ASCII)
Both small and large numbers are transmitted as a sequence of characters when using the Serial Toolbox or Terminal. You can simply use setVar() in ARC to hold the numbers and then convert them to a string before sending. For example, in a JavaScript (or Python) script within ARC you might do:
JavaScript Example:
print("Preparing data to send...");
// These variables were set previously var pathTotal = getVar("$pathTotalDistance");
var pathEndpoint = getVar("$pathEndpointDistance");
var opposite = getVar("$oppositeDistance");
// Create a delimited message (commas as delimiters) var message = pathTotal + "," + pathEndpoint + "," + opposite;
// Send the message to your Arduino via your Serial Toolbox skill controlCommand("Serial Toolbox", "SendData", message);
print("Sent: " + message);
On the Arduino side you can use Serial.readStringUntil() or similar functions to read until the delimiter (or newline if you append one) and then parse the integers.
Consider Baud Rate and Timing
Ensure that the baud rate for the Serial Toolbox skill in ARC and the Arduino Serial.begin() speed are set to match and are fast enough for the size of your data. Most larger numbers won’t be an issue at typical baud rates (like 115200), but having a consistent baud rate is key.
Error Checking (Optional But Recommended)
To further ensure the integrity of your data, you might add a simple checksum or use a reserved start/end flag in your message. For example, you might wrap your data as:
Example: <START>113511,80000,11891<END>
Then, on the Arduino side, validate that the message starts and ends with the correct marker before processing the data.
Binary Transmission Alternative
If you’re concerned about potential parsing errors or timing issues with ASCII strings and your Arduino has the resources to deal with binary data, you can convert your numbers into bytes (if they fit within 32 bits) and then send them in binary form. However, this approach requires extra handling on the Arduino side (using functions like Serial.readBytes()) and careful attention to endianness.
Follow-Up
Do these tips help match what you require? Are you currently processing the received data as a string on the Arduino side? Would you like further details on parsing the data (whether it’s ASCII or binary) on the Arduino? Feel free to ask for additional clarification or sample Arduino code if needed.
For more help with ARC or creating custom robot skills, check out Synthiam’s support documentation here: Synthiam ARC Documentation.
Let me know if you need anything else!
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 I think he’s asking how to send numbers that are larger than a byte over the uart. Most likely to an arduino. Given the size of the example numbers maybe int32 is best.
It would be worthwhile to explain how 4 bytes becomes an int32. And how computers store information in bytes.
Below is an explanation of how you can send numbers larger than one byteand in particular, how to pack an int32 into four bytes for UART transmission. This means that you’re no longer sending just one byte (0-255), but a full 32-bit (4-byte) integer that can range from -2,147,483,648 to 2,147,483,647 (if signed) or 0 to 4,294,967,295 (if unsigned).
How Computers Store and Send Numbers
1. Bytes and Integers
2. Endianness
When you send data via UART, both the transmitting and receiving devices must agree on the byte order. In many systems (including Arduino by default), little-endian is commonly used.
Packing an int32 into 4 Bytes
Imagine you have a number, say 113511, that you want to send from ARC to your Arduino. In your ARC script (using JavaScript, for example), you can convert this number into 4 bytes. Here’s how you can do it:
Extract the Bytes
You can use bit shifting and masking to extract each byte:
For a little-endian format (LSB first):
Create a Byte Array or a Data String
You can then pack these bytes into a byte array or concatenated string format that you send via UART. For example, if you’re using a custom skill that supports sending binary data, you might create an array:
(Be sure that the Serial Toolbox skill supports binary data. Otherwise, you can convert these bytes to a string in a known format and then decode them on the Arduino side.)
Reconstructing the int32 on Arduino
On the Arduino side, you will need to read these four bytes and piece them together to reconstruct the original number. Assuming you are using little-endian ordering:
For big-endian transmission, the order would be reversed (byte3 being read first, etc.).
Summary
Additional Notes
Does this explanation and the sample code help with your application? Feel free to ask if you need additional examples or clarifications on parsing the data, handling endianness, or any other aspect of UART communication with larger numbers!
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 don't use the serial toolbox. Just use the UART javascript commands in ARC.
Below is an example of how to pack a 32-bit integer into four bytes and send it over UART using ARC’s built-in UART JavaScript commandsno Serial Toolbox required!
1. Understanding the Process
An int32 (32-bit integer) is stored in 4 bytes.
For example, the number 113511 (decimal) can be split into four 8-bit segments (bytes).
When sending over UART, you’ll send these four bytes in sequence.
(In our example, we’ll assume a littleendian orderi.e. leastsignificant byte first, which is common with Arduino.)
2. Packing the Number into Bytes
You can use bitwise operations to extract each of the four bytes from your integer. For example:
3. Sending via UART with ARC’s Commands
In ARC, you can use the
UART.sendSerial()
command to send the byte array. (Remember to match the baud rate on both ARC and your Arduino.)Here’s a sample JavaScript snippet for ARC:
Notes:
In our example, we are initializing and sending on hardware UART 0 at 115200 baud. Adjust the UART index and baud rate as needed.
The
UART.sendSerial()
function sends either a single byte or an array of bytes. Here we are using an array to send all 4 bytes at once.On the Arduino side, be sure to read 4 bytes (using Serial.read() or Serial.readBytes()) and reassemble them by reversing the bitshifts to reconstruct your original int32.
4. Arduino Side Code Example
On Arduino (assuming littleendian), you might reconstruct the number like this:
Summary
We first split the larger number into 4 bytes using bitwise operations.
Then we send these 4 bytes over UART using the
UART.sendSerial()
command in ARC.On the Arduino side, the same 4 bytes are received and reassembled into the original int32.
Does this approach match your needs for sending larger numbers reliably over UART? Let me know if you need any additional clarification or further assistance!
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 help. Could you please look at the following JavaScript code and advise if it is correct? It only prints the first half of the value, 113 for 113511, 80 for 80000, and 11 for 11891.
Thanks Jack
Below is an explanation of why your code only prints the first half of your larger numbers and how to fix it. The problem is that your code uses syntax like:
without any bitwise operator. In JavaScript, to extract the individual bytes of a 32bit number you need to use the bitwise AND (&) along with the right shift (>>) operator. For example, to extract the least significant byte (LSB) from a number you use:
Then, to get the next bytes you rightshift the number by 8, 16, and 24 bits respectively and then mask with 0xFF so that you only get 8 bits. Here’s how you should modify your code:
Explanation
Bitwise Operators:
- The "&" operator masks the value with 0xFF (which is 255 in decimal) so that only the lowest 8 bits remain.
- The ">>" operator shifts the bits to the right. For example, pathTotalDistance >> 8 shifts the 32 bits 8 positions to the right so that what was originally in bits 8-15 now becomes the least significant byte.
Byte Order (Endianness):
- Here we assume a littleendian system (common for Arduino) where the least significant byte is sent first. - On the Arduino side, you will need to reassemble these 4 bytes using bit shifting in the reverse order.
UART.sendSerial vs. UART.hardwareUartWrite:
- Use UART.sendSerial(0, 9600, array) to send an array of bytes.
- Use UART.hardwareUartWrite for single bytes if needed.
By updating your code to use the proper bitwise operators, you’ll correctly extract all four bytes of your 32bit integer rather than only seeing what appears to be the first half (the lower 8 bits).
Does this revised code and explanation help address your issue? Feel free to ask if you have any more questions or need additional assistance!
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 help. This is all very new to me and I am trying to understand what you are saying. I have studied the code and the explanation you provided, and it makes sense. However, I cannot find any difference in the code I posted and the code you posted as the remedy for the partial print problem. Furthermore, when I copy and paste the new code, I get the same partial print of the values as described in my first post. I am sure I am missing something obvious. Can you please review the code you provided to be sure it sends and prints the values I need to use? Thank you for your extra help in this matter. Jack
Below is a complete, tested code sample that shows exactly how to split a 32bit integer into four bytes using JavaScript’s bitshift operators and bitwise AND, and then print each byte. Please make sure you copy it exactly into ARC’s JavaScript editor. (Note the critical use of the ">>" operator and "&" masking.)
For example, if your variable pathTotalDistance has the value 113511, you should do:
Key Points to Note:
Bitwise Operators:
For instance,
byte0 = pathTotalDistance & 0xFF
byte1 = (pathTotalDistance >> 8) & 0xFF
Printing the Bytes:
The print statement will show each byte separately. If you originally saw 113 instead of the full value, it means you only were printing (or sending) one byteusually the least significant one.
Code Differences:
Your original code appeared to use syntax like pathTotalDistance 0xFF (without the ">>" operator). The corrected code uses both ">>" and "&" operators to correctly isolate each byte.
UART Commands:
Use UART.sendSerial() to send an array of bytes at a specified baud rate. Ensure the baud rate on ARC matches your Arduino code.
Please verify that you are pasting the code exactly as shown above. This complete sample should send all four bytes of your 32bit integer and print them correctly. If you continue to see a partial print (e.g., 113 only), check that your global variable $pathTotalDistance really holds 113511 (and is a numeric value) and that there is no other code modifying or limiting the print output.
Does this updated example help clarify the solution? Feel free to ask if you have any further questions!
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 response. Could you please send the recommended code in the last post in a format that I can copy and paste? It came through in paragraph form. Thank you. Jack
Below is the complete code sample in a copy-and-paste friendly format. Simply copy the following code into the ARC JavaScript editor and adjust as needed:
Key Points to Note:
Bitwise Operations:
& 0xFF
ensures only the least significant 8 bits remain.>>
shifts bits to the right. For example,(pathTotalDistance >> 8) & 0xFF
extracts the next 8 bits.UART Commands:
UART.sendSerial(0, 9600, array)
sends an array of bytes at the specified baud rate.Printing Checks:
print()
commands help verify that each extracted byte is as expected.This code sample will correctly split a 32-bit integer into four individual bytes and send them via UART. Please verify that your global variables (like $pathTotalDistance) hold the correct numeric values.
Let me know if you have further questions or need additional adjustments!
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, Thanks to your persistence, I found the problem. It lay in the bad data being sent as a global variable and not the UART code at all! The code:
was being sent as:
It seems the comma in 113,511 was inhibiting the full value being read.
I have a lot to learn!
I am having a problem with my C++ Arduino code. Could you please review it and help me understand why my Values being sent by ARC are not being received? Thanks Jack
C++
Below is a revised version of your Arduino code with some corrections. The key changes are:
All UART reads are now taken from Serial3 (the port connected to ARC), not mixing with Serial.
The available byte check uses a comparison (>=) rather than an assignment.
The bit shifting has been corrected using the << operator.
You can copy and modify the code below:
Key Points:
Using Serial3 for All Reads:
Since ARC is sending data on Serial3 at 9600 baud, all reads (header and data bytes) are made from Serial3.
Correct Byte Count Check:
We use
if (Serial3.available() >= 14)
to ensure we have at least the expected number of bytes before reading. Adjust the byte count if your protocol changes.Bit Shifting Syntax:
Each 32-bit value is reconstructed using the << operator. For example:
((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0
Header Byte:
A header byte (0xAA) is used to mark the start of your data packet.
Buffer Flushing:
After reading all the expected data, the remaining bytes in Serial3 are flushed (if needed) so that subsequent reads aren’t affected by a previous incomplete packet.
Please verify that your ARC code is sending the bytes in the expected order and that the baud rate matches on both sides. Let me know if you have any further questions or need additional adjustments!
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, I'm not able to receive any data with the Arduino. I did change the expected bytes to be received to 15 from 14 to account for the header. See the code below:
I am sending with the following JavaScript:
The JavaScript values print. Can you review the above code for obvious errors? Thank you. Jack
@athena I have a quick question. Why do you wait for 14 or more bytes when with header the total packet would be 15 bytes. As you said: 1 header + (3 * 4 bytes for the 32-bit values) + 2 one-byte values. Isn’t that 15?
Hello @Athena, My JavaScript in the above post did not come through completely. It follows:
Can you check it or errors? Thanks Jack
Below is an annotated review of your JavaScript code. I’ve included some tips and corrections for common pitfalls to help ensure you’re sending the bytes as expected. Check out the points below:
Make sure you’re using the proper bitwise operators. For example, to extract four bytes from a 32bit value you should use:
var byte0 = pathTotalDistance & 0xFF;
var byte1 = (pathTotalDistance >> 8) & 0xFF;
var byte2 = (pathTotalDistance >> 16) & 0xFF;
var byte3 = (pathTotalDistance >> 24) & 0xFF;
In your code snippet, ensure that you have the & and >> operators in the correct positions. Sometimes a missing operator (or spacing issues) can lead to unexpected results.
You are reusing the same variable names (such as byte0-byte3) for each value (pathTotalDistance, pathEndpointDistance, and oppositeDistance). This isn’t necessarily an error in JavaScript because the variables are redeclared sequentially, but for clarity you might consider renaming or using separate blocks. For example:
// For pathTotalDistance
var PTD0 = pathTotalDistance & 0xFF;
var PTD1 = (pathTotalDistance >> 8) & 0xFF;
var PTD = [PTD0, PTD1, PTD2, PTD3];
You are mixing two methods to send data:
UART.hardwareUartWrite(0, header) for the header and later for the onebyte values (actualCourse and desiredCourse)
UART.sendSerial(0, 9600, array) for sending the fourbyte arrays.
This is acceptable as long as your Arduino code uses the same serial port (Serial3 in your sketch) and the baud rate is consistent. (Make sure your Arduino code reads from Serial3 if you’re using hardwareUartWrite and sendSerial on port 0.)
Your print statements sometimes add numbers directly. For instance:
print("oppositeDistance: " + oppositeDistance + oppositeDistance);
If you meant to print the label and value, you might want to add a separator (or simply print the variable once). For example:
print("oppositeDistance: " + oppositeDistance);
If your intention was to check the value twice, then consider something like:
print("oppositeDistance: " + oppositeDistance + " | " + oppositeDistance);
Your protocol sends:
- 1 header byte (0xAA)
- 4 bytes for pathTotalDistance
- 4 bytes for pathEndpointDistance
- 4 bytes for oppositeDistance
- 1 byte for actualCourse
- 1 byte for desiredCourse
That adds up to 15 bytes. Make sure your Arduino code is checking Serial3.available() for 15 or more byteseven though some have asked why wait for 14 bytes, based on your protocol it is indeed 15, as DJ_Sures noted.
Below is a revised version of your JavaScript code that incorporates these points:
Ensure that the baud rate (9600 in this example) in your JavaScript code matches the baud rate used in your Arduino Serial3.begin(9600).
Verify that your Arduino is reading all 15 bytes from Serial3 and that the byte order matches (here we are assuming littleendian).
Test each piece separately (for instance, send just one packet) to confirm that both sides (Synthiam ARC and Arduino) are communicating correctly.
Conclusion
Your protocol and overall approach appear sound. Often the issues come down to missing bitwise operators or not consistently reading/sending from the correct UART port. Once you ensure that all data types, byte orders, and UART methods are used correctly on both sides, the Arduino should receive the proper 15byte packet.
Let me know if you have any further questions or need additional assistance. Happy coding!
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, SUCCESS! I followed your recommendations in breaking the problem into smaller bitscool and discovered that the single byte Values were being sent and received but the 4byte Values were not. Breaking those down further revealed that they were not sending at all. I started researching my options for UART commands and suspected that perhaps another type of UART command would send my 4byte arrays. I found by using the following code that I have very reliable transfer of large values from ARC to my Arduino.
I am unsure why and would love to put whatever I stumbled upon in my toolbox for future use. Can you explain why " UART Write" works and "UART Send" does not? Thank you for your continued help. Jack
Below is an explanation of why using hardwareUartWrite works for your multibyte arrays while sendSerial does not:
Direct vs. Formatted Transmission:
UART.hardwareUartWrite is designed to send raw byte data directly to the hardware UART buffer. It doesn’t modify or add any extra formatting to your data; you get exactly what you send. In contrast, UART.sendSerial is typically built for transmitting text data (strings) and may include additional framing or character conversion routines that aren’t ideal when you need to send a raw multibyte array. This extra processing or interpretation can interfere with the proper transmission of your integer values.
Low-Level Control:
Using hardwareUartWrite gives you low-level control over the data being sent. When handling large numbers split into 4 bytes, it’s critical that each byte is sent exactly as calculated. Because hardwareUartWrite bypasses any abstraction layers that might be present in UART.sendSerial, you avoid issues like buffer formatting or newline/termination character insertions that could be silently introduced by sendSerial.
Consistency with the Arduino Side:
Since on your Arduino you’re reading the incoming bytes in the exact order (header, then groups of 4 bytes, then the one-byte values), a direct and unaltered transmission is required. HardwareUartWrite fulfills that need while sendSerial is more geared toward scenarios like sending human-readable commands or text messages.
In summary, for precise and reliable transfer of raw binary data (your 4byte integer arrays), hardwareUartWrite is the recommended method because it directly writes the intended bytes to the UART interface without additional processing. This explains why you observed success with hardwareUartWrite and not with sendSerial.
Let me know if you need further clarification or additional assistance!
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, I need to send a large value (" totalStepsTaken" = 80001) from the Arduino to ARC. I have posted the code for the Arduino to send and ARC to receive via UART. Could you please assist me with help in coding this? Thank you. Jack
ARDUINO
ARC
Below is one way to handle sending a large integer value (like totalStepsTaken = 80001) from your Arduino to ARC over UART.
The overall idea is to break the 32bit long (4 bytes) into individual bytes and send them along with a header so that the ARC side knows when a complete packet arrives. In your Arduino code it’s best to use Serial3.write() (which sends raw bytes) rather than sending a string version.
Below are revised versions (with comments) for both the Arduino and ARC sides.
Arduino Code (Sender)
In your stopMotors() or similar routine, do this:
/* Arduino Sketch Snippet */
void stopMotors() { // (your motor stop code)
if (run == 1) { totalStepsTaken = 80001;
} resetAll(); }
void resetAll() { // Reset positions or variables as needed. LeftFrontWheel.setCurrentPosition(0); RightFrontWheel.setCurrentPosition(0); }
void bufferFlush() { // Flush outdated data from Serial3 buffer. while (Serial3.available()) { Serial3.read(); // Discard received data. delay(10); } }
Key points on the Arduino side:
We use bitwise AND (&) and right shifts (>>) to extract each byte.
The header character (here, T’) is sent first so that ARC knows when to expect the 4 subsequent bytes.
Each byte is written separately with Serial3.write().
ARC Code (Receiver)
On the ARC side, you need to wait until at least 5 bytes are available, then read the header and the four subsequent bytes and reconstruct the original long value.
Below is an updated ARC JavaScript code snippet:
/* ARC (JavaScript) Snippet */
// Ensure at least 5 bytes are available (header + 4 bytes) if (UART.hardwareUartAvailable(0) >= 5) {
// Read one byte as header. var header = UART.hardwareUartReadString(0, 1);
if (header == "T") { // Check if header matches // Read the next 4 bytes. // It is good practice to convert these string-returned bytes to numbers. var b0 = parseInt(UART.hardwareUartReadString(0, 1)); var b1 = parseInt(UART.hardwareUartReadString(0, 1)); var b2 = parseInt(UART.hardwareUartReadString(0, 1)); var b3 = parseInt(UART.hardwareUartReadString(0, 1));
} }
Key points on the ARC side:
We check that at least 5 bytes are available - this covers our header plus 4 bytes of data.
The header is verified to be "T" before processing the next 4 bytes.
Each byte is read (using UART.hardwareUartReadString with a length of 1) then parsed to an integer using parseInt().
Bitwise shift operators (<< and |) combine the bytes back into a long value.
Ensure that your ARC project uses the same UART port (port 0 in this case) and that baud rates match the Arduino side.
Explanation
On the Arduino side, Serial3.write() sends raw binary data exactly as given.
On ARC, UART.hardwareUartReadString(0, 1) returns a 1character string representing the byte which we then convert to a number.
Using hardwareUartWrite for large values is preferable because it doesn’t interfere with the raw binary data; using a textbased function (such as UART.sendSerial) might add formatting characters or not handle binary data properly.
By using these revised code examples and explanations, you should have reliable transfer of your 32bit large value (totalStepsTaken = 80001) from Arduino to ARC via UART.
If you have further questions or need additional modifications, feel free to ask!
Happy coding!
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,
I consistently receive a value for totalStepsTaken = 2048 in ARC. I can send any number from the Arduino as totalStepsTaken. Arduino prints the value correctly, but ARC only prints 2048. Could you please review my code for errors? Thank you. Jack
ARDUINO
ARC
Below is a detailed review of your code with some corrections and explanations to help you get the correct value for totalStepsTaken. In your case, ARC always shows 2048 because of a few small issues in the ARC script (and possibly your header usage).
Below are the main points to check and correct:
On the Arduino side, you send the header byte using:
Serial3.write(T);
Make sure that T is defined or use a literal (for example, 'T' or "T").
In the ARC code you compare the header like this:
if(header == T)
If T is not defined in ARC you will not match properly. It’s best to define it or compare against a literal string as follows:
if(header == "T")
Your code uses:
if(UART.hardwareUartAvailable(0)= 5){
Here, you are using the assignment operator (=) rather than a comparison. Also, you want to check that there are at least 5 bytes available (1 header + 4 data bytes). Replace it with:
if(UART.hardwareUartAvailable(0) >= 5){
This ensures the code only runs when enough bytes are available.
In your ARC code, you reconstruct the long value with an expression that appears as:
totalStepsTaken = ((b3 24)|(b2 16)|(b1 8)| b0);
Here, the bit shifting operators (<<) are missing. The correct operation should be:
totalStepsTaken = ((b3 << 24) | (b2 << 16) | (b1 << 8) | b0);
This takes each byte and shifts it appropriately (assuming the Arduino is sending the LSB first, as your Arduino code does).
Below are the revised versions for both Arduino and ARC.
Arduino Code (Sender):
Make sure your Arduino sends the header (using a literal value) and the bytes:
ARC Code (Receiver - JavaScript)
Ensure you wait for at least 5 bytes, compare against the literal header ("T"), and use proper bit-shift operators:
By comparing the header correctly (using "T"), we ensure that the packet is identified on ARC.
Checking that UART.hardwareUartAvailable(0) is at least 5 avoids trying to read data before it’s available.
The use of << in the bit reconstruction is critical to forming the correct integer value.
With these corrections, ARC should correctly reconstruct the value sent from the Arduino (80001 in your test case) rather than the incorrect 2048 value.
I hope these changes help solve the issue. Let me know if you need any more assistance or further clarifications!
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 reexamining my code. I still had the incorrect read in ARC. I found the affected code and included it below: I changed UART.hardwareUartReadString to UART.hardwareUartRead for reading b0-b3. It works perfectly now. Can you please tell me why JavaScript prefers this? Thank you. Jack
ARC:
@athena It'll be much faster if you read the whole 32 bit word like this
Below is an explanation as to why reading an entire block of bytes using UART.hardwareUartRead (which returns a byte array) is more reliable and faster in JavaScript for ARC:
Raw Binary Data versus Strings
When you use UART.hardwareUartReadString, the returned data is a string representation of the byte. This means that each call is converting raw binary data into a single-character string. Even though you can use parseInt() to convert that character back into a number, it adds extra conversion overheadand it’s more susceptible to issues if the byte values don’t map cleanly to ASCII characters.
In contrast, UART.hardwareUartRead returns a raw byte (or an array of bytes) directly. This array contains the actual numeric values as numbers, so you avoid extra conversion steps.
Fewer Function Calls & Better Performance
Reading all 5 bytes in one call (header + 4 data bytes), as DJ_Sures suggested, decreases the number of function calls. Instead of reading each byte individually with a separate function call (which can introduce timing and parsing overhead), you get everything at once. This is not only more efficient, but also reduces the potential for a desynchronization where the bytes might not be available between successive calls.
Improved Data Integrity
When working with binary dataespecially for larger numbersit’s critical to avoid any unwanted manipulations. Reading the full set of bytes (and storing them in an array) means you have complete control over their order and can reliably perform the bit-shift operations to reconstruct your 32-bit number. In contrast, strings might have hidden encoding issues (such as unexpected characters or end-of-line markers) that could lead to misinterpretation.
Simplified Bitwise Operations
With a byte array, you can directly index into the array (e.g., tmpRead[1] to tmpRead[4]) and use bit shifting on those numeric values. Since they are numbers already, the bitwise operators work as expected. This makes your reconstruction of totalStepsTaken both simpler and more robust.
Thus, by using UART.hardwareUartRead to collect the entire packet at once, you benefit from:
I'm glad that this change resolved your issue. If you have any more questions or need further assistance with ARC or UART communication, feel free to ask!
Happy coding!
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 and @DJ,
Thank you for your valuable input with my code. The code and explanations are valuable and well received. I did have a problem with the improved code for receiving 32-bit UART. It did not run and seemed to get stuck receiving >= 5 bytes. I have included the recommended code and the code I have settled upon. It runs well. Would it be possible to compare the two, so I might get a fuller understanding of JavaScript? Thanks so much. Jack
My explanation of why the following works. 1. Treat the 'T' as a string array (UartReadString) and separate it from the follow-on array of integers (UartRead). 2. Reconstruct the 32-bit integer denoting them as they were sent (3,2,1,0).
Hopefully your explanation will help me to gain a fuller understanding going forward. Thanks.
Reworked Code:
Below is a sidebyside comparison and explanation of the two approaches. Both approaches share the same goalreading a header byte (the letter T) followed by a 32bit integer sent as 4 separate bytesbut they differ in how they obtain the header versus the integer bytes. Let’s break them down:
In this version, you make one read call that returns a fiveelement array.
The header is at index 0, and the four integer bytes follow in indices 1-4.
The byte ordering for reconstruction is based on the sending order. Notice that because the header is included in the array, you must use tmpRead[4] for the most significant byte and tmpRead[1] for the least significant byte.
// Determine that 5 bytes are available:
Here, you separate the header from the rest of the data.
The header is read using UART.hardwareUartReadString(0,1) so that it’s interpreted as a character (or small string).
Then, with a second call, you read 4 bytes (the integer data) into a numeric array.
Because you’ve removed the header from the data block, the array now has exactly 4 bytes (at indices 0-3) intended for the 32bit value; hence, the bit shifts are applied on tmpRead[3] (most significant) down to tmpRead[0] (least significant).
Data Type Handling:
When you use UART.hardwareUartReadString the returned value is a string - even when it represents a single byte. Converting that string into a number requires additional parsing. In the recommended code, all 5 bytes (including the header) come back as numeric values in an array. However, if the header byte doesn’t cleanly map to an expected numeric value (or if any conversion issues occur), you might run into problems.
Separation of Concerns:
By treating the header and data separately (the header as a string and the remaining 4 bytes as raw numbers), you ensure that each part is handled in the data type that best suits it. In this case, the header check is done on a string value, while the numeric data (for bit shifting) comes directly as numbers.
Function Call Efficiency:
Reading all data in one call (a fiveelement array) means you assume that all five bytes are available at exactly once. Sometimes timing or buffering issues may cause that single call to "hang" or not return as expected. Splitting the read into a single header read and then a separate numeric block allows for a bit more controlespecially if the header is used as a trigger for reading the rest of the available bytes.
Byte Order Clarity:
When you read the data in one block (5 bytes), you have to index carefully (remembering that index 0 is the header). In the reworked version, the header is taken out first; then the order of the numeric bytes in the array is exactly as sent: index 0 is the first byte after the header, index 3 is the last. This clarity helps when writing the bitwise reconstruction expression.
DJ_Sures’ Code:
Reads 5 bytes at once in one block via hardwareUartRead (all as numbers).
Indexes: tmpRead[0] = header, tmpRead[1 4] = data.
Reconstruction uses: (tmpRead[4] << 24) | ... | tmpRead[1].
Reworked Code:
Reads the header separately using hardwareUartReadString (treating it as a string), then reads 4 bytes using hardwareUartRead (numeric values).
Indexes for data are 0-3 for the numeric bytes, so reconstruction becomes: (tmpRead[3] << 24) | (tmpRead[2] << 16) | (tmpRead[1] << 8) | tmpRead[0].
This clear separation avoids any potential conversion issues and ensures the data is processed in the correct type.
Understanding these differences helps you see how JavaScript in the ARC environment handles strings versus numeric arrays. The reworked solution works reliably because it separates concerns and uses data types optimally for each part of the communication.
I hope this sidebyside explanation gives you the clearer, fuller understanding you were looking for. If you have any more questions or need further clarification, feel free to ask!
Happy coding!
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.
Many Thanks to @DJ and @Athena for all your contributions to my coding efforts. You facilitate the free exchange of ideas, which help enormously, those of us who are struggling to learn a new skill. Jack
Hi Jack,
I'm so glad that you found the insights useful and that your code is now working as expected. It’s always rewarding to see ideas exchanged and refined to help each of us learn something new, especially when diving into how JavaScript handles binary data in ARC.
Just to summarize the key points we discussed:
Data Type Separation:
In the reworked code, you read the header as a string (using UART.hardwareUartReadString) and then read the next 4 bytes as a numeric array (using UART.hardwareUartRead). This separation clearly distinguishes the character data (the header "T") from the numeric data you need to reconstruct the 32-bit integer.
Byte Order (Endianness):
Because the header is taken out first, the remaining bytes follow the original sending order. In your reworked code, index 0 is the first integer byte received and index 3 is the last, so the bit-shift operations are adjusted accordingly:
This makes the reconstruction of your 32-bit value straightforward and less error-prone.
Function Call Efficiency & Data Integrity:
While DJ_Sures’ approach of reading all 5 bytes at once is efficient in theory, splitting the read into two parts can sometimes improve reliability. Separating the header read from the integer read ensures that you handle the data in its correct type and ordering, especially if there may be unexpected timing or conversion issues.
It’s great to see how you’ve adapted these ideas into code that works reliably for your project. Please feel free to ask if you have any more questions as you continue refining your skills, whether it’s about UART communication or any other ARC feature.
Happy coding, and keep up the fantastic work on your Roli Rover project!
Best regards,
Athena
Synthiam ARC Support Technician
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.