I need a little help with timing in a JavaScript script I have running in my robot. It works great but there is one feature that I'd like to speed up. Here's what it is and what I need:
The below script that I attached polls 7 different ADC ports every 600ms on an EZBv4. Momentary buttons are attached to each of these watched ports. When one of the 7 monetary buttons are pushed and the voltage changes on its attached ADC port another script will trigger and an action will happen.
One of the sections of this script that watches these ADC ports and buttons starts several different Weather report scripts in itself, one different script after the other when this one particular momentary button is pushed. So to be clear, the first button push will give me the local temperature, the second push will give me what the actual temp feels like, the third will give me the humidity and so on. The timing of when the next button push is available is accomplished using the "ScriptStartWait" command. So, as I understand it, this command pauses the parent script calling the other child script until the "System" reports that that called child script has completed. Only then will the parent script unpause and be able to recognize the next button push to run the next script in this section.
My issue is the amount of time it takes for the next button push to be available (only in this one section using the "ScriptStartWait" method). After I push the button and the child script runs it takes at least 3 or 4 seconds for the next button push to become available after the child script ends. I'd like to get this pause shorter so the next push would be available almost right away. As is I need to wait and guess when I can push this button to hear the next step in the weather report.
Oh, also, this section also has a timer that resets the sequence back to the start if I don't push this button again within one minute
I've ran this through the ARC Script agent and it tried to adjust timing but it just messed up the script. I think the issue is using the ScriptStartWait" method. Is there any way to adjust when the system releases and unpauses the parent script thus making the next button push available? Is there a different way to write this section of the script that would let me push this button as soon as the child script completes? The timing in the rest of the script watching the other buttons is perfect.
The whole script is attached below. The section I'm referring to is labeled // ==================== Chest Button: Alpha 202, ADC4- (One button Push Each: Current Temp, Feels Like, Humidity and Wind Speed) ====================
// 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 = [];
// ================= Chest Button: Gamma 202, ADC1- (Power Down Robot Completely) ====================
actions[1] = function() {
sleep(6250);
controlCommand("Shutdown PC", "ScriptStart");
};
// ==================== Chest Button: Gamma 101, ADC2- (Personality Toggle On and Off) ====================
actions[2] = function() {
var personality = getVar("$Personality");
sleep(200);
if (personality == 0) {
turnOffPersonality();
} else if (personality == 1) {
turnOnPersonality();
}
};
function turnOffPersonality() {
controlCommand("Personality Generator", "PauseOn");
controlCommand("Weather Loop", "ScriptStop");
sleep(4000);
controlCommand("Soundboard v4", "Play", "Conclusion.mp3");
print("Personality is Off");
setVar("$Personality", 1);
}
function turnOnPersonality() {
controlCommand("Personality Generator", "PauseOff");
controlCommand("Weather Loop", "ScriptStart");
sleep(4000);
controlCommand("Soundboard v4", "Play", "GreenAndGo.mp3");
print("Personality is On");
setVar("$Personality", 0);
}
// ==================== Chest Button: Vector Hold, ADC3 (Open) ====================
actions[3] = function() {
controlCommand("Personality Generator", "PauseOn");
// setVar("$Personality", 1); //Only uncomment if this var is not set in called script.
sleep(5000);
controlCommand("Soundboard 2", "Play", "not.mp3");
sleep(600);
controlCommand("Soundboard v4", "Play", "Active-2.mp3");
controlCommand("Personality Generator", "PauseOff");
//setVar("$Personality", 0); //Only uncomment if this var is not set in called script.
};
// ==================== Chest Button: Alpha 202, ADC4- (One button Push Each: Current Temp, Feels Like, Humidity and Wind Speed) ====================
var alpha202ScriptList = ["Outside Temp", "Temp Feels LIke", "Humidity", "Wind Speed"];
var alpha202Index = 0;
var alpha202LastCompleteMs = 0;
var alpha202ResetMs = 60000; // 1 minute
actions[4] = function() {
var now = nowMs();
// Reset sequence if more than 1 minute since last completed run
if (alpha202LastCompleteMs > 0 && (now - alpha202LastCompleteMs) > alpha202ResetMs) {
alpha202Index = 0;
}
controlCommand("Personality Generator", "PauseOn");
controlCommand("Weather Loop", "ScriptStop");
sleep(4750);
var scriptToRun = alpha202ScriptList[alpha202Index];
controlCommand("Time, Date & Temp", "ScriptStartWait", scriptToRun);
alpha202LastCompleteMs = nowMs();
alpha202Index = alpha202Index + 1;
if (alpha202Index >= alpha202ScriptList.length) {
alpha202Index = 0;
}
controlCommand("Personality Generator", "PauseOff");
controlCommand("Weather Loop", "ScriptStart");
};
// ================ Chest Button: Bata 202, ADC5 -(Speak Time,Date and Environmental Report) ====================
actions[5] = function() {
controlCommand("Personality Generator", "PauseOn");
//setVar("$Personality", 1); //Only uncomment if this var is not set in called script.
sleep(6000);
controlCommand("Time, Date & Temp", "ScriptStart", "Time,Date,Enviroment");
};
// ==================== Chest Button: Detent +, ADC6 (Open) ====================
actions[6] = function() {
controlCommand("Personality Generator", "PauseOn");
//setVar("$Personality", 1); //Only uncomment if this var is not set in called script.
sleep(5000);
controlCommand("Soundboard 2", "Play", "not.mp3");
sleep(600);
controlCommand("Soundboard v4", "Play", "Active-2.mp3");
controlCommand("Personality Generator", "PauseOff");
//setVar("$Personality", 0); //Only uncomment if this var is not set in called script.
};
// ============ Chest Button: Vector Release, ADC7-(Run Soil Sampler & Speak Report ====================
actions[7] = function() {
controlCommand("Personality Generator", "PauseOn");
setVar("$Personality", 1); //Var is set because this is the control script.
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); //This Var is cleared because this is the control script.
};
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);
}

Yes - the delay is very likely coming from
ScriptStartWaititself, not from the ADC polling.What’s happening
controlCommand("Time, Date & Temp", "ScriptStartWait", scriptToRun);means:
If you’re seeing a 3-4 second gap after the child script ends, that’s usually because the parent script is still tied up in the wait/blocking behavior and then returning to the polling loop afterward.
Best fix
For this kind of "press once, run next step, be ready immediately for the next press" workflow, I’d recommend not using
ScriptStartWaithere.Instead, use:
Then let the button sequence state advance independently.
Better approach for your weather sequence
You already have
alpha202Index, so you can keep the sequence moving without waiting for the child script to "release" the parent.Replace this:
With this:
That will make the parent return to monitoring much faster.
If you need the next press to happen only after speech finishes
If the goal is not "script complete" but rather "speech/audio complete", then
ScriptStartWaitmay still not be the right tool, because child scripts can return before all audio is actually done depending on how they’re written.A more reliable pattern is to have the child script set a status variable when it is truly finished, for example:
Then the parent can watch for that variable, or better yet, avoid waiting entirely and just use the button sequence index.
The cleanest fix for your case
Because your weather reports are user-initiated button steps, I’d suggest this structure:
That way, the next press is accepted as soon as ARC gets back to the poll loop.
Example rewrite of your Alpha 202 section
Why this helps
One more important note
You’re polling every 600 ms, so even with a perfect script you can only detect a new press roughly every 0.6 seconds plus debounce. If you want the system to feel more responsive, consider lowering
pollMsto something like:or
That alone can make button response feel much snappier.
Recommendation
For this section, I’d try in this order:
ScriptStartWaittoScriptStartpollMsfrom600to100or50If you want, I can also help you rewrite just the ADC4 section into a cleaner state-machine version that preserves your timing behavior and removes the wait stall entirely.
Dave and follow up with this:
One required change to the four weather scripts
This is important. At the very end of each of these four scripts:
add:
For example, if
Outside Tempcurrently ends like this:change the end to:
That last line is what tells the ADC watcher:
This avoids guessing with sleeps and avoids relying on
ScriptStartWait.Wow Dave. Thanks. Your the best.as always I appreciate your help. I'll work on this later today and report back.
Glad to help - that’s a solid direction to try.
The key change is exactly what you pointed out: have each weather child script set a completion variable at the very end so the ADC watcher can move on immediately without waiting on
ScriptStartWait.A few quick notes before you test:
Audio.say()orAudio.sayEZB()without waiting, the completion flag should only be set after the final speech line.print()line right before the flag so you can confirm each script reaches the end.For example:
Important ARC note
If the weather scripts are launched by name from
ScriptStart, they’ll run independently, which is what you want here. This is a good use case for ARC’s scripting model.Optional improvement
If the whole weather-report flow is still a little sluggish, you can likely reduce
pollMsfrom200to100or even50to make the next press feel more immediate.If it acts weird
If you test it and the next button still doesn’t respond instantly, tell me:
sayWaitor non-blocking speech"finished"message immediatelyIf you want, I can help you trim the four weather scripts too so they all follow the same clean pattern.
Hey @dbeard,
Dave, after following your instructions and installing your script it works! Thanks. The button push responses in that section are almost instant now. I love it. Just what I was looking for.
I only had two things I had to change (for your info only. I'm not complaining).
var pollMs = xxx;" from what I had (600) to 200ms. I know this was done to make the button pushes feel more responsive like @Athena suggested. However when I changed the var pollMs back to my original 600ms the whole phrase is now said and the entire delivery sounds natural. I've never had a problem with the buttons feeling sluggish or missing a button push. When I first wrote this script I experimented with that value and found it made no difference in my setup if I kept that number below 600. Furthermore I try to keep the polling ADC ports a bit slow to keep the traffic from overwhelming the system. I'm polling 10 ADC ports at once in this and other scripts this keeps that all under control. I was having problems with my USB to Serial direct connections to the computer disconnecting and that seemed to help.It seems that the two "\" before and after the word port was illegal I removed them and the script ran as expected. This line ended up looking like this:
Oh, the rest of the script still works great.
So again, thanks for your help and all the work you put into this for me. I'm a happy camper. LOL.