Hi! I'm Gabe, a Music Technologies student from Portugal. First of all, thank you for the attention!
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!