Arduino Stepper Test Program

From Zen_Toolworks_Wiki

Jump to: navigation, search


Summary

This is just a very simple program to test the stepper drivers.

  • Just paste this into an Arduino Sketch
  • Load it onto the Arduino
  • Hook up the stepper driver and connect
    • pin 13 to the STEP pin
    • pin 3 to the DIR pin
  • Fire up a serial terminal to talk to it

Terminal on OSX and Linux

I didn't figure out how to send LF or CR over the serial line using the built-in serial terminal in the Arduino IDE so on MacOS X and Linux I use the screen command to give me a rudimentary serial terminal:

  screen /dev/tty.usbserial-A9007Laf 9600

You might have the Arduino on a different device. Have alook in your Aruino IDE to see what device you use to talk to the Arduino.

Commands

Once you are up and running you can issue commands like "help", and "step 1 1600". The "step" command should be pretty self-explanatory -- it takes two values: the direction and the number of steps. If you just press return (ie a blank line) it will repeat the last step command.


Notes

Note that the program does not do any ramp up of stepping frequency. It uses a fixed stepping frequency. This means that you could stall the stepper if the DELAY constant below is too small. If you get into trouble just double it. (Worked fine with a value of 1200 on the Minibea steppers that came with the Zen machine as well as some other steppers I have).

You can find more notes on my Zen Toolworks Machine here: Borud's Zen Toolworks Machine.

If you plan to have some software talk to the Arduino, this program isn't really suitable. It is only meant for interactive test use. You should probably consider Simen's Grbl project: http://grbl.tumblr.com/ which uses a subset of Gcode. For this program to be useful as the backend to some software you need to design a proper serial protocol that is more suitable for semi-asynchronous communication.

Source

Here is the source code. You should be able to just cut and paste this into your Arduino IDE.

/*
 * step_test.pde -- quick hack to assist me in testing the stepper
 *    drivers and to manually jog the axis on my Zen Toolworks CNC
 *    machine.  I mainly wrote this because I haven't put together
 *    a machine for running EMC yet, but I wanted to do some testing
 *    of the steppers.
 *
 * Feel free to copy, modify and distribute his code as you like.
 *
 *    - borud@borud.org
 */


#define MAX_CMD_LEN 80
#define DELAY 1200

// Command buffer
char inputString[MAX_CMD_LEN];
int offset = 0;

// Stepper pins
int dir_pin = 3;
int step_pin = 13;

// Last command
int last_dir = 0;
long last_step = 0;

void setup() {
  Serial.begin(9600);
  Serial.flush();
  inputString[0] = 0;

  // Initial setup of pins   
  pinMode(dir_pin, OUTPUT);
  pinMode(step_pin, OUTPUT);
}

void loop() {
  getCommand();
}

void processCommand(char* s) {

  // Empty command, ie the user just pressed ENTER
  if (strlen(s) == 0) {
    perform_step(s);
    return;
  }    
  
  // step command
  if (strncmp("step", s, 4) == 0) {
    perform_step(s);
    return;
  }

  // help
  if (strncmp("help", s, 4) == 0) {
    perform_help();
    return;
  }

  // just show which pins are in use etc
  if (strncmp("status", s, 6) == 0) {
    perform_status();
    return; 
  }

  // If we arrive here we did not recognize any of the commands.
  Serial.print("ERROR: Unknown command: '");
  Serial.print(s);
  Serial.println("'");
}

void perform_help() {
  Serial.println("Usage:");
  Serial.println();
  Serial.println("  step <dir> <n> : <dir> = 0 or 1, <n> = number of steps");
  Serial.println("  status         : show the status");
  Serial.println();
  Serial.println("OK"); 
}

void perform_status() {
  Serial.print("uptime=");
  Serial.println(millis());

  Serial.print("dir_pin=");
  Serial.println(dir_pin);

  Serial.print("step_pin=");
  Serial.println(step_pin);

  Serial.println("OK");
}

void perform_step(char* s) {
  int dir;
  long steps;
  char* end;

  if (strlen(s) > 0) {
    // Skip the command characters
    s += 5;

    // If there was no parseable number this returns 0, which is fine
    dir = (int) strtol(s, &end, 10);

    // We have no errno, so to determine if there was an error during parsing
    // (ie. no number) we just check if the end pointer was advanced.
    if (s == end) {
      Serial.println("ERROR: Unable to parse step command");
      return;
    }

    s = end;
    steps = strtol(s, &end, 10);
    if (steps == 0) {
      Serial.println("ERROR: Zero steps");
      return;
    }

    // Remember last dir and last step
    last_dir = dir;
    last_step = steps;
  } else {
    dir = last_dir;
    steps = last_step;
    Serial.print("repeat dir=");
    Serial.print(dir);
    Serial.print(", steps=");
    Serial.println(steps);
  }

  // First set the direction.  If direction is 0 we set the pin low
  // otherwise we set it high.  
  digitalWrite(dir_pin, (dir==0)?LOW:HIGH);

  // Wait 1ms for good measure
  delay(1);

  // Now generate the pulses.  We use a fixed rate.  It isn't fast but
  // it makes the code a lot simpler.
  for (long i=0; i < steps; i++) {
    digitalWrite(step_pin, LOW);
    digitalWrite(step_pin, HIGH);
    delayMicroseconds(DELAY); 
  }

  // Set the pin low before we end
  digitalWrite(step_pin, LOW);

  Serial.print("OK: dir=");
  Serial.print(dir);
  Serial.print(", steps=");
  Serial.println(steps);
}

void getCommand() {
  while (Serial.available() > 0) {
    char c = Serial.read();

    // Echo each character
    Serial.print(c);

    if ((c == '\n') || (c == '\r') || (c == 'X')) {
      Serial.println();
      // Terminate string
      inputString[offset] = 0;
      processCommand(inputString);
      inputString[0] = 0;
      offset = 0;
      return;
    }

    // invariant: command was not complete and we have a char
    if (offset < (MAX_CMD_LEN - 1)) {
      inputString[offset++] = c;
    } 
    else {
      // Buffer is full.  Ignore
    }
  }
}
Personal tools