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 = %00001010 stepArray = %00000110 stepArray = %00000101 stepArray = %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