Like learning to drive stepper motors again using darlington arrays.
A few years ago this was bread-and-butter do-it-in-your-sleep kind of stuff. But it's been a while. And lots has been learned. And lots has been forgotten. So we're having to get re-acquainted with the whole driving motors thing all over again.
We're also switching platforms.
For many years, I stuck steadfastly with my PIC microcontrollers. I still maintain they are far superior to the (often more fragile) AVR/ATMega microcontrollers. And when I first joined nerd club, Arduino was still very much in its infancy - and, coming from an industrial electronics background, I much favoured PICs over AVR for pretty much everything.
But the Arduino ecosystem is quite mature now.
And lots of people are familiar with it, and its bootloader sequence, and just how easy it is for hobbyists to just buy some very basic equipment and get coding with it. Not so the (rather more specialised) PIC.
And lots of people are familiar with it, and its bootloader sequence, and just how easy it is for hobbyists to just buy some very basic equipment and get coding with it. Not so the (rather more specialised) PIC.
So, while I'm not giving up on PICs, for hobby projects and for sharing with others, I'll probably default to Arduino for microcontroller stuff. For you guys ;-)
We're got our closed loop belt system finally built and ready for testing
What we need to do now is make that little motor in the middle spin, and see if it can drive the belt around in a loop....
We're using a 28BYJ-48 stepper motor (they're plentiful and super cheap and can run on anything from 5V up to 12V - the higher voltages giving a little more "welly" and supplying a bit more torque).
Internally, the stepper motor is wired like this:
Each coil is connected at the mid point to a permanent, fixed power supply. So to energise coil one, we need to drive the pin connected to the end of coil one to ground. We then need to energise one of the other coils (probably coil 3) and we do this by disconnecting the first pin then driving the pin for coil 3 to ground.
By driving the pin for coil 2 to ground, we basically invert the electro-magnetic pole across the vertical coil, then lastly we drive the last pin to ground to complete the "step sequence".
That's a very basic explanation of how to make the stepper spin. The truth is, there are "inbetween steps". You can make the motor turn a "half-step" by energising two coils together (say one AND three). This will cause the motor to turn half-way between the positions between coil 1 and coil 3.
Because two coils are energised at the same time, this actually provides a little more power to the motor. So we'll make sure to use the half-step approach (energise two coils at once) but only ever power two coils at a time (so getting the speed/performance of full-step sequence, but the power/torque of half-stepping and energising two coils at a time).
To drive the coils to ground, we'll connect each end of the coil to a ULN2803A darlington array.
The common ground is connected to pin 8.
The "freewheeling diode" on pin 9 is to handle any "back-emf" generated by energising then disconnecting coils in the motor. We can connect this to our motor power supply to safely handle any "spikes" in the motor coils.
Now Arduino has a build in stepper motor library, but it's pretty crude and uses "blocking functions". That is to say, you wire everything up, tell the microcontroller how many steps you want it to move the motor by, and the code prevents any further code execution until all the steps have taken place. We basically want to set our motor spinning and keep it spinning until we interrupt it with some kind of input signal.
So we're going to write our own simple stepper motor driver than can be interrupted at any point.
To test our coil sequence, instead of connecting the motor (which requires its own dedicated power supply, because it draws so much current) we'll connect up some LEDs and watch them light up in sequence, to make sure our code is at least triggering the correct outputs in the right sequence.
int coil1_pin = 2;
int coil2_pin = 3;
int coil3_pin = 4;
int coil4_pin = 5;
int start_stop_pin = 10;
int current_step = 1;
int step_direction = 1;
void setup() {
// when a pin is made an output, it defaults to LOW
pinMode(coil1_pin, OUTPUT);
pinMode(coil2_pin, OUTPUT);
pinMode(coil3_pin, OUTPUT);
pinMode(coil4_pin, OUTPUT);
// this is just a test pin; pull low to make the motor spin
pinMode(start_stop_pin, INPUT_PULLUP);
}
void loop() {
// to be useful we'd probably set a flag to say if the motor
// should be running or not; here we'll just read a pin state
int i = digitalRead(start_stop_pin);
if(i == LOW) {
nextStep();
}
}
void disableCoils() {
// remember we're driving a ULN2803A darlington array
// we're not driving to motor directly, so a high
// signal energises the coil (drives the output of the
// array low) - to turn off all coils, all pins should be low
digitalWrite(coil1_pin, LOW);
digitalWrite(coil2_pin, LOW);
digitalWrite(coil3_pin, LOW);
digitalWrite(coil4_pin, LOW);
}
void nextStep() {
current_step += step_direction;
if(current_step > 4) { current_step = 1; }
if(current_step < 1) { current_step = 4; }
disableCoils();
switch(current_step) {
case 1:
digitalWrite(coil4_pin, HIGH);
digitalWrite(coil2_pin, HIGH);
break;
case 2:
digitalWrite(coil2_pin, HIGH);
digitalWrite(coil3_pin, HIGH);
break;
case 3:
digitalWrite(coil3_pin, HIGH);
digitalWrite(coil1_pin, HIGH);
break;
case 4:
digitalWrite(coil1_pin, HIGH);
digitalWrite(coil4_pin, HIGH);
break;
}
// add a delay because if you try to drive
// the stepper motor too quickly it will chatter
// (if testing with LEDs, make this a longer delay)
delay(500);
}
Here's what the flashing LED sequence looks like:
Replacing the LEDs with our stepper motor, and the result (with a modified delay between steps) looks like this:
So we've got our motor spinning, albeit in a very crude way.
But it's a start - now to hook it up to our belt drive and see if we can't get the belt to move around the track....
No comments:
Post a Comment