I have a question about adding an action to an existing script I have that is written in JavaScript for ARC.
I currently have two different ARC JavaScript scripts that monitor ADC ports on a single EZB (hardware connected to the EZB; ARC sends commands and the EZB reads the ADC values).
Summary of the current scripts:
- Script A watches ADC port 0 (a micro switch inside the robot that detects when the robot’s fake power pack is inserted or removed). When the switch detects the power pack is pulled, the script triggers a sequence of ARC control commands (using ControlCommand, Digital, Servo, etc.), then pauses until the switch is released (power pack inserted) and runs the insert sequence. Practically, this simulates a visual robot power down while the EZB/robot remains powered. The script uses ADC.waitForHigher(0, 200) to detect the pack being pulled and ADC.waitForLower(0, 120) to detect insertion; it behaves like a toggle based on thresholds (start above 200, end below 160).
- Script B watches ADC ports 1-7 (momentary buttons) and maps each port to an action (animations, sounds, script starts). This script is written as a single ADC watcher that polls multiple ADC ports and invokes functions stored in an actions[] array. It works very well and reduces ADC read load by consolidating reads.
My goal:
- I want to merge the functionality of Script A (the micro switch toggle on ADC 0) into Script B so that a single ADC watcher script handles ADC 0..7 and reduces ADC read traffic. The toggle behavior for ADC 0 must be preserved (i.e., it should continue to watch for the pull/insert threshold behavior rather than acting like a momentary button).
- Alternatively, would it be better to keep Script A as the dedicated ADC 0 toggle watcher and have Script B (the multi-button watcher) call or be toggled by Script A? I’m not sure which design is better for performance or reliability in ARC.
Notes and clarifications:
- The second script already has an actions[] array and an entry actions[0] = function() (currently a placeholder). I understand that actions[0] could contain the toggle/power-pack logic, but I’m not sure of the best way to preserve the current toggle behavior (with waits and thresholds) inside the single ADC poll/debounce loop.
- Both scripts are JavaScript Robot Skills running inside an ARC project. Script A uses ADC.waitForHigher/Lower blocking calls and loops, while Script B uses a polled ADC.get approach with debounce logic. I want to know if these two read methods can be combined in one script without breaking the toggle semantics.
- I will attach both scripts below for reference and would appreciate suggestions on the best approach to handle this mixed setup: merge into one ADC watcher (with special-case handling for ADC 0 toggle) or keep the power-pack toggle as a separate watcher and have the multi-button skill trigger/coordinate with it.
I'll attach both scripts and hope for help. Thanks in advance for suggestions on the best way to handle this mixed bag.
Here is the first script that watches ADC port "0":
/*This script waits till Power Pack is pulled. Once pulled the pullPowerPack()function
will be called and run commands to make robot go dark and bend over.
Then this script will stop and wait till Power Pack is inserted. Then it will call the
insertPowerPack() function. The robot will power back up and stand up.
This script will then wait again untill power pack is pulled again and power down.
This will continue to loop with each powerpack pull or insert or untll robot is powered down.
*/
while (true) {
print("Waiting for power pack to be pulled...")
// Wait for ADC value to indicate the power pack is pulled
ADC.waitForHigher(0, 200)
// Perform actions after the power pack is pulled
pullPowerPack();
print("Waiting for power pack to be inserted...")
// Wait for ADC value to indicate the power pack is inserted
ADC.waitForLower(0, 120);
// Perform actions after the power pack is inserted
insertPowerPack();
}
function pullPowerPack(){
var conn_0 = EZB.isConnected(0);
if (conn_0 == true) { //Only proceed if EZB 0 is connected. Till trigger script if not.
ControlCommand("Personality Generator", "PauseOn");
sleep(100);
ControlCommand("Script Manager", "ScriptStart", "Mechalical Background Sounds - Stop");
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(500)
Digital.set(D8, true); //KIll Brain Lights
controlCommand("ADC Watcher", "ScriptStop");
ControlCommand("Weather Loop", "ScriptStop");
} else {
print("Reconnect EZB Connection 0 or restart Robot")
halt() //EZB 0 is not connected. Till trigger script if not connected.
}
// Wait for the Auto Position status to change to a 1
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
}
function insertPowerPack() {
ControlCommand("Script Manager", "ScriptStart", "Mechalical Background Sounds - Loop");
ControlCommand("Leg Section", "ScriptStart", "Up with Hips");
sleep(500);
ControlCommand("Head Section", "ScriptStart", "Bubble Up and Down");
sleep(500);
Digital.set(D0, true) //Turn on Ear sensor Motors
Digital.set(D8,false) //Turn on Brain lights (Kill Brain Lights)
Digital.set(D10,true) //Turn on Fast Brain lights
Digital.set(D2,true) //Turn on scanner lights
PWM.set(D9,50); //Turn on Crown Motor
sleep(4000);
Digital.set(D2,false) //Turn off scanner lights
sleep(500);
Digital.set(D4,true) //Turn on Box lights
ControlCommand("Head Section", "ScriptStart", "Radar 1/4 Sweep");
ControlCommand("Auto Both Arms", "AutoPositionAction", "Both Ars In");
sleep(5000);
while (getVar("$Lft_Elbow_Adjusting")== 1) {
sleep(100);
}
//Turn off and return to standby
//--------------------------------------------------
ControlCommand("Head Section", "ScriptStart", "Bubble Up and Down");
Digital.set(D0,false); //Turn Off Ear sensor motors.
Digital.set(D10, false); //Turn off fast brain lights
Digital.set(D4,false) //Turn off Box lights
PWM.set(D9, 0); //Turn off crown motor
controlCommand("ADC Watcher", "ScriptStart");
ControlCommand("Weather Loop", "ScriptStart");
ControlCommand("Personality Generator", "PauseOff");
}
Here's the second script I want to keep and add to it what the first script does. That is unless it's better to keep the first script and just let this second one toggle it. helped me write this one.
// Single ADC Watcher with debounce and actions
// Configure these:
var adcPorts = [0,1,2,3,4,5,6,7]; // ADC ports used (A0..A7 are ADC0..ADC7)
var threshold = 170; // value above this is considered "pressed"
var pollMs = 600; // how often to poll (milliseconds)
var debounceMs = 150; // how long value must be stable to accept
var ezbIndex = 0; // which EZB index this script is monitoring
// Map port index -> action function name or control commands
// Replace with your specific actions. Format: actions[port] = function() { ... }
var actions = [];
actions[0] = function(){ //Power Pack Pull Animation (Micro Switch is inside robot torso behind Power Pack)
sleep(3000);
ControlCommand("Soundboard 2","Track_26"); // Say "Not"
sleep(600);
ControlCommand("Soundboard v4","Track_20"); // Say "Active"
};
actions[1] = function(){ //Chest Button: Gamma 202 - Power Down Robot Compleatly
ControlCommand("Personality Generator", "PauseOn"); //Keeps personality from activating
sleep(6250);
ControlCommand("Shutdown PC", "ScriptStart");
}
actions[2] = function(){ //Chest Button: Gamma 101 - Personality Toggle On and Off
var personality = getVar("$Personality")
sleep(200)
if (personality == 0) { //0 means Personality is running.
turnOffPersonality()
}else if (personality == 1) {//1 means Personality is Paused.
turnOnPersonality()
}
}
function turnOffPersonality(){
//Personality toggle Momentary button (Gamma 101) was pushed. Will turn Persponality Off (PauseOn).
ControlCommand("Personality Generator", "PauseOn");
sleep(4000); //Holds shript here until ADC reading returns to zero before switching to other function
ControlCommand("Soundboard v4", "Track_24"); //Will do "Raspberries" sound
print("Personality is Off");
setVar( "$Personality", 1); //Sets Global Variable so next button push will turn Personalilty On
}
function turnOnPersonality(){
//Personality toggle Momentary button (Gamma 101) was pushed. Will turn Persponality On (PauseOff)
// Perform actions after Personality toggle button (Gamma 101) was pushed
ControlCommand("Personality Generator", "Pauseoff");
sleep(4000); //Holds shript here until ADC reading returns to zero before switching to other function
ControlCommand("Soundboard v4", "Track_23"); //Say "Green and GO"
print("Personality is On");
setVar( "$Personality", 0); //Sets Global Variable so next button push will turn Personalilty Off
}
actions[3] = function(){ //Chest Button: Vector Hold -
ControlCommand("Personality Generator", "PauseOn"); //Keeps personality from activating.
setVar( "$Personality", 1); //Sets Global Variable so next button push will turn Personalilty off
sleep(6000);
ControlCommand("Soundboard 2","Track_26"); // Say "Not"
sleep(600);
ControlCommand("Soundboard v4","Track_20"); // Say "Active"
ControlCommand("Personality Generator", "PauseOff");
setVar( "$Personality", 0); //Sets Global Variable so next button push will turn Personalilty on
}
actions[4] = function(){ //Chest Button: Alpha 202 -
ControlCommand("Personality Generator", "PauseOn"); //Keeps personality from activating.
setVar( "$Personality", 1); //Sets Global Variable so next button push will turn Personalilty off
sleep(6000);
ControlCommand("Soundboard 2","Track_26"); // Say "Not"
sleep(600);
ControlCommand("Soundboard v4","Track_20"); // Say "Active"
ControlCommand("Personality Generator", "PauseOff");
setVar( "$Personality", 0); //Sets Global Variable so next button push will turn Personalilty Oon
}
actions[5] = function(){ //Chest Button: Bata 202 - Speak Time, Date and Enviromental Report
ControlCommand("Personality Generator", "PauseOn"); //Keeps personality from activating. Called script will unpause.
setVar( "$Personality", 1); //Sets Global Variable so next button push will turn Personalilty off
sleep(6000); //Pause script to let robot speak confirmation of button push
ControlCommand("Time, Date & Temp", "ScriptStart", "Time,Date,Enviroment");
}
actions[6] = function() { //Chest Button: Detent +
ControlCommand("Personality Generator", "PauseOn"); //Keeps personality from activating.
setVar( "$Personality", 1); //Sets Global Variable so next button push will turn Personalilty off
sleep(6000);
ControlCommand("Soundboard 2","Track_26"); // Say "Not"
sleep(600);
ControlCommand("Soundboard v4","Track_20"); // Say "Active"
ControlCommand("Personality Generator", "PauseOff");
setVar( "$Personality", 0); //Sets Global Variable so next button push will turn Personalilty on
}
actions[7] = function(){ //Chest Button: Vector Release - Run Soil Sampler & Speak Report
ControlCommand("Personality Generator", "PauseOn"); //Keeps personality from activating.
setVar( "$Personality", 1); //Sets Global Variable so next button push will turn Personalilty off
Digital.set(D0, true) //Turn on Ear Motors
Digital.set(D23, true, 1) //Trun on Soil Samper Relay
Digital.set(D2, true) //Turn on Scanner chect lights
Digital.set(D10, true) //Turn on fast brain lights
sleep(2000)
Digital.set(D23, false, 1) //Turn off Soil Sampler Relay
ControlCommand("Leg Section", "ScriptStart", "Hip Center")
sleep(0250)
ControlCommand("Leg Section", "ScriptStart", "Hip Down Full")
sleep(6000)
ControlCommand("Leg Section", "ScriptStart", "Up with Hips")
sleep(3500)
ControlCommand("Head Section", "ScriptStart", "Bubble Up and Down")
sleep(0250)
Digital.set(D2, false) //Turn off Scanner chect lights
sleep(10000)
Digital.set(D0, false) //Turn off Ear motors
Digital.set(D10, false) //Turn off fast brain lights
ControlCommand("Personality Generator", "PauseOff");
setVar( "$Personality", 0); //Sets Global Variable so next button push will turn Personalilty on
}
// Add similar actions for other ADC ports if needed...
// Internal state
var lastState = []; // boolean pressed/unpressed
var stableStart = []; // timestamp ms when current state started
for(var i=0;i
// helper
function nowMs(){ return (new Date()).getTime(); }
print("ADC Watcher: start. Polling " + adcPorts.length + " ports every " + pollMs + "ms");
while(true){
try{
for(var i=0;i var port = adcPorts[i];
// Read ADC once per loop
var value = ADC.get(port, ezbIndex);
var pressed = (value >= threshold);
if(pressed !== lastState[i]){
// state changed - start a debounce timer if not already started
if(stableStart[i] === 0){
stableStart[i] = nowMs();
} else {
// check if we've been stable long enough
if(nowMs() - stableStart[i] >= debounceMs){
// accept new state
lastState[i] = pressed;
stableStart[i] = 0;
var t = (new Date()).toLocaleString();
print(t + " ADC" + port + " state -> " + (pressed ? "PRESSED" : "RELEASED") + " val:" + value);
if(pressed){
// call action for this port if defined
try{
if(typeof actions[i] === "function"){
actions[i]();
} else {
print("ADC Watcher: no action defined for port "+port);
}
}catch(ae){
print("ADC Watcher: action error: " + ae);
}
}
}
}
} else {
// state unchanged - reset debounce timer
stableStart[i] = 0;
}
}
}catch(e){
print("ADC Watcher: error reading ADC: " + e);
}
sleep(pollMs);
}
Related Hardware (view all EZB hardware)
Related Robot Skills (view all robot skills)
Upgrade to ARC Pro
Take control of your robot's destiny by subscribing to Synthiam ARC Pro, and watch it evolve into a versatile and responsive machine.
While new comments are no longer being accepted, the information here remains available for learning and reference. Check the most recent comment for additional details.

Whoops, here's the script:
Yes - the problem is not just removing
0fromadcPorts.Your script currently has a port-index mismatch:
adcPorts = [0,1,2,3,4,5,6,7]actions[1],actions[2], etc.actions[i]That means:
i = 0port = 0actions[0]i = 1port = 1actions[1]So when you remove
0from the array, the indexes shift:i = 0port = 1actions[0]That is why your buttons fire the wrong actions.
The fix
You need to call the action by ADC port number, not by loop index.
So change:
to:
Then you can safely remove ADC 0 from the polling list.
Also important: remove
actions[0]Since Script A owns ADC 0, Script B should not define an action for 0 at all.
Clean corrected version
Here is the corrected structure for Script B polling only ADC 1-7 and keeping your actions matched properly:
Why this works
The key change is:
instead of:
That keeps the action tied to the actual ADC port number even when ADC 0 is removed from the list.
One more thing
Your original script also had a few syntax issues like:
Pauseoffshould bePauseOffThe version above cleans that up.
If you want, I can do one more pass and make this into a fully ARC-polished version with:
lastStateinitialization so the script doesn’t falsely trigger on launchI 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.
OK, this last information and your last "cleaned" and adjusted script works great now. We did have one ControlCommand formatting issue that kept the called script from being found. However when I rewrote that command line the called script started just fine.
So, I'll move forward using this new button ADC polling script that watches ADC ports 1-7 on the EZB. I'll also keep separate and use my original Script A "as is" that's shown above. It watches only ADC port 0 on the same EZB watching a microswitch behind the Power Pack.
Removing ADC port 0 from the ADC polling script keeps that port from being polled by two different scripts. Exactly what I wanted to do. Thanks!