Speech Recognition icon Speech Recognition Windows Speech Recognition skill: detect custom phrases via PC mic, trigger configurable scripts/actions with adjustable confidence. Try it →
Asked
Resolved Resolved by Athena!

Adding An Action To An Existing Script

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)
EZ-B V4 by EZ-Robot
EZ-B v4/2 robot controller: dual Cortex ARM, Wi-Fi, audio/video, 24 servo/digital ports, I2C/UART, camera and Synthiam ARC control for custom robots
Wi-Fi / USB
Servos 24
Camera
Audio
UART 3
I2C
ADC 8
Digital 24

Related Robot Skills (view all robot skills)
Duplicate and synchronize commands from one master EZ-B to multiple slave EZ-Bs for simultaneous, mirrored robot actions.
Script by Synthiam
Multi-language ARC Script: build, run and debug Blockly, JavaScript, EZ-Script or Python with Intellisense, run/save/load and Roboscratch support

ARC Pro

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.

#9  

Whoops, here's the script:

// Single ADC Watcher with debounce and actions
// Configure these:
var adcPorts = [0,1,2,3,4,5,6,7]; // ADC ports used (A1..A7 are ADC1..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 () {
    // No ADC 0 here. Script "Power Pack Pull" handles the power pack switch.
};

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 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);
}
Author Avatar
PRO
Canada
Twitter YouTube GitHub
#10  

Yes - the problem is not just removing 0 from adcPorts.

Your script currently has a port-index mismatch:

  • adcPorts = [0,1,2,3,4,5,6,7]
  • but your actions are written as actions[1], actions[2], etc.
  • then the script calls actions[i]

That means:

  • i = 0 port = 0 actions[0]
  • i = 1 port = 1 actions[1]
  • etc.

So when you remove 0 from the array, the indexes shift:

  • i = 0 port = 1
  • but the code still calls actions[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:

actions[i]()

to:

actions[port]()

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:

// Single ADC Watcher with debounce and actions
// Polls ADC1-ADC7 only. ADC0 is handled by Script A.

var adcPorts = [1, 2, 3, 4, 5, 6, 7];
var threshold = 170;
var pollMs = 600;
var debounceMs = 150;
var ezbIndex = 0;

// Map ADC port number -> action function
var actions = [];

actions[1] = function() {
  // Chest Button: Gamma 202 - Power Down Robot Completely
  ControlCommand("Personality Generator", "PauseOn");
  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) {
    turnOffPersonality();
  } else if (personality == 1) {
    turnOnPersonality();
  }
};

function turnOffPersonality() {
  ControlCommand("Personality Generator", "PauseOn");
  sleep(4000);
  ControlCommand("Soundboard v4", "Track_24");
  print("Personality is Off");
  setVar("$Personality", 1);
}

function turnOnPersonality() {
  ControlCommand("Personality Generator", "PauseOff");
  sleep(4000);
  ControlCommand("Soundboard v4", "Track_23");
  print("Personality is On");
  setVar("$Personality", 0);
}

actions[3] = function() {
  // Chest Button: Vector Hold
  ControlCommand("Personality Generator", "PauseOn");
  setVar("$Personality", 1);
  sleep(6000);
  ControlCommand("Soundboard 2", "Track_26");
  sleep(600);
  ControlCommand("Soundboard v4", "Track_20");
  ControlCommand("Personality Generator", "PauseOff");
  setVar("$Personality", 0);
};

actions[4] = function() {
  // Chest Button: Alpha 202
  ControlCommand("Personality Generator", "PauseOn");
  setVar("$Personality", 1);
  sleep(6000);
  ControlCommand("Soundboard 2", "Track_26");
  sleep(600);
  ControlCommand("Soundboard v4", "Track_20");
  ControlCommand("Personality Generator", "PauseOff");
  setVar("$Personality", 0);
};

actions[5] = function() {
  // Chest Button: Bata 202 - Speak Time,Date and Environmental Report
  ControlCommand("Personality Generator", "PauseOn");
  setVar("$Personality", 1);
  sleep(6000);
  ControlCommand("Time,Date &Temp", "ScriptStart", "Time,Date,Enviroment");
};

actions[6] = function() {
  // Chest Button: Detent +
  ControlCommand("Personality Generator", "PauseOn");
  setVar("$Personality", 1);
  sleep(6000);
  ControlCommand("Soundboard 2", "Track_26");
  sleep(600);
  ControlCommand("Soundboard v4", "Track_20");
  ControlCommand("Personality Generator", "PauseOff");
  setVar("$Personality", 0);
};

actions[7] = function() {
  // Chest Button: Vector Release - Run Soil Sampler & Speak Report
  ControlCommand("Personality Generator", "PauseOn");
  setVar("$Personality", 1);

  Digital.set(D0, true);
  Digital.set(D23, true, 1);
  Digital.set(D2, true);
  Digital.set(D10, true);

  sleep(2000);
  Digital.set(D23, false, 1);

  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(250);
  Digital.set(D2, false);

  sleep(10000);
  Digital.set(D0, false);
  Digital.set(D10, false);

  ControlCommand("Personality Generator", "PauseOff");
  setVar("$Personality", 0);
};

var lastState = [];
var stableStart = [];

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 < adcPorts.length; i++) {
      var port = adcPorts[i];
      var value = ADC.get(port, ezbIndex);
      var pressed = (value >= threshold);

      if (pressed !== lastState[port]) {
        if (stableStart[port] == null || stableStart[port] == 0) {
          stableStart[port] = nowMs();
        } else {
          if (nowMs() - stableStart[port] >= debounceMs) {
            lastState[port] = pressed;
            stableStart[port] = 0;

            var t = new Date().toLocaleString();
            print(t + " ADC" + port + " state -> " + (pressed ? "PRESSED" : "RELEASED") + " val:" + value);

            if (pressed) {
              try {
                if (typeof actions[port] === "function") {
                  actions[port]();
                } else {
                  print("ADC Watcher: no action defined for port " + port);
                }
              } catch (ae) {
                print("ADC Watcher: action error: " + ae);
              }
            }
          }
        }
      } else {
        stableStart[port] = 0;
      }
    }
  } catch (e) {
    print("ADC Watcher: error reading ADC: " + e);
  }

  sleep(pollMs);
}

Why this works

The key change is:

actions[port]()

instead of:

actions[i]()

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:

  • Pauseoff should be PauseOff
  • some missing semicolons
  • some places where the formatting was collapsed together

The version above cleans that up.


If you want, I can do one more pass and make this into a fully ARC-polished version with:

  • consistent comments
  • safer debounce logic
  • optional startup lastState initialization so the script doesn’t falsely trigger on launch

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

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!

📚 This thread has been preserved as a helpful resource!

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.