CPX Midi Controller

CPX MIdi Controller Instructables!

 

Required items:

  • Pizza Box
  • White Paint
  • Connection cable for CPX
  • CPX Board
  • Circuit Python
  • Mu-Editor
  • Laptop
  • Midi-city loaded up in a new tab
  • Adafruit page loaded up in a new tab

 

Step1:

https://learn.adafruit.com/cpx-midi-controller

Access this link and view the tutorial of accessing the files

Step2:

Download Circuit Python, the newest version with the library bundles of the newest version as well.

here is the link to start to download CircuitPython

https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython

you click where it says download circuit python then it takes you to another page where you’ll need to click on the board you have, for instance I have a CPX board so I will press that board and it will take me to another page where I can now download circuitpython. After downloading this you’ll want to go download the libraries for the circuit python which will be on the next link.

Step3:

https://learn.adafruit.com/cpx-midi-controller/circuitpython

click on the green button that says library bundle release page, this will take you to a page where you will then be able to download circuit python bundle 5 through the links.

Step4:

Download and install Mu-Editor, this will be your way of writing code, and being able to use the circuit playground express as your midi controller.

https://learn.adafruit.com/welcome-to-circuitpython/installing-mu-editor

the tutorial is fairly simple on the website to download and run the program.

Step5: Connect ur cpx to your laptop, press the center button twice to load it into cplayboot, then drag the Adafruit-circuitpython file to change it into circuit python mode then drag your libraries into this hard drive.

STep6:

Using Mu Editor, you’ll want to copy and paste the same code that’s on the Adafruit website, which is as follows;

### cpx-expressive-midi-controller v1.2
### CircuitPython (on CPX) MIDI controller using the seven touch pads
### and accelerometer for modulation (cc1) and pitch bend
### Left button adjusts octave (switch left) or semitone (switch right)
### Right button adjusts scale, major or chromatic
### Switch right also disables pitch bend and modulation

### Tested with CPX and CircuitPython and 4.0.0-beta.5

### Needs recent adafruit_midi module

### copy this file to CPX as code.py

### MIT License.

### Copyright (c) 2019 Kevin J. Walters

### Permission is hereby granted, free of charge, to any person obtaining a copy
### of this software and associated documentation files (the “Software”), to deal
### in the Software without restriction, including without limitation the rights
### to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
### copies of the Software, and to permit persons to whom the Software is
### furnished to do so, subject to the following conditions:

### The above copyright notice and this permission notice shall be included in all
### copies or substantial portions of the Software.

### THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
### IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
### FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
### AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
### LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
### OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
### SOFTWARE.

import time

import digitalio
import touchio
import busio
import board
import usb_midi
import neopixel

import adafruit_lis3dh
import adafruit_midi

from adafruit_midi.note_on import NoteOn
from adafruit_midi.control_change import ControlChange
from adafruit_midi.pitch_bend import PitchBend

# MIDI defines middle C as 60 and modulation wheel is cc 1 by convention
midi_note_C4 = 60
midi_cc_modwheel = 1 # was const(1)

# 0x19 is the i2c address of the onboard accelerometer
acc_i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
acc_int1 = digitalio.DigitalInOut(board.ACCELEROMETER_INTERRUPT)
acc = adafruit_lis3dh.LIS3DH_I2C(acc_i2c, address=0x19, int1=acc_int1)
acc.range = adafruit_lis3dh.RANGE_2_G
acc.data_rate = adafruit_lis3dh.DATARATE_10_HZ

# brightness 1.0 saves memory by removing need for a second buffer
# 10 is number of NeoPixels on CPX
numpixels = 10 # was const(10)
pixels = neopixel.NeoPixel(board.NEOPIXEL, numpixels, brightness=1.0)

# Turn NeoPixel on to represent a note using RGB x 10
# to represent 30 notes – doesn’t do anything with pitch bend
def noteLED(pix, pnote, pvel):
note30 = (pnote – midi_note_C4) % (3 * numpixels)
pos = note30 % numpixels
r, g, b = pix[pos]
if pvel == 0:
brightness = 0
else:
# max brightness will be 32
brightness = round(pvel / 127 * 30 + 2)
# Pick R/G/B based on range within the 30 notes
if note30 < 10:
r = brightness
elif note30 < 20:
g = brightness
else:
b = brightness
pix[pos] = (r, g, b)

# white pulse used to indicate octave changes
flashbrightness = 20
def flashLED(pix, position):
pos = position % numpixels
t1 = time.monotonic()
oldcolour = pix[pos]
while time.monotonic() – t1 < 0.25:
for i in range(0, flashbrightness, 2):
pix[pos] = (i, i, i)
for i in range(flashbrightness, 0, -2):
pix[pos] = (i, i, i)
pix[pos] = oldcolour

midi_channel = 1
midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1],
out_channel=midi_channel-1)

# CPX counter-clockwise order of touch capable pads (i.e. not A0)
pads = [board.A4,
board.A5,
board.A6,
board.A7,
board.A1,
board.A2,
board.A3]

# The touch pads calibrate themselves as they are created, just once here
touchpads = [touchio.TouchIn(pad) for pad in pads]
del pads # done with that

pb_midpoint = 8192
pitch_bend_value = pb_midpoint # mid point – no bend
min_pb_change = 250

mod_wheel = 0
min_mod_change = 5

# button A is on left (usb at top)
button_left = digitalio.DigitalInOut(board.BUTTON_A)
button_left.switch_to_input(pull=digitalio.Pull.DOWN)
button_right = digitalio.DigitalInOut(board.BUTTON_B)
button_right.switch_to_input(pull=digitalio.Pull.DOWN)
switch_left = digitalio.DigitalInOut(board.SLIDE_SWITCH)
switch_left.switch_to_input(pull=digitalio.Pull.UP)

# some example scales in semitones
scale_st = {“major”: [0, 2, 4, 5, 7, 9, 11],
“chromatic”: [0, 1, 2, 3, 4, 5, 6]}
scales = [“major”, “chromatic”]
scale_idx = 0
base_note = midi_note_C4 # C4 middle C

def make_scale(scale_name):
return [semitone_offset + base_note
for semitone_offset in scale_st[scale_name]]

midi_notes = make_scale(scales[scale_idx])
keydown = [False] * 7

velocity = 127
min_octave = -3
max_octave = +3
octave = 0
min_semitone = -11
max_semitone = +11
semitone = 0

# 1/10 = 10 Hz – review data_rate setting if this is changed
acc_read_t = time.monotonic()
acc_read_period = 1/10
# For accelerometer do nothing between 0 and 1.3 (ms-2)
acc_nullzone = 1.3
acc_range = 4.0

# Convert an accelerometer reading
# from min_msm2 to min_msm2+range to an int from 0 to value_range
# or return 0 or value_range outside those values
# The conversion is applied “symmetrically” to negative numbers
def scale_acc(acc_msm2, min_msm2, range_msm2, value_range):
if acc_msm2 >= 0.0:
sign_a_m = 1
magn_acc_msm2 = acc_msm2
else:
sign_a_m = -1
magn_acc_msm2 = abs(acc_msm2)

adj_msm2 = magn_acc_msm2 – min_msm2

# deal with out of bounds values else scale value
# pylint: disable=no-else-return
if adj_msm2 <= 0:
return 0
elif adj_msm2 >= range_msm2:
return sign_a_m * value_range
else:
return sign_a_m * round(adj_msm2 / range_msm2 * value_range)

# Scan each pad and look for changes by comparing
# with keystate stored in keydown boolean list
# and send note on/off messages accordingly
# Send pitch bend and mod wheel cc based on tilt from accelerometer
# Change octave and semitone based on buttons
while True:
for idx, touchpad in enumerate(touchpads):
if touchpad.value != keydown[idx]:
keydown[idx] = touchpad.value
# 12 semitones in an octave
note = midi_notes[idx] + octave * 12 + semitone
if keydown[idx]:
midi.send(NoteOn(note, velocity))
noteLED(pixels, note, velocity)
else:
midi.send(NoteOn(note, 0)) # Using note on 0 for off
noteLED(pixels, note, 0)

# Perform rate limited checks on the accelerometer
# if switch is to left
now_t = time.monotonic()
if switch_left.value and now_t – acc_read_t > acc_read_period:
acc_read_t = time.monotonic()
ax, ay, az = acc.acceleration

# scale from 0 to 127 (maximum cc 7bit value)
new_mod_wheel = abs(scale_acc(ay, acc_nullzone, acc_range, 127))
if (abs(new_mod_wheel – mod_wheel) > min_mod_change
or (new_mod_wheel == 0 and mod_wheel != 0)):
midi.send(ControlChange(midi_cc_modwheel, new_mod_wheel))
mod_wheel = new_mod_wheel

# scale from 0 to +/- 8191 (almost maximum signed 14bit values)
new_pitch_bend_value = (pb_midpoint
– scale_acc(ax, acc_nullzone, acc_range,
pb_midpoint – 1))
if (abs(new_pitch_bend_value – pitch_bend_value) > min_pb_change
or (new_pitch_bend_value == pb_midpoint
and pitch_bend_value != pb_midpoint)):
midi.send(PitchBend(new_pitch_bend_value))
pitch_bend_value = new_pitch_bend_value

# left button increase octave / semitones shift based on switch
# does not currently clear playing notes (buglet)
if button_left.value:
if switch_left.value:
octave += 1
if octave > max_octave:
octave = min_octave
flashLED(pixels, octave)
else:
semitone += 1
if semitone > max_semitone:
semitone = min_semitone
# semitone range is more than number of pixels!
flashLED(pixels, semitone)

while button_left.value:
pass # wait for button up

# right button cycles through scales
if button_right.value:
scale_idx += 1
if scale_idx >= len(scales):
scale_idx = 0
flashLED(pixels, scale_idx)
midi_notes = make_scale(scales[scale_idx])

while button_right.value:
pass # wait for button up”

copy this into Mu-editor and save it as code.py onto the circuitpython hard drive and let it run.

Step7:

download google chrome and run https://midi.city/

this will allow you to play music on your cpx, unlike safari.

Now how to make the Dj Set using a pizza Box!

 

step 1:

Make sure you have colored paint, white, black, grey or whatever, make sure you stir the paint before you start to paint the empty pizza box.

Step 2:

start painting the pizza box because we don’t want to be giving out any free promotions.

Step3:

Give the Pizza box a second layer of Paint so we know for certain that there won’t be any free promotions.

STep4:

Let dry

Step 5:

Start drawing using pencil on the painted pizza box, I’d use a wooden pencil to start then trace over the led using a sharpie, get creative and make some new designs!

Step 6: cut out a square from one side of the pizza box, not too big but just enough so the cable of the CPX board can get through it

Step7:

Tape the CPXBoard and cable down to the painted pizza box and plug it into your computer and have fun making some new tunes!