.. note::
Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts.
**Why Join?**
- **Expert Support**: Solve post-sale issues and technical challenges with help from our community and team.
- **Learn & Share**: Exchange tips and tutorials to enhance your skills.
- **Exclusive Previews**: Get early access to new product announcements and sneak peeks.
- **Special Discounts**: Enjoy exclusive discounts on our newest products.
- **Festive Promotions and Giveaways**: Take part in giveaways and holiday promotions.
👉 Ready to explore and create with us? Click [|link_sf_facebook|] and join today!
.. _1.3.3_py_pi5:
1.3.3 Stepper Motor
====================
Introduction
------------
Stepper motors, due to their unique design, can be controlled to a high
degree of accuracy without any feedback mechanisms. The shaft of a
stepper, mounted with a series of magnets, is controlled by a series of
electromagnetic coils that are charged positively and negatively in a
specific sequence, precisely moving it forward or backward in small
\"steps\".
Required Components
------------------------------
In this project, we need the following components.
.. image:: ../python_pi5/img/1.3.3_stepper_motor_list.png
.. raw:: html
Schematic Diagram
-----------------
.. image:: /python_pi5/img/1.3.3_stepper_motor_schematic.png
Experimental Procedures
-----------------------
**Step 1:** Build the circuit.
.. image:: ../python_pi5/img/1.3.3_stepper_motor_circuit.png
**Step 2:** Open the code file.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/python-pi5
**Step 3:** Run.
.. raw:: html
.. code-block::
sudo python3 1.3.3_StepperMotor.py
As the code runs, the stepper motor will turn clockwise or anti-clockwise depending on your input \'a\' or \'c\'.
.. warning::
If there is an error prompt ``RuntimeError: Cannot determine SOC peripheral base address``, please refer to :ref:`faq_soc`
**Code**
.. note::
You can **Modify/Reset/Copy/Run/Stop** the code below. But before that, you need to go to source code path like ``davinci-kit-for-raspberry-pi/python-pi5``. After modifying the code, you can run it directly to see the effect.
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import OutputDevice
from time import sleep
# Initialize motor pins to GPIO pins 18, 23, 24, 25
motorPin = [OutputDevice(pin) for pin in (18, 23, 24, 25)]
# Set motor rotation speed parameters
rotationPerMinute = 15
stepsPerRevolution = 2048
# Calculate time to wait between each step for smooth motor operation
stepSpeed = (60 / rotationPerMinute) / stepsPerRevolution
def rotary(direction):
"""
Controls the rotation of the motor based on the specified direction.
:param direction: 'c' for clockwise, 'a' for anti-clockwise
"""
if direction == 'c':
# Execute the stepping sequence for clockwise rotation
for j in range(4):
for i in range(4):
if 0x99 << j & (0x08 >> i):
motorPin[i].on()
else:
motorPin[i].off()
sleep(stepSpeed)
elif direction == 'a':
# Execute the stepping sequence for anti-clockwise rotation
for j in range(4):
for i in range(4):
if 0x99 >> j & (0x08 >> i):
motorPin[i].on()
else:
motorPin[i].off()
sleep(stepSpeed)
def loop():
"""
Continuously prompts the user to select the motor rotation direction
and controls the motor based on this input.
"""
while True:
direction = input('Select motor direction a=anticlockwise, c=clockwise: ')
if direction == 'c':
print('Motor running clockwise\n')
break
elif direction == 'a':
print('Motor running anti-clockwise\n')
break
else:
print('Input error, please try again!')
# Keep the motor rotating in the selected direction
while True:
rotary(direction)
def destroy():
"""
Safely turns off all motor pins, used for clean shutdown.
"""
for pin in motorPin:
pin.off()
# Main program execution
try:
loop()
except KeyboardInterrupt:
destroy() # Handle keyboard interrupt to safely shut down the motor
**Code Explanation**
#. This section imports necessary libraries. ``gpiozero`` for controlling GPIO pins and ``time`` for the sleep function used in timing control.
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import OutputDevice
from time import sleep
#. Initializes GPIO pins 18, 23, 24, and 25 as output devices for controlling the stepper motor.
.. code-block:: python
# Initialize motor pins to GPIO pins 18, 23, 24, 25
motorPin = [OutputDevice(pin) for pin in (18, 23, 24, 25)]
#. Sets the motor's rotation speed and calculates the time interval between each step for smooth operation.
.. code-block:: python
# Set motor rotation speed parameters
rotationPerMinute = 15
stepsPerRevolution = 2048
# Calculate time to wait between each step for smooth motor operation
stepSpeed = (60 / rotationPerMinute) / stepsPerRevolution
#. The ``rotary`` function controls the motor's rotation. It uses bit manipulation and a stepping sequence to activate the motor pins in the correct order for either clockwise or anti-clockwise rotation.
.. code-block:: python
def rotary(direction):
"""
Controls the rotation of the motor based on the specified direction.
:param direction: 'c' for clockwise, 'a' for anti-clockwise
"""
if direction == 'c':
# Execute the stepping sequence for clockwise rotation
for j in range(4):
for i in range(4):
if 0x99 << j & (0x08 >> i):
motorPin[i].on()
else:
motorPin[i].off()
sleep(stepSpeed)
elif direction == 'a':
# Execute the stepping sequence for anti-clockwise rotation
for j in range(4):
for i in range(4):
if 0x99 >> j & (0x08 >> i):
motorPin[i].on()
else:
motorPin[i].off()
sleep(stepSpeed)
#. This function continuously prompts the user to choose the motor rotation direction and controls the motor based on the input.
.. code-block:: python
def loop():
"""
Continuously prompts the user to select the motor rotation direction
and controls the motor based on this input.
"""
while True:
direction = input('Select motor direction a=anticlockwise, c=clockwise: ')
if direction == 'c':
print('Motor running clockwise\n')
break
elif direction == 'a':
print('Motor running anti-clockwise\n')
break
else:
print('Input error, please try again!')
# Keep the motor rotating in the selected direction
while True:
rotary(direction)
#. The ``destroy`` function turns off all motor pins. It's used for a clean shutdown, ensuring that the motor stops safely when the program ends.
.. code-block:: python
def destroy():
"""
Safely turns off all motor pins, used for clean shutdown.
"""
for pin in motorPin:
pin.off()
#. The main program calls ``loop`` and handles keyboard interrupts (like Ctrl+C) to safely shut down the motor using ``destroy``.
.. code-block:: python
# Main program execution
try:
loop()
except KeyboardInterrupt:
destroy() # Handle keyboard interrupt to safely shut down the motor