Connection Diagnostic icon Connection Diagnostic Diagnose EZ-B Wi-Fi connection issues with verbose EZ-B communication logging, ping tests, log export and diagnostic reports for Synthiam support. Try it →
Asked — Edited

Global Variables Between Scripts In ARC

@Athena, can you help me set up global variables in one script (LEG_v6) so they can be read and sent by another script (UART_v6)?

Context: I'm using an EZB4 running EZB JavaScript. These are EZB JavaScript scripts that run on the EZB as part of my ARC project (not PC-side ARC scripts). LEG_v6 initializes the variables with setVar, and UART_v6 reads them with getVar and sends data over the EZB hardware UART to an Arduino. Below are both scripts for reference.

LEG_v6

print("LEG_v5 started");

setVar("$pathTotalDistance", 50000);
setVar("$combinedStepsDesired", 42000);
setVar("$oppositeDistance", 3500);
setVar("$bearingAlignment", 0);   // 0 = DA, 1 = OA
setVar("$desiredBearing100",( Servo.getPosition(17)* 100));
setVar("$actualBearing100", (Servo.getPosition(17)* 100));
setVar("$trackDir", 0);             // 0 = FD, 1 = RD

// Control flags
setVar("$waypointSent", 0);
setVar("$sendWaypointNow", 1);
setVar("$sendStopNow", 0);
setVar("$sendActualBearingNow", 0);
setVar("$obsScan", 0);
setVar("$run", 0);
setVar("$legComplete", 0);
setVar("$totalStepsTaken", 0);

print("LEG_v5 loaded:");
print("pathTotalDistance = " + getVar("$pathTotalDistance"));
print("combinedStepsDesired = " + getVar("$combinedStepsDesired"));
print("oppositeDistance = " + getVar("$oppositeDistance"));
print("bearingAlignment = " + getVar("$bearingAlignment"));
print("desiredBearing100 = " + getVar("$desiredBearing100"));
print("actualBearing100 = " + getVar("$actualBearing100"));
print("trackDir = " + getVar("$trackDir"));

UART_v6

var UART_INDEX = 0;
var UART_HEADER = 0xA5;

// ARC -> Arduino
var CMD_STOP_MOTORS = 0x01;
var CMD_ACTUAL_BEARING = 0x03;
var CMD_RIGHT_PIVOT = 0x04;
var CMD_LEFT_PIVOT = 0x05;
var CMD_WAYPOINT_DATA = 0x06;

// Arduino -> ARC
var RSP_NAV_ACK = 0x10;
var RSP_TOTAL_STEPS = 0x11;
var RSP_DESIRED_BEARING = 0x12;
var RSP_OBS_SCAN_REQUEST = 0x13;

function safeInt(v, def) {
  var n = parseInt(v);
  if (isNaN(n)) return def;
  return n;
}

function u16ToBytes(value) {
  value = value & 0xFFFF;
  return [value & 0xFF, (value >> 8) & 0xFF];
}

function u32ToBytes(value) {
  value = value >>> 0;
  return [
    value & 0xFF,
    (value >> 8) & 0xFF,
    (value >> 16) & 0xFF,
    (value >> 24) & 0xFF
  ];
}

function bytesToU16LE(b0, b1) {
  return (b0 & 0xFF) | ((b1 & 0xFF) << 8);
}

function bytesToU32LE(b0, b1, b2, b3) {
  return (b0 & 0xFF) |
    ((b1 & 0xFF) << 8) |
    ((b2 & 0xFF) << 16) |
    ((b3 & 0xFF) << 24);
}

function sendPacket(cmd, payload) {
  var packet = [UART_HEADER, cmd].concat(payload);
  UART.hardwareUartWrite(UART_INDEX, packet);
}

function sendStopMotors() {
  sendPacket(CMD_STOP_MOTORS, []);
  print("TX: STOP MOTORS");
}

function sendActualBearing() {
var bearing100 = getVar("$actualBearing100");
//  var bearing100 = safeInt(getVar("$actualBearing100", 9000), 9000);
  sendPacket(CMD_ACTUAL_BEARING, u16ToBytes(bearing100));
  print("TX: ACTUAL BEARING x100 = " + bearing100);
}

function sendWaypointData() {

var pathTotalDistance = getVar("$pathTotalDistance");
  var combinedStepsDesired = getVar("$combinedStepsDesired");
  var oppositeDistance = getVar("$oppositeDistance");
  var bearingAlignment = getVar("$bearingAlignment");
  var desiredBearing100 = getVar("$desiredBearing100");
  var actualBearing100 = getVar("$actualBearing100");
  var trackDir = getVar("$trackDir");

  var payload = [];
  payload = payload.concat(u32ToBytes(pathTotalDistance));
  payload = payload.concat(u32ToBytes(combinedStepsDesired));
  payload = payload.concat(u32ToBytes(oppositeDistance));
  payload.push(bearingAlignment & 0xFF);
  payload = payload.concat(u16ToBytes(desiredBearing100));
  payload = payload.concat(u16ToBytes(actualBearing100));
  payload.push(trackDir & 0xFF);

  sendPacket(CMD_WAYPOINT_DATA, payload);
  print("TX: WAYPOINT DATA sent");
}

// RX parser
var rxState = 0;
var rxCmd = 0;
var rxExpected = 0;
var rxPayload = [];
var rxIndex = 0;

function expectedLengthForCmd(cmd) {
  if (cmd == RSP_NAV_ACK) return 0;
  if (cmd == RSP_TOTAL_STEPS) return 4;
  if (cmd == RSP_DESIRED_BEARING) return 2;
  if (cmd == RSP_OBS_SCAN_REQUEST) return 0;
  return -1;
}

function handleRxPacket(cmd, payload) {
  if (cmd == RSP_NAV_ACK) {
    print("RX: NAV ACK");
    setVar("$run", 1);
    return;
  }

  if (cmd == RSP_TOTAL_STEPS) {
    var steps = bytesToU32LE(payload[0], payload[1], payload[2], payload[3]);
    print("RX: TOTAL STEPS = " + steps);
    setVar("$totalStepsTaken", steps);
    setVar("$legComplete", 1);
    setVar("$waypointSent", 0);
    halt();
    return;
  }

  if (cmd == RSP_DESIRED_BEARING) {
    var bearing100 = bytesToU16LE(payload[0], payload[1]);
    print("RX: DESIRED BEARING = " + (bearing100 / 100.0));
    setVar("$desiredBearing100", bearing100);
    return;
  }

  if (cmd == RSP_OBS_SCAN_REQUEST) {
    print("RX: OBSTACLE SCAN REQUEST");
    setVar("$obsScan", 1);
    return;
  }

  print("RX: Unknown command = 0x" + cmd.toString(16));
}

function processIncomingBytes() {
  var available = UART.hardwareUartAvailable(UART_INDEX);

  while (available > 0) {
    var b = UART.hardwareUartRead(UART_INDEX, 1)[0];
    available--;

    if (rxState == 0) {
      if (b == UART_HEADER) rxState = 1;
      continue;
    }

    if (rxState == 1) {
      rxCmd = b;
      rxExpected = expectedLengthForCmd(rxCmd);
      rxPayload = [];
      rxIndex = 0;

      if (rxExpected == 0) {
        handleRxPacket(rxCmd, rxPayload);
        rxState = 0;
      } else if (rxExpected > 0) {
        rxState = 2;
      } else {
        rxState = 0;
      }
      continue;
    }

    if (rxState == 2) {
      rxPayload.push(b);
      rxIndex++;

      if (rxIndex >= rxExpected) {
        handleRxPacket(rxCmd, rxPayload);
        rxState = 0;
        rxCmd = 0;
        rxExpected = 0;
        rxPayload = [];
        rxIndex = 0;
      }
      continue;
    }
  }
}

print("UART_v5 started");

while (true) {
  if (getVar("$sendWaypointNow", 0) == 1 && getVar("$waypointSent", 0) == 0) {
    sendWaypointData();
    setVar("$sendWaypointNow", 0);
    setVar("$waypointSent", 1);
  }

  if (getVar("$sendStopNow", 0) == 1) {
    sendStopMotors();
    setVar("$sendStopNow", 0);
  }

  if (getVar("$sendActualBearingNow", 0) == 1) {
    sendActualBearing();
    setVar("$sendActualBearingNow", 0);
  }

  processIncomingBytes();
  sleep(20);
}

Thanks, Jack



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)
Add custom EZ-Script functions in C# or JS; intercept unknown calls, parse parameters and return values via AdditionalFunctionEvent.
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

Subscribe to ARC Pro, and your robot will become a canvas for your imagination, limited only by your creativity.

Author Avatar
PRO
Canada
Twitter YouTube GitHub
#1  

Yes - global variables can be shared between ARC JavaScript scripts as long as they’re created with a $ prefix and you use setVar() / getVar().

Since both LEG_v6 and UART_v6 are ARC JavaScript scripts, your approach is correct:

  • LEG_v6 uses setVar("$name", value)
  • UART_v6 uses getVar("$name", defaultValue)

What to check

1) Use the $ prefix in every shared variable

You’re already doing this correctly:

setVar("$pathTotalDistance", 50000);
setVar("$sendWaypointNow", 1);

Then in the other script:

if (getVar("$sendWaypointNow", 0) == 1) {

2) Make sure both scripts are running in the same ARC project

Global variables are shared inside the same ARC project.
If LEG_v6 is in one project and UART_v6 is in another, they will not share variables.

3) Confirm the variables are being updated after startup

Your LEG_v6 initializes values once, which is fine. But if UART_v6 needs changing values later, LEG_v6 must continue calling setVar() as those values change.

For example, if bearing changes during the run:

setVar("$desiredBearing100", Servo.getPosition(17) * 100);
setVar("$actualBearing100", Servo.getPosition(17) * 100);

If those values are only set once at startup, UART_v6 will only ever read the startup values.

4) Watch out for script timing

If UART_v6 starts before LEG_v6, then getVar("$pathTotalDistance", 0) will return the default until LEG_v6 sets it.

Your code already protects against that well by using defaults:

getVar("$sendWaypointNow", 0)

That’s the right pattern.


If UART_v6 depends on initialization, it’s best to make sure LEG_v6 runs first, or have UART_v6 wait until a ready flag exists:

In LEG_v6

setVar("$legReady", 1);

In UART_v6

while (getVar("$legReady", 0) != 1) {
  sleep(50);
}
print("LEG is ready");

That avoids race conditions.


One issue I notice in your posted code

This line appears broken in the UART script:

function bytesToU16LE(b0, b1) { return (b0 & 0xFF) | ((b1 & 0xFF) 0) }

It looks like the shift operator got lost. It should likely be:

function bytesToU16LE(b0, b1) {
  return (b0 & 0xFF) | ((b1 & 0xFF) << 8);
}

Also, your u32ToBytes() is fine, but I’d recommend keeping all helper functions clean before debugging variable sharing.


If you want to send the variables to the Arduino

You can read them in UART_v6 like this:

var totalSteps = getVar("$combinedStepsDesired", 0);
var bearing = getVar("$actualBearing100", 0);

Then pack and send them over UART.


Example: shared variable flow

LEG_v6

setVar("$legReady", 1);
setVar("$sendWaypointNow", 1);
setVar("$combinedStepsDesired", 42000);

UART_v6

while (getVar("$legReady", 0) != 1) {
  sleep(50);
}

if (getVar("$sendWaypointNow", 0) == 1) {
  var steps = getVar("$combinedStepsDesired", 0);
  print("Sending steps: " + steps);
  setVar("$sendWaypointNow", 0);
}

Bottom line

Yes, your scripts can share globals.
Use:

  • setVar("$name", value) in one script
  • getVar("$name", defaultValue) in the other
  • make sure both are in the same ARC project
  • use a ready flag if startup order matters

If you want, I can also help you clean up both scripts and show you a safe UART packet format for sending combinedStepsDesired, desiredBearing100, and the control flags to the Arduino.


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.