Midi Footcontroller switch problem

When I say in the code

//go and play note

What this means is insert the code that actually plays the note. The comment itself will do nothing.

Also I did not say :-

if (a>0 & !notePlaying) // someone pressed a button!

but

if (a>0 && !notePlaying) // someone pressed a button!

The readButtons(int pin) function does both the reading of the button AND the playing of the note so there is no way the notePlaying variable can stop the production of the note.

You seem to only play two notes that on button 2 and 5.In the playNote function you need to add more notes.
I have not got your hardware but this at least compiles and makes a stab of doing it correctly.

// Example 25.3

#define DEBUG
int a=0;
boolean notePlaying;
void setup()
{
 // lcd.begin(20, 4);
 Serial.begin(31250);
 
  pinMode(A5, INPUT_PULLUP); // sets analog pin for input

}

int readButtons(int pin)
// returns the button number pressed, or zero for none pressed
// int pin is the analog pin number to read
{
  int b,c = 0;
  c=analogRead(pin); // get the analog value 
  if (c>1000)
  {
    b=0;
    // buttons have not been pressed
  }   
else
  if (c>440 && c<470)
  {
    b=1;
    // button 1 pressed
  }     
  else
    if (c<400 && c>370)
    {
      b=2;
      
      // button 2 pressed
    }       
    else
      if (c>280 && c<310)
      {
        b=3; // button 3 pressed
      }         
      else
        if (c>150 && c<180)
        {
          b=4; // button 4 pressed
        }           
        else
          if (c<20)
          {
            b=5;
          }
return b;
}

void playNote(int button){ 
switch(button){
  // add the other case statements for the other buttons.
  case 0:
    midiCc(1, 80, 0);
    midiCc(1, 81, 0);
    break;
  case 2:
      midiCc(1, 81, 127);
      break;
  case 5:
      midiCc(1, 80, 127);
      break;     
  }
}

void loop()
{
  a=readButtons(5);
  //lcd.clear();
  if (a==0 && notePlaying){
    playNote(0); // turn off the note
    notePlaying = false;
  }    
else
    if (a>0 && !notePlaying) // someone pressed a button!
    {
      notePlaying = true; // indicate the note is playing
      playNote(a); //go and play note
    }
}

void midiCc(int channel, int command, int value) {
  Serial.write(175 + channel);
  Serial.write(command);
  Serial.write(value);
}

Thanks Mike,

This is a great learning curve, the TX led is on all the time now and when i press a switch, the unit gives an error message midi buffer full.

Hi,

For some reason when i swap the true or false statements around it brings on the effect and the midi transmit led only goes on when a button is pressed but wont switch off the effect.

// Example 25.3

//define DEBUG
int a=0;
boolean notePlaying;
void setup()
{
 // lcd.begin(20, 4);
 Serial.begin(31250);
 
  pinMode(A5, INPUT_PULLUP); // sets analog pin for input

}

int readButtons(int pin)
// returns the button number pressed, or zero for none pressed
// int pin is the analog pin number to read
{
  int b,c = 0;
  c=analogRead(pin); // get the analog value
  if (c>699)
  {
    b=0;
    // buttons have not been pressed
  }   
else
  if (c>440 && c<470)
  {
    b=1;
    // button 1 pressed
  }     
  else
    if (c<400 && c>370)
    {
      b=2;
     
      // button 2 pressed
    }       
    else
      if (c>280 && c<310)
      {
        b=3; // button 3 pressed
      }         
      else
        if (c>150 && c<180)
        {
          b=4; // button 4 pressed
        }           
        else
          if (c<20)
          {
            b=5;
          }
return b;
}

void playNote(int button){
switch(button){
  // add the other case statements for the other buttons.
  case 0:
    midiCc(1, 80, 0);
    midiCc(1, 81, 0);
    midiCc(1, 82, 0);
    midiCc(1, 83, 0);
    midiCc(1, 84, 0);
    break;
  case 1:
      midiCc(1, 81, 127);
      break;
  case 2:
      midiCc(1, 82, 127);
      break;
  case 3:
      midiCc(1, 83, 127);
      break;
  case 4:
      midiCc(1, 84, 127);
      break;
 
  }
}

void loop()
{
  a=readButtons(5);
  //lcd.clear();
  if (a==0 && notePlaying){
    playNote(0); // turn off the note
    notePlaying = true;
    
  }   
else
    if (a>0 && !notePlaying) // someone pressed a button!
    {
      notePlaying = false; // indicate the note is playing
      playNote(a); //go and play note
    }
}

void midiCc(int channel, int command, int value) {
  Serial.write(175 + channel);
  Serial.write(command);
  Serial.write(value);
}

Hi,

Its working perfectly now, dont know what was going on.

Cheers Mike,

Thanks Again.

Hi,

I am trying to do the same concept over two analog pins instead of one with 2 switches into each analog pin A1 and A5, but it wont compile.

What am i doing wrong here?

// Analog Switch Buttons

#define DEBUG
int a=0;
boolean notePlaying;


void setup()
{
 // lcd.begin(20, 4);
 Serial.begin(31250);
 
  pinMode(A5, INPUT); // sets analog pin for input
  pinMode(A1, INPUT);
}

int readButtons(int pin)
// returns the button number pressed, or zero for none pressed
// int pin is the analog pin number to read
{
  int b,c = 0;
  c=analogRead(pin); // get the analog value
  if (c>0 && c<50)
  {
    b=0;
    // buttons have not been pressed
  }   
else
  if (c>500 && c<580)
  {
    b=1;
    // button 1 pressed
  }     
  else
    if (c<600 && c>640)
    {
      b=2;
     
      // button 2 pressed
    }       
    else
      if (c>400 && c<550)
      {
        b=3; // button 3 pressed
      }         
    
return b;
}

void playNote(int button){
switch(button){
  // add the other case statements for the other buttons.
  case 0:
    midiCc(1, 80, 0);
    midiCc(1, 84, 0);
    break;
  case 1:
      midiCc(1, 80, 127);
      break;
  case 2:
      midiCc(1, 84, 127);
      break;
  case 3:
      midiCc(1, 80, 127);
      midiCc(1, 84, 127);
      break;

}
}


void playNote(int button2){
switch(button2){
  // add the other case statements for the other buttons.
  case 0:
    midiCc(1, 80, 0);
    midiCc(1, 81, 0);
    break;
  case 1:
      midiCc(1, 81, 127);
      break;
  case 2:
      midiCc(1, 82, 127);
      break;
  case 3:
      midiCc(1, 81, 127);
      midiCc(1, 82, 127);
      break;

}

}
void loop()
{
  a=readButtons(5);
  //lcd.clear();
  if (a==0 && notePlaying){
    playNote(0); // turn off the note
    notePlaying = false;
    
  }   
else
    if (a>0 && !notePlaying) // someone pressed a button!
    {
      notePlaying = true; // indicate the note is playing
      playNote(a); //go and play note
    }

    
     a=readButtons(1);
  //lcd.clear();
  if (a==0 && notePlaying){
    playNote(0); // turn off the note
    notePlaying = false;
    
  }   
else
    if (a>0 && !notePlaying) // someone pressed a button!
    {
      notePlaying = true; // indicate the note is playing
      playNote(a); //go and play note
    }
}

void midiCc(int channel, int command, int value) {
  Serial.write(175 + channel);
  Serial.write(command);
  Serial.write(value);
}

What am i doing wrong here?

You have two functions with the same name. So when the compiler sees the second defination of a function called playNote it throws a wobbler.
Each function must have a unique name.

Cool Mike thanks!!,

Just for cleaning up the code is it possible to read both pins A1 and A5 in the void loop.

void loop()
{
  a=readButtons(5);
  //lcd.clear();
  if (a==0 && notePlaying){
    playNote(0); // turn off the note
    notePlaying = false;
    
  }   
else
    if (a>0 && !notePlaying) // someone pressed a button!
    {
      notePlaying = true; // indicate the note is playing
      playNote(a); //go and play note
    }

    
     a=readButtons(1);
  //lcd.clear();
  if (a==0 && notePlaying){
    playNote(0); // turn off the note
    notePlaying = false;
    
  }   
else
    if (a>0 && !notePlaying) // someone pressed a button!
    {
      notePlaying = true; // indicate the note is playing
      playNote(a); //go and play note
    }
}

to something like a=readButtons(1&5);

No each analogue input must be put into a variable one at a time. If you use the same variable one after the other then you are just throwing the first variable away.

Hi,

This is all working fine until i press 2 buttons together then it does nothing what i want it to do is when one button is pressed then the second button is pressed it activates switch three and sends 2 cc messages, it is picking up an analog reading for switch 3 (when the 2 buttons are pressed together) but not sending the message is there a boolean for making this work?

// Example 25.3

//define DEBUG
int a=0;
boolean notePlaying;
boolean notePlaying1;
void setup()
{
 // lcd.begin(20, 4);
 Serial.begin(31250);
 
  pinMode(A5, INPUT); // sets analog pin for input

}

int readButtons(int pin)
// returns the button number pressed, or zero for none pressed
// int pin is the analog pin number to read
{
  int b,c = 0;
  c=analogRead(5); // get the analog value
  if (c<50)
  {
    b=0;
    // buttons have not been pressed
  }   
else
  if (c>500 && c<550)
  {
    b=1;
    // button 1 pressed
  }     
  else
    if (c>180 && c<200)
    {
      b=2;
     
      // button 2 pressed
    }       
    else
      if (c>555 && c<580)
      {
        b=3; // button 3 pressed
      }         
   
          
return b;
}

int readButtons1(int pin1)
// returns the button number pressed, or zero for none pressed
// int pin is the analog pin number to read
{
  int b,c = 0;
  c=analogRead(pin1); // get the analog value
  if (c<50)
  {
    b=0;
    // buttons have not been pressed
  }   
else
  if (c>500 && c<550)
  {
    b=1;
    // button 1 pressed
  }     
  else
    if (c>180 && c<200)
    {
      b=2;
     
      // button 2 pressed
    }       
    else
      if (c>555 && c<580)
      {
        b=3; // button 3 pressed
      }         
   
          
return b;
}
void playNote(int button){
switch(button){
  // add the other case statements for the other buttons.
  case 0:
    midiCc(1, 80, 0);
    midiCc(1, 82, 0);
    midiCc(1, 83, 0);
    break;
  case 1:
      midiCc(1, 80, 127);
      break;
  case 2:
      midiCc(1, 82, 127);
      break;
  case 3:
      midiCc(1, 80, 127);
      midiCc(1, 82, 127);
      break;

  }
}
void playNote1(int button1){
switch(button1){
  // add the other case statements for the other buttons.
  case 0:
    midiCc(1, 81, 0);
    midiCc(1, 84, 0);

    break;
  case 1:
      midiCc(1, 81, 127);
      break;
  case 2:
      midiCc(1, 84, 127);
      break;
  case 3:
      midiCc(1, 81, 127);
      midiCc(1, 84, 127);
      break;

  }
}
void loop()
{
  a=readButtons(5);
  //lcd.clear();
  if (a==0 && notePlaying){
    playNote(0); // turn off the note
    notePlaying = false;
    
  }   
else
    if (a>0 && !notePlaying) // someone pressed a button!
    {
      notePlaying = true; // indicate the note is playing
      playNote(a); //go and play note
    }

    
     a=readButtons1(4);
  //lcd.clear();
  if (a==0 && notePlaying1){
    playNote1(0); // turn off the note
    notePlaying1 = false;
    
  }   
else
    if (a>0 && !notePlaying1) // someone pressed a button!
    {
      notePlaying1 = true; // indicate the note is playing
      playNote1(a); //go and play note
    }
  delay(100);  
}


void midiCc(int channel, int command, int value) {
  Serial.write(175 + channel);
  Serial.write(command);
  Serial.write(value);
}

This is all working fine until i press 2 buttons together then it does nothing

Using an analogue input for several buttons has the disadvantage of not working when two are pressed at the same time.
Depending on how it is wired up it could be used to detect two at once but most are not designed to do this.

There is nothing you can do in software to make it work.

Cheers Mike,

I thought doing it this way would have its limitations alright, i have included the circuit that i used just to see if the switches can detect whats going on.

The arrangement you need to detect simultaneously key presses is called a weighted ladder or an R2R ladder.

Hi,

I decided to get a mega so it would be able to cope with the extra switches, all external switches work fine except two of the internal switches wont work, the max bank is reading 63 instead of 15 and it wont let you select any other number also the midi channel is also stuck on 63 and wont select any other midi channel.so no midi is being sent, i think it has something to do with the memory, when i run the software on the nano omitting the extra switches it works perfectly.Also on the mega the bank up goes up to 631 instead of 15, i have included the sketch any help would be great.

constants.h (1.09 KB)

LCDisplay.cpp (1.26 KB)

LCDisplay.h (756 Bytes)

midfoot4buttons_mega_ino.ino (26.3 KB)

Storage.cpp (5.17 KB)

Storage.h (1.24 KB)

It seams to be acting the same way as the teensy 3.1.

After experimenting with the storage.cpp it still acts the same wont let the user change midi channel through the lcd, and has the same midi channel number as the the maximum bank number.

Is there a way to override the midi channel user select in the internal menu with code.

Hi,

I have included the midi.h and MIDI_CREATE_DEFAULT_INSTANCE();now i am getting midi to transmit to the device. change program channels are working and switches are sending midi cc messages, however it will still not let me send any midi messages from the internal menu and the lcd is displaying 12 banks as apposed to 63. i still think its something to do with storage. cpp. or the mega is faulty.

Can anyone help please.

Solved

I tried a different IDE.

All working perfectly now.

In the interest of learning, i am trying to put another switch that works of the lcd menu with a button press with the 2 existing switches.
I copied all the entry's in the sketch of switch 1 and changed them to switch 3, inorder to make the switch state on or off for switch 3 it needs to work independently.
I have narrowed the code down to the section (bool StorageClass::readS3State(int patchno))
the section with the bit_fld toggles the on and off( i think). But i dont know what the (return (EEPROM.read(Offset(patchno) + 3) & 0x1) == 0x1) is and how it works.

Would someone be kind enough to explain this, and what the new entry's for the switch should be.

i have tried changing the entry's to see how they work.but cant get it working.

// Memory stucture:
// byte 0 -> init marker
// byte 1 -> midi channel
// byte 2 -> maximum bank
// byte 4/5 -> PDL1 min
// byte 6/7 -> PDL1 max
// byte 8/9 -> PDL2 min
// byte 10/11 -> PDL2 max
// byte 12 -> Performance mode
// from byte 16 and further
// Each patch, 16 bytes long:
// 0 : ProgChangeNo
// 1 : S1 CC
// 2 : S2 CC
// 3 : S1/S2 state and vol->wah (bitwise)
// 4..15: 12-character name
// 16 : S3 CC
// 17 : S3 State
// 

#include "Storage.h"
#include "constants.h"

void StorageClass::init()
{
  if (EEPROM.read(0) != 127)
  {
    EEPROM.write(0,127);
   // for (int i = 0; i < 4024; i++)
    // EEPROM.write(i, 0);

    writeChannel(1);
    writeMaxBank(12);

    writePatchName(0, "JMP1");
    writePatchName(1, "CleanChorus");
    writePatchName(2, "Clean");
    writePatchName(3, "Lead");
    writePatchName(4, "JMP1");
    writePatchName(5, "CleanCh");
    writePatchName(6, "Cry");
    writePatchName(7, "Luke");
    writePatchName(8, "JMP1!");
    writePatchName(9, "Clubclean");
    writePatchName(10, "Country");
    writePatchName(11, "CountryTS");

	for (int i = 0; i < 63; i++)
	{
		writeS1CC(i, 50);
		writeS2CC(i, 17);
                writeS3CC(i, 90);
	}	
	for (int i = 0; i < 4; i++)
	{
		writeS1State(i, true);
	
	writeS2W2VState(6, true);
}
    writeS3State(2, true);
    
  }
}

int StorageClass::Offset(int patchno)
{
  return (patchno * 16) + 16;
}

byte StorageClass::readChannel()
{
  EEPROM.read(1);
}
void StorageClass::writeChannel(byte channel)
{
  EEPROM.write(1, channel);
}
byte StorageClass::readMaxBank()
{
  EEPROM.read(2);
}
void StorageClass::writeMaxBank(byte maxbank)
{
  // 63 programs max
  maxbank = min(byte(63 / banksize), maxbank);
  EEPROM.write(2, maxbank);
}
String StorageClass::readPatchName(int patchno)
{
  // start in EEPROM from position 16, max = 1007 => 63 patches max!
  // Each patch, 16 bytes long:
  // 0 : ProgChangeNo (not used)
  // 1 : S1 CC
  // 2 : S2 CC
  // 3 : S1/S2 state and vol->wah (bitwise)
  // 4..15: 12-character name
  char buf[13];
  for (int i = 0; i < 12; i++)
	  buf[i] = EEPROM.read(Offset(patchno) + i + 4);
  buf[12] = 0;

  return String(buf);
}
void StorageClass::writePatchName(int patchno, char *patchname)
{
  int len = strlen(patchname);
  for (int i = 0; i < 12; i++)
  {  
    if (i < len)
		EEPROM.write(Offset(patchno) + i + 4, patchname[i]);
    else
		EEPROM.write(Offset(patchno) + i + 4, ' ');
  }
}

byte StorageClass::readS1CC(int patchno)
{
	return EEPROM.read(Offset(patchno) + 1);
}
void StorageClass::writeS1CC(int patchno, byte CC)
{
	EEPROM.write(Offset(patchno) + 1, CC);
}
  byte StorageClass::readS2CC(int patchno)
{
	return EEPROM.read(Offset(patchno) + 2);
}
void StorageClass::writeS2CC(int patchno, byte CC)
{
	EEPROM.write(Offset(patchno) + 2, CC);
}
byte StorageClass::readS3CC(int patchno)
{
	return EEPROM.read(Offset(patchno) + 3);
}
void StorageClass::writeS3CC(int patchno, byte CC)
{
	EEPROM.write(Offset(patchno) + 3, CC);
}
bool StorageClass::readS1State(int patchno)
{
	// 3 : S1/S2 state and vol->wah (bitwise)
	return (EEPROM.read(Offset(patchno) + 3) & 0x1) == 0x1;
}
void StorageClass::writeS1State(int patchno, bool state)
{
	byte bit_fld = EEPROM.read(Offset(patchno) + 3);
  	if (state)
		bit_fld |= 1 << 0;
	else
		bit_fld &= ~(1 << 0);
	EEPROM.write(Offset(patchno) + 3, bit_fld);
}
bool StorageClass::readS2State(int patchno)
{
	return (EEPROM.read(Offset(patchno) + 3) & 0x2) == 0x2;
}
void StorageClass::writeS2State(int patchno, bool state)
{
	byte bit_fld = EEPROM.read(Offset(patchno) + 3);
	if (state)
		bit_fld |= 1 << 1;
	else
		bit_fld &= ~(1 << 1);
	EEPROM.write(Offset(patchno) + 3, bit_fld);
}
  bool StorageClass::readS2W2VState(int patchno)
{
	return (EEPROM.read(Offset(patchno) + 3) & 0x4) == 0x4;
}
void StorageClass::writeS2W2VState(int patchno, bool state)
{
	byte bit_fld = EEPROM.read(Offset(patchno) + 3);
	if (state)
		bit_fld |= 1 << 2;
	else
		bit_fld &= ~(1 << 2);
	EEPROM.write(Offset(patchno) + 3, bit_fld);
}

void StorageClass::writePDL1Min(int Value)
{
    EEPROM.write(4,highByte(Value));
    EEPROM.write(5,lowByte(Value));
}

int StorageClass::readPDL1Min()
{
    return word(EEPROM.read(4),EEPROM.read(5));
}

void StorageClass::writePDL1Max(int Value)
{
    EEPROM.write(6,highByte(Value));
    EEPROM.write(7,lowByte(Value));
}

int StorageClass::readPDL1Max()
{
    return word(EEPROM.read(6),EEPROM.read(7));
}

  void StorageClass::writePDL2Min(int Value)
{
    EEPROM.write(8,highByte(Value));
    EEPROM.write(9,lowByte(Value));
}

int StorageClass::readPDL2Min()
{
    return word(EEPROM.read(8),EEPROM.read(9));
}

void StorageClass::writePDL2Max(int Value)
{
    EEPROM.write(10,highByte(Value));
    EEPROM.write(11,lowByte(Value));
}

int StorageClass::readPDL2Max()
{
    return word(EEPROM.read(10),EEPROM.read(11));
}

byte StorageClass::readPrgChg(int patchno)
{
  // start in EEPROM from position 16, max = 1007 => 63 patches max!
  // Each patch, 16 bytes long:
  // 0 : ProgChangeNo (not used)
  // 1 : S1 CC
  // 2 : S2 CC
  // 3 : S1/S2 state and vol->wah (bitwise)
  // 4..15: 12-character name
  return EEPROM.read(Offset(patchno));
}
void StorageClass::writePrgChg(int patchno, byte PrgChg)
{
    EEPROM.write(Offset(patchno), PrgChg);
}

void StorageClass::ResetProgramMap()
{
    for(int i = 0; i < 63; i++)
      writePrgChg(i, i);
}

void StorageClass::writePerfMode(boolean Value)
{
    EEPROM.write(12,Value ? 1 : 0);
}

boolean StorageClass::readPerfMode()
{
    return EEPROM.read(12) == 1;
}



bool StorageClass::readS3State(int patchno)
{
	// 3 : S1/S2 state and vol->wah (bitwise)
	return (EEPROM.read(Offset(patchno) + 3) & 0x1) == 0x1;
}
void StorageClass::writeS3State(int patchno, bool state)
{
	byte bit_fld = EEPROM.read(Offset(patchno) + 3);
  	if (state)
		bit_fld |= 1 << 0;
	else
		bit_fld &= ~(1 << 0);
	EEPROM.write(Offset(patchno) + 3, bit_fld);
}

Got It working through trial and error, but would love to know how and why it works.