stuck in loop

I have 8 inputs thru a shift register (4021) the shift in part works fine. I only want to send out a midi control change if the contact inputs have changed from the previous state, but it continues to send midi CC. Stuck in a loop. can anyone make some suggestions. here is the code

#include <MIDI.h>

// ******************************************
// Variables definitions
// ******************************************
  int volume;
  byte stage;
// *********************
// Buttons Multiplexing Variables
// Definition of pins
int buttonsMuxClockPin = 7;
int buttonsMuxLatchPin = 8;
int buttonsMuxDataPin = 9;

// Define variables to hold the data 
// for each shift register.
byte muxexpression1;

// Midi channel where to send notes for each mux
int MidiChannel1 = 1;

// *********************
// Set up application
// *********************
void setup() {
 // Standard serial begin
 // Serial.begin(9600);
 // Midi serial begin
 Serial.begin(31250); 

 // Buttons Mux
 // Define pin modes
 pinMode(buttonsMuxLatchPin, OUTPUT);
 pinMode(buttonsMuxClockPin, OUTPUT); 
 pinMode(buttonsMuxDataPin, INPUT);
}

// ******************************************
// Main Loop
// ******************************************
void loop() {
 // Butons Mux
 // Function that handles digital mux for buttons
 startReadingButtonMux();

 
}

// ******************************************
// Buttons Mux
// ******************************************
// Activate Digital Mux for Buttons
void startReadingButtonMux() {
 //  Pulse the latch pin:
 //  Set it to 1 to collect parallel data
 digitalWrite(buttonsMuxLatchPin, HIGH);
 // .... collecting data from digital inputs of MUX ... wait ...
 delayMicroseconds(20);
 // Set it to 0 to transmit data serially  
 digitalWrite(buttonsMuxLatchPin, LOW);

 // While the shift register is in serial mode
 //collect each shift register into a byte
 //the register attached to the chip comes in first 
 muxexpression1 = shiftIn(buttonsMuxDataPin, buttonsMuxClockPin);

analyzeexpressionMux(muxexpression1, MidiChannel1);
}

// ShiftIn function
// Just needs the location of the data pin and the clock pin
// it returns a byte with each bit in the byte corresponding
// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
byte shiftIn(int myDataPin, int myClockPin) { 
 int i;
 int temp = 0;
  // int pinState;
 byte myDataIn = 0;

 pinMode(myClockPin, OUTPUT);
 pinMode(myDataPin, INPUT);

 // we will be holding the clock pin high 8 times (0,..,7) at the
 // end of each time through the for loop

 // at the begining of each loop when we set the clock low, it will
 // be doing the necessary low to high drop to cause the shift
 // register's DataPin to change state based on the value
 // of the next bit in its serial information flow.
 // The register transmits the information about the pins from pin 7 to pin 0
 // so that is why our function counts down
 
 // Loop for all the pins of the shift reg.
 for (i=7; i>=0; i--)
 {
   digitalWrite(myClockPin, LOW);
   delayMicroseconds(2);
   temp = digitalRead(myDataPin);
   if (temp) {
     // pinState = 1;
     // Set the bit to 1 no matter what
     myDataIn = myDataIn | (1 << i);
   }
   else {
     //turn it off -- only necessary for debuging
     //print statement since myDataIn starts as 0
     // pinState = 0;
   }

digitalWrite(myClockPin, HIGH);
 }
 //debuging print statements whitespace
 //Serial.println();
 //Serial.println(myDataIn, BIN);
 return myDataIn;
}

void analyzeexpressionMux(byte muxexpression1,  int midiChannel) {
    
  if (stage != muxexpression1){    //only send midi if input has changed
      
    switch (muxexpression1){
    
      case B00000000:
        volume = 20 ;
        break;
      case B00000001:
        volume = 33 ;
        break;
      case B00000011:
        volume = 46 ;
        break;
      case B00000111:
        volume = 59 ;
        break;
      case B00001111:
        volume = 72 ;
        break;
      case B00011111:
        volume = 85 ;
        break;
      case B00111111:
        volume = 98 ;
        break;
      case B01111111:
        volume = 111 ;
        break;
      case B11111111:
        volume = 127 ;
        break;
      default:
      stage = muxexpression1;
    }
                                             
      sendMidi(CC , volume, 7, midiChannel);
      stage = muxexpression1;                    //set current stage
      
      }
      else{                                      //input the same as before then do nothing
        if(stage == muxexpression1){
        
        }
      }
  }   



    
//void controlChange(byte channel, byte controller, byte value)


// ******************************************
// MIDI Functions
// ******************************************
// Send a MIDI note-on/off message.  
void sendMidi(char cmd, char data1, char data2, int midiChannel) {
 // Based on midi library
 MIDI.send(cmd, data1, data2, midiChannel);
}
void analyzeexpressionMux(byte muxexpression1,  int midiChannel) {
  int volume;
  byte stage;

the definition of 'stage' should be outside the definition of analyzeexpressionMux so that it is a global variable and so persists from one calling of the function to the next. As it stands you are not remembering the previous value of muxexpression1 because 'stage' is being reset every time.

Thanks Grumpy

I modified the existing code and updated it above. I get the same result. When I power up , no midi is sent but as soon as i change the input it sends the midi over and over again.

I have tried so many combinations and nothing seems to work. I used if statements to begin with but that didn't work so I decided to try the switch case.

do I have to add "byte stage" to the following when it is a global variable?

void analyzeexpressionMux(byte muxexpression1,  int midiChannel) {
    
  if (stage != muxexpression1){    //only send midi if input has changed
      
    switch (muxexpression1){
    
      case B00000000:
        volume = 20 ;
        break;

do I have to add "byte stage" to the following when it is a global variable?

No if you do you get a different variable and you will not retain the values each time round the loop.

I have tried so many combinations and nothing seems to work.

Yes but the great thing about programming errors is that it is your fault and you are doing something wrong. I say this to my self when ever I get stuck.

What I do is to strip the code down to the minimum. Here I would strip off all the MIDI stuff and just have the pin 13 led change state when you press the button. That way your mistake is in a much smaller haystack.

If something does not work for you, don't just try other combination try and simplify it even further until something works and then add bits one at a time. Also use the print statement to see what values variables are at.

It might not be solving your problem but in learning to solve your own problems you will be a better programmer.

I moved the if statement from inside the definition "analyzeexpressionMux" to after it calls analyzeexpressionMux and this fixed my problem. unfortuneatly I am not set up with in-circuit debugging. I use a parallel programmer one of these days I will get set up to do better programming.

Thanks

some interesting code, would anyone have a set of code that does midi for arduino, and already has incorperated for multiplexers, and or shift registers?

jemtone