Objects & XOD: Chaining Best Practices?

In general, XOD nodes “do their thing” when the program initializes. Each node gets “executed” again whenever any of its inputs change. Most nodes that accept a pulse input return immediately without taking any action if pulse is not dirty, so during initialization (and when other inputs change), they get “executed”, but do nothing. Aside from the flow of pulses and coding nodes to do nothing without pulse, everything will happen all-at-once on startup. “Execute when inputs change” provides an automatic flow-control when calculations are chained together, but can provide undesirable results when there are parallel calculations, so sometimes a defer node is used to wait for other branches without having to hard-code in a specific time-delay.

Use of a gate node to make sure inputs don’t change is one way to void conflict. Something like a robot with a “travel” node to start/stop the motors with PWM is a good example. You call the same “travel” node to go straight or turn right with different speeds for left/right motor. This results in there being multiple travel nodes in the final program, all trying to control the same pins for the motor controller. A gate node feeding the direction/speed/PWM pin for each motor and only enabled when the travel node gets a pulse or enable signal keeps the “turn right” copy of the travel node from firing when you are trying to go straight (or all travel nodes executing during initialization). The PWM pins are just getting set to a specific value each time a travel node executes, so the motor maintains the speed set by the last execution.

Some nodes get really messy, like the built-in servo node. The servo node uses a library that basically starts a background process to continuously send the appropriate pulses to the servo. Changing inputs on the servo node will update the background process, but having two servo nodes with the same output pin will result in the pin bouncing between the two values and the servo going spastic trying to be in two places at the same time. Adding a gate node to the servo input doesn’t help because the background process is already running with the old value. One workaround is to add an enable pin to the servo node and code the node to stop the background process (run “detach”) when the pin is false. As long as only one servo node with the same port # is enabled at a time, things work OK. Disabling all servo nodes allows the servo to free-wheel. Pulse doesn’t work very well in this case because the servo needs to be active long enough to travel to the desired destination, and free-wheeling is a bad thing in some cases (a servo-controlled arm would just collapse if allowed to free-wheel). You could work around the time-to-position issue by adding a built-in timer to the servo node so on every pulse it would be active for a specific amount of time; this might work for some things like a range-sensor that turns to read left, forward, and right values, but you would not want to read the range-finder value until servo has quit moving anyway (adding a done output to the servo would help with this). gweimer/servo has examples for both solutions.