Asked
Resolved Resolved by Athena AI!

Is This The Proper Way To Toggle Between Two Functions In A Javascript Loop?

, I have a Javascript that watched an ADC value attached to a microswitch. When the switch is operated the ADC value will change. I've written a JavaScript with two functions. One for each positions of the switch and a "While" loop in each that holds the script until the ADC value crosses a threshold. Then when one function finishes it calls the other function and holds until the ADC value changes back. When the second function operates and finishes it will callback the first function. This keeps toggling back and forth with each operation of the switch.

Is this the best way to toggle between these two functions in JavaScript or is there a better and cleaner way? Here's the script. It's started by my INT script when the robot first powers up:

/*This script Starts the pullPowerPack() function then waits till 
Power Pack is pulled. Once pulled robot will go dark and bend over. 
Then the pullPowerPack() function will stop and call the insertPowerPack() function. 
That function will wait till power pack is replaced to restor power to robot.
Then the pullPowerPack() function will stop and callback the pullPowerPack() function.
This will continue with each powerpack pull and untll robot is powered down 
*/

pullPowerPack() //Starts the pullPowerPack() function when script starts from INT script at robot power up.

sleep(100);

function pullPowerPack(){
 //Holds Script till Power pack is pulled
while (ADC.get(0, 0) > 110) {
   sleep(250);
}
ControlCommand("Personality Generator", "PauseOn");
sleep(100);
ControlCommand("Auto Both Arms", "AutoPositionAction", "Both Ars Out");
sleep(100);
ControlCommand("Leg Section", "ScriptStart", "Hip Down Full");
sleep(100);
ControlCommand("Head Section", "ScriptStart", "Bubble Full Down");
sleep(100)
Digital.set(D8, true);
ControlCommand("Script Manager","ScriptStop", "Victor Hold Soil Sampler");

// Wait for the   Auto Position status to change to a false
while (getVar("$Both_ARS_Extended")== 0) {
   sleep(100);
}
ControlCommand("Auto Both Arms", "AutoPositionAction", "Dead_Down");
sleep(200);
Servo.release(D1, 2) //Release RT Up and Down Wrist Servo
Servo.release(D0, 2) //Release RT Side to Side Servo
Servo.release(D4, 2) //Release Lft Up and Down Wrist Servo
Servo.release(D5, 2) //Release Lft Side to Side Servo
print("Power Pack has been pulled. Waiting to replace");
insertPowerPack()

}

function insertPowerPack() {
// Holds Script till Power pack is inserted
while (ADC.get(0, 0) < 110) {
   sleep(250);
}
ControlCommand("Leg Section", "ScriptStart", "Up with Hips");
sleep(500);
ControlCommand("Script Manager", "ScriptStart", "Home Radar")
sleep(500);
ControlCommand("Head Section", "ScriptStart", "Bubble Up and Down");
Digital.set(D0, true) //Turn on Ear sensor Motors
//sleep(100);
Digital.set(D8,false) //Turn on Brain lights (Kill Brain Lights)
//sleep(100);
Digital.set(D10,true) //Turn on Fast Brain lights
//sleep(100);
PWM.set(D9,50); //Turn on Crown Motor
ControlCommand("Head Section", "ScriptStart", "Radar 1/4 Sweep");
sleep(4000);
ControlCommand("Auto Both Arms", "AutoPositionAction", "Both Ars In");
sleep(50);

//Turn off and return to standby
//--------------------------------------------------
Digital.set(D0,false); //Turn Off Ear sensor motors.
sleep(100);
Digital.set(D10, false); //Turn off fast brain lights
sleep(100);
PWM.set(D9, 0); //Turn off crown motor
sleep(100);
ControlCommand("Script Manager", "ScriptStart","Victor Hold Soil Sampler");
sleep(100);
//ControlCommand("Personality Generator", "PauseOff");
print("Power Pack has been replaced! Waiting to remove");
pullPowerPack()

}


Related Hardware EZ-B v4

ARC Pro

Upgrade to ARC Pro

Stay at the forefront of robot programming innovation with ARC Pro, ensuring your robot is always equipped with the latest advancements.

PRO
Canada
#1  

Your approach to toggling between two functions based on a condition in JavaScript for your EZ-B v4 robot project is logical and functional. However, there's always room for optimization or alternative methods depending on the project's complexity and requirements. The method you've chosen, using a loop within each function to wait for a condition to change and then calling the other function, is a straightforward way to achieve the toggling behavior you described.

One potential improvement to your script could be the implementation of event-driven programming. Instead of continuously polling the ADC value in a loop, which can be CPU-intensive, you might consider using an event-driven approach if your environment or hardware supports it. This method would involve setting up an event listener for the ADC value change and triggering the appropriate function when the event occurs. However, this approach's feasibility depends on the capabilities of the Synthiam ARC environment and the EZ-B v4 hardware.

Another suggestion is to ensure that your script includes error handling or conditions to exit the loop if unexpected values are read from the ADC or if the loop runs for an unexpectedly long time. This can prevent the script from getting stuck in an infinite loop if the hardware malfunctions or if the ADC value does not change as expected.

Here's a simplified version of your script with some added comments for clarity:

// Function to handle the power pack being pulled
function pullPowerPack() {
    console.log("Waiting for power pack to be pulled...");
    // Wait for ADC value to indicate the power pack is pulled
    while (ADC.get(0, 0) > 110) {
        sleep(250);
    }
    // Perform actions after the power pack is pulled
    performPowerPackPulledActions();
    // Call the function to handle the power pack insertion
    insertPowerPack();
}

// Function to handle the power pack being inserted
function insertPowerPack() {
    console.log("Waiting for power pack to be inserted...");
    // Wait for ADC value to indicate the power pack is inserted
    while (ADC.get(0, 0) < 110) {
        sleep(250);
    }
    // Perform actions after the power pack is inserted
    performPowerPackInsertedActions();
    // Call the function to handle the power pack being pulled again
    pullPowerPack();
}

// Start the process by calling pullPowerPack initially
pullPowerPack();

Remember, continuous polling in a loop is effective but can be improved for efficiency and responsiveness, especially in complex projects. Always consider the specific needs of your project and the capabilities of your development environment when designing your solution.


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

Well, that's good to know. I've now written several Javascritps using this format for buttons and switches that are monitored by ADC ports on my EZB's. This seems to work very well for me. My buttons and switches act differently. Some are a single push to initiate action while some others need to be pushed multiple times for a toggle effect.  Using the functions in the scripts to call each other after waiting and watching the ADC port before executing its  action is a workable solution for me. Thanks.

PRO
Synthiam
#3  

@athena why not this? Don't forget there is also ADC.waitForHigher() and ADC.waitForLower() etc... documented here: https://synthiam.com/Support/javascript-api/ADC/waitForHigher

You can remove the while() and replace it with the ADC.waitForHigher

Also, I think you want the pullPowerPack to be repeated a bit better than filling the stack and calling the functions recursively. Do they need to be two functions? Could this not be easier?

// Loop this process forever for the power pack status
while (true) {

print("Waiting for power pack to be pulled...");
// Wait for ADC value to indicate the power pack is pulled
ADC.waitForHigher(0, 110);

// Perform actions after the power pack is pulled
performPowerPackPulledActions();

print("Waiting for power pack to be inserted...");
// Wait for ADC value to indicate the power pack is inserted
ADC.waitForLower(0, 110);

// Perform actions after the power pack is inserted
performPowerPackInsertedActions();
}

PRO
Canada
#4  

DJ Sures' suggestion is an excellent improvement to the original approach for several reasons:

  1. Efficiency: By using ADC.waitForHigher() and ADC.waitForLower(), you eliminate the need for continuous polling in a while loop. These functions are designed to efficiently wait for the ADC value to cross a specified threshold, making your script more responsive and less CPU-intensive.

  2. Simplicity: Consolidating the logic into a single loop that continuously checks for the power pack's status simplifies the code structure. This makes the script easier to understand and maintain.

  3. Avoiding Recursion: The original approach of having functions call each other recursively could potentially lead to a stack overflow if the switching happens too many times. DJ Sures' method of using a single loop that runs indefinitely avoids this issue by not increasing the call stack.

  4. Readability: The proposed script is more straightforward and readable. It clearly outlines the process: wait for the power pack to be pulled, perform actions, wait for the power pack to be inserted, and then perform actions again. This linear flow is easier to follow.

Here's a slightly modified version of DJ Sures' script with added comments for clarity and the inclusion of placeholder functions for the actions to be performed after the power pack is pulled and inserted:

// Placeholder function for actions after the power pack is pulled
function performPowerPackPulledActions() {
    // Actions to perform after the power pack is pulled
    console.log("Power Pack has been pulled. Performing actions...");
    // Add your control commands here
}

// Placeholder function for actions after the power pack is inserted
function performPowerPackInsertedActions() {
    // Actions to perform after the power pack is inserted
    console.log("Power Pack has been inserted. Performing actions...");
    // Add your control commands here
}

// Loop this process forever for the power pack status
while(true) {
    console.log("Waiting for power pack to be pulled.");
    // Wait for ADC value to indicate the power pack is pulled
    ADC.waitForHigher(0, 110, 0); // Assuming 0 is the ezbIndex

    // Perform actions after the power pack is pulled
    performPowerPackPulledActions();

    console.log("Waiting for power pack to be inserted.");
    // Wait for ADC value to indicate the power pack is inserted
    ADC.waitForLower(0, 110, 0); // Assuming 0 is the ezbIndex

    // Perform actions after the power pack is inserted
    performPowerPackInsertedActions();
}

This script provides a clean, efficient, and maintainable way to handle the toggling behavior based on the power pack's status using ADC ports on the EZ-B.


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

Ahh! Yes, this is just what I was wanting to know in the first place. I had totally forgotten about or just completely missed the ADC.waitForLower and ADC.waitForHigher commands. I guess I need to review the available commands more often. This really simplifies my approach and script. I'm going to follow your advice and see if I can get it to work for me. I don't want the dreaded Stack Overflow bubbling out of the top of my robot.;)

I'll report back.

#6  

OK! I rewrote my script using your outline and it works great. I like the fact that it's not polling the ADC reading as often. However it must be doing that in the background at times. How often are these ADC Wait commands set to look at the ADC read? Anyway, I love the idea of putting this all in one constant looping script. Thanks again for the guidance! I now have a few other scripts to rewrite using this method.