Interrupts how is work MY POINT OF VIEW

helo again, i have a question considering INTERRUPTS. my logic is the following.

if you have 5 or 10 leds that are light up in series 1,2,3,4,5 and again 1,2,3,4,5 and so on
or anything other sensor motor e,tc

and you Triger un interrupt in the code, from what i read, that interrupt will pause all the code and excecated the code that is inside the interrupt.

so my logic is that if for examble we light up leds in series 1,2,3,4,5 1,2,3,4,5 and the interrupt was triger when the led 1,2 are lit, then the led 3,4,5 will not light, untill the interrupt stops.

am i correct???

It depends on the processor, but on an Arduino yes that is the behaviour.
You should not however that interupts are triggered all the time, and in most cases you would not notice.

yes arduino uno is what i am using

so from what i understand, if you Triger interrupt led say with a sensor, as long the sensor is sending a signal the code will be paused, and when it stop, in few milliseconds the code will run again.

Things vary slightly, but once an interupt is triggered it does not continue, it is an almost instantaneous event. The longest part is often processing the interupt in the ISR, but in most cases this is microseconds not milliseconds.

For example, the trigger might be on the rising edge of an electronic signal from a sensor, and the processing might involve just setting a boolean flag. Later in the processing loop a check of the boolean will result in code being executed that reads the sensor.

Depends on how you write the code.
You should detect a change of the sensor output, not a state of the sensor.
Then an interrupt chould be microseconds, not milliseconds.
A human can't detect that.
Leo..

tl;dr: don't use interrupts. Yet.

Using interrupts before understanding everything everyone has said here will only get you in trouble.

Using interrupts before making a serious attempt to accomplish your goal(s) without them will only get you in trouble.

Interrupts have their place. For beginners, latching on to interrupts as a nifty solution almost always gets them into trouble.

Stay out of trouble! It already looks like you have something in mind, why not tell us about that, show us the progress you've made and where you are stuck, and get some advices?

It is possible interrupts are appropriate in your circumstances. I'd place the odds at 1 in 3937.

a7

i try to learn how thinks work, and how i can continue and finalize my project, with lot of reading and playing with the codes i manage to make a code to send midi from pins A2 -A3 it work SUPER fine if i upload it to Arduino alone.

problem is when i adopt my code to the big code (second code i post) is not working good, is working only when encoder turn CW and very rare when encoder turn CCW.

so i assume that some how with interrupt i i will pause the big code and all MCU power will go to read my enoder, when encoder stop working code will run again.

if i manage this i will add one more encoder on PINS A4 - A5 . and code finish..

i need to mension that traktorino code is not mine, i didnt write it, i try to modify it, and i have never know how to write codes, but is fun,, with out to know the slitest think i am in a good way

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
#include <Encoder.h>

Encoder browserEnc(A2, A3);
long positionBrowser  = -10;

void setup() {
  Serial.begin(115200); //31250

  MIDI.begin(MIDI_CHANNEL_OMNI);
}
void readBrowserEnc() {

  int newpositionBrowser = browserEnc.read();
  int BrowserVal = map(newpositionBrowser, -1023, 1023, -255, 255);
  int BrowserValue;

  if (BrowserVal != positionBrowser) {

    if ((BrowserVal - positionBrowser) > 0) {
      BrowserValue = 127;
    }
    else {
      BrowserValue = 1;
    }
    //Serial.println(newPosition);
    MIDI.sendControlChange(15, BrowserValue, 1);
    positionBrowser = BrowserVal;
  }
}
void loop() {
  MIDI.read();
  //  readButtons();
  readBrowserEnc();
  //  readLoopLEnc();
  //  readLoopREnc();
  //  readPots();
}
/* Traktorino

   The Traktorino is a low-cost DIY MIDI controller for DJs, based in the Arduino platform. 
   It can control any software that accepts MIDI, like Traktor, Serato, or even Ableton Live. 
   The Traktorino is completely open-source, which means you can download the code and all the schematics, so you can make one yourself! 
   And if you want to build this controller, you can buy the kit from us, this way, you will be helping more projects like this to happen! 

   http://www.musiconerd.com/shop >> buy a Traktorino kit
   http://www.musiconerd.com/traktorino >> learn more about the Traktorino
   http://github.com/silveirago/traktorino >> Download the traktorino files
   gustavosilveira@musiconerd.com >> Send me a message if you have any doubt
 
*/

/////////////////////////////////////////////
// PWM bit shifter
// You can choose the latch pin yourself.
const int ShiftPWM_latchPin = 8;

// ** uncomment this part to NOT use the SPI port and change the pin numbers. This is 2.5x slower **
#define SHIFTPWM_NOSPI
const int ShiftPWM_dataPin = 11;
const int ShiftPWM_clockPin = 12; 

// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false;

// You can enable the option below to shift the PWM phase of each shift register by 8 compared to the previous.
// This will slightly increase the interrupt load, but will prevent all PWM signals from becoming high at the same time.
// This will be a bit easier on your power supply, because the current peaks are distributed.
const bool ShiftPWM_balanceLoad = false;

/////////////////////////////////////////////
// LIBRARIES
#include <ShiftPWM.h>  // Bit shifter library >> https://github.com/elcojacobs/ShiftPWM - include ShiftPWM.h after setting the pins!
// If using with ATmega328 - Uno, Mega, Nano...
#include <MIDI.h> // MIDI library (by Forty Seven Effects) >> https://github.com/FortySevenEffects/arduino_midi_library/releases/tag/4.3.1
MIDI_CREATE_DEFAULT_INSTANCE();
#include <Multiplexer4067.h> // Multiplexer CD4067 library >> https://github.com/sumotoy/Multiplexer4067
#include <Thread.h> // Threads library (by Ivan seidel) >> https://github.com/ivanseidel/ArduinoThread
#include <ThreadController.h> 
#include <Encoder.h> // Encoder library >> https://github.com/PaulStoffregen/Encoder


/////////////////////////////////////////////
// buttons
const byte muxNButtons = 13; // *coloque aqui o numero de entradas digitais utilizadas no multiplexer
const byte NButtons = 1; // *coloque aqui o numero de entradas digitais utilizadas
const byte totalButtons = muxNButtons + NButtons;
const byte muxButtonPin[muxNButtons] = {0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14, 15}; // *neste array coloque na ordem desejada os pinos das portas digitais utilizadas
const byte buttonPin[NButtons] = {9}; // *neste array coloque na ordem desejada os pinos das portas digitais utilizadas
int buttonCState[totalButtons] = {0}; // estado atual da porta digital
int buttonPState[totalButtons] = {0}; // estado previo da porta digital

/////////////////////////////////////////////
// debounce
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 5;    // the debounce time; increase if the output flickers

/////////////////////////////////////////////
// potentiometers
const byte NPots = 14; // *coloque aqui o numero de entradas analogicas utilizadas
const byte muxPotPin[NPots] = {0, 1,}; // *neste array coloque na ordem desejada os pinos das portas analogicas, ou mux channel, utilizadas
int potCState[NPots] = {0}; // estado atual da porta analogica
int potPState[NPots] = {0}; // estado previo da porta analogica
int potVar = 0; // variacao entre o valor do estado previo e o atual da porta analogica
int lastCcValue[NPots] = {0};

/////////////////////////////////////////////
// pot reading
int TIMEOUT = 50; //quantidade de tempo em que o potenciometro sera lido apos ultrapassar o varThreshold
byte varThreshold = 8; //threshold para a variacao no sinal do potenciometro
boolean potMoving = true; // se o potenciometro esta se movendo
unsigned long pTime[NPots] = {0}; // tempo armazenado anteriormente
unsigned long timer[NPots] = {0}; // armazena o tempo que passou desde que o timer foi zerado

/////////////////////////////////////////////
// encoder
Encoder myEnc(3, 2);
Encoder browserEnc(A2, A3);
long oldPosition  = -10;
long positionBrowser  = -999;
/////////////////////////////////////////////
// midi
byte midiCh = 1; // *Canal midi a ser utilizado
byte note = 36; // *Nota mais grave que sera utilizada
byte cc = 1; // *CC mais baixo que sera utilizado

int ccLastValue = 0;

/////////////////////////////////////////////
// Leds
const byte ledNum = 24; // total number of leds used
unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
unsigned int numRegisters = 3;
unsigned int numOutputs = numRegisters * 8;
unsigned int numRGBLeds = numRegisters * 8 / 3;
unsigned int fadingMode = 0; //start with all LED's off.

unsigned int VuL[7] = {1, 2, 3, 4, 5, 6, 7}; // VU left pins
unsigned int VuR[7] = {15, 14, 13, 12, 11, 10, 9}; // VU righ pins
unsigned int buttonsLedL[5] = {20, 19, 18, 17, 16};
unsigned int buttonsLedR[5] = {8, 0, 23, 22, 21};

unsigned int red = 180;
unsigned int green = 255;
unsigned int blue = 10;
unsigned int yellow = 100;

byte ledOnOffPin = 10; //On Off pin

/////////////////////////////////////////////
// Multiplexer
Multiplexer4067 mplexPots = Multiplexer4067(4, 5, 6, 7, A0);
Multiplexer4067 mplexButtons = Multiplexer4067(4, 5, 6, 7, A1);

/////////////////////////////////////////////
// threads - programa cada atividade do Arduino para acontecer em um determinado tempo
ThreadController cpu; //thread master, onde as outras vao ser adicionadas
Thread threadReadPots; // thread para controlar os pots
Thread threadReadButtons; // thread para controlar os botoes

/////////////////////////////////////////////
void setup() {

  Serial.begin(115200); // 115200 for hairless - 31250 for MOCO lufa
  
  MIDI.turnThruOff();
  //MIDI.begin(MIDI_CHANNEL_OMNI);
  /////////////////////////////////////////////
  // Midi in
  MIDI.setHandleControlChange(handleControlChange);
  MIDI.setHandleNoteOn(handleNoteOn);
  MIDI.setHandleNoteOff(handleNoteOff);

  /////////////////////////////////////////////
  // Multiplexers
  mplexPots.begin(); // inicializa o multiplexer
  mplexButtons.begin(); // inicializa o multiplexer
  pinMode(A1, INPUT_PULLUP); // Buttons need input pull up
  
  
  /////////////////////////////////////////////
  // buttons on Arduino Digital pins
  for (int i = 0; i < NButtons; i++) { // buttons on Digital pin
    pinMode(buttonPin[i], INPUT_PULLUP);
  }
  
  /////////////////////////////////////////////
  // Leds
  //  leds.setBitCount(ledNum); // Mux Leds
  //  leds.setPins(clockPin, dataPin, latchPin);
  pinMode(ledOnOffPin, OUTPUT);

  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);
  ShiftPWM.SetAll(0);
  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);
  // SetPinGrouping allows flexibility in LED setup.
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  ShiftPWM.SetPinGrouping(1); //This is the default, but I added here to demonstrate how to use the funtion
  ShiftPWM.Start(pwmFrequency, maxBrightness);

  /////////////////////////////////////////////
  // threads
  // pots
  threadReadPots.setInterval(10);
  threadReadPots.onRun(readPots);
  cpu.add(&threadReadPots);
  // buttons
  threadReadButtons.setInterval(20);
  threadReadButtons.onRun(readButtons);
  cpu.add(&threadReadButtons);

  /////////////////////////////////////////////
  //leds
  analogWrite(ledOnOffPin, 255); // on/off led

//  for (int i = 0; i < ledNum; i++) { // writeBit works just like digitalWrite
//    ShiftPWM.SetOne(i, LOW);
//  }

}

void loop() {
  
  
  cpu.run();
  MIDI.read();
  readEncoder();
  readBrowserEnc();
//

}

/////////////////////////////////////////////
// read buttons

void readButtons() {

  for (int i = 0; i < muxNButtons; i++) { //reads buttons on mux
    int buttonReading = mplexButtons.readChannel(muxButtonPin[i]);
    //buttonCState[i] = map(mplex.readChannel(muxButtonPin[i]), 22, 1023, 0, 2); // stores on buttonCState
    if (buttonReading > 100) {
      buttonCState[i] = HIGH;
    }
    else {
      buttonCState[i] = LOW;
    }
    //Serial.print(buttonCState[i]); Serial.print("   ");
  }
  //Serial.println();

  for (int i = 0; i < NButtons; i++) { //read buttons on Arduino
    buttonCState[i + muxNButtons] = digitalRead(buttonPin[i]); // stores in the rest of buttonCState
  }

  for (int i = 0; i < totalButtons; i++) {

    if ((millis() - lastDebounceTime) > debounceDelay) {

      if (buttonCState[i] != buttonPState[i]) {
        lastDebounceTime = millis();

        if (buttonCState[i] == LOW) {
          //          noteOn(potMidiCh(), note + i, 127);  // Channel 0, middle C, normal velocity
          //          MidiUSB.flush();
          MIDI.sendNoteOn(note + i, 127, midiCh); // envia NoteOn(nota, velocity, canal midi)
          //Serial.print("Note: "); Serial.print(note + i); Serial.println(" On");
          buttonPState[i] = buttonCState[i];
        }
        else {
          //          noteOn(potMidiCh(), note + i, 0);  // Channel 0, middle C, normal velocity
          //          MidiUSB.flush();
          MIDI.sendNoteOn(note + i, 0, midiCh);
          //Serial.print("Note: "); Serial.print(note + i); Serial.println(" Off");
          buttonPState[i] = buttonCState[i];
        }
      }
    }

  }

}

////////////////////////////////////////////
//read potentiometers

void readPots() {

  for (int i = 0; i < NPots; i++) { // le todas entradas analogicas utilizadas, menos a dedicada a troca do canal midi
    potCState[i] = mplexPots.readChannel(muxPotPin[i]);
  }

  for (int i = 0; i < NPots; i++) {

    potVar = abs(potCState[i] - potPState[i]); // calcula a variacao da porta analogica

    if (potVar >= varThreshold) {  //sets a threshold for the variance in the pot state, if it varies more than x it sends the cc message
      pTime[i] = millis(); // armazena o tempo previo
    }
    timer[i] = millis() - pTime[i]; // reseta o timer
    if (timer[i] < TIMEOUT) { // se o timer for menor que o tempo maximo permitido significa que o potenciometro ainda esta se movendo
      potMoving = true;
    }
    else {
      potMoving = false;
    }

    if (potMoving == true) { // se o potenciometro ainda esta se movendo, mande o control change
      int ccValue = map(potCState[i], 0, 1023, 0, 127);
      if (lastCcValue[i] != ccValue) {
        //        controlChange(11, cc + i, ccValue); // manda control change (channel, CC, value)
        //        MidiUSB.flush();
        MIDI.sendControlChange(cc + i, map(potCState[i], 0, 1023, 0, 127), 11); // envia Control Change (numero do CC, valor do CC, canal midi)
        //Serial.print("CC: "); Serial.print(cc + i); Serial.print(" value:"); Serial.println(map(potCState[i], 0, 1023, 0, 127));
        potPState[i] = potCState[i]; // armazena a leitura atual do potenciometro para comparar com a proxima
        lastCcValue[i] = ccValue;
      }
    }
  }

}

////////////////////////////////////////////
//// read encoder
void readEncoder () {

  int newPosition = myEnc.read();
  int encoderVal = map(newPosition, -1024, 1024, -256, 256);
  int encoderValue;

  if (encoderVal != oldPosition) {

    if ((encoderVal - oldPosition) > 0) {
      encoderValue = 127;
    }
    else {
      encoderValue = 1;
    }

    MIDI.sendControlChange(14, encoderValue, 1);

    oldPosition = encoderVal;
  }

}
void readBrowserEnc() {

  int newpositionBrowser = browserEnc.read();
  int BrowserVal = map(newpositionBrowser, -1023, 1023, -255, 255);
  int BrowserValue;

  if (BrowserVal != positionBrowser) {

    if ((BrowserVal - positionBrowser) > 0) {
      BrowserValue = 127;
     
    }
    else {
      BrowserValue = 1;
    }
    //Serial.println(newPosition);
    MIDI.sendControlChange(15, BrowserValue, 1);
    delay(10);
    positionBrowser = BrowserVal;
  }
}

////////////////////////////////////////////
// led feedback
void handleControlChange(byte channel, byte number, byte value) {

  //handleControlChange

  //int value_ = round(map(value, 0, 127, 0, 7));
  int value_ = value;

  if (value_ != ccLastValue) {

    // Left VU
    if (number == 12) {

      switch (value_) {
        case 0:
          for (int i = 0; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          break;
        case 1:
          for (int i = 1; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          ShiftPWM.SetOne(VuL[0], green);
          break;
        case 2:
          for (int i = 2; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          for (int i = 0; i < 2; i++) {
            ShiftPWM.SetOne(VuL[i], green);
          }
          break;
        case 3:
          for (int i = 3; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          for (int i = 0; i < 3; i++) {
            ShiftPWM.SetOne(VuL[i], green);
          }
          break;
        case 4:
          for (int i = 4; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          for (int i = 0; i < 4; i++) {
            ShiftPWM.SetOne(VuL[i], green);
          }
          break;
        case 5:
          for (int i = 5; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          for (int i = 0; i < 5; i++) {
            ShiftPWM.SetOne(VuL[i], green);
          }
          break;
        case 6:
          for (int i = 6; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          for (int i = 0; i < 5; i++) {
            ShiftPWM.SetOne(VuL[i], green);
          }
          ShiftPWM.SetOne(VuL[5], yellow);
          break;
        case 7:
          for (int i = 6; i < 7; i++) {
            ShiftPWM.SetOne(VuL[i], LOW);
          }
          for (int i = 0; i < 5; i++) {
            ShiftPWM.SetOne(VuL[i], green);
          }
          ShiftPWM.SetOne(VuL[5], yellow);
          ShiftPWM.SetOne(VuL[6], red);
          break;
      }
    }

    // Right VU
    if (number == 13) {

      switch (value_) {
        case 0:
          for (int i = 0; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          break;
        case 1:
          for (int i = 1; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          ShiftPWM.SetOne(VuR[0], green);
          break;
        case 2:
          for (int i = 2; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          for (int i = 0; i < 2; i++) {
            ShiftPWM.SetOne(VuR[i], green);
          }
          break;
        case 3:
          for (int i = 3; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          for (int i = 0; i < 3; i++) {
            ShiftPWM.SetOne(VuR[i], green);
          }
          break;
        case 4:
          for (int i = 4; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          for (int i = 0; i < 4; i++) {
            ShiftPWM.SetOne(VuR[i], green);
          }
          break;
        case 5:
          for (int i = 5; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          for (int i = 0; i < 5; i++) {
            ShiftPWM.SetOne(VuR[i], green);
          }
          break;
        case 6:
          for (int i = 6; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          for (int i = 0; i < 5; i++) {
            ShiftPWM.SetOne(VuR[i], green);
          }
          ShiftPWM.SetOne(VuR[5], yellow);
          break;
        case 7:
          for (int i = 6; i < 7; i++) {
            ShiftPWM.SetOne(VuR[i], LOW);
          }
          for (int i = 0; i < 5; i++) {
            ShiftPWM.SetOne(VuR[i], green);
          }
          ShiftPWM.SetOne(VuR[5], yellow);
          ShiftPWM.SetOne(VuR[6], red);
          break;
      }
    }
    ccLastValue = value;
  }

}

void handleNoteOn(byte channel, byte number, byte value)
{

  switch (number) {
    // Left buttons
    case 40: //sync
      ShiftPWM.SetOne(buttonsLedL[0], blue);
      break;
    case 39: //cue
      ShiftPWM.SetOne(buttonsLedL[1], blue);
      break;
    case 38: //play
      ShiftPWM.SetOne(buttonsLedL[2], blue);
      break;
    case 37: //phones
      ShiftPWM.SetOne(buttonsLedL[3], blue);
      break;
    case 36: //filter on
      ShiftPWM.SetOne(buttonsLedL[4], blue);
      break;

    // Righ buttons
    case 44: //sync
      ShiftPWM.SetOne(buttonsLedR[0], blue);
      break;
    case 45: //cue
      ShiftPWM.SetOne(buttonsLedR[1], blue);
      break;
    case 46: //play
      ShiftPWM.SetOne(buttonsLedR[2], blue);
      break;
    case 47: //phones
      ShiftPWM.SetOne(buttonsLedR[3], blue);
      break;
    case 48: //filter on
      ShiftPWM.SetOne(buttonsLedR[4], blue);
      break;
  }

}

void handleNoteOff(byte channel, byte number, byte value) {

  switch (number) {
    // Left buttons
    case 40: //sync
      ShiftPWM.SetOne(buttonsLedL[0], LOW);
      break;
    case 39: //cue
      ShiftPWM.SetOne(buttonsLedL[1], LOW);
      break;
    case 38: //play
      ShiftPWM.SetOne(buttonsLedL[2], LOW);
      break;
    case 37: //phones
      ShiftPWM.SetOne(buttonsLedL[3], LOW);
      break;
    case 36: //filter on
      ShiftPWM.SetOne(buttonsLedL[4], LOW);
      break;

    // Righ buttons
    case 44: //sync
      ShiftPWM.SetOne(buttonsLedR[0], LOW);
      break;
    case 45: //cue
      ShiftPWM.SetOne(buttonsLedR[1], LOW);
      break;
    case 46: //play
      ShiftPWM.SetOne(buttonsLedR[2], LOW);
      break;
    case 47: //phones
      ShiftPWM.SetOne(buttonsLedR[3], LOW);
      break;
    case 48: //filter on
      ShiftPWM.SetOne(buttonsLedR[4], LOW);
      break;
  }

}

/*
  buttons midi order
  40 44 - sync
  39 45 - cue
  38 46 - play
  37 47 - phones
  36 48 - filter

     VU order
  7 9
  6 10
  5 11
  4 12
  3 13
  2 14
  1 15

*/

Before I go blind reading the second program you have supplied (thanks for both!), is it correct to say

You have a small program that works well as is, one encoder and so forth, but you are having trouble adding a second encoder that will be doing something else.

I ask because “when i adopt my code to the big code” doesn’t clearly specify what your goal is.

Back up another step and describe the entire device you are working on.

BTW interrupts are often used with rotary encoders. Some would claim they just can’t work reliably otherwise, my experience is different. I have used them without involving interrupts. But you have the encoder library, so you really don’t need to know much about how it works, only about how to exploit its features.

a7

Volatile

the main program, have one encoder only, i need 2 more encoders, those 2 new encoders will be jog wheel for traktor dj softwear. so the one encoder need to send midi lets say ch1 cc15 and the other will send lets say ch1 cc16 or what ever.. i will map the midi notes inside the TRAKTOR DJ SOFTWEAR ,

thats why i am trying to add 2 more encoders

Your interrupt should not take more than a few microseconds to complete. If it takes as long as a millisecond (1000 microseconds) you are doing something very wrong.

If done correctly, there will be no delay at all in lighting the 3, 4, and 5 LEDs.

OK. So now you should start showing us all the code that doesn’t work when you try to have a few encoders.

Something complete, that compiles and fails to do what you want, which you must very careful,y describe. What do you want it to do, and what is it doing or not doing.

Not this and I want to add that… we want to see your best current effort at doing.

a7

tomorrow, i have 12 hours reading and playing with codes today..
i will do my best to show what is happening, have in mind i am totally nobody in coding :slight_smile:

Well enjoy being young while you can. The only thing I can do for 12 hours in one day is sleep.

Or nap. :wink:

a7

am all most 50 maid :slight_smile:

My interrupt rule of thumb.
(Not a hard rule but it's kept me out of trouble).

Do as little as possible in the ISR.
Set a global flag then exit the ISR.
Process the flag in loop().

continuing my project after long time, i think i may find the way to make my encoders to work.
but i am stuck, and you maybe give some help.

when i turn the encoder i want to send midi notes, but from what i read encoders need interrupt, and Arduino Uno have only 1 pin that it uses interrupt.

the way i think to make it work is to use software interrupt, so every 500mil to go and check if there is any changes in the encoder. if the encoder moves then interrupt stop the code execute the encoder work sending midi notes and if encoder stop moving continuous the code.

so in my code below think to add int flag =0

now problem come, what code to add in the ( void readLoopLEnc() )
so when the encoder move int flag to be 1 ( int flag =1) and if flag is 1 to stop all and go to the void loop and reading the encoder.

#include <TimerOne.h>
#include <MIDI.h>
#include <Encoder.h>
int flag =0;
MIDI_CREATE_DEFAULT_INSTANCE();


Encoder LoopLEnc(A3, A4);
long positionLoopL = -100;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  MIDI.setHandleControlChange(readLoopLEnc);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);
  Timer1.initialize(500);
  Timer1.attachInterrupt(readLoopLEnc);
}

void loop() {

  MIDI.read();

}
void readLoopLEnc() {

  int newpositionLoopL = LoopLEnc.read();
  int LoopLVal = map(newpositionLoopL, -1023, 1023, -256, 256);
  int LoopLValue;
  if (LoopLVal != positionLoopL) {

    if ((LoopLVal - positionLoopL) > 0) {
      LoopLValue = 127;
    }
    else {
      LoopLValue = 1;
    }
    //Serial.println(newPosition);
    MIDI.sendControlChange(15, LoopLValue, 1);
    positionLoopL = LoopLVal;
  }
}

The UNO has TWO external interrupt pins: 2 and 3.

It also has "Pin Change Interrupts" that can be enabled on most pins. That feature is NOT part of the built-in libraries so you would typically use a third-party library to use those.

Checking inputs frequently is called "poling". Every 500 milliseconds is WAY too slow. That is two samples per second. You need to check about twice as fast as you expect the signals to change. How many steps per revolution do your encoders have? How fast do you expect to turn the encoders? A 400-step encoder turning at 60 RPM is 400 steps per second. You should check the inputs at least 800 times a second. That's not much more than 1 millisecond between samples.

encoder will be used as a jog wheel, by my hand and not all the time, it may pass minutes before i use it again. can tell that most of time, will be a half turn, or maybe a 2 complete rounds. that's why because i dont need it all the time i said every half a second to be creaked is fine.
i don't know how many steps my encoder have is encoder that it comes within Arduino uno kit.
i count that is 20 clicks per round

You still need to check it frequently, unless you want very bad response to whenever you do turn it.

So it needs to be polled, always, or at least whenever you are in the (a) mode where it is allowed to be used.

Somewhat less frequently perhaps than 1000 times a second, as it is just turned by hand. I doubt you need it to response to being fully rotated 360 in one second, so work backwards from the number of pulses per second you would like to recognize and try polling at 4x thy frequency.

A little experimentation will go a long way. 100 per second polling might be OK &c. All depends on how you want it to feel, and whether it is important to count the number of “clicks” accurately or just being able to move a value up or down.

Set up an isolated experiment and play with it.

L8R: wokwi is not a good place to experiment with rotary encoder polling! But I got out some garden rotary encoders from an abandoned project, it looks here like 1000 Hz (1 millisecond) polling is necessary for smooth monotonic response. 500 works but you can turn a knob fast enough so it is unsatisfying response.

I can see why ppl steer us to interrupts, a good case can be made for that approach. I generally prefer to avoid interrupts. I have polling code that came from somewhere before I made it my own that works well. I have no trouble giving it the proper frequent attention needed.

As always YMMV.

a7