Choreographic Intent:
I created a pattern of oscillation to the main line of the song “I will always love you” by Whitney Houston. My main intent was to recreate the beat of this song using the sound of the servo motions.
Code:
print(“Starting servo_sweep script.”)
import math, time
import board
import pwmio
——————————————————————————–
class Servo():
def init(self, pin, pulse_rate=50):
self.pwm = pwmio.PWMOut(board.GP0, duty_cycle=0, frequency=pulse_rate)
# Save the initialization arguments within the object for later reference. self.pin = pin self.pulse_rate = pulse_rate # Initialize the other state variables. self.target = None # target angle; None indicates the "OFF" state self.debug = False # flag to control print output def write(self, angle): # calculate the desired pulse width in units of seconds if angle is None: pulse_width = 0.0 else: pulse_width = 0.001 + angle * (0.001 / 180.0) # calculate the duration in seconds of a single pulse cycle cycle_period = 1.0 / self.pulse_rate # calculate the desired ratio of pulse ON time to cycle duration duty_cycle = pulse_width / cycle_period # convert the ratio into a 16-bit fixed point integer duty_fixed = int(2**16 * duty_cycle) # limit the ratio range and apply to the hardware driver self.pwm.duty_cycle = min(max(duty_fixed, 0), 65535) # save the target value in the object attribute (i.e. variable) self.target = angle # if requested, print some diagnostics to the console if self.debug: print(f"Driving servo to angle {angle}") print(f" Pulse width {pulse_width} seconds") print(f" Duty cycle {duty_cycle}") print(f" Command value {self.pwm.duty_cycle}\n")
——————————————————————————–
def linear_move(servo, start, end, speed=60, update_rate=50):
# Calculate the number of seconds to wait between target updates to allow
# the motor to move.
# Units: seconds = 1.0 / (cycles/second)
interval = 1.0 / update_rate
# Compute the size of each step in degrees. # Units: degrees = (degrees/second) * second step = speed * interval # Output the start angle once before beginning the loop. This guarantees at # least one angle will be output even if the start and end are equal. angle = start servo.write(angle) # Loop once for each incremental angle change. while angle != end: time.sleep(interval) # pause for the sampling interval # Update the target angle. The positive and negative movement directions # are treated separately. if end >= start: angle += step; # movement in the positive direction if angle > end: angle = end # end at an exact position else: angle -= step # movement in the negative direction if angle < end: angle = end # end at an exact position servo.write(angle) # update the hardware
——————————————————————————–
def ringing_move(servo, q_d, q=0.0, qd=0.0, k=4math.pimath.pi, b=2.0,
update_rate=50, duration=2.0, debug=False):
interval = 1.0 / update_rate while duration > 0.0: # Calculate the acceleration. # qdd acceleration in angles/sec^2 # k spring constant relating the acceleration to the angular displacement # b damping constant relating the acceleration to velocity qdd = k * (q_d - q) - b * qd # integrate one time step using forward Euler integration q += qd * interval # position changes in proportion to velocity qd += qdd * interval # velocity changes in proportion to acceleration # update the servo command with the new angle servo.write(q) # print the output for plotting if requested if debug: print(q) time.sleep(interval) duration -= interval
——————————————————————————–
Create an object to represent a servo on the given hardware pin.
print(“Creating servo object.”)
servo = Servo(board.GP0)
print(“Starting main script.”)
while True:
# initial pause
time.sleep(2.0)
print("Starting ringing motions.") #and ringing_move(servo, 90.0, duration=1) #i ringing_move(servo, 45.0, duration=1) #e ringing_move(servo, 90.0, duration=1) print("Starting linear motions.") #i linear_move(servo, 0.0, 180.0, speed=45) #will ringing_move(servo, 90.0, duration=1) #al ringing_move(servo, 45.0, duration=1) #ways linear_move(servo, 180.0, 0.0, speed=45) #love ringing_move(servo, 90.0, duration=1) #you linear_move(servo, 0.0, 180.0, speed=45) # final pause time.sleep(2.0)
Leave a Reply
You must be logged in to post a comment.