Skip to content

Instantly share code, notes, and snippets.

@ubidefeo
Last active June 13, 2020 06:06
Show Gist options
  • Save ubidefeo/3e7362235cee5317cec4a36f07585e29 to your computer and use it in GitHub Desktop.
Save ubidefeo/3e7362235cee5317cec4a36f07585e29 to your computer and use it in GitHub Desktop.
/* Arduino analog to BLE MIDI
Ubi de Feo @ Bar Arduino
https://www.youtube.com/watch?v=0zNmt_IKwRg
supported boards:
- Arduino MKR WiFi 1010
- Arduino Nano 33 IoT
- Arduino Nano 33 BLE
- Arduino Nano 33 BLE Sense
- Arduino UNO WiFI Rev. 2
**** Sketch for USB MIDI version (Nano 33 BLE not supported) ****
**** can be found here https://gist.github.com/ubidefeo/6098d95332b6529f1b0599bfd443ebae ****
**** Thank you Larry Bank for pointing out the lack of a BLE version ****
BLE init code courtesy of T. Igoe
https://tigoe.github.io/SoundExamples/midi-ble.html
*/
#include <ArduinoBLE.h>
byte midiData[] = {0x80, 0x80, 0x00, 0x00, 0x00};
const byte emptyMIDIMessage[] = {0x80, 0x80, 0x00, 0x00, 0x00};
// set up the MIDI service and MIDI message characteristic:
BLEService midiService("03B80E5A-EDE8-4B33-A751-6CE34EC4C700");
BLECharacteristic midiCharacteristic("7772E5DB-3868-4112-A1A9-F2669D106BF3",
BLEWrite | BLEWriteWithoutResponse |
BLENotify | BLERead,
sizeof(midiData));
bool isMIDIOn = false;
void controlChange(byte channel, byte control, byte value) {
midiData[2] = 0xB0 | channel;
midiData[3] = control;
midiData[4] = value;
midiCharacteristic.setValue(midiData, sizeof(midiData));
}
const int SAMPLES_COUNT = 20;
// FIFO
int samplesBuffer[SAMPLES_COUNT] = {0};
int sampleIndex = 0;
const int knobInputPin = A1;
const int changeThreshold = 20;
int lastSensorValue;
int lastMappedValue;
unsigned long samplesSum = 0;
void setup() {
Serial.begin(57600);
delay(5000);
// Initialize BLE:
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (true)
;
}
// set local name and advertised service for BLE:
BLE.setLocalName("ARDUINO_MIDI_BLE");
BLE.setAdvertisedService(midiService);
// add the characteristic and service:
midiService.addCharacteristic(midiCharacteristic);
BLE.addService(midiService);
// start advertising
BLE.advertise();
Serial.println("SETUP");
}
void loop() {
int knobReadOut = filterAnalogValue(knobInputPin);
int mappedValue = map(knobReadOut, 0, 1023, 0, 127);
BLEDevice central = BLE.central();
// When a central is connected to the peripheral we initially send
// an empty MIDI command in order to let certain platforms acknowledge the MIDI device
// Once that is done we set isMIDIOn to true and do not send the empty message until
// a reconnection happens upon disconnection (isMIDIOn needs to be false)
if (central && !isMIDIOn) {
midiCharacteristic.setValue(emptyMIDIMessage, sizeof(emptyMIDIMessage));
isMIDIOn = true;
}else{
isMIDIOn = false;
}
if(isMIDIOn){
if (lastMappedValue != mappedValue) {
// Serial.println("************ CHANGE ***************");
// Serial.print(">>> ");
// Serial.print(mappedValue);
// Serial.println(" <<<");
controlChange(0, 4, mappedValue);
}
lastMappedValue = mappedValue;
}
//delay(100);
}
int filterAnalogValue(int _inputPin) {
samplesSum = 0;
int analogValue = analogRead(_inputPin);
// int valueDelta = abs(analogValue - lastSensorValue);
// Serial.print(analogValue);
// Serial.print(" - ");
// Serial.println(lastSensorValue);
// if(valueDelta < changeThreshold){
// analogValue = lastSensorValue;
// }
if (sampleIndex < SAMPLES_COUNT) {
samplesBuffer[sampleIndex] = analogValue;
sampleIndex++;
} else {
for (int samplePosition = 0; samplePosition < sampleIndex - 1;
samplePosition++) {
0;
samplesBuffer[samplePosition] = samplesBuffer[samplePosition + 1];
}
samplesBuffer[SAMPLES_COUNT - 1] = analogValue;
}
for (int samplePosition = 0; samplePosition < sampleIndex; samplePosition++) {
0;
samplesSum += samplesBuffer[samplePosition];
}
// lastSensorValue = analogValue;
if (samplesSum == 0)
return 0;
unsigned int filteredValue = samplesSum / sampleIndex;
return filteredValue;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment