MIDI Controller with Sensors - Help ! MIDI note off doesn't turn off the note it should

Hi! I'm Gabe, a Music Technologies student from Portugal. First of all, thank you for the attention! :grin:
I am building a custom MIDI controller with a few sensors for a uni project. I've managed to get it working almost as I envision, but I've hit a roadblock.

I'm using an Arduino Mega Joy-it clone. There's two HC-SR04 distance sensors, one APDS9960 acting as a gesture sensor, and a LDR, all sending MIDI CC messages or MIDI note on/off messages.

To stop the whole thing getting slow and sluggish, I managed to get the HC-SR04 and APDS9960 only sending new MIDI messages when the value they read changes using a simple if clause comparing the last state with the current one. Big improvement!

However, once I tried to implement the same change to the LDR it just stops working. I've experimenting with removing several lines of code to see if anthing would change, but it's only when I add the if clause that it messes up.

So I'm sure I've got my breadboarding done right, it has to be my code that's wrong.

It also seems to still have plenty of room left:

Here's the code:

// Use an LDR to control MIDI CC 44 - Cuttoff on Volca Keys
// Use a HC-SR04 to control MIDI CC 46 - LFO Rate on Volca Keys
// Use a HC-SR04 to control MIDI CC 53 - Delay Feedback on Volca Keys
// copyright Queer_Gabe 2023 ESML

#include <MIDI.h>
#include <NewPing.h>            // for the distance sensor
#include "Adafruit_APDS9960.h"  // for the gesture sensor
Adafruit_APDS9960 apds;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDIA);  // create MIDI OUT A
// using the default was getting the serial print and MIDI messages all jumbled
// using serial1 with pins 18 and 19

MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDIB);  // create MIDI OUT B
// using the default was getting the serial print and MIDI messages all jumbled
// using serial1 with pins 16 and 17

int ldrPin = A1;   // select the input pin for LDR
int ldrValue = 0;  // variable to store the value coming from the sensor
int lastldrValue = 0;

int ledA = 2;  // select output pin for status LED A
int ledB = 3;  // select output pin for status LED B

#define MAX_DISTANCE 50  // max distance for new ping library

// variables to store sensor's A and B distance info
int distanceA = 1;
int lastdistanceA = 1;
int distanceB = 1;
int lastdistanceB = 1;

// NewPing setup (trigger pin, echo pin, max distance)

NewPing sonarA(31, 32, MAX_DISTANCE);
NewPing sonarB(41, 42, MAX_DISTANCE);

void setup() {
  Serial.begin(9600);              //sets serial port for communication
  pinMode(ldrPin, INPUT);          // sets ldr as input
  pinMode(ledA, OUTPUT);           // sets ledA as output
  pinMode(ledB, OUTPUT);           // sets ledB as output
  MIDIA.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port A
  MIDIB.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port B

  // initialize APDS9960
  if (!apds.begin()) {
    Serial.println("failed to initialize device! Please check your wiring.");
  } else Serial.println("Device initialized!");

  //gesture mode will be entered once proximity mode senses something close
  apds.enableProximity(true);
  apds.enableGesture(true);
}
void loop() {

  // LDR code
  ldrValue = analogRead(ldrPin);           // read the value from the sensor
  ldrValue = ldrValue / 7;                 // divide by 7 to make it fit better with MIDI values
  ldrValue = constrain(ldrValue, 0, 127);  // force it to be within MIDI values

  if (lastldrValue - ldrValue > 1) {
    MIDIA.sendControlChange(44, ldrValue, 1);  //send the MIDI CC message to channel 1
    lastldrValue = ldrValue;
    Serial.print("Cutoff");
    Serial.println(ldrValue);  //prints the values coming from the sensor
    //turns on ledA for half a second
    digitalWrite(ledA, HIGH);
    delay(500);
    digitalWrite(ledA, LOW);
    delay(50);  // keep it from flooding the arduino with too many messages
  }

  // HC-SR04 code A

  unsigned int distanceA = sonarA.ping_cm();
  distanceA = distanceA * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceA - distanceA > 1) {
    MIDIA.sendControlChange(53, distanceA, 1);  //send the MIDI CC message to channel 1
    lastdistanceA = distanceA;
    Serial.println("Delay Feedback");
    Serial.print(distanceA);
    //turns on ledA for half a second
    digitalWrite(ledA, HIGH);
    delay(500);
    digitalWrite(ledA, LOW);
    delay(50);  // keep it from flooding the arduino with too many messages
  }

  // HC-SR04 code B

  unsigned int distanceB = sonarB.ping_cm();
  distanceB = distanceB * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceB - distanceB > 1) {
    MIDIA.sendControlChange(46, distanceB, 1);  //send the MIDI CC message to channel 1
    lastdistanceB = distanceB;
    Serial.println("LFO Rate");
    Serial.print(distanceB);
    //turns on ledA for half a second
    digitalWrite(ledA, HIGH);
    delay(500);
    digitalWrite(ledA, LOW);

    delay(50);  // keep it from flooding the arduino with too many messages
  }

  // APDS9960 code
  //read a gesture from the device
  uint8_t gesture = apds.readGesture();
  if (gesture == APDS9960_DOWN) {
    Serial.println("DOWN");
    digitalWrite(ledB, HIGH);
    MIDIA.sendNoteOn(60, 127, 1);
    delay(500);
    MIDIA.sendNoteOff(60, 0, 1);
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_UP) {
    Serial.println("UP");
    digitalWrite(ledB, HIGH);
    MIDIA.sendNoteOn(61, 127, 1);
    delay(500);
    MIDIA.sendNoteOff(61, 0, 1);
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_LEFT) {
    Serial.println("LEFT");
    digitalWrite(ledB, HIGH);
    MIDIA.sendNoteOn(62, 127, 1);
    delay(500);
    MIDIA.sendNoteOff(62, 0, 1);
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_RIGHT) {
    Serial.println("RIGHT");
    digitalWrite(ledB, HIGH);
    MIDIA.sendNoteOn(63, 127, 1);
    delay(500);
    MIDIA.sendNoteOff(63, 0, 1);
    digitalWrite(ledB, LOW);
  }
  delay(50);
}

What could be the issue? Should I try a different approach, or am I just missing a tiny detail?
If you find any other random glaring beginner mistakes in my code, feel free to point them out too.

Thank you once again for your time!

try changing to this..

if (lastldrValue  !=  ldrValue )

means if the 2 values are not equal..
would be a better check condition..

good luck.. ~q

1 Like

Thank you so much for the quick reply! :pray: That worked perfectly! It must have been some weird math going on the background that didn't add up.

1 Like

Glad it helped..
Might want to change the other ifs the same way.. :slight_smile:

happy coding.. ~q

1 Like

Math isn't weird. Consider, for example, what happens when the result of this expression 'lastldrValue - ldrValue' is a negative number.

I should correct myself, then, I am weird with math :sweat_smile: I've been getting a lot better recently, but my understanding of it isn't particularly deep.

Considering that, it might have been the case that ldrValue was a much bigger number than lastldrValue, this resulting in a negative number, and in which case it isn't >1. So it never triggered the if clause. What I'm being unable to understand now is how it worked for the other two sensors but not the LDR. Why was it only turning into a negative number in that case? It seems like it could happen just as easily for the other two cases.

Thank you for provoking my curiosity and encouraging me to understand the subjacent math better, @flashko !

And yeah, I did change the rest of the code immediately, @qubits-us , it is a much better way to do it!

Maybe because 'unsigned int' cannot be negative.

My pleasure.

1 Like

I've ran into another issue. Now I'm trying to use one of the distance sensors as a way to send MIDI notes - kinda like a theremin, controlling the pitch.

I am trying to get the note to only change when the HC-SR04 reads a new value, and if the value stabilizes and doesn't change for a bit I want to stop the MIDI note. I've tried to implement this with MIDI note on and note off messages, unsuccessfully. Without that empty if clause it keeps returning to the 0 value note... but I don't understand why.

// This is a sketch for a custom MIDI controller with sensors for a uni project.
// A Korg Volca keys runs thru a NTS-1's FX.
// There are two MIDI out ports, one for side A and other for side B on the controller.
// This is a controller meant for two people to play together.
// LDR A - MIDI CC 44 - Cuttoff on Volca Keys
// HC-SR04 A - Pitch on Volca Keys
// HC-SR04 B - Mod depth on NTS1
// APDS9960 B to turn on an off the FX on the Korg NTS-1
// Feel free to use and modify this sketch to your heart's content.
// copyright Queer_Gabe 2023 ESML

#include <MIDI.h>
#include <NewPing.h>            // for the distance sensor
#include "Adafruit_APDS9960.h"  // for the gesture sensor
Adafruit_APDS9960 apds;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDIA);  // create MIDI OUT A
// using the default was getting the serial print and MIDI messages all jumbled
// using serial1 with pins 18 and 19

MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDIB);  // create MIDI OUT B
// using serial1 with pins 16 and 17

int ldrPin = A1;   // select the input pin for LDR
int ldrValue = 0;  // variable to store the value coming from the sensor
int lastldrValue = 0;

int ledA = 2;  // select output pin for status LED A
int ledB = 3;  // select output pin for status LED B

#define MAX_DISTANCE 50  // max distance for new ping library

// variables to store sensor's A and B distance info
int distanceA = 1;
int lastdistanceA = 1;
int distanceB = 1;
int lastdistanceB = 1;

// NewPing setup (trigger pin, echo pin, max distance)

NewPing sonarA(31, 32, MAX_DISTANCE);
NewPing sonarB(41, 42, MAX_DISTANCE);

void setup() {
  Serial.begin(9600);              //sets serial port for communication
  pinMode(ldrPin, INPUT);          // sets ldr as input
  pinMode(ledA, OUTPUT);           // sets ledA as output
  pinMode(ledB, OUTPUT);           // sets ledB as output
  MIDIA.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port A
  MIDIB.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port B

  // initialize APDS9960
  if (!apds.begin()) {
    Serial.println("failed to initialize device! Please check your wiring.");
  } else Serial.println("Device initialized!");

  //gesture mode will be entered once proximity mode senses something close
  apds.enableProximity(true);
  apds.enableGesture(true);
}
void loop() {

  // LDR code
  ldrValue = analogRead(ldrPin);           // read the value from the sensor
  ldrValue = ldrValue / 7;                 // divide by 7 to make it fit better with MIDI values
  ldrValue = constrain(ldrValue, 0, 127);  // force it to be within MIDI values

  if (lastldrValue != ldrValue) {              // if there's a change on the value, send MIDI message
    MIDIA.sendControlChange(44, ldrValue, 1);  //send the MIDI CC message to channel 1
    lastldrValue = ldrValue;
    Serial.print("Cutoff");
    Serial.println(ldrValue);  //prints the values coming from the sensor
    //turns on ledB for a quarter second
    digitalWrite(ledA, HIGH);
    delay(200);
    digitalWrite(ledA, LOW);
    //delay(50);  // keep it from flooding the arduino with too many messages
  }

  // HC-SR04 code A

  unsigned int distanceA = sonarA.ping_cm();
  distanceA = distanceA * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceA != distanceA) {  // if there's a change on the value, send MIDI message
    MIDIA.sendNoteOff(lastdistanceA, 0, 1);
    MIDIA.sendNoteOn(distanceA, 127, 1);
    digitalWrite(ledA, HIGH);
    lastdistanceA = distanceA;
    Serial.println("Pitch C2 to C5");
    Serial.print(lastdistanceA);
    delay(250);
    //MIDIA.sendNoteOff(lastdistanceA, 0, 1);
    digitalWrite(ledA, LOW);
    //delay(50);  // keep it from flooding the arduino with too many messages
  }

  if (lastdistanceA = 0) {  // this makes it stay at the last note played, but why?
    // digitalWrite(ledA, HIGH);
    // //MIDIA.sendNoteOff(distanceA, 0, 1);
    // Serial.println("Pitch off");
    // Serial.print(distanceA);
    // delay(200);
    // digitalWrite(ledA, LOW);
  }

  // HC-SR04 code B

  unsigned int distanceB = sonarB.ping_cm();
  distanceB = distanceB * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceB != distanceB) {             // if there's a change on the value, send MIDI message
    MIDIB.sendControlChange(29, distanceB, 1);  //send the MIDI CC message to channel 1
    lastdistanceB = distanceB;
    Serial.println("Flanger Depth");
    Serial.print(distanceB);
    //turns on ledB for a quarter second
    digitalWrite(ledB, HIGH);
    delay(250);
    digitalWrite(ledB, LOW);

    delay(50);  // keep it from flooding the arduino with too many messages
  }

  // APDS9960 code
  //read a gesture from the device
  uint8_t gesture = apds.readGesture();
  if (gesture == APDS9960_DOWN) {
    Serial.println("DOWN - Delay Off");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(89, 0, 1);  // cc for NTS1 delay type off
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_UP) {
    Serial.println("UP - Delay on");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(89, 110, 1);  // cc for NTS1 Delay type Tape
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_LEFT) {
    Serial.println("LEFT - Flanger On");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(88, 110, 1);  // cc for NTS1 Mod type Flanger
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_RIGHT) {
    Serial.println("RIGHT - Flanger Off");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(88, 0, 1);  // cc for NTS1 Mod type off
    digitalWrite(ledB, LOW);
  }
  delay(50);
}

Maybe there's a better way to do this with pitch bend, then it'd be more like a Theremin. Would that be a better approach?

But I was trying to lock the MIDI notes to a specific scale so it would be easier to integrate in jams with other instruments, that would be my next step in the coding process. How would I go about achieving that? Is there something in the midi library or another library I could add that would easily let me pick a scale?

Thank you again for your time and attention! :grin:

No worries,
If I understand correctly..
you need an else on the if and a millis timer..
inside the if distance is not the same, capture millis() value..
then in the else if distance is the same and we haven't turned off (another bool to add), check the millis timer and turn off and update turned off bool so you don't turn off more than once..


  if (lastdistanceA != distanceA) {  // if there's a change on the value, send MIDI message
    lastMillis = millis();
    NotePlaying = true;
    MIDIA.sendNoteOff(lastdistanceA, 0, 1);
    MIDIA.sendNoteOn(distanceA, 127, 1);
    digitalWrite(ledA, HIGH);
    lastdistanceA = distanceA;
    Serial.println("Pitch C2 to C5");
    Serial.print(lastdistanceA);
    delay(250);
    //MIDIA.sendNoteOff(lastdistanceA, 0, 1);
    digitalWrite(ledA, LOW);
    //delay(50);  // keep it from flooding the arduino with too many messages
  } else {
      //they are the same
      if (NotePlaying){
        if (millis()-lastMillis>=intervalDelay){
          NotePlaying = false;
          MIDIA.sendNoteOff(distanceA, 0, 1);
        }
      }
  }

declared above setup..

unsigned long lastMillis = 0;
int intervalDelay = 1000;
bool NotePlaying = false;

untested sorry..

is the issue only to stop the note??

~q

Thank you for the helpful suggestions once more!
This code worked to make the note stop once it stabilizes!

But there's still a minor quirk I'd like to iron out: if I keep my hand still it will stop the note. If I remove my hand it always plays the note corresponding to 0 before it stops instead of the note corresponding to the hand position being the last. It makes the melody make a weird jump. That happens because the sensor stops measuring, and thus sends out a 0 value, I assume.

Here's the updated code:

// This is a sketch for a custom MIDI controller with sensors for a uni project.
// A Korg Volca keys runs thru a NTS-1's FX.
// There are two MIDI out ports, one for side A and other for side B on the controller.
// This is a controller meant for two people to play together.
// LDR A - MIDI CC 44 - Cuttoff on Volca Keys
// HC-SR04 A - MIDI CC 46 - LFO Rate on Volca Keys
// HC-SR04 B - MIDI CC 53 - Delay Feedback on Volca Keys
// APDS9960 B to turn on an off the FX on the Korg NTS-1
// Feel free to use and modify this sketch to your heart's content.
// copyright Queer_Gabe 2023 ESML

#include <MIDI.h>
#include <NewPing.h>            // for the distance sensor
#include "Adafruit_APDS9960.h"  // for the gesture sensor
Adafruit_APDS9960 apds;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDIA);  // create MIDI OUT A
// using the default was getting the serial print and MIDI messages all jumbled
// using serial1 with pins 18 and 19

MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDIB);  // create MIDI OUT B
// using serial1 with pins 16 and 17

int ldrPin = A1;   // select the input pin for LDR
int ldrValue = 0;  // variable to store the value coming from the sensor
int lastldrValue = 0;

int ledA = 2;  // select output pin for status LED A
int ledB = 3;  // select output pin for status LED B

#define MAX_DISTANCE 50  // max distance for new ping library

// variables to store sensor's A and B distance info
int distanceA = 1;
int lastdistanceA = 1;
int distanceB = 1;
int lastdistanceB = 1;

// variables for the pitch sensor
unsigned long lastMillis = 0;
int intervalDelay = 1000;
bool NotePlaying = false;

// NewPing setup (trigger pin, echo pin, max distance)

NewPing sonarA(31, 32, MAX_DISTANCE);
NewPing sonarB(41, 42, MAX_DISTANCE);

void setup() {
  Serial.begin(9600);              //sets serial port for communication
  pinMode(ldrPin, INPUT);          // sets ldr as input
  pinMode(ledA, OUTPUT);           // sets ledA as output
  pinMode(ledB, OUTPUT);           // sets ledB as output
  MIDIA.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port A
  MIDIB.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port B

  // initialize APDS9960
  if (!apds.begin()) {
    Serial.println("failed to initialize device! Please check your wiring.");
  } else Serial.println("Device initialized!");

  //gesture mode will be entered once proximity mode senses something close
  apds.enableProximity(true);
  apds.enableGesture(true);
}
void loop() {

  // LDR code
  ldrValue = analogRead(ldrPin);           // read the value from the sensor
  ldrValue = ldrValue / 7;                 // divide by 7 to make it fit better with MIDI values
  ldrValue = constrain(ldrValue, 0, 127);  // force it to be within MIDI values

  if (lastldrValue != ldrValue) {              // if there's a change on the value, send MIDI message
    MIDIA.sendControlChange(44, ldrValue, 1);  //send the MIDI CC message to channel 1
    lastldrValue = ldrValue;
    Serial.print("Cutoff");
    Serial.println(ldrValue);  //prints the values coming from the sensor
    //turns on ledB for a quarter second
    digitalWrite(ledA, HIGH);
    delay(200);
    digitalWrite(ledA, LOW);
    //delay(50);  // keep it from flooding the arduino with too many messages
  }

  // HC-SR04 code A - volca keys pitch/notes

  unsigned int distanceA = sonarA.ping_cm();
  distanceA = distanceA * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceA != distanceA) {  // if there's a change on the value, send MIDI message
    lastMillis = millis();
    NotePlaying = true;
    MIDIA.sendNoteOff(lastdistanceA, 0, 1);
    MIDIA.sendNoteOn(distanceA, 127, 1);
    digitalWrite(ledA, HIGH);
    lastdistanceA = distanceA;
    Serial.println("Pitch C2 to C5");
    Serial.print(lastdistanceA);
    delay(250);
    digitalWrite(ledA, LOW);
  } else {
    //they are the same
    if (NotePlaying) {
      if (millis() - lastMillis >= intervalDelay) {
        NotePlaying = false;
        MIDIA.sendNoteOff(distanceA, 0, 1);
      }
    }
  }

  // HC-SR04 code B

  unsigned int distanceB = sonarB.ping_cm();
  distanceB = distanceB * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceB != distanceB) {             // if there's a change on the value, send MIDI message
    MIDIB.sendControlChange(29, distanceB, 1);  //send the MIDI CC message to channel 1
    lastdistanceB = distanceB;
    Serial.println("Flanger Depth");
    Serial.print(distanceB);
    //turns on ledB for a quarter second
    digitalWrite(ledB, HIGH);
    delay(250);
    digitalWrite(ledB, LOW);

    delay(50);  // keep it from flooding the arduino with too many messages
  }

  // APDS9960 code
  //read a gesture from the device
  uint8_t gesture = apds.readGesture();
  if (gesture == APDS9960_DOWN) {
    Serial.println("DOWN - Delay Off");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(89, 0, 1);  // cc for NTS1 delay type off
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_UP) {
    Serial.println("UP - Delay on");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(89, 110, 1);  // cc for NTS1 Delay type Tape
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_LEFT) {
    Serial.println("LEFT - Flanger On");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(88, 110, 1);  // cc for NTS1 Mod type Flanger
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_RIGHT) {
    Serial.println("RIGHT - Flanger Off");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(88, 0, 1);  // cc for NTS1 Mod type off
    digitalWrite(ledB, LOW);
  }
  delay(50);
}

as it should, the distance hasn't changed..
but as soon as distance changes new tone should be played..
wonder if it doesn't like stopping a note when there is no note..
try this..

// This is a sketch for a custom MIDI controller with sensors for a uni project.
// A Korg Volca keys runs thru a NTS-1's FX.
// There are two MIDI out ports, one for side A and other for side B on the controller.
// This is a controller meant for two people to play together.
// LDR A - MIDI CC 44 - Cuttoff on Volca Keys
// HC-SR04 A - MIDI CC 46 - LFO Rate on Volca Keys
// HC-SR04 B - MIDI CC 53 - Delay Feedback on Volca Keys
// APDS9960 B to turn on an off the FX on the Korg NTS-1
// Feel free to use and modify this sketch to your heart's content.
// copyright Queer_Gabe 2023 ESML

#include <MIDI.h>
#include <NewPing.h>            // for the distance sensor
#include "Adafruit_APDS9960.h"  // for the gesture sensor
Adafruit_APDS9960 apds;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDIA);  // create MIDI OUT A
// using the default was getting the serial print and MIDI messages all jumbled
// using serial1 with pins 18 and 19

MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDIB);  // create MIDI OUT B
// using serial1 with pins 16 and 17

int ldrPin = A1;   // select the input pin for LDR
int ldrValue = 0;  // variable to store the value coming from the sensor
int lastldrValue = 0;

int ledA = 2;  // select output pin for status LED A
int ledB = 3;  // select output pin for status LED B

#define MAX_DISTANCE 50  // max distance for new ping library

// variables to store sensor's A and B distance info
int distanceA = 1;
int lastdistanceA = 1;
int distanceB = 1;
int lastdistanceB = 1;

// variables for the pitch sensor
unsigned long lastMillis = 0;
int intervalDelay = 1000;
bool NotePlaying = false;

// NewPing setup (trigger pin, echo pin, max distance)

NewPing sonarA(31, 32, MAX_DISTANCE);
NewPing sonarB(41, 42, MAX_DISTANCE);

void setup() {
  Serial.begin(9600);              //sets serial port for communication
  pinMode(ldrPin, INPUT);          // sets ldr as input
  pinMode(ledA, OUTPUT);           // sets ledA as output
  pinMode(ledB, OUTPUT);           // sets ledB as output
  MIDIA.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port A
  MIDIB.begin(MIDI_CHANNEL_OMNI);  // initialize MIDI library for port B

  // initialize APDS9960
  if (!apds.begin()) {
    Serial.println("failed to initialize device! Please check your wiring.");
  } else Serial.println("Device initialized!");

  //gesture mode will be entered once proximity mode senses something close
  apds.enableProximity(true);
  apds.enableGesture(true);
}
void loop() {

  // LDR code
  ldrValue = analogRead(ldrPin);           // read the value from the sensor
  ldrValue = ldrValue / 7;                 // divide by 7 to make it fit better with MIDI values
  ldrValue = constrain(ldrValue, 0, 127);  // force it to be within MIDI values

  if (lastldrValue != ldrValue) {              // if there's a change on the value, send MIDI message
    MIDIA.sendControlChange(44, ldrValue, 1);  //send the MIDI CC message to channel 1
    lastldrValue = ldrValue;
    Serial.print("Cutoff");
    Serial.println(ldrValue);  //prints the values coming from the sensor
    //turns on ledB for a quarter second
    digitalWrite(ledA, HIGH);
    delay(200);
    digitalWrite(ledA, LOW);
    //delay(50);  // keep it from flooding the arduino with too many messages
  }

  // HC-SR04 code A - volca keys pitch/notes

  unsigned int distanceA = sonarA.ping_cm();
  distanceA = distanceA * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceA != distanceA) {  // if there's a change on the value, send MIDI message
    lastMillis = millis();
    //shut down note if there is one playing..
    if (NotePlaying) {
      MIDIA.sendNoteOff(lastdistanceA, 0, 1);
    }
    //start new note..
    MIDIA.sendNoteOn(distanceA, 127, 1);
    NotePlaying = true;
    digitalWrite(ledA, HIGH);
    //remember
    lastdistanceA = distanceA;
    Serial.println("Pitch C2 to C5");
    Serial.print(lastdistanceA);
    delay(250);
    digitalWrite(ledA, LOW);
  } else {
    //they are the same
    if (NotePlaying) {
      if (millis() - lastMillis >= intervalDelay) {
        NotePlaying = false;
        MIDIA.sendNoteOff(distanceA, 0, 1);
      }
    }
  }

  // HC-SR04 code B

  unsigned int distanceB = sonarB.ping_cm();
  distanceB = distanceB * 2.54;  // make it fit MIDI values when using 50 cm max distance

  if (lastdistanceB != distanceB) {             // if there's a change on the value, send MIDI message
    MIDIB.sendControlChange(29, distanceB, 1);  //send the MIDI CC message to channel 1
    lastdistanceB = distanceB;
    Serial.println("Flanger Depth");
    Serial.print(distanceB);
    //turns on ledB for a quarter second
    digitalWrite(ledB, HIGH);
    delay(250);
    digitalWrite(ledB, LOW);

    delay(50);  // keep it from flooding the arduino with too many messages
  }

  // APDS9960 code
  //read a gesture from the device
  uint8_t gesture = apds.readGesture();
  if (gesture == APDS9960_DOWN) {
    Serial.println("DOWN - Delay Off");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(89, 0, 1);  // cc for NTS1 delay type off
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_UP) {
    Serial.println("UP - Delay on");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(89, 110, 1);  // cc for NTS1 Delay type Tape
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_LEFT) {
    Serial.println("LEFT - Flanger On");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(88, 110, 1);  // cc for NTS1 Mod type Flanger
    digitalWrite(ledB, LOW);
  }
  if (gesture == APDS9960_RIGHT) {
    Serial.println("RIGHT - Flanger Off");
    digitalWrite(ledB, HIGH);
    MIDIB.sendControlChange(88, 0, 1);  // cc for NTS1 Mod type off
    digitalWrite(ledB, LOW);
  }
  delay(50);
}

just one small change really..

~q

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.