Hi
I'm yet another NON-Programmer trying to cobble things into a working state...
The issue is that when I upload this sketch, I think it kills the board USB port - so that it becomes unusable, ie. the IDE can't see the board or USB port. (I have tried the various tricks to bring a board back to life, but none have worked so far... they will have to wait!).
I have 3 boards which do not work now.
The sketch is for a simple midi control box with 5 knobs, a button and a Trigger input.
Originally the sketch was for 5 knobs and a button - and that works perfectly in an existing unit. The issue started when I tried adding the Trigger input - and then the boards started stopping working completely.
So if a kind soul could possibly spot the issue I would be eternally grateful!
The addition of the Trigger code comes from a different Project Source to the knobs and button, so any suggestions for improving the Trigger code are also very welcome!
Many thanks in advance!
//
// Copyright Will Hitchings 2024
//
// PLUS-4
// ======
//
// Sketch for a Midi Box to control a
//
// SELF-CONTAINED KICK + SUB SYSTEM
// ================================
//
// 1x BUTTON SWITCH (D1)
// 1x TRIGGER INPUT (A5)
// 5x POTENTIOMETERS (A0-1-2-3-4)
//
// PIN ASSIGNMENTS
//
// A0 = POT 1 FREQ CC01
// A1 = POT 2 KICK 1 CC02
// A2 = POT 3 KICK 2 CC03
// A3 = POT 4 KICK 3 CC04
// A4 = POT 5 KICK SUB CC05
// A5 = TRIGGER INPUT NOTE 36
// D1 = BUTTON NOTE 30
//
// MIDI CHANNEL 1
//
// = = = CHECK 'boards.txt' ! ! !
//
#include "MIDIUSB.h"
// BUTTON + TRIGGER to MIDI Notes
//
#define BTN_NOTE 30 // BOOM BUTTON
#define TRIG_NOTE 36 // KICK TRIGGER
#define deviceChannel 0 // This is the MIDI channel number 0-15
#define buttonDebounceTime 150 // Debounce time for each button in milliseconds (prevents multiple triggers due to chatter)
const int ButtonPin[1] = {1}; // BOOM BUTTON
const int TriggerPin[1] = {'A5'}; // KICK TRIGGER
//
// TRIGGER
//
char pinAssignments[1] = {'A5'};
byte TrigNote[1] = {36}; // MIDI note
int TrigCutOff[1] = {5}; // Minimum Analog value to cause a drum hit
int MaxPlayTime[1] = {150}; // Cycles before a 2nd hit is allowed
boolean VelocityFlag = true;
boolean activeTrig[1] = {0}; // Array of flags of pad currently playing
int PinPlayTime[1] = {0}; // Counter since pad started to play
byte status1;
int pin = A5;
int hitavg = 0;
//
// POTENTIOMETERS
//
const int NPots = 5; // total number of POTS
const int potPin[NPots] = {A0, A1, A2 , A3, A4}; // Arduino POT Pins ; Leave nothing in the array if 0 pots {}
int potCState[NPots] = {0}; // Current state of the pot; delete 0 if 0 pots
int potPState[NPots] = {0}; // Previous state of the pot; delete 0 if 0 pots
int potVar = 0; // Difference between the current and previous state of the pot
int midiCState[NPots] = {0}; // Current state of the midi value; delete 0 if 0 pots
int midiPState[NPots] = {0}; // Previous state of the midi value; delete 0 if 0 pots
const int TIMEOUT = 300; //* Amount of time the potentiometer will be read after it exceeds the varThreshold
const int varThreshold = 20; //* Threshold for the potentiometer signal variation
boolean potMoving = true; // If the potentiometer is moving
unsigned long PTime[NPots] = {0}; // Previously stored time; delete 0 if 0 pots
unsigned long timer[NPots] = {0}; // Stores the time that has elapsed since the timer was reset; delete 0 if 0 pots
//
// MIDI Assignments
//
// byte midiCh = 1; //* MIDI channel to be used
byte note = 30; //* Lowest note to be used; 30 = BOOM BUTTON, 36 = KICK TRIGGER
byte cc = 1; //* Lowest MIDI CC to be used
// --------------------------------------------------------
bool InternalLED_state = LOW;
bool buttonState[1] = {0};
unsigned long buttonToggleTime[1] = {0};
//-----------------------------------------------------
//
// START of SETUP
//
void setup()
{
Serial.begin(115200);
// Serial.println(hitavg);
for (int i=0; i<1; i++)
{
pinMode(ButtonPin[1], INPUT); // For All buttons
pinMode(TriggerPin[A5], INPUT); // For All buttons
}
}
//
// END of SETUP
//
//-----------------------------------------------------
//
// START of VOID LOOP
//
void loop()
{
//
// TRIGGER
//
{
for (int pin=A5; pin++;) // pin < 16; pin++)
//
{
//int pin = 3;
// for (pinRead=0; pinRead < 16, pin++){
hitavg = analogRead(pinAssignments[pin]);
//Serial.println(hitavg);
// read the input pin
if((hitavg > TrigCutOff[pin]))
{
if((activeTrig[pin] == false))
{
if(VelocityFlag == true)
{
// hitavg = 127 / ((1023 - PadCutOff[pin]) / (hitavg - PadCutOff[pin])); // With full range (Too sensitive ?)
hitavg = (hitavg / 4) -1 ; // Upper range
}
else
{
hitavg = 127;
}
//noteOn(144,TrigNote[pin],hitavg); //note on
noteOn(deviceChannel, TRIG_NOTE, 127); // Channel, Note, Velocity
PinPlayTime[pin] = 0;
activeTrig[pin] = true;
}
else
{
PinPlayTime[pin] = PinPlayTime[pin] + 1;
}
}
else if((activeTrig[pin] == true))
{
PinPlayTime[pin] = PinPlayTime[pin] + 1;
if(PinPlayTime[pin] > MaxPlayTime[pin])
{
activeTrig[pin] = false;
//noteOff(144,TrigNote[pin],,0);
noteOff(deviceChannel, TRIG_NOTE,0);
}
}
}
}
//
// END TRIGGER
//
//
// POTS
//
potentiometers();
midiEventPacket_t rx;
rx = MidiUSB.read(); // Check for Message
if (rx.header != 0); // If message Received
//
// CHECK BUTTON
//
for (int i=0; i<1; i++){ // ALL BUTTONS
if (millis() < buttonToggleTime[i] + buttonDebounceTime){ // If it was recently changed
continue; // Skip this SWITCH. Do next one
}
if (buttonState[i] == 0){ // If BUTTON is Not Pressed Already
if (digitalRead(ButtonPin[i]) == 0){ // Pin is Low, BUTTON is pressed
buttonState[i] = 1; // Mark as pressed
buttonToggleTime[i] = millis(); // Update Event Time
switch(i){ // Pick which Note it is (from BUTTON ID)
case 0:
noteOff(deviceChannel, BTN_NOTE, 0); // Channel, Note, Velocity
break;
} // End CHECK SWITCHES
} // End SWITCHES Read
} // End IF (SWITCH Not Already Pressed)
else{ // SWITCH Already Pressed (SWITCH State == 1)
if (digitalRead(ButtonPin[i]) == 1){ // Pin is High, SWITCH is released
//toggleOnBoardLED(); // FOR DEBUGGING - CAN BE REMOVED - WH added ;
buttonState[i] = 0; // Mark as released
buttonToggleTime[i] = millis(); // Update Event Time
//
// MIDI NOTE OFF MESSAGES FOR SWITCHES
//
switch(i){ // Pick which Note it is (from button ID)
case 0:
noteOn(deviceChannel, BTN_NOTE, 127); // Channel, Note, Velocity
break;
} // End SWITCHES
}// End SWITCHES READ
} // End ELSE (SWITCH Already Pressed)
}// End IF SWITCHES
//
}// END of VOID LOOP
//
//
//-----------------------------------------------------
//
//
// START of FINAL VOID
//
//
// POTENTIOMETERS
//
void potentiometers()
{
for (int i = 0; i < NPots; i++) { // Loops through all the potentiometers
potCState[i] = analogRead(potPin[i]); // reads the pins from arduino
midiCState[i] = map(potCState[i], 0, 1023, 0, 200); // Maps the reading of the potCState to a value usable in midi
potVar = abs(potCState[i] - potPState[i]); // Calculates the absolute value between the difference between the current and previous state of the pot
if (potVar > varThreshold) { // Opens the gate if the potentiometer variation is greater than the threshold
PTime[i] = millis(); // Stores the previous time
}
timer[i] = millis() - PTime[i]; // Resets the timer 11000 - 11000 = 0ms
if (timer[i] < TIMEOUT) { // If the timer is less than the maximum allowed time it means that the potentiometer is still moving
potMoving = true;
}
else {
potMoving = false;
}
if (potMoving == true) { // If the potentiometer is still moving, send the change control
if (midiPState[i] != midiCState[i]) {
// Sends MIDI CC
// Use if using with ATmega32U4 (micro, pro micro, leonardo...)
controlChange(deviceChannel, cc + i, midiCState[i]); // (channel, CC number, CC value)
MidiUSB.flush();
potPState[i] = potCState[i]; // Stores the current reading of the potentiometer to compare with the next
midiPState[i] = midiCState[i];
}
}
}
}// FOR END
//
// END POTENTIOMETERS
//
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(event);
}
//
//
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
MidiUSB.flush();// Send note now
}
//
//
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
MidiUSB.flush(); // Send note now
}
//
// END of FINAL VOID
//