Hello,
I've currently got a MIDI project going, and I'm trying to use a SR04 sensor to control pitch bend.
Here's what I've got:
void loop() {
a=sr04.Distance();
if (a <= 20){ //If Distance is less than 20cm, start pitch bending.
pitchBend = map(a,0,20,8191,-8192); // Map 0-20cm to Pitch Bend Parameters (close is higher, further is lower pitch).
if (pitchBend>8191){pitchBend=8191;};if (pitchBend<-8192){pitchBend=-8192;} // Debug
PitchWheelChange(pitchBend);
void PitchWheelChange(int value) { // Pitch Wheel Function taken from here: [url=https://forum.arduino.cc/index.php?topic=119790.0]https://forum.arduino.cc/index.php?topic=119790.0[/url]
unsigned int change = 0x2000 + value; // 0x2000 == No Change
unsigned char low = change & 0x7F; // Low 7 bits
unsigned char high = (change >> 7) & 0x7F; // High 7 bits
midiMessage(0xE0, low, high);
}
void midiMessage(int commandByte, int data1Byte, int data2Byte) { // Midi Output Function
Serial.write(commandByte);
Serial.write(data1Byte);
Serial.write(data2Byte);
}
So essentially I've mapped 0-20cm distance to pitch bend midi parameters, which outputs to a MIDI Message Function.
The issue I'm having is that Hairless MIDI freaks out with its "Received a Status Byte when we were expecting 1 more data byte" message. And my DAW (FL Studio) simply states that I'm sending pitch bend of 158/168 cents no matter what the distance is. I guess therefore, SOMETHING works, but there is obviously something wrong.
Any ideas on this? Perhaps my coding is wrong? I also heard the default library for those ultrasonc modules are very temperamental. Maybe worth getting a new library?
This code emulates a Theremin using two Sharp IR distance sensors that produce an analogue input on analogue 0 & 1. I notice from your code that you never actually send a note on message. An unexpected status byte message is often produced by hairless if the baud rate is not set the same at both ends. If you want to use this code with Hairless then you will have to up the serial rate to match the Hairless default.
If you have no sharp IR sensors you can always replace them with pots for a test.
// Theremin - Grumpy Mike
boolean playing = false;
const byte channel = 0;
const byte baseNote = 72;
void setup(){
Serial.begin(31250); // MIDI baud rate
analogReference(EXTERNAL);
controlSend(0, 0); // set bank 0 MSB
controlSend(32, 0); // set bank 0 LSB
programChange(52); // send voice number
// set up Pitch bend sensitivity
controlSend(101, 0);
controlSend(100, 0);
controlSend(6,72); // set to 6 octaves
controlSend(38, 0); // and zero cents
}
void loop(){
int av1 = 1027 - analogRead(0);
int av2 = 1027 - analogRead(1);
if(av1 <870 && av2 < 870){
if(!playing)noteOn();
else {
trackNote(av2,av1);
}
}
else {
if(playing) noteOff();
}
}
void noteOff(){
playing= false;
// note off + sustain off
noteSend(0x80,baseNote,127);
controlSend(64, 0);
}
void noteOn(){
// note on + sustain on
noteSend(0x90,baseNote,127);
controlSend(64, 127);
playing = true;
}
int trackNote(int freq, int volume){
int pb = 0x2000 - (435 - freq);
sendPB(pb);
int vel = volume>> 3;
controlSend(7, vel);
}
void noteSend(byte cmd, byte data1, byte data2) {
cmd = cmd | channel;
Serial.write(cmd);
Serial.write(data1);
Serial.write(data2);
}
void controlSend(byte CCnumber, byte CCdata) {
byte CCchannel = channel | 0xB0; // convert to Controller message
Serial.write(CCchannel);
Serial.write(CCnumber);
Serial.write(CCdata);
}
void sendPB(int pb){ // send pitch bend message
Serial.write( (byte)0xE0 | channel);
Serial.write( pb & (byte)0x7f);
Serial.write( (pb>>7) & (byte)0x7f);
}
void programChange(byte voice){
Serial.write((byte)0xC0 | channel);
Serial.write(voice);
}