/ Flying_Fader / code.py
code.py
  1  # SPDX-FileCopyrightText: 2022 John Park for Adafruit Industries
  2  # SPDX-License-Identifier: MIT
  3  # Motorized fader demo
  4  import time
  5  import board
  6  import pwmio
  7  import analogio
  8  import touchio
  9  import neopixel
 10  from digitalio import DigitalInOut, Pull
 11  from adafruit_debouncer import Debouncer
 12  from adafruit_motor import motor
 13  
 14  MIDI_DEMO = False  # set to True to send MIDI CC
 15  
 16  # optional MIDI setup
 17  if MIDI_DEMO:
 18      import usb_midi
 19      import adafruit_midi
 20      from adafruit_midi.control_change import ControlChange
 21      midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0)
 22      fader_cc_number = 16
 23  
 24  # Button setup to store four saved values
 25  button_pins = (board.D10, board.D9, board.D6, board.D5)
 26  buttons = []
 27  for button_pin in button_pins:
 28      tmp_pin = DigitalInOut(button_pin)
 29      tmp_pin.pull = Pull.UP
 30      buttons.append(Debouncer(tmp_pin))
 31  
 32  saved_positions = (230, 180, 120, 60)  # pre-saved positions for the buttons to call
 33  
 34  # Slide pot setup
 35  fader = analogio.AnalogIn(board.A0)
 36  fader_position = fader.value  # ranges from 0-65535
 37  fader_pos = fader.value // 256  # make 0-255 range
 38  last_fader_pos = fader_pos
 39  
 40  # Motor setup
 41  PWM_PIN_A = board.D12  # pick any pwm pins on their own channels
 42  PWM_PIN_B = board.D11
 43  
 44  # DC motor driver setup -- these pins go to h-bridge driver such as L9110
 45  pwm_a = pwmio.PWMOut(PWM_PIN_A, frequency=50)
 46  pwm_b = pwmio.PWMOut(PWM_PIN_B, frequency=50)
 47  motor1 = motor.DCMotor(pwm_a, pwm_b)
 48  
 49  # Touch setup  pin goes from touch pin on slide pot to touch capable pin and then 1MΩ to gnd
 50  touch = touchio.TouchIn(board.A3)
 51  touch.threshold = touch.raw_value + 30  # tune for fader knob cap
 52  
 53  # NeoPixel setup
 54  led = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2, auto_write=True)
 55  led.fill(0xff0000)
 56  
 57  def clamp(num, min_value, max_value):  # function for clamping motor throttle -1.0 to 1.0
 58      return max(min(num, max_value), min_value)
 59  
 60  def go_to_position(new_position):
 61      global fader_pos  # pylint: disable=global-statement
 62      fader_pos = int(fader.value//256)
 63      while abs(fader_pos - new_position) > 2 :
 64          if fader_pos > new_position :
 65              speed = 2.25 * abs(fader_pos - new_position) / 256 + 0.12
 66              speed = clamp(speed, -1.0, 1.0)
 67              motor1.throttle = speed
 68              led[0] = (fader_pos, 0, 0)
 69  
 70              if MIDI_DEMO:
 71                  global fader_cc  # pylint: disable=global-statement
 72                  fader_cc = int(fader_pos / 2)  # cc is 0-127
 73                  midi.send(ControlChange(fader_cc_number, fader_cc))
 74  
 75          if fader_pos < new_position:
 76              speed = -2.25 * abs(fader_pos - new_position) / 256 - 0.12
 77              speed = clamp(speed, -1.0, 1.0)
 78              motor1.throttle = speed
 79              led[0] = (fader_pos, 0, 0)
 80  
 81              if MIDI_DEMO:
 82                  fader_cc = int(fader_pos / 2)  # cc is 0-127
 83                  midi.send(ControlChange(fader_cc_number, fader_cc))
 84  
 85          fader_pos = int(fader.value//256)
 86      motor1.throttle = None
 87  print("--__ Flying Fader Demo __--")
 88  print("\n"*4)
 89  
 90  go_to_position(saved_positions[3])  # boot up demo
 91  go_to_position(saved_positions[0])
 92  time.sleep(.6)
 93  
 94  current_saved_position = 0  # state to store which is current position from the list
 95  
 96  while True:
 97      for i in range(len(buttons)):
 98          buttons[i].update()
 99          if buttons[i].fell:  # if a button is pressed, update the position from list
100              current_saved_position = i
101  
102      if touch.value:
103          motor1.throttle = None  # idle
104      else:
105          go_to_position(saved_positions[current_saved_position])
106  
107      filter_amt = 0.1  # higher number will be a slower filter between 1.0 and 0.1 is good
108      fader_pos = int((filter_amt * last_fader_pos) + ((1.0-filter_amt) * fader.value//256))
109      led[0] = (fader_pos, 0, 0)
110      if abs(fader_pos - last_fader_pos) > 1 :  # do things in here, e.g. send MIDI CC
111          fader_width = 90  # for text visualization in serial output
112          print("-" * (fader_width - int(fader_pos/3)), fader_pos, "-" * int(fader_pos/3), end='\r')
113          last_fader_pos = fader_pos
114          if MIDI_DEMO:
115              fader_cc = int(fader_pos / 2)  # cc is 0-127
116              midi.send(ControlChange(fader_cc_number, fader_cc))