This program controls a stepper motor from an analog input. In testing it, I used a potentiometer, which gives a persistent value. An analog input that changes when it’s not contacted, like a SpectraSymbol linear or circular pot, wouldn’t work with this example.
Thanks to the Fall ’05 Wednesday morning class for the early experimentation on this code.
Written in PicBasic Pro, tested on a PIC18F252
To understand this example, consider four possible conditions:

Either your new position is greater than or equal to than half a circle away from your old position, or it’s less than half a circle. In either case, you want to move the shortest possible distance, so you have to take different routes depending on which is true.
If the difference is greater than half a circle, and your new position is greater than the old one, then you move clockwise to get there fastest. If the new position is less than the old one, then you move counterclockwise to get there.
If the difference is less than half a circle, and your new position is greater than the old one, then you move counterclockwise to get there fastest. If the new position is less than the old one, then you move clockwise to get there.
If the distance is exactly half a circle, you can go either direction to get there, both are equidistant.
' Analog Stepper
'
' Moves a stepper motor in response to a potentiometer
' attached to Analog input channel 0.
'
' This example doesn't correct for small fluctuations in the
' analog input, and it doesn't error correct the stepper.
'
' By Tom Igoe, 31 oct 2005
' updated 25 Oct. 2005
' Define ADCIN parameters
DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in uS
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %10000010 ' Set PORTA analog and right justify result
' serial pins and constants:
tx var portc.6
rx var portc.7
inv9600 con 16468
' LED pin:
LEDPin var portb.0
' total number of steps:
totalSteps con 100
' pause time between steps. Steppers have a minimum
' pause time, usually one or two milliseconds.
pauseTime con 10
' set variables:
adcVar var word ' analog in reading, 0 - 1023
newPosition var byte ' stepper position from adcVar, 0 - 100
oldPosition var byte ' previous stepper position, 0 - 100
distance VAR BYTE ' number of steps from old to new
steps VAR byte ' counter for number of steps taken
stepArray VAR BYTE(4) ' arry to hold step patterns
i var byte ' counter for blink subroutine
clear ' set all variables to 0
TRISC = %11110000 ' set lower pins of port to output
PORTC = 255 ' set all pins of port high
' Stepping patterns:
stepArray[0] = %00001010
stepArray[1] = %00000110
stepArray[2] = %00000101
stepArray[3] = %00001001
gosub blink
Pause 1000
main:
' read analog in:
adcin 0, adcVar
' convert to a range of 0 - 100
newPosition = (adcVar / 10) min totalSteps
' calculate number of steps from old to new:
distance = abs(newPosition - oldPosition)
' if we need to move:
if (distance <> 0) then
serout2 tx, inv9600, [dec oldposition, " ---> " , dec newPosition, _
" Steps: ", DEC distance, 10, 13]
' the choice of direction is different depending
' on whether the difference is more than
' half a circle or less:
' If we're moving more than half a circle:
if (distance >= totalSteps / 2 ) then
if newPosition > oldPosition then
' move counterclockwise
gosub counterClockwise
else
' move clockwise
gosub clockwise
endif
' else we're moving less than half a circle:
else
if newPosition > oldPosition then
' move clockwise
gosub clockwise
else
' move counterclockwise
gosub counterCLockwise
endif
endif
' update oldPosition with most recent value:
oldPosition = newPosition
endif
GoTo main
clockwise:
steps = 0
while steps < distance
serout2 tx, inv9600, ["--> ", DEC steps, 10, 13]
PORTC = stepArray[steps //4]
steps = steps + 1
pause pauseTime
wend
return
counterClockwise:
steps = distance
while steps > 0
serout2 tx, inv9600, ["<-- ", DEC steps, 10, 13]
PORTC = stepArray[steps //4]
steps = steps - 1
pause pauseTime
wend
return
blink:
serout2 tx, inv9600, [10,13,10,13, "Start-----", 10, 13]
for i = 0 to 2
high LEDpin
pause 200
low LEDPin
pause 200
next
return