The video shows the principle of moving the garden hose with the motor.
Part Name | Description | Quantity | Price (EUR) |
---|---|---|---|
ACT Motor 23HS8430 1.9 Nm | 1 | 17.90 | |
TB6600 Stepper Motor Driver | 1 | 9.90 | |
ARM Cortex-A53 with Wi-Fi and Bluetooth | 1 | 44.45 | |
4 flange couplings | 4 | 9.99 | |
Option 1: Adapter for Aldi Ferrex battery, charging cradle, gray PLA+ | 1 | 11.90 | |
Option 2: Power supply transformer for LED strips and lighting | 1 | 12.99 | |
Jumper wire cables for breadboard connections | 1 | 4.99 | |
Aluminum case with cooling fan and heatsinks for Raspberry Pi | 1 | 14.99 | |
Total (Price Range) | 114 - 116 |
Note: Prices are based on Amazon.de listings as of June 2024 and may be subject to change.
This guide has been adapted from https://www.heimkino-praxis.de/leinwand-maskierung-schrittmotor-steuerung/ - many thanks to the author Bert Kößler
This color coding is specific to the ACT Motor 23HS8430. Always verify these connections against the motor's datasheet, as even within the same model, there can be variations.
On one side of the driver, you'll find 6 small switches that configure the driver for your motor. The top of the driver should have a printed table explaining the switch settings. A barely visible arrow on the switch should indicate which position is "On".
Important: Always start with lower current settings and gradually increase. Too little current can cause weak motor performance and missed steps, while too much current can overheat and damage the motor.
This color coding is specific to the ACT Motor 23HS8430. Always verify these connections against the motor's datasheet, as even within the same model, there can be variations.
On one side of the driver, you'll find 6 small switches that configure the driver for your motor. The top of the driver should have a printed table explaining the switch settings. A barely visible arrow on the switch should indicate which position is "On".
Important: Always start with lower current settings and gradually increase. Too little current can cause weak motor performance and missed steps, while too much current can overheat and damage the motor.
Save the following code as stepper.py
:
"""
stepper.py
Control a stepper motor connected to a Raspberry Pi through a TB6600 driver.
Author: Wolfgang, ChatGPT
Date: 2023-03-28 (ISO 8601 format)
"""
import RPi.GPIO as GPIO
import time
import argparse
class StepperMotor:
"""
Controls a stepper motor connected to a TB6600 driver on a Raspberry Pi.
"""
def __init__(self, dir_pin: int = 33, pul_pin: int = 35, ena_pin: int = 37, frequency_hz: int = 500, rpm: int = 30):
"""
Initializes the stepper motor with the provided pin numbers, pulse frequency, and RPM.
Args:
dir_pin (int): Pin number for direction control (default 33)
pul_pin (int): Pin number for pulse control (default 35)
ena_pin (int): Pin number for enable control (default 37)
frequency_hz (int): Pulse frequency in Hz (default 500 Hz)
rpm (int): Motor speed in RPM (default 30 RPM)
"""
self.dir_pin = dir_pin
self.pul_pin = pul_pin
self.ena_pin = ena_pin
self.frequency_hz = frequency_hz
self.rpm = rpm
self.half_period_s = 1 / (2 * self.frequency_hz) # Pulse width based on frequency
self.step_delay_s = 60 / (self.rpm * 200) # Time delay between steps based on RPM
# Set up GPIO pins
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.dir_pin, GPIO.OUT)
GPIO.setup(self.pul_pin, GPIO.OUT)
GPIO.setup(self.ena_pin, GPIO.OUT)
def move(self, angle: float, direction: str):
"""
Moves the stepper motor by the specified angle in the given direction.
Args:
angle (float): Angle in degrees to move the motor
direction (str): Direction to move ('left' or 'right')
"""
steps = abs(angle) * 200 / 360 # Calculate number of steps based on angle
GPIO.output(self.ena_pin, GPIO.LOW) # Lock motor
# Set direction
if direction == 'left':
GPIO.output(self.dir_pin, GPIO.HIGH)
elif direction == 'right':
GPIO.output(self.dir_pin, GPIO.LOW)
else:
raise ValueError(f"Invalid direction: {direction}")
# Pulse modulation
for _ in range(int(steps)):
GPIO.output(self.pul_pin, GPIO.HIGH)
time.sleep(self.half_period_s)
GPIO.output(self.pul_pin, GPIO.LOW)
time.sleep(self.step_delay_s) # Use RPM based delay between steps
def usage(self):
"""
Prints usage instructions for the StepperMotor class.
"""
print(f"Usage: {self.__class__.__name__}(dir_pin, pul_pin, ena_pin, frequency_hz, rpm)")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Control a stepper motor connected to a Raspberry Pi through a TB6600 driver.')
parser.add_argument('--dir-pin', type=int, default=33, help='Pin number for direction control')
parser.add_argument('--pul-pin', type=int, default=35, help='Pin number for pulse control')
parser.add_argument('--ena-pin', type=int, default=37, help='Pin number for enable control')
parser.add_argument('--frequency-hz', type=int, default=500, help='Pulse frequency in Hz')
parser.add_argument('--rpm', type=int, default=30, help='Motor speed in RPM')
parser.add_argument('--angle', type=float, help='Angle in degrees', default=90)
parser.add_argument('--direction', choices=['left', 'right'], help='Movement direction', default='left')
args = parser.parse_args()
# Create StepperMotor instance with RPM and frequency
stepper = StepperMotor(args.dir_pin, args.pul_pin, args.ena_pin, args.frequency_hz, args.rpm)
# Move the stepper motor based on command line arguments
stepper.move(args.angle, args.direction)
Save the following code as water
and make it executable
chmod +x water
#!/bin/bash
# Bash script to control a garden hose motor for watering a lawn
# Utilizes stepper.py to turn the motor
# Define the path to your stepper.py script
STEPPER_SCRIPT_PATH="./stepper.py"
# Define motor movement parameters
ANGLE=170 # Angle to rotate, slightly less than 170 degrees for better control
FREQ=200 # Stepper frequency - 200 = 1 sec per full turn
RPM=10 # Motor speed in RPM
DIRECTION_LEFT="left"
DIRECTION_RIGHT="right"
# Get the number of cycles from the command line argument or set default to 5
CYCLES=${1:-5}
# Main loop to rotate motor left and right for specified cycles
for (( i=0; i<CYCLES; i++ )); do
# Move motor to the left
echo "Cycle $((i+1)) of $CYCLES: Turning motor left"
sudo python3 $STEPPER_SCRIPT_PATH --angle $ANGLE --direction $DIRECTION_LEFT --frequency-hz $FREQ --rpm $RPM
# Move motor to the right
echo "Cycle $((i+1)) of $CYCLES: Turning motor right"
sudo python3 $STEPPER_SCRIPT_PATH --angle $ANGLE --direction $DIRECTION_RIGHT --frequency-hz $FREQ --rpm $RPM
done
echo "Completed $CYCLES cycles of watering."
To control the stepper motor directly: sudo python3 stepper.py --angle 90 --direction left --frequency-hz 500 --rpm 30
sudo is necessary for accessing the kernel memory directly.
To run the water control script: ./water 10
This will run 10 cycles of watering. Adjust the number as needed.
Save the following code as stepper.py
:
"""
stepper.py
Control a stepper motor connected to a Raspberry Pi through a TB6600 driver.
Author: Wolfgang, ChatGPT
Date: 2023-03-28 (ISO 8601 format)
"""
import RPi.GPIO as GPIO
import time
import argparse
class StepperMotor:
"""
Controls a stepper motor connected to a TB6600 driver on a Raspberry Pi.
"""
def __init__(self, dir_pin: int = 33, pul_pin: int = 35, ena_pin: int = 37, frequency_hz: int = 500, rpm: int = 30):
"""
Initializes the stepper motor with the provided pin numbers, pulse frequency, and RPM.
Args:
dir_pin (int): Pin number for direction control (default 33)
pul_pin (int): Pin number for pulse control (default 35)
ena_pin (int): Pin number for enable control (default 37)
frequency_hz (int): Pulse frequency in Hz (default 500 Hz)
rpm (int): Motor speed in RPM (default 30 RPM)
"""
self.dir_pin = dir_pin
self.pul_pin = pul_pin
self.ena_pin = ena_pin
self.frequency_hz = frequency_hz
self.rpm = rpm
self.half_period_s = 1 / (2 * self.frequency_hz) # Pulse width based on frequency
self.step_delay_s = 60 / (self.rpm * 200) # Time delay between steps based on RPM
# Set up GPIO pins
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.dir_pin, GPIO.OUT)
GPIO.setup(self.pul_pin, GPIO.OUT)
GPIO.setup(self.ena_pin, GPIO.OUT)
def move(self, angle: float, direction: str):
"""
Moves the stepper motor by the specified angle in the given direction.
Args:
angle (float): Angle in degrees to move the motor
direction (str): Direction to move ('left' or 'right')
"""
steps = abs(angle) * 200 / 360 # Calculate number of steps based on angle
GPIO.output(self.ena_pin, GPIO.LOW) # Lock motor
# Set direction
if direction == 'left':
GPIO.output(self.dir_pin, GPIO.HIGH)
elif direction == 'right':
GPIO.output(self.dir_pin, GPIO.LOW)
else:
raise ValueError(f"Invalid direction: {direction}")
# Pulse modulation
for _ in range(int(steps)):
GPIO.output(self.pul_pin, GPIO.HIGH)
time.sleep(self.half_period_s)
GPIO.output(self.pul_pin, GPIO.LOW)
time.sleep(self.step_delay_s) # Use RPM based delay between steps
def usage(self):
"""
Prints usage instructions for the StepperMotor class.
"""
print(f"Usage: {self.__class__.__name__}(dir_pin, pul_pin, ena_pin, frequency_hz, rpm)")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Control a stepper motor connected to a Raspberry Pi through a TB6600 driver.')
parser.add_argument('--dir-pin', type=int, default=33, help='Pin number for direction control')
parser.add_argument('--pul-pin', type=int, default=35, help='Pin number for pulse control')
parser.add_argument('--ena-pin', type=int, default=37, help='Pin number for enable control')
parser.add_argument('--frequency-hz', type=int, default=500, help='Pulse frequency in Hz')
parser.add_argument('--rpm', type=int, default=30, help='Motor speed in RPM')
parser.add_argument('--angle', type=float, help='Angle in degrees', default=90)
parser.add_argument('--direction', choices=['left', 'right'], help='Movement direction', default='left')
args = parser.parse_args()
# Create StepperMotor instance with RPM and frequency
stepper = StepperMotor(args.dir_pin, args.pul_pin, args.ena_pin, args.frequency_hz, args.rpm)
# Move the stepper motor based on command line arguments
stepper.move(args.angle, args.direction)
Save the following code as water
and make it executable
chmod +x water
#!/bin/bash
# Bash script to control a garden hose motor for watering a lawn
# Utilizes stepper.py to turn the motor
# Define the path to your stepper.py script
STEPPER_SCRIPT_PATH="./stepper.py"
# Define motor movement parameters
ANGLE=170 # Angle to rotate, slightly less than 170 degrees for better control
FREQ=200 # Stepper frequency - 200 = 1 sec per full turn
RPM=10 # Motor speed in RPM
DIRECTION_LEFT="left"
DIRECTION_RIGHT="right"
# Get the number of cycles from the command line argument or set default to 5
CYCLES=${1:-5}
# Main loop to rotate motor left and right for specified cycles
for (( i=0; i<CYCLES; i++ )); do
# Move motor to the left
echo "Cycle $((i+1)) of $CYCLES: Turning motor left"
sudo python3 $STEPPER_SCRIPT_PATH --angle $ANGLE --direction $DIRECTION_LEFT --frequency-hz $FREQ --rpm $RPM
# Move motor to the right
echo "Cycle $((i+1)) of $CYCLES: Turning motor right"
sudo python3 $STEPPER_SCRIPT_PATH --angle $ANGLE --direction $DIRECTION_RIGHT --frequency-hz $FREQ --rpm $RPM
done
echo "Completed $CYCLES cycles of watering."
To control the stepper motor directly: sudo python3 stepper.py --angle 90 --direction left --frequency-hz 500 --rpm 30
sudo is necessary for accessing the kernel memory directly.
To run the water control script: ./water 10
This will run 10 cycles of watering. Adjust the number as needed.
When searching for relevant patents we found:
Please note that this might not be the only patent relevant for this system
This patent, filed in 1993 (over 30 years ago), already attempted to create a "3D sprinkling" system by controlling the hose direction with two angles and the water flow. Key features include:
The patent abstract states:
An automatic robotic lawn sprinkler providing a water powered articulated, actuation and control system aiming a continuous stream of water to all coordinates within a polar coordinate system comprising a manually programmable base assembly for anchoring to the ground and containing size specific range data, an azimuth rotor assembly rotatably mounted to the base in a horizontal plane, a range rotor assembly rotatably mounted in a vertical plane substantially perpendicular to the azimuth rotor an azimuth actuation and control system range actuation and control system, and a mechanism for variably controlling range rate and flow volume.
This early attempt at robotic lawn sprinkler technology shows how much easier things are these days.
While the patent mention above has expired, it is important to note that there may be other active patents related to this system. The expiration of one patent does not guarantee freedom from all patent restrictions.
The effect of expired and potentially unknown patents on this DIY project:
Builders of this system are advised to use this information for personal, non-commercial purposes only. If you plan to commercialize or distribute this system, it is strongly recommended to consult with a patent attorney to ensure compliance with current patent laws.
This project is provided for educational and informational purposes only. The authors and contributors to this wiki page do not assume any legal responsibility for the use or misuse of this information.