encoders and for loops

good evening
It is my first message here and I hope to help within what my knowledge allows me
I am trying to program 5 encoders in an arduino uno, using a for loop to better manage and reduce the code
I have two other for loops programmed with 16 buttons each and they work perfect for me, but in this case, I am not able to make it work
Could someone guide me a bit?
a greeting

#include <EnableInterrupt.h>
#include<MIDI.h>


const int numberofencoders = 5;
const int cccustom[numberofencoders] = {12 , 13 , 14 , 15 , 16};
int counter[numberofencoders] = {0};
int Astate[numberofencoders] = {0};
int PrevAstate[numberofencoders] = {0};
const int outputA[numberofencoders] = {13 , 11 , 9 , 14 , 16};
const int outputB[numberofencoders] = {12 , 10 , 8 , 15 , 17};

void setup() {
  Serial.begin(9600);
  pinMode(13 , INPUT_PULLUP);
  pinMode(12 , INPUT_PULLUP);
  pinMode(11 , INPUT_PULLUP);
  pinMode(10 , INPUT_PULLUP);
  pinMode(9 , INPUT_PULLUP);
  pinMode(8 , INPUT_PULLUP);
  pinMode(14 , INPUT_PULLUP);
  pinMode(15 , INPUT_PULLUP);
  pinMode(16 , INPUT_PULLUP);
  pinMode(17 , INPUT_PULLUP);
  enableInterrupt(outputA[numberofencoders] , encoder , CHANGE);
  enableInterrupt(outputB[numberofencoders] , encoder , CHANGE);


}

void loop(){}


void encoder(){
for (int i = 0 ; i <numberofencoders ; i++)
{
  
 Astate[i] = digitalRead(outputA[i]);
  if (Astate[i] != PrevAstate[i])
  { if (digitalRead(outputB[i]) != Astate[i])
    { counter[i]++;
      if (counter[i] > 127)
      {
        counter[i] = 127;
      }
    }
    else
    { counter[i]--;
      if (counter[i] < 0)
      {
        counter[i] = 0;
      }
    }
    MIDI.sendControlChange( cccustom[i], counter[i] , 2);
          Serial.println(counter[i]);

   }

      Astate[i] = PrevAstate[i];

}

}

Thanks for using code tags. What exactly happens or doesn't happen? Can you describe the problem?

Shouldn't

  }

      Astate[i] = PrevAstate[i];

be

      Astate[i] = PrevAstate[i];
  }

???

i suggest first making things work for a single encoder, but do it in a way that treats the encoder as an object, not as multiple arrays of things

consider.
assume you see how encoder [] can be expanded


struct Encoder_s {
    byte    pinClk;
    byte    pinDat;
    byte    state;
    byte    cnt;
};

Encoder_s encoder [] = {
    { A1, A2 }
};

#define N_ENC    (sizeof(encoder)/sizeof(Encoder_s))

bool
encChg (
    Encoder_s *e)
{
    byte clk = digitalRead (e->pinClk);
    byte dat = digitalRead (e->pinDat);
    byte st  = clk << 1 | dat;
    
    if (e->state == st)
        return 0;

#define DAT_BIT     1
    if (DAT_BIT == (e->state ^ st))
        e->cnt += (clk ^ dat) ?  1 : -1;
    else
        e->cnt += (clk ^ dat) ? -1 :  1;

    e->state = st;

    return true;
}

void
encInit (
    Encoder_s *e)
{
    pinMode (e->pinClk, INPUT_PULLUP);
    pinMode (e->pinDat, INPUT_PULLUP);

    e->state = digitalRead (e->pinClk) << 1 | digitalRead (e->pinDat);
}

// -----------------------------------------------------------------------------
void loop (void)
{
    if (encChg (& encoder [0]))
        Serial.println (encoder [0].cnt);
}

void setup (void)
{
    Serial.begin (9600);

    Encoder_s  *e = & encoder [0];
    for (unsigned n = 0; n < N_ENC; n++, e++)
        encInit (e);
}

You missed a trick here:

  pinMode(13 , INPUT_PULLUP);
  pinMode(12 , INPUT_PULLUP);
  pinMode(11 , INPUT_PULLUP);
  pinMode(10 , INPUT_PULLUP);
  pinMode(9 , INPUT_PULLUP);
  pinMode(8 , INPUT_PULLUP);
  pinMode(14 , INPUT_PULLUP);
  pinMode(15 , INPUT_PULLUP);
  pinMode(16 , INPUT_PULLUP);
  pinMode(17 , INPUT_PULLUP);

can be:

for (int i = 0 ; i <numberofencoders ; i++) {
  pinMode(outputA[i], INPUT_PULLUP);
  pinMode(outputB[i], INPUT_PULLUP);
}

However, this:

  enableInterrupt(outputA[numberofencoders] , encoder , CHANGE);
  enableInterrupt(outputB[numberofencoders] , encoder , CHANGE);

isn't valid. You are accessing index 5 of those arrays, and the indexes only go up to 4.

Perhaps you wanted to enable interrupts on all 10 pins? Uno only has 2 interrupt pins (2 & 3). EDIT: Ah, I see you are using a library that automatically uses pin change interrupts. So try this:

for (int i = 0 ; i <numberofencoders ; i++) {
  pinMode(outputA[i], INPUT_PULLUP);
  pinMode(outputB[i], INPUT_PULLUP);
  enableInterrupt(outputA[i] , encoder , CHANGE);
  enableInterrupt(outputB[i] , encoder , CHANGE);
}

thank you all for answering
I tell you, that same structure works with a single encoder, in the serial port I receive the perfect information and send the midi message that I want, the problem has been when using the for loop, I do not receive any information through the serial port, I was making some changes and only value 0 or 127 and it does not stop sending data when I only want it to send data when I am moving it, that's why I am so lost, surely it is a simple thing
as soon as I get home I try some things that you have told me and I will tell you
Thanks again for the help !!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.