code.py
  1  # SPDX-FileCopyrightText: 2021 John Park for Adafruit Industries.
  2  #
  3  # SPDX-License-Identifier: MIT
  4  """
  5  Power Glove BLE MIDI with Feather Sense nRF52840
  6  Sends MIDI CC values based on finger flex sensors and accelerometer
  7  """
  8  import time
  9  import board
 10  import adafruit_ble
 11  from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
 12  import adafruit_ble_midi
 13  import adafruit_midi
 14  from adafruit_midi.control_change import ControlChange
 15  # from adafruit_midi.note_on import NoteOn
 16  # from adafruit_midi.pitch_bend import PitchBend
 17  import adafruit_lsm6ds.lsm6ds33  # accelerometer
 18  import simpleio
 19  from analogio import AnalogIn
 20  
 21  i2c = board.I2C()
 22  sense_accel = adafruit_lsm6ds.lsm6ds33.LSM6DS33(i2c)
 23  
 24  analog_in_thumb = AnalogIn(board.A3)
 25  analog_in_index = AnalogIn(board.A2)
 26  analog_in_middle = AnalogIn(board.A1)
 27  analog_in_ring = AnalogIn(board.A0)
 28  
 29  # Pick your MIDI CC numbers here
 30  cc_x_num = 7  # volume
 31  cc_y_num = 70  # unassigned
 32  cc_thumb_num = 71  # unassigned
 33  cc_index_num = 75  # unassigned
 34  cc_middle_num = 76  # unassigned
 35  cc_ring_num = 77  # unassigned
 36  
 37  midi_channel = 1  # pick your midi out channel here
 38  
 39  # Use default HID descriptor
 40  midi_service = adafruit_ble_midi.MIDIService()
 41  advertisement = ProvideServicesAdvertisement(midi_service)
 42  
 43  ble = adafruit_ble.BLERadio()
 44  if ble.connected:
 45      for c in ble.connections:
 46          c.disconnect()
 47  
 48  midi = adafruit_midi.MIDI(midi_out=midi_service, out_channel=midi_channel - 1)
 49  
 50  print("advertising")
 51  ble.name="Power Glove MIDI"
 52  ble.start_advertising(advertisement)
 53  
 54  # reads an analog pin and returns value remapped to out range, e.g., 0-127
 55  def get_flex_cc(sensor, low_in, high_in, min_out, max_out):
 56      flex_raw = sensor.value
 57      flex_cc = simpleio.map_range(flex_raw, low_in, high_in, min_out, max_out)
 58      flex_cc = int(flex_cc)
 59      return flex_cc
 60  
 61  
 62  debug = False  # set debug mode True to test raw values, set False to run BLE MIDI
 63  
 64  while True:
 65      if debug:
 66          accel_data = sense_accel.acceleration  # get accelerometer reading
 67          accel_x = accel_data[0]
 68          accel_y = accel_data[1]
 69          accel_z = accel_data[2]
 70  
 71          print(
 72              "x:{} y:{} z:{} thumb:{} index:{} middle:{} ring:{}".format(
 73                  accel_x,
 74                  accel_y,
 75                  accel_x,
 76                  analog_in_thumb.value,
 77                  analog_in_index.value,
 78                  analog_in_middle.value,
 79                  analog_in_ring.value,
 80              )
 81          )
 82          time.sleep(0.2)
 83  
 84      else:
 85          print("Waiting for connection")
 86          while not ble.connected:
 87              pass
 88          print("Connected")
 89          while ble.connected:
 90              # Feather Sense accelerometer readings to CC
 91              accel_data = sense_accel.acceleration  # get accelerometer reading
 92              accel_x = accel_data[0]
 93              accel_y = accel_data[1]
 94              # accel_z = accel_data[2]
 95              # Remap analog readings to cc range
 96              cc_x = int(simpleio.map_range(accel_x, 0, 9, 127, 0))
 97              cc_y = int(simpleio.map_range(accel_y, 1, -9, 0, 127))
 98  
 99              cc_thumb = get_flex_cc(analog_in_thumb, 49000, 35000, 127, 0)
100              cc_index = get_flex_cc(analog_in_index, 50000, 35000, 0, 127)
101              cc_middle = get_flex_cc(analog_in_middle, 55000, 40000, 0, 127)
102              cc_ring = get_flex_cc(analog_in_ring, 55000, 42000, 0, 127)
103              '''
104              print(
105                  "CC_X:{} CC_Y:{} CC_Thumb:{} CC_Index:{} CC_Middle:{} CC_Ring:{}".format(
106                      cc_x, cc_y, cc_thumb, cc_index, cc_middle, cc_ring
107                  )
108              )'''
109  
110              # send all the midi messages in a list
111              midi.send(
112                  [
113                      ControlChange(cc_x_num, cc_x),
114                      ControlChange(cc_y_num, cc_y),
115                      ControlChange(cc_thumb_num, cc_thumb),
116                      ControlChange(cc_index_num, cc_index),
117                      ControlChange(cc_middle_num, cc_middle),
118                      ControlChange(cc_ring_num, cc_ring),
119                  ]
120              )
121  
122              # If you want to send NoteOn or Pitch Bend, here are examples:
123              # midi.send(NoteOn(44, 120))  # G sharp 2nd octave
124              # a_pitch_bend = PitchBend(random.randint(0, 16383))
125              # midi.send(a_pitch_bend)
126  
127          print("Disconnected")
128          print()
129          ble.start_advertising(advertisement)