Reflection: The intent of the project was to build a rain-tube like machine, where the marbles hitting against the pegs as they rolled down the tube would create a soothing sound. The user input is positioning the sensor. If the user wants the tube to continuously spin, the user can place the sensor away from the tube. If the user wants the tube to rock back and forth, the user can place the sensor near the tube.

If we could redo aspects of this project, we would work out the spacing of the pegs better so that not all the balls would just flow down the sides when the tube is turned over slowly. We can also experiment with different modes of user input, such as the user pressing a button when they want the tube to turn. As well as implementing more interactive sensing which might give the user angle control in addition to speed control. We would also like to experiment with networking and other interfaces to increase the compatibility of the music we can create

Video: https://drive.google.com/file/d/1IrCWwKjV1mRumPzaRAGrWUcxnvIRX1Br/view?usp=sharing

# This assumes a Pololu DRV8833 dual motor driver has been wired up to the Pico as follows:
#   Pico pin 24, GPIO18   -> AIN1
#   Pico pin 25, GPIO19   -> AIN2
#   Pico pin 26, GPIO20   -> BIN2
#   Pico pin 27, GPIO21   -> BIN1
#   any Pico GND          -> GND
 
# DRV8833 carrier board: https://www.pololu.com/product/2130
 
################################################################
# CircuitPython module documentation:
# time    https://circuitpython.readthedocs.io/en/latest/shared-bindings/time/index.html
# math    https://circuitpython.readthedocs.io/en/latest/shared-bindings/math/index.html
# board   https://circuitpython.readthedocs.io/en/latest/shared-bindings/board/index.html
# pwmio   https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html
 
################################################################################
# print a banner as reminder of what code is loaded
print("Starting dual_spin script.")
 
# load standard Python modules
import math, time
 
# load the CircuitPython hardware definition module for pin definitions
import board
 
# load the CircuitPython pulse-width-modulation module for driving hardware
import pwmio
from digitalio import DigitalInOut, Direction, Pull
 
import analogio
import digitalio
import random
 
#--------------------------------------------------------------------------------
# Class to represent a single dual H-bridge driver.
class DRV8833():
    def __init__(self, AIN1=board.GP18, AIN2=board.GP19, BIN2=board.GP20, BIN1=board.GP21, pwm_rate=20000):
        # Create a pair of PWMOut objects for each motor channel.
        self.ain1 = pwmio.PWMOut(AIN1, duty_cycle=0, frequency=pwm_rate)
        self.ain2 = pwmio.PWMOut(AIN2, duty_cycle=0, frequency=pwm_rate)
 
        self.bin1 = pwmio.PWMOut(BIN1, duty_cycle=0, frequency=pwm_rate)
        self.bin2 = pwmio.PWMOut(BIN2, duty_cycle=0, frequency=pwm_rate)
 
    def write(self, channel, rate):
        """Set the speed and direction on a single motor channel.
 
        :param channel:  0 for motor A, 1 for motor B
        :param rate: modulation value between -1.0 and 1.0, full reverse to full forward."""
 
        # convert the rate into a 16-bit fixed point integer
        pwm = min(max(int(2**16 * abs(rate)), 0), 65535)
 
        if channel == 0:
            if rate < 0:
                self.ain1.duty_cycle = pwm
                self.ain2.duty_cycle = 0
            else:
                self.ain1.duty_cycle = 0
                self.ain2.duty_cycle = pwm
        else:
            if rate < 0:
                self.bin1.duty_cycle = pwm
                self.bin2.duty_cycle = 0
            else:
                self.bin1.duty_cycle = 0
                self.bin2.duty_cycle = pwm
 
 
#--------------------------------------------------------------------------------
# Create an object to represent a dual motor driver.
print("Creating driver object.")
driver = DRV8833()
 
#--------------------------------------------------------------------------------
# Begin the main processing loop.  This is structured as a looping script, since
# each movement primitive 'blocks', i.e. doesn't return until the action is
# finished.
 
# Set up built-in green LED for output.
led = DigitalInOut(board.LED)  # GP25
led.direction = Direction.OUTPUT
 
# Set up an analog input on ADC0 (GP26), which is physically pin 31.
# E.g., this may be attached to photocell or photointerrupter with associated pullup resistor.
# sensor = analogio.AnalogIn(board.A0)

sensor_direction = analogio.AnalogIn(board.A1)
 
# These may be need to be adjusted for your particular hardware.  The Pico has
# 12-bit analog-to-digital conversion so the actual conversion has 4096 possible
# values, but the results are scaled to a 16-bit unsigned integer with range
# from 0 to 65535.
lower_threshold =  8000
upper_threshold = 45000
 

state_index = False
#switch = DigitalInOut(board.GP15)
#switch.direction = Direction.INPUT
 

last_change_time = time.time()
 
start_time = time.time()
print("Starting main script.")
change_action_time = 0
prev_direction = 1
SENSOR_THRESHOLD = 1000
state_index = False
while True:
    motor_power = 1

    sensor_direction_level = sensor_direction.value

    
    if state_index is False:
        if sensor_direction_level < lower_threshold:
            led.value = True
            state_index = True
            print("On")

    elif state_index is True:
        if sensor_direction_level &gt; upper_threshold:
            led.value = False
            state_index = False
            print("Off")
            prev_direction *= -1
            driver.write(1, prev_direction * motor_power)
            time.sleep(0.5)
    
    driver.write(1, prev_direction * motor_power)

     
   
    # uncomment the following to print tuples to plot with the mu editor
    # print((sensor_level, motor_power))
    # time.sleep(0.02)  # slow sampling to avoid flooding