I bought a teensyrom a while ago.
UPDATE 20250712 : Display
Tyrone and I wanted to control the settings using potmeters.
So I grabbed a Teensy 4.1 controller and some 10K potmeters, and worte some code
Code for 12 pots, pitch bend and display, don’t forget to set your USB mode to midi!
Schematic soon, also all tweaks and note sending.
Todo: Nice 3D printed Pitch Bend wheel, rest of display code and extra buttons!
Let’s use an old box to hold the pots!
#include <MIDIUSB.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define OLED_RESET 4 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // A0 -> A3, A6 -> A13 const int numPots = 12; // A14 - Pitch bend! int lastPitch = -1; //A4 A5 I2C display // Custom mappings: const int potPins[numPots] = {A0, A1, A2, A3, A6, A7, A8, A9, A10, A11, A12, A13}; // Analog pins const int ccNumbers[numPots] = {0,1,2,3,4,5,19,7,8,9,13,14}; // CC numbers const int midiChannels[numPots]= {1,1,1,1,1,1,1,1,1,1,1,1}; // MIDI channels (1–16) int lastValues[numPots]; // Store last values to reduce redundant MIDI messages void setup() { for (int i = 0; i < numPots; i++) { pinMode(potPins[i], INPUT); lastValues[i] = -1; } display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.setTextSize(2); display.setTextColor(WHITE); display.clearDisplay(); display.display(); } void loop() { for (int i = 0; i < numPots; i++) { int analogValue = analogRead(potPins[i]); int midiValue = analogValue / 8; // Scale 0–1023 to 0–127 if (abs(midiValue - lastValues[i]) > 1) { usbMIDI.sendControlChange(ccNumbers[i], midiValue, midiChannels[i]); lastValues[i] = midiValue; } } int potValue = analogRead(A12); // Read pot (0–1023) int pitchBend = map(potValue, 0, 1023, 0, 16383); // Map to MIDI Pitch Bend range if (abs(pitchBend - lastPitch) > 5) { // Send only on significant change sendPitchBend(pitchBend, 0); // Channel 1 lastPitch = pitchBend; } displayInfo(); delay(5); // CPU-friendly update rate } void sendPitchBend(int value, byte channel) { byte lsb = value & 0x7F; byte msb = (value >> 7) & 0x7F; midiEventPacket_t pitchBendPacket = {0x0E, 0xE0 | (channel & 0x0F), lsb, msb}; MidiUSB.sendMIDI(pitchBendPacket); // Needed? MidiUSB.flush(); } void displayInfo(){ byte x0, y0, x1, y1; // start/end coordinates for drawing lines on OLED display.clearDisplay(); display.setCursor(0, 0); display.print("MidiInfo"); // Working on this part display.display(); }