{"id":5097,"date":"2021-10-25T02:09:10","date_gmt":"2021-10-25T06:09:10","guid":{"rendered":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/?p=5097"},"modified":"2021-10-25T02:09:12","modified_gmt":"2021-10-25T06:09:12","slug":"rain-box","status":"publish","type":"post","link":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/2021\/10\/25\/rain-box\/","title":{"rendered":"Rain Box"},"content":{"rendered":"\n<p>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.<\/p>\n\n\n\n<p>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<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Video: <a href=\"https:\/\/drive.google.com\/file\/d\/1IrCWwKjV1mRumPzaRAGrWUcxnvIRX1Br\/view?usp=sharing\">https:\/\/drive.google.com\/file\/d\/1IrCWwKjV1mRumPzaRAGrWUcxnvIRX1Br\/view?usp=sharing<\/a><\/p>\n\n\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# This assumes a Pololu DRV8833 dual motor driver has been wired up to the Pico as follows:\n#   Pico pin 24, GPIO18   -&amp;gt; AIN1\n#   Pico pin 25, GPIO19   -&amp;gt; AIN2\n#   Pico pin 26, GPIO20   -&amp;gt; BIN2\n#   Pico pin 27, GPIO21   -&amp;gt; BIN1\n#   any Pico GND          -&amp;gt; GND\n \n# DRV8833 carrier board: https:\/\/www.pololu.com\/product\/2130\n \n################################################################\n# CircuitPython module documentation:\n# time    https:\/\/circuitpython.readthedocs.io\/en\/latest\/shared-bindings\/time\/index.html\n# math    https:\/\/circuitpython.readthedocs.io\/en\/latest\/shared-bindings\/math\/index.html\n# board   https:\/\/circuitpython.readthedocs.io\/en\/latest\/shared-bindings\/board\/index.html\n# pwmio   https:\/\/circuitpython.readthedocs.io\/en\/latest\/shared-bindings\/pwmio\/index.html\n \n################################################################################\n# print a banner as reminder of what code is loaded\nprint(&quot;Starting dual_spin script.&quot;)\n \n# load standard Python modules\nimport math, time\n \n# load the CircuitPython hardware definition module for pin definitions\nimport board\n \n# load the CircuitPython pulse-width-modulation module for driving hardware\nimport pwmio\nfrom digitalio import DigitalInOut, Direction, Pull\n \nimport analogio\nimport digitalio\nimport random\n \n#--------------------------------------------------------------------------------\n# Class to represent a single dual H-bridge driver.\nclass DRV8833():\n    def __init__(self, AIN1=board.GP18, AIN2=board.GP19, BIN2=board.GP20, BIN1=board.GP21, pwm_rate=20000):\n        # Create a pair of PWMOut objects for each motor channel.\n        self.ain1 = pwmio.PWMOut(AIN1, duty_cycle=0, frequency=pwm_rate)\n        self.ain2 = pwmio.PWMOut(AIN2, duty_cycle=0, frequency=pwm_rate)\n \n        self.bin1 = pwmio.PWMOut(BIN1, duty_cycle=0, frequency=pwm_rate)\n        self.bin2 = pwmio.PWMOut(BIN2, duty_cycle=0, frequency=pwm_rate)\n \n    def write(self, channel, rate):\n        &quot;&quot;&quot;Set the speed and direction on a single motor channel.\n \n        :param channel:  0 for motor A, 1 for motor B\n        :param rate: modulation value between -1.0 and 1.0, full reverse to full forward.&quot;&quot;&quot;\n \n        # convert the rate into a 16-bit fixed point integer\n        pwm = min(max(int(2**16 * abs(rate)), 0), 65535)\n \n        if channel == 0:\n            if rate &lt; 0:\n                self.ain1.duty_cycle = pwm\n                self.ain2.duty_cycle = 0\n            else:\n                self.ain1.duty_cycle = 0\n                self.ain2.duty_cycle = pwm\n        else:\n            if rate &lt; 0:\n                self.bin1.duty_cycle = pwm\n                self.bin2.duty_cycle = 0\n            else:\n                self.bin1.duty_cycle = 0\n                self.bin2.duty_cycle = pwm\n \n \n#--------------------------------------------------------------------------------\n# Create an object to represent a dual motor driver.\nprint(&quot;Creating driver object.&quot;)\ndriver = DRV8833()\n \n#--------------------------------------------------------------------------------\n# Begin the main processing loop.  This is structured as a looping script, since\n# each movement primitive 'blocks', i.e. doesn't return until the action is\n# finished.\n \n# Set up built-in green LED for output.\nled = DigitalInOut(board.LED)  # GP25\nled.direction = Direction.OUTPUT\n \n# Set up an analog input on ADC0 (GP26), which is physically pin 31.\n# E.g., this may be attached to photocell or photointerrupter with associated pullup resistor.\n# sensor = analogio.AnalogIn(board.A0)\n\nsensor_direction = analogio.AnalogIn(board.A1)\n \n# These may be need to be adjusted for your particular hardware.  The Pico has\n# 12-bit analog-to-digital conversion so the actual conversion has 4096 possible\n# values, but the results are scaled to a 16-bit unsigned integer with range\n# from 0 to 65535.\nlower_threshold =  8000\nupper_threshold = 45000\n \n\nstate_index = False\n#switch = DigitalInOut(board.GP15)\n#switch.direction = Direction.INPUT\n \n\nlast_change_time = time.time()\n \nstart_time = time.time()\nprint(&quot;Starting main script.&quot;)\nchange_action_time = 0\nprev_direction = 1\nSENSOR_THRESHOLD = 1000\nstate_index = False\nwhile True:\n    motor_power = 1\n\n    sensor_direction_level = sensor_direction.value\n\n    \n    if state_index is False:\n        if sensor_direction_level &lt; lower_threshold:\n            led.value = True\n            state_index = True\n            print(&quot;On&quot;)\n\n    elif state_index is True:\n        if sensor_direction_level &amp;gt; upper_threshold:\n            led.value = False\n            state_index = False\n            print(&quot;Off&quot;)\n            prev_direction *= -1\n            driver.write(1, prev_direction * motor_power)\n            time.sleep(0.5)\n    \n    driver.write(1, prev_direction * motor_power)\n\n     \n   \n    # uncomment the following to print tuples to plot with the mu editor\n    # print((sensor_level, motor_power))\n    # time.sleep(0.02)  # slow sampling to avoid flooding\n<\/pre>\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-content\/uploads\/2021\/10\/cadModels.zip\">cadModels<\/a><a href=\"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-content\/uploads\/2021\/10\/cadModels.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>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&#8230;<\/p>\n","protected":false},"author":41,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/posts\/5097"}],"collection":[{"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/comments?post=5097"}],"version-history":[{"count":7,"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/posts\/5097\/revisions"}],"predecessor-version":[{"id":5110,"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/posts\/5097\/revisions\/5110"}],"wp:attachment":[{"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/media?parent=5097"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/categories?post=5097"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/16-223\/f2021\/work\/wp-json\/wp\/v2\/tags?post=5097"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}