unipolar stepper control
JBWolf
Posts: 405
Hello,
I am having trouble controlling uni-polar stepper motors with the propeller.
I have been working the past week on a simple x/y axis scanner for making my own laser show system.
I have tried several different programming methods but I always end up with overshoots, lost movements and cannot create a circle at all.
Wiring: Two 12v, 1amp steppers wired directly to 8 pins on the propeller with an ULN2803.
I am using simple out commands to create a phase position as such:
outa[12..15] := phase[stp]
Here are the phases I am using with the 'phase[stp]'
HStep byte %1001, %1000, %1100, %0100, %0110, %0010, %0011, %0001 ' Half Step
FStep byte %1001, %1100, %0110, %0011 ' Full Step
WStep byte %1000, %0100, %0010, %0001 ' Wave Step
Am I supposed to be sending a frequency rather than a simple outa[12..5] to control movements?
I am using a simple loop to try to get it to move a specific distance:
Say I want a horizontal line.... it moves right 10 steps, then left one, then no movement for 9 sec, then repeats. I cannot figure out why!
I also cannot get both motors to move at the same time.
I am having trouble controlling uni-polar stepper motors with the propeller.
I have been working the past week on a simple x/y axis scanner for making my own laser show system.
I have tried several different programming methods but I always end up with overshoots, lost movements and cannot create a circle at all.
Wiring: Two 12v, 1amp steppers wired directly to 8 pins on the propeller with an ULN2803.
I am using simple out commands to create a phase position as such:
outa[12..15] := phase[stp]
Here are the phases I am using with the 'phase[stp]'
HStep byte %1001, %1000, %1100, %0100, %0110, %0010, %0011, %0001 ' Half Step
FStep byte %1001, %1100, %0110, %0011 ' Full Step
WStep byte %1000, %0100, %0010, %0001 ' Wave Step
Am I supposed to be sending a frequency rather than a simple outa[12..5] to control movements?
I am using a simple loop to try to get it to move a specific distance:
Say I want a horizontal line.... it moves right 10 steps, then left one, then no movement for 9 sec, then repeats. I cannot figure out why!
I also cannot get both motors to move at the same time.
PUB test1 | dist, delay delay := 200 dist := 10 repeat 6 xaxis(right, dist, delay) waitcnt(clkfreq + cnt) xaxis(left, dist, delay) waitcnt(clkfreq + cnt) PUB Xaxis (dir, distx, delay) repeat distx ' cycle phase dist many times if dir == 2 ' decrement if direction = down stpx := stpx - 1 if stpx == -1 stpx := 7 if dir == 1 ' increment if direction = up stpx := stpx + 1 if stpx := 8 stpx := 0 outa[12..15] := HStep[stpx] ' send phase pulse waitcnt(clkfreq/delay + cnt) ' set speed, max speed = H1800 F800 W700All variables are initialized to 0 before use.
Comments
Maybe slow the clock rate and drop some LEDs on the output to see if the phase seq is was you think that it should be. Down the road a piece, if the surplus gods smile on you, you might try doing the laser thing using a galvo/mirror system for some speed....
Frank
Each method would be in an endless repeat loop to keep it running, each is passed 3 variable addresses with @. The variable addresses hold values for Direction, Distance and Delay respectively.
The 6 variables are set in the VAR section as longs and initialized before use.
The 2 methods for controlling the motors are now running in their own cog. The X & Yaxis method repeats endlessly until the direction variable is greater than 0 (1 = left, 2 = right). It then loops 'distance' many times, and simply in/decrements the 'stp' variable for outputting the next proper phase (dont want to jump across phases as it will cause unpredictable movements).
So now it should be as simple as writing the delay, distance and lastly direction for either axis control method. Once the direction variable is greater than 0, the X or Y method should then start in/decrementing the counter and looping distance many times.
To avoid sending a new movement command before the last has completed, I first tried using a simple delay: The weird thing is... sometimes this works, sometimes it does not.
If I send one movement such as writing the Xaxis delay and distance, then write the direction and use the above delay, it works. but if I try to write the X and Yaxis delay and distance, then write both directions... it does not work with that delay all the time.
Sometimes I have to add another command to write 0 to both direction variables, delay for a very short period, then continue with movement commands, the write 0's, short delay, movements.......
I cannot find any stable method to program this at all!
I keep getting varying results using the same code!
I am right now trying to implement an 'enable' variable.
This variable is 0 when either the X or Yaxis method is NOT inside the 'if direction > 0' loop, indicating that it is ready for a movement command. When it enters the loop, it writes 1 to the enable variable, and when done it writes 0 to enable again.
I use a simple "repeat until enable == 0" to act as the delay.
For some reason, this does not work.
The enable is declared as long in VAR, Initialized before use, and the address is passed with @ during the Xaxis method launch into a new cog.
I have tried writing the variable inside the Xaxis method with " enable := 1 " and "long[enable] := 1", but it still wont work.
I just cannot get anything right. Everything I have tried just leads to more confusion.
Can someone please point me in the right direction
Here is the code I am using to launch into cogs and await variable change.
It just when I try to use it with multiple movement commands or try to achieve an arc or circle.... I have made an octagon and tried to make the delay 3/4'ths the actual time needed to complete the move so that it will 'round off' the end of the line.. this is the closest I have gotten to a circle.
Thinking about this, you may be better served using a galvo arrangement the galvo can give ramdom access positioning whereas a stepper will be sequential access to points..
If sticking with steppers, it may be easier to set the steppers up to continuously scan x and y directions while using the z axis to enable/disable the laser point much like the television does it. Maybe sync the zero detect points of the stepper scans to a slow version of the ntsc tv prop object to paint the image.
Frank
This all happens in real time... the cogs do not communicate to, or share each others data.
But I have been having alot of timing trouble, can you please fill me in?
Thats interesting, I was just talking with a friend who suggested the same TV idea.
Only problem with this method I can see, is the motor has a .9 degree half step, which means there will be dots instead of lines.
So I'm a little worried about resolution.
But I'll give it a try! I have a TTL laser driver thats optically isolated, I think it should work.
What advantage would I get out of using the NTSC object? I havent used it before so I know nothing about it.
I simply switched the order in which I was writing the variables and now it works... but only with even delay times, or it moves opposite the direction of what I am sending. I cannot use a delay of ... 1300, 1500, 1700
weird... really weird
so this:
repeat 400
dirX := right
distX := dist
repeat until enx == 0
Was changed to this:
repeat 400
distX := dist
dirX := right
repeat until enx == 0
Typically we give ~100 longs of stack space. It looks like you're only giving 40 longs...
Whenever strange things like this happen, I try increasing the stack space...
Sync first. I mentioned syncronization because you seem to be placing the beam with and x and y position. if you plot the math function of a circle, you will get an x and y position for each point on the circle (Yeah I know, resounding Duh!!), but if you are trying to draw the circle using a continuous list of points, you would need some way of making sure that the intended x and y positions are what the prop believes them to be, either with an index of similar positional indicator. Once syncronized, the prop cores could independently map their x and y as long as they are working from a shared table. So as long as they are singing from the same page, they should be able to position the mirrors independently.
As for the NTSC object, I have not looked at it in detail, only tried it out for another experiment. The reason I mentioned it is that TV does the electronic equivalent of a mechanical scan. My reasoning for using it would be that at any speed, the timings would still have to maintain the same approximate timing sequence. What you would have to do is adapt the timing for the Horizontal and Vertical timings to the actual stepper position of x and y. After that it should be the same as providing an image in the frame buffer to be painted by the laser.
You are correct of course regarding the effect of the step angle over distance. On a table I adjusted couple of weeks ago, a 2.3 degree offset from horizontal resulted in over 1cm offset at about 20cm from the hinge. you may need to go with a finer step angle. Or a galvo-mirror where the offset would be dependent on the number of bits in the DAC used to drive the galvo motor.
Frank
I do not follow this at all. How would I approach this?
At the beginning of launching the X & Yaxis cogs, it runs through a 'calibrate' which moves the motors back 45 degrees where they hit a metal bar, then forward 15 degrees. This way they always start in the center.
So after calibrate, it knows where home is and simply moves from its current position to the next. If I move right 10, then obviously left 10 brings me back home... this is the way I have been keeping them in alignment.
I do not understand how to do any kind of synchronization.
Right now If I do not choose a delay time that it 'likes' such as 1000 but not 1100.... the thing goes crazy with missed steps and wrong directions... makes no sense to me.
If I change to a delay of 1200.... works 100% fine, 1300 goes crazy, 1400 works fine.... no idea whats going on.
The delay function I am using is : waitcnt(clkfreq / delay + cnt) I have also tried waitcnt((clkfreq / delay) + cnt)
Sorry to have confused things.
Finding zero at some point of both steppers is basically what I meant by syncing the two so that they start at a known position. It looks like it knows where zero is and seems able to track where it is and the octagon shows the ability to do simultaneous movement on x and y to get a diagonal line. I am not sure how you are giving it data to form the circle or octagon. Which make/model of stepper are you using?
You mention that it has difficulties when trying to do both directions together. What does the power supply look like when doing this (scope?) and what to the outputs to the stepper look like? Can the supply handle both steppers at the same instant? Almost sounds like the unit is slipping from too fast a step rate or too high a load on the motor. Or power supply not able to provide the needed current when stepping. If the steppers are slipping, the prop will loose track of the position unless an init call is done to re-zero the steppers.
Frank
Another alternative to the stepper for moving your mirror(s) may be a servo motor. Lots of objects in the OBEX and quite a fine possibly higher resolution than the stepper depending on which you use. Far cheaper than a true galvo motor such as Laser Surplus or similar would sell for.....