hey all I could use some help ..
I wrote this code for a 2 button midi with Expression on A0
but its causing some issues when I connect
can someone help me find and fix please
#include <MIDI.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # ((was 4) or -1 if sharing Arduino reset pin)
#define OLED_ADDR 0x3C // address of my 128x64 OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// error blink codes
#define ERR_DISP_ALLOC 3 // display allocation error
#define EXPRESSION_PIN A0
static const unsigned ledPin = LED_BUILTIN; // use onboard LED as activity indicator
static const byte switchPin[] = {2,3}; // pins for footswitch inputs
static const byte switchCount = 2; // number of footswitches used
static bool switchPressed[switchCount]; // current state of footswitches
static bool switchLastState[switchCount]; //previous state of footswitches (used for long press detection)
static unsigned long lastPressMillis[switchCount]; // when the last button press was detected
static unsigned long lastReleaseMillis[switchCount]; // when the last button was released
// Created and binds the MIDI interface to the default hardware Serial port
MIDI_CREATE_DEFAULT_INSTANCE();
void errBlink(int errCode) {
byte blinkTime = 200; // duration for each blink
byte blinkGap = 200; // gap between each blink
int burstWait = 1000; // wait time between bursts
for (;;) { // loop forever
for (int i = 1; i <= errCode; i++) {
digitalWrite(ledPin,HIGH);
delay(blinkTime);
digitalWrite(ledPin,LOW);
delay(blinkGap);
}
delay(burstWait);
}
} // end of errBlink()
void setup() {
pinMode(ledPin, OUTPUT); // setup activity LED pin for output
Serial.begin(9600);
MIDI.begin(MIDI_CHANNEL_OMNI); // Listen to all incoming messages
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { // Address 0x3C for my 128x64 variant
errBlink(ERR_DISP_ALLOC);
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(500); // Pause for 0.5 seconds
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // DraW white text
display.setCursor(0, 0); // Start at top-left corner
display.println("STRNGVELCITY");
display.cp437(true); // Use full 256 char 'Code Page 437' font
display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // DraW white text
display.setCursor(0, 0); // Start at top-left corner
display.println(" STRNG");
display.println(" VELCTY");
display.cp437(true); // Use full 256 char 'Code Page 437' font
display.display();
delay(5000);
// Initialise switches and related variable arrays
for (int i=0;i<switchCount;i++) {
pinMode(switchPin[i], INPUT_PULLUP); // add pullup resistors to all footswitch input pins
switchPressed[i] = false; //initialise switch state
switchLastState[i] = false; //initialse last switch state
lastReleaseMillis[i] = millis(); // initialise time switch last released
lastPressMillis[i] = lastPressMillis[i] -1; // initialise time switch last pressed
}
} // end of setup
void loop() {
readButtons();
readExpressionPedal();
displayUpdate();
midiSend();
} // end of loop
/*
* ----------------------------------------
*
* Input related declarations and functions
*
* ----------------------------------------
*/
static const bool switchDown = LOW; // because we are using pullup resistor and switch to GND
static const byte debounceTime = 1000; // after processing a button press, ignore further input for some milliseconds
static const byte debounceDelay = 3; // amount of time to wait before retesting debounceTime
static const int longPressTime = 600; // how long a switch has to be held to count as a long press
static int switchPressedCounter = 0; // how many switches are currently pressed
static byte nextCommand = -1; // most important pending action - the switch that was last pressed, or other command via multi or long press
static byte lastCommand = -1; // last command sent (used for display confirmation)
static unsigned long commandMillis = millis(); // the time that nextCommand was last set - ie the last switch to be pressed
static const byte pagePatchReset = 5*switchCount + 3;
static const byte pageUp = 5*switchCount + 2;
static const byte pageDn = 5*switchCount + 1;
static byte currentPage = 0; // the current page / bank to be displayed
static const byte pageCount =5; // how many pages we have configured
void readButtons() {
switchPressedCounter = 0;
for (int i=0;i<switchCount;i++) {
switchPressed[i] = ( digitalRead(switchPin[i]) == switchDown ); // set array element to true if switch is currently pressed, or false if not
if (switchPressed[i] != switchLastState[i]) { //potential press or release detected
if (switchPressed[i]) { // potential new press detected
if ( millis() > (lastPressMillis[i] + debounceTime) ) { // genuine press and not switch bounce
lastPressMillis[i] = millis();
switchLastState[i] = true;
nextCommand = i;
commandMillis = millis();
}
}
else if (!switchPressed[i]) { //potential switch release detected
if ( millis() > (lastReleaseMillis[i] + debounceTime ) ) { // genuine release and not switch bounce
lastReleaseMillis[i] = millis();
switchLastState[i] = false;
}
}
}
if (switchPressed[i]) {
switchPressedCounter++; //increment counter used to check multiple presses
if ( millis() > (lastPressMillis[i] + longPressTime) ) { // long press detected
lastPressMillis[i] = millis(); // reset timer so it doesn't re-trigger every loop
nextCommand = i + switchCount; // use the next n numbers as a second bank of commands representing long press actions
}
}
}
static bool comboActive = false; // remembers whether multiple presses were detected to avoid re-triggering every loop
if (switchPressedCounter > 1 ) { // multiple presses detected
if (!comboActive) {
comboActive = true;
if ( switchPressed[2] && switchPressed[3]) { // first two switches -> Page Down
nextCommand = pageDn;
changePageDown();
}
else if ( switchPressed[0] && switchPressed[1]) { // second two switches -> Page Up
nextCommand = pageUp;
changePageUp();
}
}
}
else {
comboActive = false; // we can reset this as no more than one switch currently pressed
}
lastCommand = nextCommand;
} // end of read_buttons()
void changePageUp() {
currentPage++;
if (currentPage >= pageCount) { // we have gone past the last page
currentPage = 0; // reset to first page
}
}
void changePageDown() {
currentPage--;
if (currentPage > pageCount) { // we have scrolled back past the first page
currentPage = (pageCount -1); // reset to last page
}
}
/*
*
* Display related functions
*
*/
void invSelection(int i=(lastCommand+1)) {
if (lastCommand == i) {
display.setTextColor(BLACK, WHITE);
}
else {
display.setTextColor(WHITE, BLACK);
}
}
void displayLine(const __FlashStringHelper *str0, const __FlashStringHelper *str1, const __FlashStringHelper *str2, const __FlashStringHelper *str3, int startBtn) {
display.print(F(""));
invSelection(0+startBtn);
display.print(str0);
invSelection();
display.print(F(""));
invSelection(1+startBtn);
display.print(str1);
invSelection();
display.print(F(""));
invSelection(2+startBtn);
display.print(str2);
invSelection();
display.print(F(""));
invSelection(3+startBtn);
display.print(str3);
invSelection();
display.println(F(""));
}
void displayUpdate(void) { // maybe change this to put labels in arrays, but this will do for now
display.clearDisplay();
display.setCursor(0, 0); // Start at top-left corner
switch (currentPage) {
case 0:
displayLine(F(" SV"),F(" 4"),F("--5 "),F(" FTSW"),4);
break;
case 1:
displayLine(F(" SV"),F(" Pv"),F("/Nxt"),F(" PRST"),4);
break;
case 2:
displayLine(F(" SV"),F(" Pv"),F("/Nxt"),F(" SNPS"),4);
break;
case 3:
displayLine(F(" SV"),F(" Pv"),F("/Nxt"),F(" MODE"),4);
break;
case 4:
displayLine(F(" SV"),F(" Tap/"),F(""),F(" Tune"),4);
break;
}
display.display();
}
/*
*
* MIDI output related functions
*
*/
void readExpressionPedal() {
int expressionValue = analogRead(EXPRESSION_PIN);
int midiValue = map(expressionValue, 0, 1023, 0, 127);
MIDI.sendControlChange(1, midiValue, 1);
}
void midiSend() {
// do something
if (nextCommand >=0) {
if (nextCommand == pagePatchReset) { // SW7 & SW8 should reset page and patch to 0 regardless of which page/patch currently active
MIDI.sendProgramChange(0,1);
}
switch(currentPage) {
case 0: // menu page 0 (1 of 5)
switch(nextCommand) {
case 0:
MIDI.sendControlChange(52,1,1); //FS 4
break;
case 1:
MIDI.sendControlChange(53,127,1); //FS 5
break;
} // end of menu page 1
break;
case 1: // menu page 2 (2 of 5)
switch(nextCommand) {
case 0:
MIDI.sendControlChange(72,0,1); //Preset Dwn
break;
case 1:
MIDI.sendControlChange(72,127,1); //Preset Up
break;
} // end of menu page 2
break;
case 2: // menu page 3 (3 of 5)
switch(nextCommand) {
case 0:
MIDI.sendControlChange(69,9,1); //Snap Shot Prev
break;
case 1:
MIDI.sendControlChange(69,8,1); //Snap Shot Nxt
break;
} // end of menu page 3
break;
case 3: // menu page 4 (4 of 5)
switch(nextCommand) {
case 0:
MIDI.sendControlChange(71,4,1); //Mode Prev
break;
case 1:
MIDI.sendControlChange(71,5,1); //Mode Nxt
break;
} // end of menu page 4
break;
case 4: // menu page 5 (5 of 5)
switch(nextCommand) {
case 0:
MIDI.sendControlChange(64,0,1); //Tuner
break;
case 1:
MIDI.sendControlChange(68,127,1); //Tap
break;
} // end of menu page 4
} // end of outer nested switch case
nextCommand = -1; // re-initialise this so we don't send the same message repeatedly
}
} // end midisend