MicroPython class for unipolar stepper motors such as 28BYJ-48. Also a classic tune by Peter Tosh.
I was experimenting with a 28BYJ-48 stepper motor driven by a ULN2003 connected to an ESP32-C3 OLED. Found no existing module that I liked, so I made this one. Maybe it will help someone else.
The main feature, compared to other ULN2003-modules, is that this module considers the current step position (active coils) before taking a new step. Thus, not trying to move the rotor more than one position at a time.
Default is full drive stepping, for more power. Wave drive is also supported. Drive type is determined by first_step
when instantiating the class.
- Wave drive: The four coils take turn being active one at a time, such as
[1,0,0,0]
to[0,1,0,0]
to[0,0,1,0]
to[0,0,0,1]
to[1,0,0,0]
and so on. Or the reverse order for counter-clockwise. - Full drive: The four coils take turn being active two at a time, such as
[1,1,0,0]
to[0,1,1,0]
to[0,0,1,1]
to[1,0,0,1]
to[1,1,0,0]
and so on. Or the reverse order for counter-clockwise.
- Upload
steppingrazor.py
to your ESP32 or similar MicroPython device. - In your MicroPython device, run
import-module steppingrazor
Basic: my_stepper = steppingrazor.uln2003(0, 1, 2, 21)
where the four INT's are your four pins going to IN
ports on the ULN2003. 0,1,2,21 is just a convenient example of pins on an ESP32-C3 OLED version.
Advanced: my_stepper = steppingrazor.uln2003(in1=0, in2=1, in3=2, in4=21, first_step=[0,1,1,0], steps_per_rev=2048.0, delay_ms=3)
where
in1
...in4
are the numbers of four pins going toIN
ports on the ULN2003. N.b! Just the pin numbers, not machine.Pin().first_step
is the step configuration, i.e. active coils to start with. Full/Wave drive is determined by the pattern of 0/1 in this list.steps_per_rev
is how many steps the motor needs to rotate 360 degreesdelay_ms
is the delay after taking a step. Anti-proportional to speed. The rotor needs some time to move after each re-configuration of active coil(s).
Rotate an angle in degrees. Can be less than 0
and more than 360
.
Get/set position to a number of degrees from home. Can be less than 0
and more than 360
.
- Get:
my_stepper.position_deg()
- Set:
my_stepper.position_deg(600)
Rotate a number of steps. Can be under 0
and over steps_per_rev
.
Get/set position to a number of steps from home. Can be under 0
and over steps_per_rev
.
- Get:
my_stepper.position_steps()
. - Set:
my_stepper.position_steps(3000)
.
Take a single step
- clockwise:
my_stepper.step_once(1)
Any INT between 1 and infinity = 1 step clockwise. - counter clockwise:
my_stepper.step_once(-1)
Any INT between -1 and -infinity = 1 step counter clockwise.
Set home at current position/step.
Activate the four coils according to a list.
After instantiating my_stepper
, no coils are active - i.e. the shaft can move freely until a step is set. This way, you can store the last step (=position) to non-volatile storage, and then at boot set_coils()
to the last known position of the shaft. Example usages to set coils to...
- class default list:
my_stepper.set_coils()
- first position:
my_stepper.set_coils([1,1,0,0])
- free rotation:
my_stepper.set_coils([0,0,0,0])
If your'e not worried about precise decimal degrees, just forget about this function, and use rotate_*()
or, position_*()
described above.
Get/set step counter INT to answer the question "where am I?". Mostly for internal use.
Get/set inversion of rotation. Useful since "clockwise" may mean different things in different setups.
- Get:
my_stepper.invert_rotation()
- Set:
my_stepper.invert_rotation(True)
or False
Get/set milliseconds delay between steps to control speed vs torque.
- Get:
my_stepper.delay_ms()
- Set:
my_stepper.delay_ms(10)
Get/set how many steps the motor takes forone full revolution (360deg).
- Get:
my_stepper.steps_per_revolution()
- Set:
my_stepper.steps_per_revolution(2048)
Standard 28BYJ-48
Get drive type, wave
or full
depending on first_step
list.