Asked — Edited
Resolved Resolved by Athena AI!

Sending Larger Variables Via UART

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

ARC Pro

Upgrade to ARC Pro

Stay on the cutting edge of robotics with ARC Pro, guaranteeing that your robot is always ahead of the game.

PRO
Canada
#1  

Below is a few tips to ensure larger numeric values are transmitted reliably via UART from ARC to your Arduino:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.
PRO
Synthiam
#2  

@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.

PRO
Canada
#3  

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

  • A byte is 8 bits of data.
  • A 32-bit integer (commonly called an int32) is made up of 4 bytes (4 × 8 bits = 32 bits).
  • This means the full number is stored across 4 different bytes.

2. Endianness

  • Little-endian: The least significant byte (LSB) comes first.
  • Big-endian: The most significant byte (MSB) comes first.

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:

  1. Extract the Bytes

    You can use bit shifting and masking to extract each byte:

    • Byte0: the lowest order byte
    • Byte1: the next byte
    • Byte2: the next byte
    • Byte3: the highest order byte

    For a little-endian format (LSB first):

    var number = 113511; // or any larger number
    var byte0 = number & 0xFF;              // LSB
    var byte1 = (number >> 8) & 0xFF;         // next byte
    var byte2 = (number >> 16) & 0xFF;        // next byte
    var byte3 = (number >> 24) & 0xFF;        // MSB
    
  2. 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:

    var data = [byte0, byte1, byte2, byte3];
    controlCommand("Serial Toolbox", "SendBytes", data);
    

    (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:

int32_t receivedNumber = 0;
if (Serial.available() >= 4) {  // wait until 4 bytes are available
  uint8_t byte0 = Serial.read();
  uint8_t byte1 = Serial.read();
  uint8_t byte2 = Serial.read();
  uint8_t byte3 = Serial.read();

  // For little-endian reconstruction:
  receivedNumber = byte0 | (byte1 << 8) | (byte2 << 16) | (byte3 << 24);
  
  // Now, receivedNumber should equal the original value sent from ARC.
}

For big-endian transmission, the order would be reversed (byte3 being read first, etc.).


Summary

  • Int32 Representation: A 32-bit (int32) number occupies 4 bytes.
  • Splitting into Bytes: Use bit masking and shifting on the transmitting side in ARC:
    • byte0 = number & 0xFF
    • byte1 = (number >> 8) & 0xFF
    • byte2 = (number >> 16) & 0xFF
    • byte3 = (number >> 24) & 0xFF
  • Transmitting Data: Send these 4 bytes via UART.
  • Reconstructing on Arduino: Read 4 bytes and combine them using bit shifting to recreate the original number.

Additional Notes

  • Error Checking: You might include start and end markers or checksums to confirm that the correct number of bytes have been received and that no data has been corrupted.
  • Baud Rate: Ensure that both ARC and Arduino are using the same baud rate (for example, 115200) to maintain data integrity.
  • Binary vs. ASCII: While sending numbers as text (ASCII) can work, sending binary representations saves bandwidth and ensures that the full 32-bit value is transmitted without any ambiguity.

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.
PRO
Synthiam
#4  

@Athena don't use the serial toolbox. Just use the UART javascript commands in ARC.

PRO
Canada
#5   — Edited

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:

  • Byte0 = number & 0xFF       // Lowest-order byte
  • Byte1 = (number >> 8) & 0xFF   // Next byte
  • Byte2 = (number >> 16) & 0xFF  // Next byte
  • Byte3 = (number >> 24) & 0xFF  // Highest-order byte

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:


/* Example: Sending an int32 (113511) as 4 bytes via UART */

// Define your number (here: 113511)
var number = 113511;

// Extract four bytes (assuming little-endian; LSB first)
var byte0 = number & 0xFF;             // Least Significant Byte
var byte1 = (number >> 8) & 0xFF;       
var byte2 = (number >> 16) & 0xFF;
var byte3 = (number >> 24) & 0xFF;       // Most Significant Byte

// Create an array of bytes
var data = [byte0, byte1, byte2, byte3];

// (Optional) Print the bytes to check their values
print("Byte0: " + byte0 + " | Byte1: " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);

// Initialize the UART (if not already done)
// For example, initialize UART 0 with baud rate 115200
UART.initHardwareUart(0, 115200);

// Now, send the byte array via UART.
// Use the UART.sendSerial() command: 
//   UART.sendSerial(port, baudRate, byte or byteArray, [ezbIndex])
// Replace 'COMx' with the actual port name if needed or use the hardware UART by specifying the EZB index.
UART.sendSerial(0, 115200, data);  

print("Sent int32 value " + number + " as 4 bytes over UART.");

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:


/* Arduino: Reconstructing a 32-bit number from 4 received UART bytes */
if (Serial.available() >= 4) {
  uint8_t byte0 = Serial.read();
  uint8_t byte1 = Serial.read();
  uint8_t byte2 = Serial.read();
  uint8_t byte3 = Serial.read();
  
  // Combine bytes to form int32: (little-endian)
  int32_t receivedNumber = ((int32_t)byte3 << 24) |
                           ((int32_t)byte2 << 16) |
                           ((int32_t)byte1 << 8)  |
                           (int32_t)byte0;
  
  Serial.print("Received Number: ");
  Serial.println(receivedNumber);
}


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.
#6  

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

// Making local variables from global variables.
var pathTotalDistance = getVar("$pathTotalDistance");//113511 steps

var pathEndpointDistance = getVar("$pathEndpointDistance");//80000 steps

var oppositeDistance = getVar("$oppositeDistance");//11891 steps

var actualCourse = getVar("$actualCourse");

var desiredCourse = getVar("$desiredCourse");

sleep(1000);

// Send the variables to Arduino


var header = 0xAA; // Arbitrary header byte
UART.hardwareUartWrite(0, [header]);


// Extract four bytes (assuming little-endian; LSB first)
var byte0 = pathTotalDistance & 0xFF; // Least Significant Byte
var byte1 = (pathTotalDistance >> 8) & 0xFF;       
var byte2 = (pathTotalDistance >> 16) & 0xFF;
var byte3 = (pathTotalDistance >> 24) & 0xFF; // Most Significant Byte
// Create an array of bytes
var PTD = [byte0, byte1, byte2, byte3];
UART.sendSerial(0, 9600, PTD);

//  Print the bytes to check their values
print("Byte0: " + byte0 + " | Byte1: " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);  
print("Sent int32 value " + pathTotalDistance + " as 4 bytes over UART.");


var byte0 = pathEndpointDistance & 0xFF;//LSB
var byte1 = (pathEndpointDistance >> 8) & 0xFF;
var byte2 = (pathEndpointDistance >> 16) & 0xFF;
var byte3 = (pathEndpointDistance >> 24) & 0xFF;//MSB
//Create an array of bytes
var PED = [byte0, byte1, byte2, byte3];
UART.sendSerial(0, 9600, PED);

//  Print the bytes to check their values
print("Byte0:  " + byte0 + " | Byte1:  " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);  
print("Sent int32 value " + pathEndpointDistance + " as 4 bytes over UART.");



var byte0 = oppositeDistance & 0xFF;//LSB
var byte1 = (oppositeDistance >> 8) & 0xFF;
var byte2 = (oppositeDistance >> 16) & 0xFF;
var byte3 = (oppositeDistance >> 24) & 0xFF;//MSB
//Create an array of bytes
var OD = [byte0, byte1, byte2, byte3];
UART.sendSerial(0, 9600, OD);

//  Print the bytes to check their values
print("Byte0:  " + byte0 + " | Byte1:  " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);  
print("Sent int32 value " + oppositeDistance + " as 4 bytes over UART.");


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));



UART.hardwareUartWrite(0, [actualCourse]); // Send as one byte
UART.hardwareUartWrite(0, [desiredCourse]);  // Send as one byte
//print("Sending actualCourse   " + actualCourse);
//print("Sending desiredlCourse   " + desiredCourse);
//setVar("$actualCourse", (Servo.GetPosition(17)));


PRO
Canada
#7   — Edited

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:

  pathTotalDistance 0xFF

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:

  var byte0 = pathTotalDistance & 0xFF;

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:


/* Example: Sending a 32bit integer over UART using the builtin UART JavaScript commands */

// Retrieve the global variable (example value: 113511)
var pathTotalDistance = getVar($pathTotalDistance);  // e.g. 113511

// Wait a bit before transmission
sleep(1000);  

// Send a header if needed (0xAA in this case)
var header = 0xAA;
UART.hardwareUartWrite(0, [header]);  

// Extract the 4 bytes using bitwise AND (&) and right shift (>>)
// Assuming littleendian (LSB first)
var byte0 = pathTotalDistance & 0xFF;                  // Least Significant Byte
var byte1 = (pathTotalDistance >> 8) & 0xFF;
var byte2 = (pathTotalDistance >> 16) & 0xFF;
var byte3 = (pathTotalDistance >> 24) & 0xFF;            // Most Significant Byte

// Create an array of bytes to send
var PTD = [byte0, byte1, byte2, byte3];

// Send the byte array over UART, using a baud rate of 9600 (adjust as needed)
UART.sendSerial(0, 9600, PTD);

// Print the bytes to check their values
print("Byte0: " + byte0 + " | Byte1: " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);
print("Sent int32 value " + pathTotalDistance + " as 4 bytes over UART.");

/* Repeat similar steps for the other values, for example: */

var pathEndpointDistance = getVar($pathEndpointDistance);  // e.g. 80000
var byte0 = pathEndpointDistance & 0xFF;
var byte1 = (pathEndpointDistance >> 8) & 0xFF;
var byte2 = (pathEndpointDistance >> 16) & 0xFF;
var byte3 = (pathEndpointDistance >> 24) & 0xFF;
var PED = [byte0, byte1, byte2, byte3];
UART.sendSerial(0, 9600, PED);
print("Sent int32 value " + pathEndpointDistance + " as 4 bytes over UART.");

// And for oppositeDistance
var oppositeDistance = getVar($oppositeDistance);  // e.g. 11891
var byte0 = oppositeDistance & 0xFF;
var byte1 = (oppositeDistance >> 8) & 0xFF;
var byte2 = (oppositeDistance >> 16) & 0xFF;
var byte3 = (oppositeDistance >> 24) & 0xFF;
var OD = [byte0, byte1, byte2, byte3];
UART.sendSerial(0, 9600, OD);
print("Sent int32 value " + oppositeDistance + " as 4 bytes over UART.");

/* The remainder of your code (actualCourse and desiredCourse) remains the same,
   provided that they are within one byte, so they can be sent directly using UART.hardwareUartWrite */
UART.hardwareUartWrite(0, [ getVar($actualCourse) ]); // Send as one byte
UART.hardwareUartWrite(0, [ getVar($desiredCourse) ]);  // Send as one byte

Explanation

  1. 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.

  2. 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.

  3. 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.
#8  

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

PRO
Canada
#9   — Edited

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:


/* Example: Split a 32-bit integer and send it via UART */

// Retrieve global variable (assume it has a proper numeric value)
var pathTotalDistance = getVar($pathTotalDistance);  // e.g. 113511

// Wait a bit (optional)
sleep(1000);

// Optional: send a header byte (e.g., 0xAA)
var header = 0xAA;
UART.hardwareUartWrite(0, [header]);

// Use bit shifting and bitwise AND to extract each byte (little-endian)
var byte0 = pathTotalDistance & 0xFF;                   // Least Significant Byte
var byte1 = (pathTotalDistance >> 8) & 0xFF;
var byte2 = (pathTotalDistance >> 16) & 0xFF;
var byte3 = (pathTotalDistance >> 24) & 0xFF;             // Most Significant Byte

// Create an array of the four bytes
var PTD = [byte0, byte1, byte2, byte3];

// Send the bytes over UART (make sure baud rate matches on both ends)
UART.sendSerial(0, 9600, PTD);

// Print each byte for troubleshooting purposes
print("Byte0: " + byte0 + " | Byte1: " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);
print("Sent int32 value " + pathTotalDistance + " as 4 bytes over UART.");

// Repeat similar steps for the other values if needed:
var pathEndpointDistance = getVar($pathEndpointDistance);  // e.g. 80000
var ped0 = pathEndpointDistance & 0xFF;
var ped1 = (pathEndpointDistance >> 8) & 0xFF;
var ped2 = (pathEndpointDistance >> 16) & 0xFF;
var ped3 = (pathEndpointDistance >> 24) & 0xFF;
var PED = [ped0, ped1, ped2, ped3];
UART.sendSerial(0, 9600, PED);
print("Sent int32 value " + pathEndpointDistance + " as 4 bytes over UART.");

var oppositeDistance = getVar($oppositeDistance);  // e.g. 11891
var od0 = oppositeDistance & 0xFF;
var od1 = (oppositeDistance >> 8) & 0xFF;
var od2 = (oppositeDistance >> 16) & 0xFF;
var od3 = (oppositeDistance >> 24) & 0xFF;
var OD = [od0, od1, od2, od3];
UART.sendSerial(0, 9600, OD);
print("Sent int32 value " + oppositeDistance + " as 4 bytes over UART.");

// If actualCourse and desiredCourse are one byte values, send them as-is:
UART.hardwareUartWrite(0, [ getVar($actualCourse) ]);
UART.hardwareUartWrite(0, [ getVar($desiredCourse) ]);

Key Points to Note:

  1. Bitwise Operators:

    • The operator ">>" shifts bits to the right (e.g., pathTotalDistance >> 8 shifts by 8 bits).
    • The "& 0xFF" mask ensures that only the lowest 8 bits of the result are kept.

    For instance,
    byte0 = pathTotalDistance & 0xFF
    byte1 = (pathTotalDistance >> 8) & 0xFF

  2. 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.

  3. 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.

  4. 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.
#10  

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

PRO
Canada
#11  

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:


/* Example: Split a 32-bit integer and send it via UART */

// Retrieve the global variable (assume it holds a numeric value)
var pathTotalDistance = getVar($pathTotalDistance); // e.g. 113511

// Wait a bit (optional)
sleep(1000);

// Optional: send a header byte (e.g., 0xAA)
var header = 0xAA;
UART.hardwareUartWrite(0, [header]);

// Use bit shifting and bitwise AND to extract each byte (little-endian)
var byte0 = pathTotalDistance & 0xFF;             // Least Significant Byte
var byte1 = (pathTotalDistance >> 8) & 0xFF;
var byte2 = (pathTotalDistance >> 16) & 0xFF;
var byte3 = (pathTotalDistance >> 24) & 0xFF;       // Most Significant Byte

// Create an array of the four bytes
var PTD = [byte0, byte1, byte2, byte3];

// Send the bytes over UART (ensure baud rate on both ends is matching)
UART.sendSerial(0, 9600, PTD);

// Print each byte for troubleshooting purposes
print("Byte0: " + byte0 + " | Byte1: " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);
print("Sent int32 value " + pathTotalDistance + " as 4 bytes over UART.");

// --- Repeat similar steps for pathEndpointDistance ---
var pathEndpointDistance = getVar($pathEndpointDistance); // e.g. 80000
var ped0 = pathEndpointDistance & 0xFF;
var ped1 = (pathEndpointDistance >> 8) & 0xFF;
var ped2 = (pathEndpointDistance >> 16) & 0xFF;
var ped3 = (pathEndpointDistance >> 24) & 0xFF;
var PED = [ped0, ped1, ped2, ped3];
UART.sendSerial(0, 9600, PED);
print("Sent int32 value " + pathEndpointDistance + " as 4 bytes over UART.");

// --- Repeat similar steps for oppositeDistance ---
var oppositeDistance = getVar($oppositeDistance); // e.g. 11891
var od0 = oppositeDistance & 0xFF;
var od1 = (oppositeDistance >> 8) & 0xFF;
var od2 = (oppositeDistance >> 16) & 0xFF;
var od3 = (oppositeDistance >> 24) & 0xFF;
var OD = [od0, od1, od2, od3];
UART.sendSerial(0, 9600, OD);
print("Sent int32 value " + oppositeDistance + " as 4 bytes over UART.");

// --- For one-byte values (actualCourse and desiredCourse), send directly ---
UART.hardwareUartWrite(0, [ getVar($actualCourse) ]);
UART.hardwareUartWrite(0, [ getVar($desiredCourse) ]);

Key Points to Note:

  1. Bitwise Operations:

    • The operator & 0xFF ensures only the least significant 8 bits remain.
    • The operator >> shifts bits to the right. For example, (pathTotalDistance >> 8) & 0xFF extracts the next 8 bits.
  2. UART Commands:

    • UART.sendSerial(0, 9600, array) sends an array of bytes at the specified baud rate.
    • Make sure the baud rate set in ARC matches your Arduino baud rate.
  3. Printing Checks:

    • The 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.
#12  

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:

setVar("$pathTotalDistance" ,  113511);//SET VALUE STEPS

was being sent as:

setVar("$pathTotalDistance" ,  113,511);//SET VALUE STEPS

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++

#include 
#include 


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 targetLeftSpeed = leftSpeed;
//int targetRightSpeed = rightSpeed;
AccelStepper LeftFrontWheel(1, 3, 6);
AccelStepper LeftBackWheel(1, 2, 5);
AccelStepper RightFrontWheel(1, 12, 13);
AccelStepper RightBackWheel(1, 4, 7);
int run = 0;
int wheelSpeed = 2000;


void setup() {
  Serial3.begin(9600); // Communication with EZ-B
    Serial.begin(9600);  // Debugging via Serial Monitor
   LeftFrontWheel.setMaxSpeed(wheelSpeed * 2);
  LeftBackWheel.setMaxSpeed(wheelSpeed * 2);
  RightFrontWheel.setMaxSpeed(wheelSpeed * 2);
  RightBackWheel.setMaxSpeed(wheelSpeed * 2);
   }



void loop() {

 Main:
if (run == 0) {  //State of RUN when robot has yet to begin movement towards the reflector.
if (lastIncomingByte == 'N') {

// Check if there are at least 9 bytes available (1 header + 8 data bytes)
    if (Serial3.available() >= 14) {
      byte header = Serial3.read();
      if (header == 0xAA) { // Check for header byte


  uint8_t byte0 = Serial.read();
  uint8_t byte1 = Serial.read();
  uint8_t byte2 = Serial.read();
  uint8_t byte3 = Serial.read();
  
  // Combine bytes to form int32: (little-endian)
  int32_t pathTotalDistance = ((int32_t)byte3 << 24) |
                              ((int32_t)byte2 << 16) |
                              ((int32_t)byte1 << 8)  |
                              (int32_t)byte0;
  
  
  Serial.print("pathTotalDistance: ");
  Serial.println(pathTotalDistance);



  uint8_t PEDbyte0 = Serial.read();
  uint8_t PEDbyte1 = Serial.read();
  uint8_t PEDbyte2 = Serial.read();
  uint8_t PEDbyte3 = Serial.read();
  
  // Combine bytes to form int32: (little-endian)
  int32_t pathEndpointDistance = ((int32_t)byte3 << 24) |
                                 ((int32_t)byte2 << 16) |
                                 ((int32_t)byte1 << 8)  |
                                 (int32_t)byte0;
  
  Serial.print("pathEndpointDistance: ");
  Serial.println(pathEndpointDistance);

     
  uint8_t ODbyte0 = Serial.read();
  uint8_t ODbyte1 = Serial.read();
  uint8_t ODbyte2 = Serial.read();
  uint8_t ODbyte3 = Serial.read();
  
  // Combine bytes to form int32: (little-endian)
  int32_t oppositeDistance = ((int32_t)byte3 << 24) |
                             ((int32_t)byte2 << 16) |
                             ((int32_t)byte1 << 8)  |
                             (int32_t)byte0;
  
  Serial.print("oppositeDistance: ");
  Serial.println(oppositeDistance);
  
    
        actualCourse = Serial3.read(); //  Read and store actualCourse
        desiredCourse = Serial3.read();//  Read and store desiredCourse

       // Print the above received paramenters
       Serial.print("actualCourse:  ");
        Serial.println(actualCourse);
        Serial.print("desiredCourse:  ");
        Serial.println(desiredCourse);
        delay(10);
        bufferFlush();
        

 }   
}
}
PRO
Canada
#13  

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:


#include <AccelStepper.h>

// Global variables
long pathTotalDistance = 0;
long pathEndpointDistance = 0;
long oppositeDistance = 0;
float desiredCourse = 0;
long actualCourse = 0;

// Setup your stepper motors
AccelStepper LeftFrontWheel(1, 3, 6);
AccelStepper LeftBackWheel(1, 2, 5);
AccelStepper RightFrontWheel(1, 12, 13);
AccelStepper RightBackWheel(1, 4, 7);

int run = 0;
int wheelSpeed = 2000;

void setup() {
  Serial3.begin(9600); // Communication with EZ-B (ARC)
  Serial.begin(9600);  // Debug output via Serial Monitor

  LeftFrontWheel.setMaxSpeed(wheelSpeed * 2);
  LeftBackWheel.setMaxSpeed(wheelSpeed * 2);
  RightFrontWheel.setMaxSpeed(wheelSpeed * 2);
  RightBackWheel.setMaxSpeed(wheelSpeed * 2);
}

void loop() {
  // Only run if the robot is not already in motion
  if (run == 0) {
    // Check that at least 14 bytes are available:
    // 1 header + (3 * 4 bytes for the 32-bit values) + 2 one-byte values
    if (Serial3.available() >= 14) {
      byte header = Serial3.read();
      if (header == 0xAA) {  // Confirm header byte
        // Read 4 bytes for pathTotalDistance
        uint8_t b0 = Serial3.read();
        uint8_t b1 = Serial3.read();
        uint8_t b2 = Serial3.read();
        uint8_t b3 = Serial3.read();
        // Reconstruct the 32-bit integer (little-endian)
        pathTotalDistance = ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0;
        Serial.print("pathTotalDistance: ");
        Serial.println(pathTotalDistance);

        // Read 4 bytes for pathEndpointDistance
        b0 = Serial3.read();
        b1 = Serial3.read();
        b2 = Serial3.read();
        b3 = Serial3.read();
        pathEndpointDistance = ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0;
        Serial.print("pathEndpointDistance: ");
        Serial.println(pathEndpointDistance);

        // Read 4 bytes for oppositeDistance
        b0 = Serial3.read();
        b1 = Serial3.read();
        b2 = Serial3.read();
        b3 = Serial3.read();
        oppositeDistance = ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0;
        Serial.print("oppositeDistance: ");
        Serial.println(oppositeDistance);

        // Read one byte for actualCourse and one for desiredCourse
        actualCourse = Serial3.read();       // one byte value
        desiredCourse = Serial3.read();        // one byte value
        Serial.print("actualCourse: ");
        Serial.println(actualCourse);
        Serial.print("desiredCourse: ");
        Serial.println(desiredCourse);

        // You might want to flush the Serial3 buffer here, if needed.
        // For example:
        while (Serial3.available()) {
          Serial3.read();
        }
      } // end if header
    } // end available check
  } // end run==0 block

  // Other code can follow...
}

Key Points:

  1. 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.

  2. 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.

  3. Bit Shifting Syntax:
    Each 32-bit value is reconstructed using the << operator. For example:
    ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0

  4. Header Byte:
    A header byte (0xAA) is used to mark the start of your data packet.

  5. 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.
#14  

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:

#include 
#include 

// Global variables
long pathTotalDistance = 0;
long pathEndpointDistance = 0;
long oppositeDistance = 0;
float desiredCourse = 0;
long actualCourse = 0;

// Setup your stepper motors
AccelStepper LeftFrontWheel(1, 3, 6);
AccelStepper LeftBackWheel(1, 2, 5);
AccelStepper RightFrontWheel(1, 12, 13);
AccelStepper RightBackWheel(1, 4, 7);

int run = 0;
int wheelSpeed = 2000;

void setup() {
  Serial3.begin(9600); // Communication with EZ-B (ARC)
  Serial.begin(9600);  // Debug output via Serial Monitor

  LeftFrontWheel.setMaxSpeed(wheelSpeed * 2);
  LeftBackWheel.setMaxSpeed(wheelSpeed * 2);
  RightFrontWheel.setMaxSpeed(wheelSpeed * 2);
  RightBackWheel.setMaxSpeed(wheelSpeed * 2);
}

void loop() {
  // Only run if the robot is not already in motion
  if (run == 0) {
    // Check that at least 14 bytes are available:
    // 1 header + (3 * 4 bytes for the 32-bit values) + 2 one-byte values
    if (Serial3.available() >= 15) {
      byte header = Serial3.read();
      if (header == 0xAA) {  // Confirm header byte
        // Read 4 bytes for pathTotalDistance
        uint8_t b0 = Serial3.read();
        uint8_t b1 = Serial3.read();
        uint8_t b2 = Serial3.read();
        uint8_t b3 = Serial3.read();
        // Reconstruct the 32-bit integer (little-endian)
        pathTotalDistance = ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0;
        Serial.print("pathTotalDistance: ");
        Serial.println(pathTotalDistance);

        // Read 4 bytes for pathEndpointDistance
        b0 = Serial3.read();
        b1 = Serial3.read();
        b2 = Serial3.read();
        b3 = Serial3.read();
        pathEndpointDistance = ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0;
        Serial.print("pathEndpointDistance: ");
        Serial.println(pathEndpointDistance);

        // Read 4 bytes for oppositeDistance
        b0 = Serial3.read();
        b1 = Serial3.read();
        b2 = Serial3.read();
        b3 = Serial3.read();
        oppositeDistance = ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | b0;
        Serial.print("oppositeDistance: ");
        Serial.println(oppositeDistance);

        // Read one byte for actualCourse and one for desiredCourse
        actualCourse = Serial3.read();       // one byte value
        desiredCourse = Serial3.read();        // one byte value
        Serial.print("actualCourse: ");
        Serial.println(actualCourse);
        Serial.print("desiredCourse: ");
        Serial.println(desiredCourse);

        // You might want to flush the Serial3 buffer here, if needed.
        // For example:
        while (Serial3.available()) {
          Serial3.read();
        }
      } // end if header
    } // end available check
  } // end run==0 block

  // Other code can follow...
}

I am sending with the following JavaScript:

// Making local variables from global variables.
var pathTotalDistance = getVar("$pathTotalDistance");//113511 steps

var pathEndpointDistance = getVar("$pathEndpointDistance");//80000 steps

var oppositeDistance = getVar("$oppositeDistance");//11891 steps

var actualCourse = getVar("$actualCourse");

var desiredCourse = getVar("$desiredCourse");


The JavaScript values print.  Can you review the above code for obvious errors? Thank you. Jack

PRO
Synthiam
#15  

@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?

#16  

Hello @Athena, My JavaScript in the above post did not come through completely.  It follows:

// Making local variables from global variables.
var pathTotalDistance = getVar("$pathTotalDistance");//113511 steps

var pathEndpointDistance = getVar("$pathEndpointDistance");//80000 steps

var oppositeDistance = getVar("$oppositeDistance");//11891 steps

var actualCourse = getVar("$actualCourse");

var desiredCourse = getVar("$desiredCourse");


// Send the variables to Arduino
var header = 0xAA; // Arbitrary header byte
UART.hardwareUartWrite(0, header);
print("header:  " + header);


// Extract the 4 bytes using bitwise AND (&) and right shift (>>)
// Assuming littleendian (LSB first)
var byte0 = pathTotalDistance & 0xFF;                  // Least Significant Byte
var byte1 = (pathTotalDistance >> 8) & 0xFF;
var byte2 = (pathTotalDistance >> 16) & 0xFF;
var byte3 = (pathTotalDistance >> 24) & 0xFF;            // Most Significant Byte

// Create an array of bytes to send
var PTD = [byte0, byte1, byte2, byte3];

// Send the byte array over UART, using a baud rate of 9600 (adjust as needed)
UART.sendSerial(0, 9600, PTD);

// Print the bytes to check their values
//print("Byte0: " + byte0 + " | Byte1: " + byte1 + " | Byte2: " + byte2 + " | Byte3: " + byte3);
print("pathTotalDistance:   " + pathTotalDistance );




//var pathEndpointDistance = getVar($pathEndpointDistance);  // e.g. 80000
var byte0 = pathEndpointDistance & 0xFF;
var byte1 = (pathEndpointDistance >> 8) & 0xFF;
var byte2 = (pathEndpointDistance >> 16) & 0xFF;
var byte3 = (pathEndpointDistance >> 24) & 0xFF;
var PED = [byte0, byte1, byte2, byte3];
UART.sendSerial(0, 9600, PED);
print("pathEndpointDistance:  " + pathEndpointDistance);

// And for oppositeDistance
//var oppositeDistance = getVar($oppositeDistance);  // e.g. 11891
var byte0 = oppositeDistance & 0xFF;
var byte1 = (oppositeDistance >> 8) & 0xFF;
var byte2 = (oppositeDistance >> 16) & 0xFF;
var byte3 = (oppositeDistance >> 24) & 0xFF;
var OD = [byte0, byte1, byte2, byte3];
UART.sendSerial(0, 9600, OD);
print("oppositeDistance   " + oppositeDistance);

/* The remainder of your code (actualCourse and desiredCourse) remains the same,
   provided that they are within one byte, so they can be sent directly using UART.hardwareUartWrite */
UART.hardwareUartWrite(0, actualCourse); // Send as one byte
UART.hardwareUartWrite(0, desiredCourse);  // Send as one byte
print("actualCourse  " + actualCourse);
print("desiredCourse  " + desiredCourse);




Can you check it or errors? Thanks Jack

PRO
Canada
#17  

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:

  1. Bitwise Operators and Byte Extraction

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.

  1. Reusing Variable Names

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];

  1. UART Functions

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.)

  1. Print Statements

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);

  1. Confirming Data Order

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.

  1. Overall Example Revised Code

Below is a revised version of your JavaScript code that incorporates these points:


// Making local variables from global variables.
var pathTotalDistance = getVar($pathTotalDistance);  // e.g., 113511 steps
var pathEndpointDistance = getVar($pathEndpointDistance); // e.g., 80000 steps
var oppositeDistance = getVar($oppositeDistance);   // e.g., 11891 steps
var actualCourse = getVar($actualCourse);
var desiredCourse = getVar($desiredCourse);

// Send header
var header = 0xAA;  // Arbitrary header byte
UART.hardwareUartWrite(0, header);
print("header: " + header);

// ==============================
// Send pathTotalDistance as 4 bytes (LSB first)
var ptdByte0 = pathTotalDistance & 0xFF;
var ptdByte1 = (pathTotalDistance >> 8) & 0xFF;
var ptdByte2 = (pathTotalDistance >> 16) & 0xFF;
var ptdByte3 = (pathTotalDistance >> 24) & 0xFF;

var PTD = [ptdByte0, ptdByte1, ptdByte2, ptdByte3];
UART.sendSerial(0, 9600, PTD);
print("pathTotalDistance: " + pathTotalDistance + " | Bytes: " + PTD);

// ==============================
// Send pathEndpointDistance as 4 bytes
var pedByte0 = pathEndpointDistance & 0xFF;
var pedByte1 = (pathEndpointDistance >> 8) & 0xFF;
var pedByte2 = (pathEndpointDistance >> 16) & 0xFF;
var pedByte3 = (pathEndpointDistance >> 24) & 0xFF;

var PED = [pedByte0, pedByte1, pedByte2, pedByte3];
UART.sendSerial(0, 9600, PED);
print("pathEndpointDistance: " + pathEndpointDistance + " | Bytes: " + PED);

// ==============================
// Send oppositeDistance as 4 bytes
var odByte0 = oppositeDistance & 0xFF;
var odByte1 = (oppositeDistance >> 8) & 0xFF;
var odByte2 = (oppositeDistance >> 16) & 0xFF;
var odByte3 = (oppositeDistance >> 24) & 0xFF;

var OD = [odByte0, odByte1, odByte2, odByte3];
UART.sendSerial(0, 9600, OD);
print("oppositeDistance: " + oppositeDistance + " | Bytes: " + OD);

// ==============================
// Send one-byte values for actualCourse and desiredCourse
UART.hardwareUartWrite(0, actualCourse); // one byte
UART.hardwareUartWrite(0, desiredCourse);  // one byte

print("actualCourse: " + actualCourse);
print("desiredCourse: " + desiredCourse);

  1. Final Checks

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.
#18  

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.

UART.hardwareUartWrite(0, PTD);  //This line of code works
//UART.sendSerial(0, 9600, PTD);  //This line of code does not send

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

PRO
Canada
#19  

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.
#20  

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

#include 
#include 

long pathTotalDistance = 0;
long totalStepsTaken = 0;
long adjacentRemainingDistance = 0;
long pathEndpointDistance = 0;
long oppositeDistance = 0;
float desiredCourse;
long actualCourse;
float diffCourse=0;
float lastDiff= 100;
int lastIncomingByte;
//int targetLeftSpeed = leftSpeed;
//int targetRightSpeed = rightSpeed;
AccelStepper LeftFrontWheel(1, 3, 6);
AccelStepper LeftBackWheel(1, 2, 5);
AccelStepper RightFrontWheel(1, 12, 13);
AccelStepper RightBackWheel(1, 4, 7);
int run = 1;
int wheelSpeed = 2000;


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}




void stopMotors() {  //  For motor stop 
       
        LeftFrontWheel.setSpeed(0);
    LeftBackWheel.setSpeed(0);
    RightFrontWheel.setSpeed(0);
    RightBackWheel.setSpeed(0);

    LeftFrontWheel.runSpeed();
    LeftBackWheel.runSpeed();
    RightFrontWheel.runSpeed();
    RightBackWheel.runSpeed();

    if (run == 1) {

      totalStepsTaken = 80001;
      

       int Byte0 = totalStepsTaken & 0xFF;
       int Byte1 = (totalStepsTaken >> 8) & 0xFF;
       int Byte2 = (totalStepsTaken >> 16) & 0xFF;
       int Byte3 = (totalStepsTaken >> 24) & 0xFF;

       int TST = (Byte0, Byte1, Byte2, Byte3);
      Serial3.write(TST);
      Serial.print("Sent TST:  ");
      Serial.println(totalStepsTaken);

        Serial3.write('T');  //  Send commands to EZB4 to alert other scripts of motor stop
       Serial.print("Sent   ");
       Serial.println('T');
       Serial.print("Left Steps:  ");
       Serial.println(LeftFrontWheel.currentPosition());
       Serial.print("Right Steps:  ");
       Serial.println(RightFrontWheel.currentPosition());
      

        delay(100);
        }
        bufferFlush();

        delay(10);
        
         resetAll();   
}



void resetAll() {  //  Reset some variable
   // run = 0;
   LeftFrontWheel.setCurrentPosition(0);  //Setup for "while"loop to demonstrate trackRight
RightFrontWheel.setCurrentPosition(0);
   // lastDiff= 100;
    }



void bufferFlush() {
while (Serial3.available()) {
        Serial3.read(); // Discard any unwanted data
        delay(10);
    }
}


ARC

if (UART.hardwareUartAvailable(0) >= 5) {

         var receivedChar = UART.hardwareUartReadString(0, 1);
       
        if (receivedChar == 'T') {
            print("Received: " + receivedChar);
            
            var b0 = UART.hardwareUartReadString(0,1);
            var b1 = UART.hardwareUartReadString(0,1);
            var b2 = UART.hardwareUartReadString(0,1);
            var b3 = UART.hardwareUartReadString(0,1);
           totalStepsTaken = ((b3 << 24) | (b2 << 16) | (b1 << 8) | b0);
            print("totalStepsTaken:  " + totalStepsTaken);
            
            sleep(100);
            
            halt();
}

}
PRO
Canada
#21  

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;

// Break the long into four bytes (LSB first)
int byte0 = totalStepsTaken & 0xFF;
int byte1 = (totalStepsTaken >> 8) & 0xFF;
int byte2 = (totalStepsTaken >> 16) & 0xFF;
int byte3 = (totalStepsTaken >> 24) & 0xFF;

// Send a header 'T' to indicate start of our 4-byte data packet.
Serial3.write('T');

// Send the four bytes one by one.
Serial3.write(byte0);
Serial3.write(byte1);
Serial3.write(byte2);
Serial3.write(byte3);

// (Optional) Send an extra command if needed:
// For example, you might decide to send a terminating character.
//Serial3.write('X');

// Print information to the Arduino Serial Monitor for debugging.
Serial.print("Sent totalStepsTaken: ");
Serial.println(totalStepsTaken);

// Clear (or flush) the Serial3 RX buffer (if desired)
bufferFlush();
delay(100);

} 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));

// Reconstruct the long value.
// Here we assume the data is sent LSB first:
totalStepsTaken = ((b3 << 24) | (b2 << 16) | (b1 << 8) | b0);

print("totalStepsTaken: " + totalStepsTaken);

sleep(100);
halt();  // Optional: stop script once data is received.

} }

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.
#22  

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

#include 
#include 

long pathTotalDistance = 0;
long totalStepsTaken = 0;
long adjacentRemainingDistance = 0;
long pathEndpointDistance = 0;
long oppositeDistance = 0;
float desiredCourse;
long actualCourse;
float diffCourse=0;
float lastDiff= 100;
int lastIncomingByte;
//int targetLeftSpeed = leftSpeed;
//int targetRightSpeed = rightSpeed;
AccelStepper LeftFrontWheel(1, 3, 6);
AccelStepper LeftBackWheel(1, 2, 5);
AccelStepper RightFrontWheel(1, 12, 13);
AccelStepper RightBackWheel(1, 4, 7);
int run = 1;
int wheelSpeed = 2000;


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}




void stopMotors() {  //  For motor stop 
       
        LeftFrontWheel.setSpeed(0);
    LeftBackWheel.setSpeed(0);
    RightFrontWheel.setSpeed(0);
    RightBackWheel.setSpeed(0);

    LeftFrontWheel.runSpeed();
    LeftBackWheel.runSpeed();
    RightFrontWheel.runSpeed();
    RightBackWheel.runSpeed();

    if (run == 1) {

     //totalStepsTaken = (LeftFrontWheel.currentPosition() + RightFrontWheel.currentPosition());
      totalStepsTaken = 80001;

       int byte0 = totalStepsTaken & 0xFF;
       int byte1 = (totalStepsTaken >> 8) & 0xFF;
       int byte2 = (totalStepsTaken >> 16) & 0xFF;
       int byte3 = (totalStepsTaken >> 24) & 0xFF;
       
       Serial3.write('T'); //Header for Total Steps Taken

         // Send the four bytes one by one.
      Serial3.write(byte0);
      Serial3.write(byte1);
      Serial3.write(byte2);
      Serial3.write(byte3);

       
       Serial.print("Sent   ");
       Serial.println('T');
       Serial.print("Left Steps:  ");
       Serial.println(LeftFrontWheel.currentPosition());
       Serial.print("Right Steps:  ");
       Serial.println(RightFrontWheel.currentPosition());
      Serial.print("Sent TST:  ");
      Serial.println(totalStepsTaken);

        delay(100);
        }
        bufferFlush();

        delay(10);
        
         resetAll();   
}



void resetAll() {  //  Reset some variable
   // run = 0;
   LeftFrontWheel.setCurrentPosition(0);  //Setup for "while"loop to demonstrate trackRight
RightFrontWheel.setCurrentPosition(0);
   // lastDiff= 100;
    }



void bufferFlush() {
while (Serial3.available()) {
        Serial3.read(); // Discard any unwanted data
        delay(10);
    }
}


ARC

var totalStepsTaken = 0;


if (UART.hardwareUartAvailable(0) >= 5) {

         var header = UART.hardwareUartReadString(0, 1);
       
        if (header == 'T') {
            print("Received: " + header);
            
            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));
            
           totalStepsTaken = ((b3 << 24) | (b2 << 16) | (b1 << 8) | b0);
            print("totalStepsTaken:  " + totalStepsTaken);
            
            sleep(100);
            
            halt();
}

}
PRO
Canada
#23   — Edited

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:

  1. Header Comparison

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")

  1. Checking Available Bytes

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.

  1. Bit Shifting in ARC Code

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).

  1. Complete Revised Code Examples

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:


/* Arduino Code Snippet */
void stopMotors() {
  // Stop motor commands ...

  if(run == 1) {
    totalStepsTaken = 80001;
    // Break the long into 4 bytes (Lowest Byte sent first)
    int byte0 = totalStepsTaken & 0xFF;
    int byte1 = (totalStepsTaken >> 8) & 0xFF;
    int byte2 = (totalStepsTaken >> 16) & 0xFF;
    int byte3 = (totalStepsTaken >> 24) & 0xFF;

    // Send a header, for example, the character 'T'
    Serial3.write('T'); 

    // Send the 4 bytes sequentially
    Serial3.write(byte0);
    Serial3.write(byte1);
    Serial3.write(byte2);
    Serial3.write(byte3);

    Serial.print("Sent TST: ");
    Serial.println(totalStepsTaken);
  
    delay(100);
  }
  bufferFlush();
  delay(10);
  resetAll();
}

ARC Code (Receiver - JavaScript)

Ensure you wait for at least 5 bytes, compare against the literal header ("T"), and use proper bit-shift operators:


/* ARC JavaScript Code Snippet */
var totalStepsTaken = 0;
if (UART.hardwareUartAvailable(0) >= 5) {
    // Read the header (one character)
    var header = UART.hardwareUartReadString(0, 1);
    if (header == "T") {
        print("Received header: " + header);
        
        // Read the next 4 bytes as strings and convert them to integers
        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));
        
        // Reconstruct the 32-bit long using bit shifting
        totalStepsTaken = ((b3 << 24) | (b2 << 16) | (b1 << 8) | b0);
        print("totalStepsTaken: " + totalStepsTaken);
        sleep(100);
        halt();
    }
}

  1. Explanation

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.
#24  

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:

if (UART.hardwareUartAvailable(0) >= 5) {

         var header = UART.hardwareUartReadString(0, 1);
       
        if (header == 'T') {
            print("Received: " + header);
                              
            var b0 = parseInt(UART.hardwareUartRead(0,1));
            var b1 = parseInt(UART.hardwareUartRead(0,1));
            var b2 = parseInt(UART.hardwareUartRead(0,1));
            var b3 = parseInt(UART.hardwareUartRead(0,1));
            
           totalStepsTaken = (( b3 << 24) | ( b2 << 16) | ( b1 << 8) | b0);
            print("totalStepsTaken:  " + totalStepsTaken);
            
            sleep(100);
            
            halt();
}

}
PRO
Synthiam
#25  

@athena It'll be much faster if you read the whole 32 bit word like this

if (UART.hardwareUartAvailable(0) >= 5) {

  // read all 5 bytes from uart #0 that we need for this condition into the array tmpRead
  var tmpRead = UART.hardwareUartRead(0, 5);

  // header is first byte of the array
  if (tmpRead[0] == 'T') {

    print("Header: " + tmpRead[0]);

    totalStepsTaken = (( tmpRead[4] << 24) | ( tmpRead[3] << 16) | ( tmpRead[2] << 8) | tmpRead[1]);
    print("totalStepsTaken: " + totalStepsTaken);

    sleep(100);

    halt();
  }

}

PRO
Canada
#26  

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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:

  • Direct access to numerical values without unnecessary conversion.
  • Fewer function calls, which boosts performance.
  • A reduced chance of misinterpreting or losing data due to conversion issues.

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.
#27  

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

if (UART.hardwareUartAvailable(0) >= 5) {

  // read all 5 bytes from uart #0 that we need for this condition into the array tmpRead
  var tmpRead = UART.hardwareUartRead(0, 5);

  // header is first byte of the array
  if (tmpRead[0] == 'T') {

    print("Header: " + tmpRead[0]);

    totalStepsTaken = (( tmpRead[4] << 24) | ( tmpRead[3] << 16) | ( tmpRead[2] << 8) | tmpRead[1]);
    print("totalStepsTaken: " + totalStepsTaken);

    sleep(100);

    halt();
  }

}

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:

 //Determine if >= 5 Bytes available    
 if (UART.hardwareUartAvailable(0) >= 5) {
 
 // header is first byte of the array
  var header = UART.hardwareUartReadString(0,1);
    
      
  if (header == 'T') {
    print("Header: " + header);
  
  // read all 4 bytes from uart #0 that we need for this condition into the array tmpRead
  var tmpRead = UART.hardwareUartRead(0, 4);
    
    // tmpRead[3,2,1,0] are denoted as they were sent 0,1,2,3
    totalStepsTaken = (( tmpRead[3] << 24) | ( tmpRead[2] << 16) | ( tmpRead[1] << 8) | tmpRead[0]);
    print("totalStepsTaken: " + totalStepsTaken);

    sleep(100);

    halt();
  }

}
PRO
Canada
#28   — Edited

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:

  1. DJ_Sures’ Recommended Code
  if (UART.hardwareUartAvailable(0) == 5) {
   // Read all 5 bytes at once into an array. The first byte is the header.
   var tmpRead = UART.hardwareUartRead(0, 5);
   if (tmpRead[0] == T) {
    print("Header:" + tmpRead[0]);
    // Reconstruct the 32bit integer.
    totalStepsTaken = ((tmpRead[4] << 24) | (tmpRead[3] << 16) | (tmpRead[2] << 8) | tmpRead[1]);
    print("totalStepsTaken:" + totalStepsTaken);
    sleep(100);
    halt();
   }
  }

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.

  1. Your Reworked Code

// Determine that 5 bytes are available:

  if (UART.hardwareUartAvailable(0) == 5) {
   // Read the header as a string.
   var header = UART.hardwareUartReadString(0, 1);
   if (header == T) {
    print("Header:" + header);
    // Now read the remaining 4 bytes as a numeric array.
    var tmpRead = UART.hardwareUartRead(0, 4);
    // In this array, the bytes appear in the order they were sent: index 0 is the least significant byte, index 3 is the most significant.
    totalStepsTaken = ((tmpRead[3] << 24) | (tmpRead[2] << 16) | (tmpRead[1] << 8) | tmpRead[0]);
    print("totalStepsTaken:" + totalStepsTaken);
    sleep(100);
    halt();
   }
  }

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).

  1. Why Does JavaScript Prefer This (or Why Does It Work Better)?

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.

  1. Summary Comparison
  • 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.
#29  

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

PRO
Canada
#30  

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:

    totalStepsTaken = ((tmpRead[3] << 24) | (tmpRead[2] << 16) | (tmpRead[1] << 8) | tmpRead[0]);
    

    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.