Hi All ,
I have been working through a number of stepper control designs over the past few months.
Presently I have a Pico controlling an Adafruit A4988 with a 24BYJ48 and an ssd1306 to give information feedback.
This is so I can mount a GoPro on it to perform rotational Time Lapse movies
It is all working really well except that at approx line 185/186 in the code below I have included the line
move_stepper_steps(STEPS_PER_MOVE)
Here is an explanation of the problem taken from the comments in the code
# <<<<< if this line is included the ssd1306 and REPL counts down the steps and the motor doesn't move,
## if it is commented out then the motor will move but there will not be a count in either place
Here is the full code
# from 12v stepper Pico Works well now attempting to
# add print and ssd1306 information
# import machine
# import time
from machine import Pin, SoftI2C
import time
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
from time import sleep
import ssd1306
oled_width = 128
oled_height = 64
# Example uses I2C(0) with GP4 (SDA) and GP5 (SCL) - commonly used in tutorials
#i2c = I2C(0, sda=Pin(8), scl=Pin(9), freq=400000)
i2c = SoftI2C(scl=Pin(5), sda=Pin(4))
# Initialize the SSD1306 driver (128x64 pixels is common, adjust if using 128x32)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# Clear the display buffer
oled.fill(0)
oled.show()
# Display parameters
LINE_HEIGHT = 8 # Standard font height in pixels
MAX_LINES = oled_height // LINE_HEIGHT
# --- Pin Definitions ---
DIR_PIN = 7
STEP_PIN = 8
ENABLE_PIN = 11
BUTTON_START = 9 #RED/BLACK MOMENTARY
BUTTON_DIR = 14 #SMALL BLACK MOMENTARY
LED_STEP = 18 #RGB BLUE
LED_END = 17 # RGB RED
LED_CW = 26 #red / green
LED_CCW = 27 #red / green
# --- Setup ---
direction_pin = machine.Pin(DIR_PIN, machine.Pin.OUT)
step_pin = machine.Pin(STEP_PIN, machine.Pin.OUT)
enable_pin = machine.Pin(ENABLE_PIN, machine.Pin.OUT)
btn_start = machine.Pin(BUTTON_START, machine.Pin.IN, machine.Pin.PULL_UP)
btn_dir = machine.Pin(BUTTON_DIR, machine.Pin.IN, machine.Pin.PULL_UP)
led_step = machine.Pin(LED_STEP, machine.Pin.OUT)
led_end = machine.Pin(LED_END, machine.Pin.OUT)
led_cw = machine.Pin(LED_CW, machine.Pin.OUT)
led_ccw = machine.Pin(LED_CCW, machine.Pin.OUT)
# --- Initial State ---
motor_running = False
direction = 0 # 0 for CW, 1 for CCW
# Power on flash 2x
for _ in range(2):
led_step.value(1)
time.sleep(0.25)
led_step.value(0)
time.sleep(0.25)
led_end.value(1)
time.sleep(0.25)
led_end.value(0)
time.sleep(0.25)
led_cw.value(1)
time.sleep(0.25)
led_cw.value(0)
time.sleep(0.25)
led_ccw.value(1)
time.sleep(0.25)
led_ccw.value(0)
time.sleep(0.25)
# Initialize states
enable_pin.value(0) # Disable motor (High = Disable)
current_dir = 1 # 1: CW, 0: CCW 0 ### 1: CW, 0: CCW with this setup it starts CW // 0: CW, 1: CCW with this setup it starts CCW
direction_pin.value(current_dir)
led_cw.value(1)
led_ccw.value(0)
# 1/16 mode needs 16 times more steps for same rotation
# 300 steps at 1/16 is fine, it means roughly 18 full steps (300/16)
STEPS_TO_MOVE = 7000 #8500 ===== close to 180deg
STEP_DELAY = 0.015 # this value is variable depending on the final requirements
STEPS_PER_MOVE = 10 # this = 7000 total steps which = approx xxx min,, this value is #also variable
STEP_COUNT = 0
# Display text: text(string, x, y)
oled.text("Rotating T/L", 0, 0) # Top-left corner
#oled.fill #()
oled.show()
oled.text("TOTAL STEPS 7000", 0, 18)
oled.text("Mode = 1/16 mode", 0, 28)
oled.show()
time.sleep(2.0) #5
oled.fill(0)
oled.show()
oled.text("Rotating T/L", 0, 0) # Top-left corner
oled.text("PRESS RED (side)", 0, 18)
oled.text("TO START(button)", 0, 28)
oled.show()
time.sleep(2.0) #3
oled.fill(0)
oled.show()
print("Total Steps =100")
print("ACTUAL_STEPS count down from...{7000, 1/16 mode}")
def toggle_direction(pin):
global current_dir
time.sleep_ms(50) # Debounce
if btn_dir.value() == 0:
current_dir = 1 - current_dir
direction_pin.value(current_dir)
if current_dir == 0:
led_cw.value(1)
led_ccw.value(0)
else:
led_cw.value(0)
led_ccw.value(1)
print("Direction changed:", "CW" if current_dir == 0 else "CCW")
# Attach interrupt for direction button
btn_dir.irq(trigger=machine.Pin.IRQ_FALLING, handler=toggle_direction)
print("Ready. Push Button (GP2) to start.")
def move_stepper_steps(steps):
"""Moves the stepper motor a specified number of steps."""
global STEP_COUNT
remaining_steps = 7000 - STEP_COUNT
name = "Remain"
# # 2. Convert variables to strings and draw text
# # oled.text("text", x_coord, y_coord, [color])
oled.text("Rotating T/L", 0, 0) # Top-left corner
oled.text("Steps: " + str(remaining_steps), 0, 48) # Convert float to string
oled.text("count down", 0, 14)
oled.text("{from 7000}", 0, 28)
oled.text("Remain:",0 ,38)
#oled.text("{7000-STEP_COUNT}",0, 38)
#oled.text("Total steps: {STEP_COUNT % TOTAL_STEPS}", 0, 32)
oled.show()
time.sleep(2.0)
oled.fill(0)
oled.show()
#seq = STEP_COUNT
for _ in range(abs(steps)):
# Calculate the current step in the sequence
#seq_index = STEP_COUNT % len(STEP_SEQUENCE)
Remain = STEPS_TO_MOVE - STEPS_PER_MOVE
current_step = Remain
# Update step count with direction consideration
if STEP_COUNT ==():
STEP_COUNT += 1
else:
STEP_COUNT += 1
if STEP_COUNT < 0:
STEP_COUNT = len(STEPS_TO_MOVE) - 1
#STEP_COUNT = len(STEPS_PER_MOVE) - 1
#############
print(f"Moved {STEPS_PER_MOVE} steps. Actual steps: {STEPS_PER_MOVE+STEP_COUNT}. Remain:{7000-STEP_COUNT} ")
while True:
if btn_start.value() == 0:
time.sleep_ms(100) # Debounce
print("Starting sequence...")
oled.fill(0)
oled.show()
oled.text("Rotating T/L", 0, 0) # Top-left corner
oled.text("IN PROGRESS", 0, 18)
oled.show()
time.sleep(3.0)
enable_pin.value(0) # Enable motor
move_stepper_steps(STEPS_PER_MOVE)
# Move motor
for _ in range(STEPS_TO_MOVE): # = TOTAL STEPS
#move_stepper_steps(STEPS_PER_MOVE) # <<<<< if this line is included the ssd1306 and REPL counts down the steps and the motor doesn't move,
## if it is commented out then the motor will move but there will not be a count in either place
#move_stepper_steps(STEPS_TO_MOVE)
step_pin.value(1)
led_step.value(1)
time.sleep(STEP_DELAY)
step_pin.value(0)
led_step.value(0)
time.sleep(STEP_DELAY)
# End sequence: Fast blink
print("Sequence complete. Ending...")
oled.fill(0)
oled.show()
oled.text("Rotating T/L", 0, 0) # Top-left corner
oled.text("Sequence end", 0, 18)
oled.show()
time.sleep(3.0)
oled.fill(0)
oled.show()
for _ in range(30):
led_end.value(1)
time.sleep_ms(50)
led_end.value(0)
time.sleep_ms(50)
enable_pin.value(1) # Turn off motor
print("Motor off.")
oled.text("Motor Off", 0, 28)
oled.show()
time.sleep(10.0)
oled.fill(0)
oled.show()
time.sleep(1) # Debounce start button
I am not sure what I need to do to be able to have the motor moving and the count down happening at the same time. Preferably in both places .
Any assistance will be appreciated
cheers
Nick