From: ted@nmsu.edu (Ted Dunning)
Subject: Re: Stepper motor programs wanted
Reply-To: ted@nmsu.edu
Organization: Computing Research Lab
	<bubpe7.1wt@wang.com>
Date: Thu, 10 Sep 1992 17:34:28 GMT



since i have had some requests for my multi-axis stepper motor code,
and since i deleted the original code years ago, i wrote this small
program this morning.  hope it helps.  hope nobody minds code in this
group.  (it _is_ short).  send me any comments.

/*   copyright (c) 1992 ted dunning  (ted@nmsu.edu)

this code may be duplicated and modified for non-commercial use.

write and ask for permission for duplication and modification for
commercial use.

   coordinate multiple stepping in many axes.  uses a variation on
   bresenham's algorithm adapted for multiple dimensions

for the demo version the number of steps for each axis are given on
the command line and the output consists of one line of output for
each step.  a simple change in the code can give slightly different
results that might be considered more asthetic by some.

for example (my additions marked by #):

> motor 1 2 5			# without mid step mods
stepping 0			# first step for 0
stepping 1			# and 1
stepping 2			# and 2

stepping 2			# second step for 2

stepping 1			# second step for 1
stepping 2			# third for 2

stepping 2			# fourth for 2

stepping 2			# and fifth for 2.

> motor 1 2 5			# with mid step mods
stepping 2			# step 1 for 2

stepping 1			# step 1 for 1
stepping 2			# step 2 for 2

stepping 0			# step 1 for 0
stepping 2			# step 3 for 2

stepping 1			# step 2 for 1
stepping 2			# step 4 for 2

stepping 2			# step 5 for 2

it may help to define a dummy motor if you want to space the
steps out in time.  stepping the dummy motor would only involve
waiting for the next time tick.

*/

#include <stdio.h>
#include <assert.h>
#include <malloc.h>

static int array_max(int x[], int n)
{
    int max, i;

    assert(n>0);
    max = x[0];
    for (i=1;i<n;i++) {
	if (max<x[i]) max = x[i];
    }
    return max;
}

/* each motors count will be decremented by dx[i] each of biggest times
   through the main loop.  each time it goes negative, it will be
   incremented by biggest.  at the end, each will have been decremented
   by a total of biggest * dx[i], and since the test comes after the
   decrement, it will have be >= 0 after the loop.  since it will have
   been incremented by biggest the smallest number of times, it will,
   in fact, have been incremented dx[i] times for a total of dx[i] * biggest.
   thus, each count will be = 0 at the end.  furthermore... it is pretty
   clear that the increment operations will be spaced out pretty much
   as nicely as possible.

   one problem with this code is that every motor takes a step on the first
   tick.  this leads to unsavory effects in graphics programs, but i think
   it might be good for motors.  if you don't like it, then double the
   increments and decrements and start each count at biggest.  remember to
   change the test at the end to check for biggest instead of zero.
   */

void coordinate(int dx[], int n, void (*stepper)(int))
{
    int biggest;
    static int oldn=0;
    static int *count=NULL;
    int step, i;

    if (oldn < n) {
	if (count) free(count);
	count = calloc(n, sizeof(count[0]));
	assert(count);

	oldn = n;
    }

    biggest = array_max(dx, n);
    for (i=0;i<n;i++) {
	count[i] = 0;		/* = biggest for mid step version*/
    }

    for (step=0;step<biggest;step++) {
	/* check each motor for possible step */
	for (i=0;i<n;i++) {
	    count[i] -= dx[i];	/* -= 2*dx[i] for mid step version */
	    if (count[i] < 0) {
		count[i] += biggest; /* += 2*biggest for mid step version */
		stepper(i);
	    }
	}
    }

    for (i=0;i<n;i++) {		/* sanity check... */
	assert(count[i] == 0);	/* == biggest for mid step version */
    }
}

/* handy for testing without motors */
void print_step(int which)
{
    printf("stepping %d\n", which);
}

/* test driver.  read step counts from the command line, then print
   out the stepping pattern */
main(int argc, char *argv[])
{
    int *dx;
    int i, n;

    n = argc-1;
    dx = calloc(n, sizeof(dx[0]));
    assert(dx);

    for (i=0;i<n;i++) {
	sscanf(argv[i+1], "%d", &dx[i]);
    }

    coordinate(dx, n, print_step);
}
	
--

REALLY, instead of hyping low impact soles, I think what we need
are more low impact souls.
					Greg Jahn