Hi @Athena,
I'm nearly ready to put this script into production. Could you rewrite the complete Rev25 script into a cleaner Rev26 for my ARC project? This is the full Rev25 script used as a robot skill (scripting) in my ARC project. Please produce Rev26 that includes:
- the runaway servo protection that I added
- the existing edge logic preserved
- safer NEG/POS sweep limits
- simplified state handling
- clear comments on each section for easier maintenance
Notes / context:
- This script is used as an ARC robot skill (scripting) and controls servos via ARC-compatible hardware (EZB or other supported controllers).
- Preserve all current behavior and edge cases while improving readability, safety, and state management.
- I have not included the script here - let me know if you want the full Rev25 pasted into the thread or attached.
Thanks - Jack

Absolutely - I can help turn Rev25 into a cleaner Rev26, but I’ll need the full script first.
Please paste the entire Rev25 script here (or attach it), and I’ll rewrite it into a more maintainable Rev26 with:
If the script currently uses EZ-Script, I can still help by converting it to JavaScript or Python for ARC. I can’t author EZ-Script from scratch, but I can convert it and modernize it.
A couple quick questions before you paste it:
Which scripting language is Rev25 using right now?
What servo hardware is it controlling?
What should "runaway protection" do in your preferred behavior?
For example:
If you want, you can paste the script in chunks. Once I have it, I’ll return a polished Rev26 in a single code block with notes on what changed.
If you’re working on code cleanup like this often, the ARC AI Assistant inside ARC can also help rewrite scripts directly in the editor:
https://synthiam.com/Products/AI-Assistant
@Athena. Thank you for your continued support. The logic for function ' updateBearingFromEdges(edgeName) ':
negInitactualBearing = (negInit + posInit) / 2negFinalactualBearing = (negFinal + posFinal) / 2posInitactualBearing = (posInit + negInit) / 2posFinalactualBearing = (posFinal + negFinal) / 2The logic for function ' scanStep() ':
The script below follows the logic stated above. Please review the following script for efficiency, accuracy, and simplicity.
REV 25
Your last recommendation:
Updated
moveServoForSweep()Here’s the safer version:
Hopefully this is enough previous info.
Can you please add a simple way to prevent a runaway servo for NEG sweep if negInit is never found or for a POS sweep if posInit is never found? Criteria for the runaway servo prevention:
Thanks. Jack
Yes - that makes sense. Below is a cleaned Rev26 JavaScript version that keeps the edge logic, adds runaway protection, and simplifies the state handling a bit while staying ARC-friendly.
I made one important assumption:
negInitis not found before the servo goes 20 past desiredBearing in the NEG direction, the script aborts.posInitis not found before the servo goes 20 past desiredBearing in the POS direction, the script aborts.Servo.setPosition(servoPort, desiredBearing)setVar("$sendStopNow", 1)Rev26
What I changed
abortSweep()helper.handleNegSweep()andhandlePosSweep().d17as requested.One thing to confirm
Your runaway requirement says:
That means:
70110That is exactly what this version does based on the current desiredBearing.
If you want, I can also do a Rev26.1 pass that:
posFinal/negFinalcapture points if those are missing elsewhere,If you paste the complete Rev25 script, I can make this 100% faithful to your original behavior line-for-line while still cleaning it up.
@Athena. Thank you.
Review the function
scanStep().negInitshould be <=reflectorThreshold.negFinalis missing. Please include it and the operator will be >reflectorThreshold.posInitshould be <=reflectorThreshold.posFinalis missing. Please include it and the operator will be >reflectorThreshold.When I run the script in it's current form it runs away to 0 degrees. Can you please rewrite REV 25?
Thanks. Jack
Yes - the current version needs to be rewritten more carefully. The issue is that the
scanStep()logic appears to be malformed and the runaway condition is not guarding the NEG sweep correctly, so it can keep stepping all the way to0instead of stopping neardesiredBearing - 20.Since you asked to rewrite REV 25, I’ll provide a cleaner Rev26-style replacement for the scan logic with:
negInitposInitdesiredBearing$sendStopNow = 1Revised
scanStep()and support functionsImportant note
Your message suggests the real issue is that
scanStep()in the current code has a broken comparison operator aroundnegInitandposInit. In the rewrite above, I used:irValue <= reflectorThresholdto detect the reflectorirValue > reflectorThresholdto detect leaving itIf your sensor behaves opposite of that, we should flip the comparisons.
Why it was running to 0 degrees
The most likely causes were:
negInitwas never being detected correctlyQuick question
For your IR sensor, does the reflector produce:
That detail determines whether the threshold test should be:
irValue <= reflectorThresholdirValue >= reflectorThresholdIf you want, paste the full current Rev25 script again and I’ll rewrite it into a complete production-ready Rev26 with the exact same behavior preserved, but cleaned and corrected end-to-end.
@Athena. When I run the script, after a normal NEG scan and POS scan, it aborts in NEG sweep.
I believe the negInit & negFinal are not being reset to (-1) value for subsequent NEG sweeps. I noticed that posInit & posFinal are not being reset to (-1) as well.
Can you check and rewrite REV 25 to run without aborting the scan prematurely?
To answer your question: For your IR sensor, does the reflector produce:
The reflected light causes lower ADC values, hence when detecting the reflector for negInit, the ADC value is <=15. This lower ADC value will continue until a higher value (>15) is detected indicating negFinal.
The same is true for posInit and posFinal.
Thank you. Jack
Yes - you’ve identified the real issue.
If negInit / negFinal / posInit / posFinal are not reset before each new scan cycle, the next sweep can inherit stale values and trigger the wrong edge pairing or premature aborts. Since your reflector causes lower ADC values, the scan logic should treat:
irValue <= reflectorThresholdirValue > reflectorThresholdAlso, the cleanest fix is to:
desiredBearingand set$sendStopNow = 1on runawayBelow is a rewritten Rev25-cleaned Rev26 version in JavaScript for ARC.
Rev26 - cleaned and safer rewrite
What was fixed
desiredBearingImportant note
Because your reflector is detected by lower ADC values, this logic now uses:
That is the correct direction for your sensor.
One thing I want to confirm
When the scan is in the NEG or POS sweep, do you want the edge pair to be finalized on:
or
I assumed the current behavior is:
negInit= reflector first detectednegFinal= reflector no longer detectedIf that matches your hardware, this version should behave much more reliably.
If you want, I can now do a Rev26.1 tightening pass and further simplify this into a small state machine so it’s easier to maintain in ARC.
@Athena. Thank you for REV 26. Something seems to be causing function 'updateBearingFromEdges(edgeName)' from running completely after it is called. I believe it is due to function 'resetSweepEdges()' being called at inappropriate times. This prevents the logic of the function 'updateBearingFromEdges(edgeName)' from running successfully.
Can you investigate and rewrite REV 26 to fix this?
Also, I'm not sure 'negObsTot++;' and 'posObsTot++;' are totaling ir values at each pass. The total sum of (ir values) during NEG sweep should equal negObsTot. The total sum of (ir values) during POS sweep should equal posObsTot. These ObsTot values should be checked against ObsMax limits at the end of each particular sweep, then zeroed out. (After NEG sweep, check negObsTot against negObsMax and zero out. Same sequence for POS sweep.)
Can you investigate and rewrite REV 26 to reflect this?
To answer your question: When the scan is in the NEG or POS sweep, do you want the edge pair to be finalized on:
Yes. negInit is the point of reflector entering (IR <= 15), then negFinal is the point of reflector leaving (IR > 15). (The same conditions for posInit and posFinal.)
Thank you. Jack