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