StepperShow Arduino Sketch

This sketch is a modification of the StepperSpline Arduino Sketch to include a script execution component. This supports self-contained performances which smoothly control four stepper motors.

The full code for the sketch spans several files; all files may be downloaded in a single archive file as StepperShow.zip, browsed in raw form in the source folder, or browsed below.

Compiling the sketch requires installing the optional TimerOne library in the Arduino IDE for supporting timer interrupt processing.

Scripting

This page only addresses the added Script.ino file, as the rest of the code is unchanged from StepperSpline apart from adding the hooks described below.

void script_setup(void)

Script engine initialization called from setup(). Currently unused.

void script_poll(unsigned long interval)

Script engine polling function called from loop() as often as possible. Interval is the number of microseconds since the last update.

void transition(int new_state)

Script state machine convenience function to manage entering a new state.

Script.ino

The example belwo shows a sample program structure for programming a pattern of autonomous motions which runs entirely on the Arduino. The chief complication is that the scripting functions cannot use any form of delay or sleep since the system needs to poll the motion generators continuously.

This solution is a switch-case state machine updated at a constant rate. On each update, it enters one case corresponding to the current state and evaluates rules to decide whether to change to a different state. State transitions issue movement commands as a side effect.

This style is very general but does become cumbersome for complex patterns. For some performances it may be more convenient to representing the active sequence as a data array and then use a simpler state machine to sequence between the events.

The script example can be found in file Script.ino, and is reproduced below.

  1/// Script.ino : movement control state machine for StepperShow
  2
  3/// This example shows a sample program structure for programming a pattern of
  4/// autonomous motions which runs entirely on the Arduino.  The chief
  5/// complication is that the system needs to poll the motion generators
  6/// continuously, so the scripting functions cannot use any form of delay or
  7/// sleep.
  8
  9/// The script_poll() function below is called from within the main loop()
 10/// function to update the status of the script and immediately return.  This
 11/// example is entirely time based, so it keeps track of elapsed time until a
 12/// script event takes place, then issues movement commands and updates the
 13/// internal state for the next event.  This scripting system works in parallel
 14/// with the regular serial input and output so external control is still
 15/// possible.
 16
 17//================================================================
 18// Interval in microseconds between script updates.
 19static unsigned long script_poll_interval = 10000000; // 1 Hz update rate
 20
 21// Script state machine index.
 22static int script_index = 0;
 23
 24// Time counter within the script engine.
 25static long script_seconds = 0;
 26
 27//================================================================
 28// Transition function to change state.
 29void transition(int new_state)
 30{
 31  script_seconds = 0;
 32  script_index = new_state;
 33  Serial.print("dbg Script entering state ");
 34  Serial.println(new_state);
 35}
 36
 37//================================================================
 38/// This is called once to initialize script state.
 39void script_setup(void)
 40{
 41}
 42
 43/****************************************************************/
 44/// This should be called from loop() as often as feasible to update the
 45/// movement state machine.  Interval is the number of microseconds since the
 46/// last update.
 47void script_poll(unsigned long interval)
 48{
 49  static long timer = 0;
 50
 51  // wake up at regular intervals (default is once per second)
 52  timer -= interval;
 53  if (timer < 0) {
 54    timer += script_poll_interval;
 55    script_seconds += 1;
 56
 57    switch(script_index) {
 58
 59    case 0: // wakeup
 60      transition(1);
 61      break;
 62
 63    case 1: // initial pause
 64      if (script_seconds >= 2) {
 65        set_driver_enable(1);
 66        x_path.incrementTarget(800);
 67        transition(10);
 68      }
 69      break;
 70
 71    case 10: // first movement
 72      if (script_seconds >= 10) {
 73        y_path.incrementTarget(800);
 74        transition(20);
 75      }
 76      break;
 77
 78    case 20:
 79      if (script_seconds >= 10) {
 80        z_path.incrementTarget(800);
 81        transition(30);
 82      }
 83      break;
 84
 85    case 30:
 86      if (script_seconds >= 10) {
 87        a_path.incrementTarget(800);
 88        transition(40);
 89      }
 90      break;
 91
 92    case 40:
 93      if (script_seconds >= 10) {
 94        x_path.incrementTarget(800);
 95        transition(10);
 96      }
 97      break;
 98    }
 99  }
100}