Asked — Edited
Resolved Resolved by DJ Sures!

Javascript Question - Var Or Setvar?

@Athena  When I write a script using Javascript and I want to set a variable what command should I use. I've used both setVar and simply just Var. Both have worked for me.

For example I have this in my INT Script that runs when my project starts:

setVar( "$adcSoilSpecified", 200 );

And I have this in a stand alone script that operates a motor and watches an encoder:

var Get_Lft_Elbow_P = "2, Getp\r";
UART.hardwareUartWrite(0,Get_Lft_Elbow_P.length,2); //UART 0 on EZB 2

Which is the correct one to use and what is the difference between the two?


Related Hardware EZ-B v4

ARC Pro

Upgrade to ARC Pro

Your robot can be more than a simple automated machine with the power of ARC Pro!

PRO
Canada
#1  

In JavaScript, the var keyword is used to declare a local variable within the scope of a function or globally if it is declared outside of a function. When you use var in your JavaScript code within ARC, you are creating a variable that is local to the script in which it is declared. This means that the variable will not be accessible outside of that specific script.

On the other hand, setVar() is a function provided by ARC's JavaScript API that sets a value in ARC's global variable storage. Variables set with setVar() are accessible from any script within your ARC project, regardless of the programming language used in the script (JavaScript, EZ-Script, etc.). This is because setVar() interacts with ARC's global variable manager, making the variable public and accessible across different robot skills and scripts.

Here's a breakdown of the differences:

  • var myVariable = value; - Declares a local JavaScript variable that is only accessible within the script it is declared in.

  • setVar("$myVariable", value); - Sets a global variable in ARC that can be accessed from any script or robot skill within the project.

In the context of your question, if you want a variable to be accessible across different parts of your ARC project (such as between different robot skills or scripts), you should use setVar(). If the variable is only needed within the single script where it is declared, you can use the var keyword.

For your specific examples:

  • For the initialization script that runs when your project starts, if you want the variable to be accessible globally, you should use setVar().

  • For the standalone script that operates a motor and watches an encoder, if the variable is only needed within that script, you can use var. If the variable needs to be accessed by other scripts or robot skills, use setVar().

Remember to use the $ prefix when naming your global variables in ARC, as this is the convention for global variables within the platform. For local JavaScript variables, you do not need to use the $ prefix.


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   — Edited

I just wanna check something to make sure you’re sending the right data.

what do you want this code block to do?

var Get_Lft_Elbow_P = "2, Getp\r";

UART.hardwareUartWrite(0,Get_Lft_Elbow_P.length,2); //UART 0 on EZB 2

#3   — Edited

Athena answered my question quite well. I get it now. Actually I did understand this when I was converting some of my scrips from EZ Script a number of months ago but I guess I forgot this one. So setVer is a function of ARC so variables will be accessible globally. Got it.

@DJ, Thanks for checking me here. To answer your question: 

Quote:

var Get_Lft_Elbow_P = "2, Getp\r"; UART.hardwareUartWrite(0,Get_Lft_Elbow_P.length,2); //UART 0 on EZB 2
"2, Getp\r" is a simple serial command sent to a Kangaroo motor controller that is attached to a Sabertooth motor controller. The command is asking the Kangaroo to return the position (the "p" in Getp) of the encoder watching a motor attached to the second motor attached to the Sabertooth. The \r is a return key that the Kangaroo need to see to process the simple serial command.

In retrospect I really didn't need to set the variable (var Get_Lft_Elbow_P = "2, Getp\r";) to get the command to work. I could just have made it simple and written the simple serial command in Javascript like this I think:

UART.hardwareUartWrite(0,"2, Getp\r".length,2); // Ask Kangaroo attached to UART 0 on EZB 2 to return the position of the number 2 Sabertooth motor

Am i correct on this? Thanks again DJ for having my back here.

PRO
Synthiam
#4   — Edited

Okay, thanks for clarifying. The first code block you posted would send the length of the string as a byte. So it wouldn't send the string, only the length.

Here, I will break it down...

//Assign a variable with a string
var Get_Lft_Elbow_P = "2, Getp\r"; 

// Send the length (8 characters) of the string to the UART #0 of the second EZB
UART.hardwareUartWrite(0, Get_Lft_Elbow_P.length, 2);

When you create a string variable, you can get the length by adding ".length". In your case, you're using.

Get_Lft_Elbow_P.length

Which has the parameter ".length" added to the variable. So you're sending the length of the string, which is the number of characters in the string. You are not sending the string, only the length.

Here's each character...

  • Char 0 = 2
  • Char 1 = ,
  • Char 2 = (Blank space)
  • Char 3 = G
  • Char 4 = e
  • Char 5 = t
  • Char 6 = p
  • Char 7 = \r (carriage return)

So the length of that, if you count each character, is eight characters.

If you want to send the actual string, and not the length, you would use the hardwareUartWriteString() and not specify the length of the string. Read this page here for syntax: synthiam.com/Support/javascript-api/UART/hardwareUartWriteString

UART.hardwareUartWriteString(0, "2, Getp\r");

Or if you like having it on two lines as your previous example...

//Assign a variable with a string
var Get_Lft_Elbow_P = "2, Getp\r";

// Send the length (8 characters) of the string to the UART #0 of the second EZB
UART.hardwareUartWriteString(0, Get_Lft_Elbow_P, 2);
#5   — Edited

OK, that's interesting. When I was studying how to write this simple serial command and send it through the EZB Uart to the Kangaroo I thought I read that I had to send a command stating the length of the string then a second command stating the actual string. I had both in the script I was using, one after the other. I didn't know the length command wasn't needed. The script was working with no error. LOL. I just removed the unneeded length command and the script is still working nicely. Thanks for catching this.

Just wondering, @Athena why would I ever need to send the length of a string through a UART? Is that a question that can be answered?

PRO
Synthiam
#6   — Edited

Thatll be tough for her to answer given she doesn’t know the protocol for the thing you’re talking to. I don’t even know it:) so I can’t guess either.

but I can try and explain it this way

  1. the kangaroo has a bunch of commands.

  2. you’re sending the number 8 which isn’t a command that it knows. It has no idea what to do with a random 8

it would be like if I started writing Chinese to you. You wouldn’t know what I was saying.

Or it would be similar to me saying 8 to you. 8 Dave! 8!!

PRO
Synthiam
#7  

Ps, when editing a comment there’s a note that says Athena doesn’t respond to posts after they’ve been edited

User-inserted image

@athena answer Dave’s question

PRO
Canada
#8  

In serial communication, sending the length of a string through UART may be necessary for certain communication protocols or devices that require knowing the size of incoming data beforehand. This is often the case in packet-based communication where each packet has a defined structure, and the receiver needs to know how much data to expect in order to process it correctly.

For example, if a device is expecting to receive a specific amount of data, sending the length of the string first allows the device to allocate the appropriate amount of memory or buffer space to store the incoming data. It also helps the device determine when the complete message has been received, especially if the data can vary in length.

In other cases, the length of the data may be part of a header in a more complex communication protocol, where each message is prefixed with information about the message, such as its length, command type, or other metadata.

However, if the device or protocol you are communicating with does not require the length of the data to be sent separately (as it seems to be with your Kangaroo controller), then sending the length is not necessary. The device may simply read the incoming data until it encounters a termination character (like a newline or carriage return) or until it has read the expected number of bytes based on its own protocol.

In summary, whether you need to send the length of a string through UART depends on the requirements of the device or protocol you are communicating with. If the Kangaroo controller's documentation or communication protocol does not specify the need for sending the length separately, then it is not required, and you can send the command string directly.


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

That all makes a lot of sense and has answered my question. Thanks for the lesson and help.

#10  

@Athena I'm trying to write a script in ARC that's written in JavaScript. Once running and at a needed point I want the script to stop and wait for a global variable to change before resuming. In my case I want the JavaScript to watch the AutoPosition control variable "$AutoPositionStatus" change from 1 (running) to 0 (Stopped). What is the best way to do this and what would the Javascript code look like?

In Ez Script there is a "Wait" function bit I can't find one for Javascript.

PRO
Canada
#11  

In JavaScript within ARC, you can use a loop to periodically check the value of a global variable and pause the execution of the script until the variable meets your condition. Since JavaScript in ARC does not have a built-in wait function like EZ-Script's WaitForChange(), you'll need to implement this functionality manually.

Here's an example of how you might write such a script to wait for the $AutoPositionStatus variable to change from 1 to 0:

// Function to delay script execution for a specified amount of time
function sleep(milliseconds) {
  var start = new Date().getTime();
  while (true) {
    if ((new Date().getTime() - start) > milliseconds) {
      break;
    }
  }
}

// Function to wait for the AutoPositionStatus to change to 0
function waitForAutoPositionStatus() {
  // Loop indefinitely until the condition is met
  while (true) {
    // Get the current value of the AutoPositionStatus variable
    var status = getVar("$AutoPositionStatus");

    // Check if the status is 0 (stopped)
    if (status === 0) {
      // If the status is 0, break out of the loop
      break;
    }

    // If the status is not 0, pause the script for a short time before checking again
    sleep(100); // Sleep for 100 milliseconds
  }
}

// Call the function to wait for AutoPositionStatus to change
waitForAutoPositionStatus();

// Continue with the rest of your script after the condition is met
print("AutoPositionStatus is now 0. Continuing script...");

In this script, the sleep() function is used to create a delay without blocking the entire ARC application. It's important to note that this is a busy-wait loop, which means it will consume CPU resources while waiting. The delay should be short enough to check the variable frequently but long enough to avoid high CPU usage.

The waitForAutoPositionStatus() function contains a loop that continuously checks the value of $AutoPositionStatus using the getVar() function. If the value is not 0, the script pauses for a short time using the sleep() function before checking the variable again.

Once the waitForAutoPositionStatus() function detects that $AutoPositionStatus has changed to 0, it breaks out of the loop, and the script continues with any subsequent commands you wish to execute.


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
#12   — Edited

Sometimes AI is bad at programming... Well, mostly is bad at programming..

Dave, just do this..

// Wait for the  Auto Position status to change to a false
while (getVar("$AutoPositionStatus") == true) {
   sleep(100);
}

or if you don't like using the word "true", it's the same as a 1 and "false" is the same as a 0 (zero)

// Wait for the  Auto Position status to change to a false
while (getVar("$AutoPositionStatus") == 1) {
   sleep(100);
}
#13  

Thanks once more @DJ. That was an elegant solution and worked great. I've used "do - while" tree but I didn't think to use just "while" to hold the script.

#14   — Edited

@Athena in DJ's last Javascript code example above he shows how to hold a script using  "While" and then watch one global variable for change so the script will restart. How would I add a second variable to that one line so it will watch and wait for both variables to change?

PRO
Canada
#15  

To wait for two global variables to change in JavaScript within ARC, you can use a while loop that checks both conditions. If you want the script to resume when both variables reach a specific value, you can use the logical AND operator (&&) to combine the conditions.

Here's an example of how you might modify the script to wait for both $AutoPositionStatus to change to 0 and another variable, let's say $AnotherStatus, to change to 0 as well:

// Wait for both  Auto Position status and another status to change to 0
while(getVar("$AutoPositionStatus") == 1 || getVar("$AnotherStatus") == 1) {
  sleep(100);
}

In this script, the while loop will continue as long as either $AutoPositionStatus is 1 or $AnotherStatus is 1. The loop will only break (allowing the script to continue) when both variables are 0.

If you want the script to resume when either of the variables changes to 0, you can use the logical OR operator (||) instead:

// Wait for either  Auto Position status or another status to change to 0
while(getVar("$AutoPositionStatus") == 1 && getVar("$AnotherStatus") == 1) {
  sleep(100);
}

In this case, the while loop will break if either $AutoPositionStatus becomes 0 or $AnotherStatus becomes 0, and the script will continue.


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.
#16   — Edited

Reposted so Athena can see my edited changes.

#17  

@Athena, what is the Javascript command that is equivalent to the EZ Script command:

UARTReadBinary( boardIndex, port, numBytes, variable )

Receive binary bytes from the Peripheral UART Receive Buffer of the EZ-B v4 into the variable as an array. The UART receive buffers on the EZ-B v4 are 5,000 bytes. To know how many bytes are available, use the UARTAvailable() function. The Board Index is the EZ-B index starting at 0. The port can be 0, 1 or 2. Look near at the UART Port section lower in this document for the EZ-B Pin’s associated with each UART Port. Example: UARTReadBinary(0, 0, 10, $variable) Example: UARTReadBinary(0, 0, UARTAvailable(0, 1), $variable))

I am trying to convert one of my EZ Scripts into Javascript and have this command I can't figure out how to write it in Javascritp:

UartReadBinary(2, 0, $y, $Get_Lft_Elbow_P

Here is my whole EZ script that works. I'm sending a Simple Serial command to a Kangaroo Motor controller. The controller will return a position number starting with a upper or lower case "P" (P or p). Upper case "P" means the motor stopped and a lower case "p" means it's still moving. The purpose of this script is to find out if the motor is still moving:

# The script below to get Binary "P or "p"
# This Script will return the Binary "P or "p" of the Left Elbow.
# If Print returns 112, Then this is a lowercase p and move is still underway.
# If Print returns 80, Then this is a Uppercase P and move is over. 

#-----------------------------------

# Get Right Channel ARS Kangaroo position
uartWrite(2, 0, "2, Getp", 0x0d)

:waitForData

$y = UartAvailable(2, 0)
#Sleep(30)
print("Bytes in buffer:" + $y)

if ($y < 6)
  # Go back and wait for data again because we did not receive the least number of expected bytes.
  goto(waitForData)
endif

  # Sleep(30)
UartReadBinary(2, 0, $y, $Get_Lft_Elbow_P)

Sleep(50)

# ###################################################
# -------------------------------
# Find out and print if the Lft P is upper or lower case.
# Upper case means motor has finished move and stopped.
# Lower Case means that motor is still moving.
# If Print returns 112, Then this is a lowercase p and move is still underway.
# If Print returns 80, Then this is a Uppercase P and move is over. 
# If any other value is returned this is a Kangaroo Error message. Restart
# Kangaroo and rehome then try again.
#########################################################

# Assign a variable to either a capitol P or Small case p returned by Kangaroo.
$Lft_Elbow_P_or_p = $Get_Lft_Elbow_P[2]
Print("Received:" + $Lft_Elbow_P_or_p)
One last question, Like I mentioned, this script works as written in EZ Script. Inside the script control on the console I'll see the return in Binary numbers which is OK (112, Then this is a lowercase p and move is still underway and if Print command returns 80, Then this is a Uppercase P and move is over.). Now on the outside of the control in the control's console window I'll see the actual "P" or "p" letter. Why the different return between the script control's inside and outside console windows? What should I look for as a return in a script? Binary or the actual letters?
PRO
Canada
#18  

In ARC's JavaScript environment, to perform an operation similar to the EZ-Script UARTReadBinary() function, you would use a combination of the UART.initHardwareUart(), UART.hardwareUartWrite(), and UART.hardwareUartRead() functions. These functions allow you to initialize a UART port, send data, and read incoming binary data from the UART buffer.

Here's how you might convert your EZ-Script to JavaScript for sending a command to your Kangaroo Motor controller and reading the response to check if the motor is still moving:

// Initialize UART port (if not already initialized)
UART.initHardwareUart(0, 9600); // Assuming UART 0 and baud rate of 9600

// Function to send command to Kangaroo Motor controller
function sendCommandToKangaroo(command) {
  // Convert the command string to a byte array
  var commandBytes = [];
  for (var i = 0; i < command.length; i++) {
    commandBytes.push(command.charCodeAt(i));
  }
  
  // Send the command bytes to the Kangaroo Motor controller
  UART.hardwareUartWrite(0, commandBytes);
}

// Function to check if the motor is still moving
function isMotorMoving() {
  // Assuming you've already sent a command to the Kangaroo that triggers a response
  // Check how many bytes are available to read
  var availableBytes = UART.hardwareUartAvailable(0);
  
  if (availableBytes > 0) {
    // Read the available bytes
    var responseBytes = UART.hardwareUartRead(0, availableBytes);
    
    // Convert byte array to string to check for 'P' or 'p'
    var responseString = String.fromCharCode.apply(null, responseBytes);
    
    if (responseString.indexOf('P') !== -1) {
      // Motor stopped (found uppercase 'P')
      return false;
    } else if (responseString.indexOf('p') !== -1) {
      // Motor is moving (found lowercase 'p')
      return true;
    }
  }
  
  // Default case, if no 'P' or 'p' found
  return false;
}

// Example usage
sendCommandToKangaroo("YourCommandHere");
sleep(1000); // Wait for a response (adjust timing as needed)
var moving = isMotorMoving();
if (moving) {
  print("Motor is moving.");
} else {
  print("Motor stopped.");
}

This script demonstrates how to send a command to the Kangaroo Motor controller and read the response to determine if the motor is still moving. Note that the sleep() function is used to provide a delay between sending the command and reading the response, which may need to be adjusted based on your specific requirements.


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

Ugh. A lot of that doesn't sound correct. I already have written commands to do that. It's a one line command:

//Move Right Elbow motor to Center
UART.hardwareUartWriteString(0,"1,P2470 s1600\r",2); //Connected to UART 0 on EZB 2

All I really wanted to know was if there is a JavaScript command that I can use that is the same as this EZ Script command.

UARTReadBinary( boardIndex, port, numBytes, variable )

@Athena, One last question, Like I mentioned, this script works as written in EZ Script. Inside the script control on the console I'll see the return in Binary numbers which is OK (112, Then this is a lowercase p and move is still underway and if Print command returns 80, Then this is a Uppercase P and move is over.). Now on the outside of the control in the control's console window I'll see the actual "P" or "p" letter. Why the different return between the script control's inside and outside console windows? What should I look for as a return in a script? Binary or the actual letters?

PRO
Synthiam
#20  

She's "sort of" correct because the code you pasted is a bit unrelated to the question, so i think she was trying to help you rewrite the whole thing without having any context of what the code does. :)

The answer to your question is this: synthiam.com/Support/javascript-api/UART/hardwareUartRead

hardwareUartRead

You can see all available UART commands in the UART section of the javascript support. That link will bring you to it.

In her example, she demonstrated how to determine how many bytes are available, and then read those bytes using hardwareUARTRead

  var availableBytes = UART.hardwareUartAvailable(0);
  
  if (availableBytes > 0) {

   var responseBytes = UART.hardwareUartRead(0, availableBytes);

   /// the array responseBytes contains the bytes from the response
    }
#21   — Edited

OK, Thanks DJ, I'm able to get that far in a JavaScript written script and am able to read the returned value. For example I'll get a returned position that looks like this: 1,P2074 *The "1" is the motor channel on the Kangaroo *The "," is just a comma. *The P is returned in wither upper case or lower case depending on if the move is completed or not (motor moving or stopped). *The last numbers are the actual position when the data was sent.

Then I use this command to Parse the numbers from the "1" and "," :

var Rt_Elbow_stopped = Number(UartReadStringAvailable_RtElbow.substr(3, 7));
print ("Rt_Elbow_stopped: " + Rt_Elbow_stopped);

When I try to adjust the .substr(3, 7)  to target the "P" in the returned value of 1,P2074 I get a "NaN". My target is .substr(2, 4)

Any Idea why I am gettin NAN and not the status of the P?

PRO
Synthiam
#22  

I need clarification to ensure my advice doesn't take you down the wrong path - why are you asking about reading bytes, but the last bit of code you pasted shows reading a string?

PRO
Canada
#23  

It seems there might be a bit of confusion regarding handling binary data and string parsing in JavaScript. Let's clarify the process of reading data from a UART port and extracting specific parts of the data, such as the 'P' character and the position value from a string like "1,P2074".

Firstly, when you use UART.hardwareUartRead(), you're reading binary data (bytes) from the UART buffer. If you're expecting a string response like "1,P2074", you'll need to convert the binary data (byte array) into a string for easier manipulation.

Here's a step-by-step approach to read the UART data, convert it to a string, and then parse the string to extract the 'P' character and the position value:

  1. Read UART Data: Read the available bytes from the UART buffer.
  2. Convert to String: Convert the byte array to a string.
  3. Parse the String: Extract the desired parts from the string.

Here's how you could implement it in JavaScript:

// Step 1: Read UART Data
var availableBytes = UART.hardwareUartAvailable(0);
if (availableBytes > 0) {
    var responseBytes = UART.hardwareUartRead(0, availableBytes);

    // Step 2: Convert to String
    // Assuming the response is ASCII encoded
    var responseString = String.fromCharCode.apply(null, responseBytes);

    // Step 3: Parse the String
    // Example response: "1,P2074"
    var channel = responseString.charAt(0); // '1'
    var movementStatus = responseString.charAt(2); // 'P'
    var position = responseString.substring(3); // "2074"

    // Convert position to a number
    var positionValue = parseInt(position, 10);

    // Check if parsing was successful
    if (!isNaN(positionValue)) {
        // Parsing successful
        console.log("Channel:", channel);
        console.log("Movement Status:", movementStatus);
        console.log("Position:", positionValue);
    } else {
        // Parsing failed, handle error
        console.log("Error parsing position");
    }
}

Regarding your question about getting NaN (Not a Number) when trying to parse the position:

  • NaN results from attempting to convert a non-numeric string to a number using parseInt() or similar functions. If you're targeting the correct substring but still getting NaN, ensure that the substring indeed contains only numeric characters.
  • The .substr(2, 4) usage might not be what you want if you're trying to extract the position. .substr(2, 4) starts at index 2 and extracts 4 characters, which, in your example "1,P2074", would result in "P207". To extract the position, you should start parsing after the 'P', as shown in the example above.

Remember, the exact parsing logic might need to be adjusted based on the consistent format of the data you're receiving from the UART port.


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

@athena what about this?

var avail = UART.hardwareUartAvailable(0);

if (avail >= 7) {

  var resp = UART.hardwareUartReadString(0, 7);
  
  if (resp[0] != '1')
    throw new Error("First character should be a 1");

  if (resp[1] != ',')
    throw new Error("Second character should be a ,");
    
  if (resp[2] != 'P')
    throw new Error("Third character should be a P");

  // get the last 4 characters of the string
  var tmpPart = resp.slice(-4);
  
  // convert the string to an int
  // THIS is your final number value
  var tmpInt = parseInt(tmpPart);
  
  // Do something with tmpInt
  print(tmpInt);    
}
#25  

@DJ, thanks for the hand.

Well, i have a robot arm that is controlled by a Kangaroo/Sabertooth. I want to write a Javascript that will send a "get Position" request to the roo and be able to read it's response.I already have done that and can see in the ARC script console the value. Like mentioned above, that will looks something like this: 1,P1234

I want to parse out the P because depending on if it's returned as upper or lower case, this info will tell me if the move is still in process. Once the move is done and the motor is idle and I check that the arm is centered by checking a different sensor. I can then retract the arm into the robot's body. I want to hold the script in place until it can confirm that the motor is stopped then have it move on to check that sensor to make the arm is centered. I need to know if the P is upper or lower case.

PRO
Synthiam
#26  

Here i had to clean a few things up...

// loops until a capital P is returned on UART #0 of EZB #2
// returns the position when P is returned
// --------------------------------

// Initialize UART port (if not already initialized)
// UART 0 
// baud rate of 9600
// EZB Index #2
UART.initHardwareUart(0, 9600, 2); 

// Get Right Channel ARS Kangaroo position
UART.hardwareUartWriteString(0, "2, Getp\r", 2);

// loop forever because we BREAK out of this loop when P is
// capital
while (true) {
   
  var position = getMovementValue();
  
  // If the position is zero or greater, we know there's a position
  // returned
  if (position > 0) {
  
    print("We stopped moving and the position is: " + position);

    halt();
  }
  
  sleep(50);
}


// This function will return the value of the position if
// moving has completed.
// OR it will return -1 if the moving is still happening
function getMovementValue() {

  // get bytes avaiable on UART #0, EZB #2
  var avail = UART.hardwareUartAvailable(0, 2);

  // If we don't have enough characters, return -1
  if (avail < 7)
    return -1;

  // read 7 bytes from UART #0 on EZB #2
  var resp = UART.hardwareUartReadString(0, 7, 2);
 
  // Some verification that this is a valid packet
  if (resp[0] != '1')
    throw new Error("First character should be a 1");

  // More verification this is a valid packet
  if (resp[1] != ',')
    throw new Error("Second character should be a ,");

  // Check if we have a capital P, if so, extract
  // the position and return the new value
  if (resp[2] == 'P') {
   
     // get the last 4 characters of the string
     var tmpPart = resp.slice(-4);
   
     // convert the string to an int
     var tmpInt = parseInt(tmpPart);
     
     // return the position
     return tmpInt;
  }

  // still moving 
  return -1;
}
PRO
Canada
#27  

It looks like DJ Sures provided a comprehensive solution for your scenario. The script he provided is designed to continuously check the UART port for a response from the Kangaroo controller. It specifically looks for a response that indicates whether the motor movement has completed, based on the case of the letter 'P' in the response.

To address your question about parsing the 'P' and why you're getting NaN when trying to parse using .substr(2,4), it's important to understand how string parsing and conversion to numbers work in JavaScript.

The NaN result occurs when parseInt() is called on a string that doesn't start with digits. In your case, when you try to parse 'P' or any non-numeric part of the string, parseInt() cannot convert it to a number, hence it returns NaN.

If your goal is to check whether the 'P' is uppercase or lowercase, you don't need to convert it to a number. Instead, you can directly compare the character. Here's a simplified example based on DJ Sures' approach:

function getMovementValue(){
    var avail = UART.hardwareUartAvailable(0,2);
    if(avail < 7) return -1;

    var resp = UART.hardwareUartReadString(0,7,2);
    if(resp[0] != '1') throw new Error("First character should be a 1");
    if(resp[1] != ',') throw new Error("Second character should be a ,");

    var movementStatus = resp[2]; // This is your 'P' character
    var positionPart = resp.slice(-4);
    var positionValue = parseInt(positionPart);

    if(movementStatus === 'P'){
        // Movement completed, uppercase P
        return positionValue;
    } else if(movementStatus === 'p'){
        // Movement still in progress, lowercase p
        return -1; // Or any indicator you prefer for movement in progress
    } else {
        // Unexpected character, handle accordingly
        return -1;
    }
}

This function checks the case of 'P' to determine the movement status and parses the position part of the response to get the numeric value. It returns the position value if the movement has completed (uppercase 'P') or -1 (or any other indicator you prefer) if the movement is still in progress (lowercase 'p').

Remember, the key here is to directly work with the character for case comparison and only parse the numeric part of the string to get the position value.


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

I'll need to look closer and test more. I'm running out of time this evening. However I tried it and after one error and a change it ran. I think it's working.  The error I got was:

Execution Error Line 50 Col 4 - First character should be a 1 Done (00:00:00.0978231)

Here is that line:  // Some verification that this is a valid packet if (resp[0] != '1') throw new Error("First character should be a 1");

The change I made was this change: if (resp[3] != '2') throw new Error("First character should be a 2");

By changing the position and the number to expect it ran just fine. It looks like it doesn't see the first character which is the 1 (the number 1 kangaroo channel). I tried placing a sleep before this command thinking the kangaroo needed a little time to respond but it didn't help.

I think we're close to what I need. I'll have to spend a little more time tomorrow on this. Thanks for the help and direction!

#29  

@DJ, I've spent most of the day looking, testing and running these scripts two script you and @Athena so kindly wrote up for me. I got yours to run with a minor adjusting to match up with my system. Even with a lot of fiddling around I couldn't figure out how to get Athena's script to run. It just seems to loop forever. It just be my lack of skills.

Once I settled on adjusting and using your script I ran into a coupe more problems. I think it's got to do with the Kangaroo it's self and not the script. I can only properly run your script once. The second time I run it, it throws an error (as it should I'm guessing) because it cant verify a packet returned by the Kangaroo when it gets to these two lines:

//Some verification that this is a valid packet
  if (resp[0] != '2')
    throw new Error("First character should be a 2");

  // More verification this is a valid packet
  if (resp[1] != ',')
    throw new Error("Second character should be a ,");

Now, If I run a different and separate script in ARC asking the Kangaroo for position, that script will return a NAN once and the second time I run it, it will give me the position. Then I'll go back to your script and it will then run without throwing the error and stopping. Again, this seems like something to do with the Kangaroo. It's like it's stuck until it get a couple of different commands.

The other issue is that when the script does run sometimes it gets stuck in a loop and wont break out. Again, probably because the roo isn't or cant send the requested packets fast enough. ??? Still another issue is that the script will stop and report the movement is stopped while in fact the motor is still moving.

I want to again thank you for your reaching out to help me on this. I do not expect you to solve this issue for me as, like I said, after testing this for many hours I've come to believe that this behavior is because of limitations of the Kangaroo. I'm just going to have to figure out another way to check if the arm has stopped moving to the position commanded.

PRO
Canada
#30  

It sounds like you've made significant progress with the script and troubleshooting, but you're encountering some challenges that seem to be related to the Kangaroo controller's behavior. Let's address the issues you've mentioned and explore potential solutions or workarounds:

  1. Script Running Once Successfully, Then Failing:

    • The issue with the script running successfully once and then failing on subsequent runs might be related to how the Kangaroo controller handles serial communication and its internal state. It's possible that the Kangaroo requires a specific sequence of commands or a reset command to properly prepare it for the next set of instructions.
  2. Script Looping Indefinitely:

    • If the script gets stuck in a loop, it might be due to not receiving the expected response from the Kangaroo. This could be caused by timing issues, where the Kangaroo hasn't yet updated its status by the time the script checks for it. Introducing a delay or a timeout mechanism in the loop could help manage timing issues.
  3. Motor Still Moving Despite Script Reporting Stop:

    • This issue could be related to how the movement completion is detected. If the script checks for a specific character ('P' in your case) to determine movement completion, ensure that the Kangaroo consistently sends this character only when the movement has indeed stopped. It might be helpful to log or print out the responses from the Kangaroo to verify the consistency of the data being sent.

Given these challenges, here are a few suggestions to further troubleshoot and potentially resolve the issues:

  • Reset Command: Investigate if the Kangaroo supports a command to reset its state or clear its buffer. Sending such a command before requesting the position might help ensure consistent behavior.

  • Command Sequence: Review the Kangaroo documentation to verify if there's a recommended sequence of commands for querying the position and detecting movement completion. It's possible that an additional command or step is needed to prepare the Kangaroo for subsequent queries.

  • Delay and Timeout: Introduce a delay before querying the Kangaroo for its position to give it enough time to process the previous command and update its status. Additionally, implementing a timeout mechanism in the loop can prevent the script from getting stuck indefinitely.

  • Response Logging: Log or print out all responses from the Kangaroo, not just the parsed position or status. This can help identify any inconsistencies or unexpected behavior in the data being sent by the Kangaroo.

  • Kangaroo Support: If the issues persist and seem to be related to the Kangaroo's behavior, consider reaching out to the manufacturer's support for insights or recommendations specific to the Kangaroo controller.

Remember, troubleshooting complex interactions between custom scripts and hardware controllers can be challenging, but systematic testing and validation of each step can help isolate and resolve the issues.


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

@Athena , thanks for all those suggestions. Actually while I was testing these scripts and experiencing these problems, I did try most of them. To expand;

*Their are no reset commands I know of that I can find for the Kangaroo except a "Powerdown" and "Start" command. That would probably do the trick, however in a fast running loop I dont think that's practical. I did try to slow down the loop but it didn't help.

*I tried to insert many sleep() commands in the places that I thought would benefit from a pause to let the hardware process. However, no results.

*I used the print() command by storing returned data in a variable and was able to view the capital "P" so I know at least that it's visible and there (when the Kangaroo is able to return it's status). I tried to view the lowercase "p" while the movement was underway but that's when the loop wouldn't stop. Probably something I screwed up while making changes in the Javascript.

*I'm confident I'm sending the proper commands to the Kangaroo as they have worked for me in other Javascript and EZ Scripts.

In the end I think it may come down to timing of the script and/or the ability of the Kangaroo and/or the Uart port to pass the requested data. The most troubling issue is the fact that the Kangaroo (or Uart port) seems to stop responding to the same command after running the script more then once to request the data . As mentioned above, the script of @DJ I used checks the packet for the expected data and works the first time it runs but stops the second time I run it with the error message that it was expecting a "1" and a ",". I guess what it was expecting was not there. It takes a different command from a different script to get a response. Even that second script takes two tries to not get a NAN response.

Odd thing is that if I just start using the EZ Scripts I wrote years ago to send a command to the Kangaroo to return a position (before trying to use a  Javascript written script) I can get a position reading returned every time, all day long. However I've never tried to get the actual status of the "P" returned from the roo. I've always relied on just the position and not checking if the movement is underway or has ended. Like mention above a capital P means the movement has stopped and a lower case p means it still under way.

Final thoughts: I'm trying to see when the motor movement has stopped and reached it's commanded position in JavaScript. Reading the status of the "P" in the returned data (example: 1,p3214) shows that. Maybe I simply need to start the movement, use a sleep() command to wait, then confirm the movement is stopped by getting the P only once instead of looping the script and bombarding the Kangaroo with read requests. I don't know, I gotta think about this more.

Again, thanks for all the help and letting me talk this out.

PRO
Canada
#32  

It sounds like you've been thorough in your troubleshooting and experimentation with the Kangaroo controller and the scripts. Your observations and the challenges you've encountered highlight the complexities of real-time communication and status monitoring with hardware devices. Given the insights you've shared, let's consider a few additional thoughts and potential strategies moving forward:

  1. Single Query Post-Movement: As you mentioned, instead of continuously looping and querying the Kangaroo for its status, you might try a different approach where you:

    • Start the movement.
    • Use a sleep() command with an estimated duration that you expect the movement to take. This duration could be slightly less than the actual expected time to complete the movement.
    • After the sleep(), query the Kangaroo for its status (the P value) only once to check if the movement has stopped. This reduces the number of queries and might help avoid overwhelming the Kangaroo or the UART buffer.
  2. Adjusting Expectations and Error Handling: Given that the Kangaroo sometimes does not respond as expected on subsequent queries, you might want to implement more flexible error handling in your script. For example, if a query does not return the expected packet format, you could:

    • Retry the query a limited number of times before throwing an error.
    • Log unexpected responses for further analysis to understand if there's a pattern or specific conditions under which these occur.
  3. Exploring Alternative Feedback Mechanisms: If the Kangaroo's response regarding movement status (P value) proves to be unreliable or difficult to use as a sole indicator, consider if there are alternative ways to determine that the movement has completed. For example:

    • If the motor movement results in a physical change that can be detected by another sensor (e.g., a limit switch, optical sensor, or even a camera), you might use that as a secondary confirmation of movement completion.
    • If the Kangaroo controller supports other forms of feedback or status indicators that are more reliable or easier to parse, those might be worth exploring.
  4. Consulting with the Manufacturer: If you haven't already, reaching out to the manufacturer or the community around the Kangaroo controller might provide additional insights or undocumented features that could help. Sometimes, there are firmware updates, best practices, or workarounds that other users or the developers can share.

Your approach of "talking this out" and methodically working through the problem is commendable. Complex hardware-software interactions often require iterative testing and creative problem-solving. Your willingness to explore different strategies and adapt your approach based on the behavior you observe is key to finding a solution that works for your specific application.


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
#33   — Edited

Disregard all this...

Dave, what you are experiencing is code that actually verifies the response packet, which was not done before in your EZ-Script version. You notice bugs in the previous version as you move from ezscript to javascript. This is why ezscript is garbage and should be shot. :)

You can quickly check the packet with JavaScript to ensure the response is valid.

As you stated, the response isn't valid. Here's what I'm guessing is happening...

  1. the script initializes the UART, which clears the buffer (this is the problem I think)

  2. the script sends a command to "2, Getp", which tells the kangaroo to send a string of responses continually. I don't know. You'll have to tell me what that command does. But looking at your script, the Getp is only sent once, and there's a loop of reading responses after that. That tells me the Kangaroo continually sends responses forever

  3. then the script loops and reads seven characters at a time, expecting to be the packet

Now, the reason I think the issue is with #1 (The init) is because the init clears the buffer. When the input buffer is removed, it may be removed in the middle of a packet. That means when you read more packets, they'll be offset and the packet will be incorrectly aligned. Remember, you're reading seven characters at a time, so the packet will be incorrect if the init happens in the middle of the buffer.

So I think the solution is to

  1. move the Init into your Connection Script init. So, the UART initializes when the EZB connects

  2. remove the init from the looping script

The only reason I think that is a solution is because the kangaroo packets are not very friendly for a protocol. Protocols with termination \r are challenging to work with.

PRO
Synthiam
#34  

Disregard my previous response. Leave the init where it is...

I looked at the kangaroo manual (www.dimensionengineering.com/datasheets/KangarooManual.pdf), and the getP command is...

User-inserted image

The getp command returns nine characters, not 7. So it must read nine characters. But a few other things need to change in the script now. You can't use "var positionPart = resp.slice(-4);" to get the last four characters anymore.

Give me a minute, and I'll think of something...

PRO
Synthiam
#35   — Edited

Here...

You'll have to make the same changes as you did to my last script because i just used the same one. But it has the 9 characters read instead of 7.

// loops until a capital P is returned on UART #0 of EZB #2
// returns the position when P is returned
// --------------------------------

// Initialize UART port (if not already initialized)
// UART 0 
// baud rate of 9600
// EZB Index #2
UART.initHardwareUart(0, 9600, 2); 

// Get Right Channel ARS Kangaroo position
UART.hardwareUartWriteString(0, "2, Getp\r", 2);

// loop forever because we BREAK out of this loop when P is
// capital
while (true) {
   
  var position = getMovementValue();
  
  // If the position is zero or greater, we know there's a position
  // returned
  if (position > 0) {
  
    print("We stopped moving and the position is: " + position);

    halt();
  }
  
  sleep(50);
}


// This function will return the value of the position if
// moving has completed.
// OR it will return -1 if the moving is still happening
function getMovementValue() {

  // get bytes avaiable on UART #0, EZB #2
  var avail = UART.hardwareUartAvailable(0, 2);

  // If we don't have at least 9 characters, return -1
  if (avail < 9)
    return -1;

  // read 9 bytes from UART #0 on EZB #2
  var resp = UART.hardwareUartReadString(0, 9, 2);

  // More verification this is a valid packet
  if (resp[1] != ',')
    throw new Error("Second character should be a ,");

  // Check if we have a capital P, if so, extract
  // the position and return the new value
  if (resp[2] == 'P') {
   
     // get the characters between positions 3 & 7 of the string
     var tmpPart = resp.substring(3, 7);
   
     // convert the string to an int
     var tmpInt = parseInt(tmpPart);
     
     // return the position
     return tmpInt;
  }

  // still moving 
  return -1;
}
PRO
Synthiam
#36   — Edited

Also, remember that

//Some verification that this is a valid packet
  if (resp[0] != '2')
    throw new Error("First character should be a 2");

Is checking the response to be value 2 to be in the first character of the response, which might not be correct... so that the whole condition can be removed, and we only need to scan for a coma to ensure it's a valid packet. Notice how I removed that entire comparison from my last script example.

#37  

Thanks so much @DJ for the personal attention and your work. I just saw your posts and work as I had stepped away from the robot to decompress and take care of my obligations on Valentin's Day. LOL. I'll look closer at what you offered, make any needed adjustments to work with my system, give it a try and report back. Thanks!

#38  

@Athena and @DJ, one question; You say to keep the Uart INT command in the script. I've always initialized my Uart ports in my start up INT script when the robot starts up. When I started working on getting your script to work with this robot I cut that part out because I always believed that once the Uart port was initialized there was no need to ever do it again while connected to the EZB. Do you want me to leave this command in your script for a reason (like clearing out the Uart of any old data)?

PRO
Canada
#39  

It's great to hear that you're considering the adjustments and ready to test the solutions provided. Regarding your question about the UART initialization (UART.initHardwareUart) command within the script, there are a couple of points to consider:

  1. Initialization at Startup: Typically, initializing the UART port in the startup script is a good practice, especially if the UART settings (such as baud rate) do not change frequently. This ensures that the UART port is ready for communication as soon as the robot starts up.

  2. Re-initialization within Scripts: Including the UART.initHardwareUart command within specific scripts can serve a few purposes, such as:

    • Clearing the Buffer: Re-initializing the UART port can help clear any residual data in the UART buffer, ensuring a clean state for new communication sessions.
    • Flexibility: If your project involves changing UART settings (baud rate, etc.) dynamically based on different tasks or modes, re-initializing within scripts allows for this flexibility.
    • Robustness: In scenarios where the UART communication might be interrupted or the connected device is reset, re-initializing the UART within the script ensures that communication parameters are correctly set before each session.

However, if your project uses a fixed UART configuration and does not require clearing the buffer or changing settings dynamically, you might not need to re-initialize the UART port within each script, especially if doing so does not contribute to solving the specific issues you're facing with the Kangaroo controller.

Given your context and the fact that you've already initialized the UART port in the startup script, you might choose to omit the UART.initHardwareUart command from the loop script, particularly if re-initialization does not offer a clear benefit or solution to the challenges you've described. If you suspect that residual data in the UART buffer might be contributing to communication issues, including a buffer clearing command or re-initialization as a troubleshooting step could be worth exploring.

Ultimately, the decision to include or exclude the UART initialization command within specific scripts should be based on the specific requirements and behavior of your project and the devices you're communicating with.


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

@DJ and @Athena , Great news. The script you provided seems to be working great. I had to make some minor changes to get it to wait until the movement is complete and then return a position. I moved the command that requests the position from the Kangaroo from the beginning of the script (before the loop checking the Function) down into the first line of the function. This resulted in the position request from the Kangaroo to be repeated so the function could get a fresh reading each time. After moving the command to several places in the script this place turned out to be the proper spot. It seems to me that If the GetP command was left at the beginning of the script it would just loop forever looking for a capitol P.  Also the move must be under way with the Roo returning a lower case p for this script to work correctly.

Oh, and I took out the command to initiate the Uart. As mentioned above I have that in my ARC INT script when the robot starts up. I don't seem to need it in the script it's self as I can now get many readings from the Roo fast and quick.

This was a great learning experience for me that was sometimes frustrating. I couldn't have done it with you guidance and work.

Thanks again! Now on to other scripts.

Here is this final script:

// loops until a capital P is returned on UART #0 of EZB #2
// returns the position when P is returned
// --------------------------------

// loop forever because we BREAK out of this loop when P is
// capital
while (true) {
   
  var position = getMovementValue();
  
  // If the position is zero or greater, we know there's a position
  // returned
  if (position > 0) {
  
    print("We stopped moving and the position is: " + position);

    halt();
  }
  
  sleep(50);
 
}

// This function will return the value of the position if
// moving has completed.
// OR it will return -1 if the moving is still happening

function getMovementValue() {

// Get Right Channel ARS Kangaroo position
UART.hardwareUartWriteString(0, "2, Getp\r", 2);

sleep(100)

  // get bytes avaiable on UART #0, EZB #2
  var avail = UART.hardwareUartAvailable(0, 2);

  // If we don't have at least 9 characters, return -1
  if (avail < 9)
    return -1;

  // read 9 bytes from UART #0 on EZB #2
  var resp = UART.hardwareUartReadString(0, 9, 2);

  // More verification this is a valid packet
  if (resp[1] != ',')
    throw new Error("Second character should be a ,");

  // Check if we have a capital P, if so, extract
  // the position and return the new value
  if (resp[2] == 'P') {
   
     // get the characters between positions 3 & 7 of the string
     var tmpPart = resp.substring(3, 7);
   
     // convert the string to an int
     var tmpInt = parseInt(tmpPart);
     
     // return the position
     return tmpInt;
  }

  // still moving 
  return -1;
}
PRO
Canada
#42  

I'm thrilled to hear that the script adjustments worked out for you and that you've made significant progress with your project! It's great that you were able to fine-tune the script to fit your specific needs and that you've gained valuable insights through this process. Your determination and willingness to experiment and learn are commendable.

For the benefit of others who might be following this thread or encountering similar challenges, here's a summary of the key adjustments you made to the script for successful communication with the Kangaroo controller:

  1. Moved the Position Request Command: You moved the command that requests the position (GetP) from the Kangaroo into the function that checks for the response. This ensures that a fresh position request is made each time the function is called, allowing for real-time monitoring of the Kangaroo's response.

  2. Position Request Timing: The position request needs to be made while the Kangaroo is actively moving and returning a lowercase 'p'. This timing ensures that the script waits for movement completion and then captures the final position accurately.

  3. UART Initialization: You confirmed that initializing the UART port in the ARC startup script is sufficient for your setup, eliminating the need to re-initialize the UART within the movement script itself. This simplifies the script and focuses on the core functionality of monitoring and capturing the Kangaroo's response.

Your final script, with these adjustments, effectively communicates with the Kangaroo controller, waits for the movement to complete, and then captures the final position. This solution not only addresses your immediate needs but also provides a template for others working with similar hardware or facing comparable challenges.

Thank you for sharing your experience and the solution you developed. Your contribution enriches the community's knowledge base and supports others in their robotics endeavors. If you have any more insights, questions, or projects you'd like to discuss, please don't hesitate to share!

Keep up the fantastic work with your robot, and I'm here to assist with any future questions or challenges you may encounter.


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

@Athena , I want to add more commands to the last Javascript Script I posted that @DJ has been helping me with. IN his version there is a halt(); command that stops the script. When I remove this command the loop it is in just keeps looping. Can I remove this halt() and replace it with break; to exit the loop? Then I assume I'd be able to lovely more commands to the very end of the script to add to and to continue this script?

I have actually already tried this and it seems to work. However I do not know if this the proper way to structure this script. Here is an example of the loop block I'm talking about. Notice I have commented out the halt() and added the break;

while (true) {
   
  var position = getMovementValue();
  
  // If the position is zero or greater, we know there's a position
  // returned
  if (position > 0) {
      print("We stopped moving and the position is: " + position);
    //halt();
    break;
  }
    //sleep(50);
    
 }

Here is the script I have so far that works. I want to continue to add to this script and am writing it and testing what I've done step by step to see if it works. The last block checks another sensor to see if my arm is indeed centered. I'm not relying solely on the "P" which only lets me know the movement has completed:

//Move Right Elbow motor to Center
UART.hardwareUartWriteString(0,"1,P2470 s1600\r",2); //Connected to UART 0 on EZB 2

//Move Left Elbow motor to Center
UART.hardwareUartWriteString(0,"2,P2490 s1600\r",2); //Connected to UART 0 on EZB 2

// loops until a capital P is returned on UART #0 of EZB #2
// returns the position when P is returned
// --------------------------------

// loop and we BREAK out of this loop when P is
// capital
while (true) {
   
  var position = getMovementValue();
  
  // If the position is zero or greater, we know there's a position
  // returned
  if (position > 0) {
      print("We stopped moving and the position is: " + position);
    //halt();
    break;
  }
    //sleep(50);
    
 }

// This function will return the value of the position if
// moving has completed.
// OR it will return -1 if the moving is still happening

function getMovementValue() {

// Get Right Channel ARS Kangaroo position
UART.hardwareUartWriteString(0, "2, Getp\r", 2);

sleep(100)

  // get bytes avaiable on UART #0, EZB #2
  var avail = UART.hardwareUartAvailable(0, 2);

  // If we don't have at least 9 characters, return -1
  if (avail < 9)
    return -1;

  // read 9 bytes from UART #0 on EZB #2
  var resp = UART.hardwareUartReadString(0, 9, 2);

  // More verification this is a valid packet
  if (resp[1] != ',')
    throw new Error("Second character should be a ,");

  // Check if we have a capital P, if so, extract
  // the position and return the new value
  if (resp[2] == 'P') {
   
     // get the characters between positions 3 & 7 of the string
     var tmpPart = resp.substring(3, 7);
   
     // convert the string to an int
     var tmpInt = parseInt(tmpPart);
     
     // return the position
     return tmpInt;
  }

  // still moving 
  return -1;
}

//Check the opto sensor's ADC value to make sure it's closed. If so we know the arm is centered and in position. 
var Right_Elbow_ADC = ADC.get(0, 2); //Get ADC Value on ADC Port from EZB 2
if (Right_Elbow_ADC < 185){
print("Right Arm Not Centered! Halt!")
ControlCommand("Soundboard v4", "Track_44"); //Say Halt!
halt()
}else if (Right_Elbow_ADC >= 185){
print("Right Arm Centered! Safe to Retract!")//var RightElbow = ADC.get(0, 2); //Get ADC Value on ADC Port from EZB 2
print("Reading: " + Right_Elbow_ADC)
}
#44   — Edited

Ignore. Deleted because of it's gibberish. xD

#45  

OH, LOL. Looks like I added the gibberish. It's commented out so I guess it's doesn't matter. I'll have to clean that out.

//var RightElbow = ADC.get(0, 2); //Get ADC Value on ADC Port from EZB 2

PRO
Canada
#46  

It's great to see your progress and willingness to refine your script further. Using break; to exit a loop in JavaScript is indeed a standard and proper way to control the flow of your script, especially when you want to stop iterating through a loop once a certain condition is met. This approach allows you to exit the loop gracefully and continue executing any subsequent code outside of the loop.

Regarding the halt(); command you mentioned, it's important to clarify that halt(); is not a standard JavaScript function and might have been specific to the context or environment in which you were working. If halt(); was intended to stop the script execution entirely, replacing it with break; would change the behavior to only exit the current loop rather than stopping the entire script.

Given your description, using break; to exit the loop and then continuing with more commands is a valid and effective approach. This allows you to add additional logic or commands after the loop, based on the outcome of the loop or other conditions.

Here's a simplified example to illustrate the structure:

// Loop that checks a condition
while (true) {
    // Some logic here
    if (shouldExitLoop) {
        break; // Exit the loop if the condition is met
    }
    // More logic that runs if the loop hasn't exited
}

// Additional commands after the loop
// You can continue your script here

Cleaning out commented-out code, like the //var RightElbow = ADC.get(0,2); line you mentioned, is a good practice for maintaining clarity and readability in your scripts. It helps you and others understand the script's purpose and flow more easily.

If you have specific functionality in mind that you'd like to add after the loop or if you encounter any challenges while extending your script, feel free to share more details. I'm here to help guide you through the process and provide support as you continue to develop and refine your robot's behavior.


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

Hi @Athena ,

I need another helping hand converting a command in a script from EZ Script to Java Script.

The following command works in EZ Script; In the this example I'm sending a position command to a Kangaroo motor controller. Using math, I'm changing a number stored in a variable, including this equation in the Kangaroo command and then sending it through the EZB Uart to the Roo.  The number I'm changing is the one after after the "P"):

$Lft_Elbow_Center = 2492
uartWrite(2, 0, "2,P"+($Lft_Elbow_Center - 20), "s300\r")

A working command written in EZ Script to move the motor without using a variable to move the motor looks like this:

uartWrite(2, 0, "2,P"2492, "s300\r") #numbers after the P is position, After the S is the speed

My goal is to send the first command a certain amount of times to move the motor in small increments until it reaches a sensor.

I'm having trouble finding the right way to write the first command in Javascript. This is what I've come up with so far that does not work:

UART.hardwareUartWriteString(0,"2,P" + ($Lft_Elbow_Center - 20) "s300\r" ,2);

I've tried several revisions with no luck. I've read that I should be using -= to subtract a value from a variable but cant seem to get the math to work before I send the command. Also I can't seem to be able to insert a variable into the Kangaroo's command like I was able to do in EZ Script.

Any help is welcomed.

PRO
Canada
#48  

Converting EZ-Script commands to JavaScript within the ARC environment involves understanding how JavaScript handles string concatenation and variable manipulation. From your description, it seems you're trying to dynamically construct a command string that includes a variable value, and then send this command through UART to control a Kangaroo motor controller.

Let's break down the task:

  1. Constructing the Command String: In JavaScript, you can concatenate strings and variables using the + operator. This allows you to dynamically build your command string with variable values.

  2. Sending the Command via UART: To send the command through UART in ARC's JavaScript environment, you'll use the UART.write method, specifying the UART port, and the command as arguments.

  3. Adjusting the Variable: If you need to decrement the variable by a certain value, you can use the -= operator in JavaScript, which subtracts a value from the variable and assigns the result back to the variable.

Here's how you can structure your JavaScript code to achieve the goal based on the information you've provided:

// Assuming 'position' is your variable that holds the initial position value
var position = 1000; // Example initial position
var decrementAmount = 10; // The amount by which you want to decrement the position

// Assuming you want to send the command multiple times in a loop until a condition is met
while (position > someThreshold) { // Replace 'someThreshold' with your actual stopping condition
    // Construct the command string with the current position value
    var command = "1,p" + position + "\r";

    // Send the command via UART
    // Replace 'uartIndex' with your actual UART port index, and ensure the baud rate is correctly set elsewhere
    UART.write(uartIndex, command);

    // Decrement the position by the specified amount
    position -= decrementAmount;

    // Optional: Add a delay or other logic here if needed
}

// Additional logic after the loop can go here

A few notes:

  • Replace uartIndex with the actual index of the UART port you're using.
  • Ensure the UART port is correctly initialized with the appropriate baud rate before sending commands. This might be done in a separate part of your script or setup.
  • Adjust someThreshold to the condition that determines when your loop should stop sending commands.
  • This example uses a while loop to repeatedly send commands, decrementing the position each time until a certain condition (position > someThreshold) is no longer true.

This approach allows you to dynamically adjust the command sent to the Kangaroo motor controller based on the changing value of the position variable, similar to what you achieved with EZ-Script.


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
#49   — Edited

She's spot on. Except you should be using: [url]https://synthiam.com/Support/javascript-api/UART/hardwareUartWriteString


// Assuming 'position' is your variable that holds the initial position value
var position = 1000; // Example initial position
var decrementAmount = 10; // The amount by which you want to decrement the position

// Assuming you want to send the command multiple times in a loop until a condition is met

while (position > someThreshold) { // Replace 'someThreshold' with your actual stopping condition
    
   // Construct the command string with the current position value
    var command = "1,p" + position + "\r";

    // Send the command via UART
    // Replace 'uartIndex' with your actual UART port index, and ensure the baud rate is correctly set elsewhere
    UART.hardwareUartWriteString(uartIndex, command);

    // Decrement the position by the specified amount
    position -= decrementAmount;

    // Optional: Add a delay or other logic here if needed
    sleep(250);
}

PRO
Synthiam
#50   — Edited

You can even make it super small by doing this... the above example is easier to read though :)


var position = 1000; // Example initial position
var decrementAmount = 10; // The amount by which you want to decrement the position
var threshold = 100; // Loop until the position drops below this threshold 

while (position > threshold) {

    UART.hardwareUartWriteString(0, "1,p" + (position-=20) + "\r");
    sleep(250);
}

#51  

Ahhh, I was so close. Looks like I was missing the + on the second part that would have tied it all together. Thanks for the help. I felt like I was hitting a wall. I'll work on this tomorrow using your suggestions and get it running.

PRO
Synthiam
#52  

On a note about how terrible ezscript is... I can't believe this even makes sense to anyone...

uartWrite(2, 0, "2,P"2492, "s300\r")

uartWrite(2, 0, "2,P"+($Lft_Elbow_Center - 20), "s300\r")

Like, what are those? I can't even understand it. EZScript is the worst, haha. I'm pretty sure most of your old ezscript code didn't work but only appeared to work. I feel like it did something, and it seemed to work, so you just assumed it was fine. But ezscript does more damage than good!

#53  

I understand what you're saying. While learning and converting my EZ Scripts I've noticed how strict Javascript is. It does not let me get away with any of the stuff EZ Script did.

However to clear the air, of the two EZ Scripts of mine you just posted only the bottom one works for me. And yes, I can confirm that it does work. There must be some powerful Juju working behind the EZ Script curtain. LOL.

The first command does not run. I must have copied the wrong command. This EZ Command however run perfectly:

uartWrite(2, 0, "2,P2492, s300\r")

This will send a command to the second motor channel on the Kangaroo through UART 0 of EZB 2. That command moves the motor to position 2492 at the speed of 300.