millis() clashing with interrupt

Hello,

I am trying to use a stepper to track a sinusoidal reference. I would like to use t = millis() to calculate the value of a sinusoidal reference r = sin(2pif*t), however it clashes with the interrupts I set up to check the state of my encoder, blocking the operation at seemingly random points. Printing t results therefore in the same value being repeated indefinitely after a short period of the code working.

Here is some context in case it is needed:

I have a system that consists of a 5 V battery pack, a UNO, a ULN2003 drive, a 28BJ-48 stepper and a KY040 rotary encoder. The shaft of the encoder is connected to the one of the motor, so that every revolution of the motor's shaft corresponds to one revolution of the encoder's. The motor then rotates CKW if the current value of r is smaller than the previous value r_old, CCKW if the opposite is true. The value of the encoder y is updated using interrupts every time the state of PIN 3 changes.

The hardware is working, so it is surely a problem of the code and not the wiring, power supply etc. In fact:

  1. When replacing the millis() function by a counter the code works;
  2. When the encoder is not rotating the code works.
    This is why I presume the problem is in the clashing of the encoder interrupt and the millis() function.

Here is my entire code:

 // ================= Declarations =================
#define pi 3.1415926535897932384626433832795  
float t;
float r_old;
float r;

// Encoder
const int PinCLK = 2;           // Encoder CLK (White)
const int PinDT = 3;            // Encoder DT (Brown)
int pos_last = 0;               // Last position
volatile int y = 0;             // Current position

// Motor
int Pin1 = 8;              // Driver pin 1 (Yellow) 
int Pin2 = 9;              // Driver pin 2 (Orange) 
int Pin3 = 10;             // Driver pin 3 (Green) 
int Pin4 = 11;             // Driver pin 4 (Blue)
int v = 2;                     // Motor speed (1 max speed)

// ================= Functions =================

void idle (){
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
}
  
  void CCKW (){
 // 1
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(v);
 // 2
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay (v);
 // 3
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(v);
 // 4
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(v);
 // 5
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(v);
 // 6
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, HIGH);
 delay (v);
 // 7
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(v);
 // 8
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(v);
}

void CKW(){
 // 1
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(v);
 // 2
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay (v);
 // 3
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(v);
 // 4
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(v);
 // 5
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(v);
 // 6
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, HIGH);
 delay (v);
 // 7
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(v);
 // 8
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(v);
}

// Interrupt
void isr ()  {                                                           
  if (digitalRead(PinDT) == LOW)
  {
    y-- ; 
  }
  else {
    y++ ; 
  }
}
// Track: If the current rotary switch position has changed then update everything
void track() {
  noInterrupts () ;
  pos_last = y ;  // read the volatile in a critical section
  interrupts () ;
}  
  // ================= Setup =================

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

  // Encoder
  pinMode(PinCLK,INPUT);
  pinMode(PinDT, INPUT);
  // Motor
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);
  pinMode(Pin3, OUTPUT);
  pinMode(Pin4, OUTPUT);

  // Attach the routine to service the interrupts
  attachInterrupt(digitalPinToInterrupt(PinCLK), isr, LOW);
}

  // ================= Loop =================

void loop() {
    track(); // void function that uses interrupts to check when the 
             // rotary encoder changed position and updates its value if it did
    t = 0.001*millis();
    r_old = r;
    r = 20*sin(0.05*pi*t); 
    Serial.println(t);
    if(r-r_old<0) {
      CKW(); // Turn 1 stepper step clockwise
    }
    if(r-r_old>0) {
      CCKW(); // Turn 1 stepper step counter-clockwise
    }   
    if(r-r_old==0) {
      idle(); // Do not move
    }
}

This is a shorter version including only the (in my opinion) relevant part:

#define pi 3.1415926535897932384626433832795  
float t;
float r_old;
float r;

// Encoder
const int PinCLK = 2;           // Encoder CLK (White)
const int PinDT = 3;            // Encoder DT (Brown)
int pos_last = 0;               // Last position
volatile int y = 0;             // Current position

void idle (){
...
} 
  void CCKW (){
...
}
void CKW(){
...
}

// Interrupt
void isr ()  {                                                           
  if (digitalRead(PinDT) == LOW)
  {
    y-- ; 
  }
  else {
    y++ ; 
  }
}
// Track: If the current rotary switch position has changed then update everything
void track() {
  noInterrupts () ;
  pos_last = y ;  // read the volatile in a critical section
  interrupts () ;
}  
  // ================= Setup =================

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

  // Attach the routine to service the interrupts
  attachInterrupt(digitalPinToInterrupt(PinCLK), isr, LOW);
}

  // ================= Loop =================

void loop() {
    track(); // void function that uses interrupts to check when the 
             // rotary encoder changed position and updates its value if it did
    t = 0.001*millis();
    r_old = r;
    r = 20*sin(0.05*pi*t); 
    Serial.println(t);
    if(r-r_old<0) {
      CKW(); // Turn 1 stepper step clockwise
    }
    if(r-r_old>0) {
      CCKW(); // Turn 1 stepper step counter-clockwise
    }   
    if(r-r_old==0) {
      idle(); // Do not move
    }
}

I have looked at the full code - snippets that don't work are useless.

Please don't use single character variable names as it is impossible to find all instances of them.

It seems strange to be using an interrupt and also using the delay() function.

I suggest you add into your ISR a line that sets a flag when the value chenges - perhaps like this
EDIT -- there is a mistake in this - see Reply #18

void isr ()  {                                                           
  if (digitalRead(PinDT) == LOW)
  {
    newPulse = true;
    y-- ; 
  }
  else {
    y++ ; 
  }
}

and then in change your track() function like this so it does not pause interrupts unnecessarily

void track() {
  if (newPulse == true) {
     noInterrupts () ;
        pos_last = y ;  // read the volatile in a critical section
        newPulse = false;
    interrupts () ;
}

You say "1) When replacing the millis() function by a counter the code works; " but without seeing that version of your program I can't understand why it might make a difference.

I wonder if multiplying by millis() creates a problem as millis() can be an extremely large number. What is the purpose of this code ?

t = 0.001*millis();
r_old = r;
r = 20*sin(0.05*pi*t);

...R

#define pi 3.1415926535897932384626433832795

Seriously? Exactly how much precision / accuracy do you think you get out of a 32-bit float (only float type supported on 8-bit AVR)?

    if(r-r_old==0) {
      idle(); // Do not move
    }

Comparing float values for equality is ill-advised. Better to compare the difference against some acceptably small epsilon.

This is part of Arduino.h . line 46 ff:

#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define EULER 2.718281828459045235360287471352

8.bit Controllers will handle that!

RudolfAtRTC:
8.bit Controllers will handle that!

Of course they'll "handle" it. But, specifying anything beyond 6 or so significant figures is pointless.

Comparing float values for equality is ill-advised.

Ill advised is a bit of an understatement, chances of this statement actually being true are not to big

 if(r-r_old==0) {

This is part of Arduino.h . line 46 ff:

#define PI 3.1415926535897932384626433832795

So there is no real need to define it again using lowercase.

t = 0.001*millis();Sure this will result in the seconds to be displayed with all ms behind the dot.
Could you humor me though, and comment out this line:Serial.println(t);

Thanks everyone for your help. It is really appreciated. I changed my code according to your suggestions, hopefully I did not miss anything or made new mistakes.

Updated complete code:

 // ================= Declarations =================
float timer;
float ref_old;
float ref;
bool newPulse = false;

// Encoder
const int PinCLK = 2;           // Encoder CLK (White)
const int PinDT = 3;            // Encoder DT (Brown)
int pos_last = 0;               // Last position
volatile int pos = 0;             // Current position

// Motor
int Pin1 = 8;              // Driver pin 1 (Yellow) 
int Pin2 = 9;              // Driver pin 2 (Orange) 
int Pin3 = 10;             // Driver pin 3 (Green) 
int Pin4 = 11;             // Driver pin 4 (Blue)
int vel = 2;                     // Motor speed (1 max speed)

// ================= Functions =================

void idle (){
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
}
  
  void CCKW (){
 // 1
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 2
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay (vel);
 // 3
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 4
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 5
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 6
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, HIGH);
 delay (vel);
 // 7
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(vel);
 // 8
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(vel);
}

void CKW(){
 // 1
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 2
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay (vel);
 // 3
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 4
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 5
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 6
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, HIGH);
 delay (vel);
 // 7
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(vel);
 // 8
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(vel);
}

// Interrupt
void isr ()  {                                                           
  if (digitalRead(PinDT) == LOW)
  {
    newPulse = true;
    pos-- ;
  }
  else {
    pos++ ;
  }
}
// Track: If the current rotary switch position has changed then update everything
void track() {
  if (newPulse == true) {
     noInterrupts () ;
        pos_last = pos ;  // read the volatile in a critical section
        newPulse = false;
    interrupts () ;
  }
}  
  // ================= Setup =================

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

  // Encoder
  pinMode(PinCLK,INPUT);
  pinMode(PinDT, INPUT);
  // Motor
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);
  pinMode(Pin3, OUTPUT);
  pinMode(Pin4, OUTPUT);

  // Attach the routine to service the interrupts
  attachInterrupt(digitalPinToInterrupt(PinCLK), isr, LOW);
}

  // ================= Loop =================

void loop() {
    track(); // void function that uses interrupts to check when the 
             // rotary encoder changed position and updates its value if it did
    timer = 0.001*millis();
    ref_old = ref;
    ref  = 20*sin(0.05*PI*timer); 
    if(ref-ref_old<0) {
      CKW(); // Turn 1 stepper step clockwise
    }
    if(ref-ref_old>0) {
      CCKW(); // Turn 1 stepper step counter-clockwise
    }   
    else {
      idle(); // Do not move
    }
}

Unfortunately the problem persists.

Robin2:
I wonder if multiplying by millis() creates a problem as millis() can be an extremely large number. What is the purpose of this code ?

t = 0.001*millis();

r_old = r;
r = 20sin(0.05pi*t);

Sorry if I wasn't clear enough. I am trying to follow my reference r using a stepper. t is needed to determine at what point of r I am right now, so that then the stepper can move accordingly. The stepper will then move based on the difference between the current r and the previous value r_old. I hope it is clear now, if not please let me know.

Robin2:
You say "1) When replacing the millis() function by a counter the code works; " but without seeing that version of your program I can't understand why it might make a difference.

My apologies again for not being clear. Practically, I estimated the time between steps as my sampling time ts, found through trial and error. This snippet then replaces the loop() void. So, instead of using millis() it would approximate the time that has passed using a counter.

    for(i=0;i<8051;i=i+1) { // Iterate through array 
    track(); // void function that uses interrupts to check when the 
             // rotary encoder changed position and updates its value if it did
    timer = i*ts;
    ref_old = ref;
    r = 20*sin(0.05*PI*timer);         
    Serial.println(pos_last);
    if(ref_old-ref<0) {
      CKW(); // Turn 1 stepper step clockwise
    }
    if(ref_old-ref>0) {
      CCKW(); // Turn 1 stepper step counter-clockwise
    }   
    else {
      idle(); // Do not move
    }  
  }

Have not seen the full code so just a guess here but this might be of interest

attachInterrupt()

Note
Inside the attached function, delay() won’t work and the value returned by millis() will not increment. Serial data received while in the function may be lost. You should declare as volatile any variables that you modify within the attached function. See the section on ISRs below for more information.

If you want to know more, attachInterrupt()

void isr ()  {                                                           
  if (digitalRead(PinDT) == LOW)
  {
    newPulse = true; // if it is going to be set only if pos is decreased it will anyway only work in 1 direction
    pos-- ;
  }
  else {
    pos++ ;
  }
}

Follow the instructions given in post number 1 to begin to resolve your issue.

Idahowalker:
Follow the instructions given in post number 1 to begin to resolve your issue.

Maybe I am missing something, but that's exactly what I did in my updated code, no?

Deva_Rishi:

void isr ()  {                                                           

if (digitalRead(PinDT) == LOW)
 {
   newPulse = true; // if it is going to be set only if pos is decreased it will anyway only work in 1 direction
   pos-- ;
 }
 else {
   pos++ ;
 }
}

I don't understand what you are trying to say. Is this wrong? It was suggested by Robin2.

Oi! Sorry my error.

I am curious.

else {
    pos++ ;
  }

When do you expect that to happen?

Remember the "attachInterrupt(digitalPinToInterrupt(PinCLK), isr, LOW);", with the keyword being LOW?

When you fix those things repost your entire code. Your code is kind of doing the task switching thing and not seeing what could be going on when is complicated without all the code. Also, if your anything like me, when working on one problem, I find changes in other places, I want to make, whiles waiting for an answer to a posted question, right?

Idahowalker:
When do you expect that to happen?

When the encoder moves clockwise, right? I found the code of the encoder on this forum actually and it works really well.

Here is a TLDR for clarity:

There exists two codes, one working, and one not. The one that is working replaces the t = millis() function, with a for loop counter.

Code without millis() function - WORKING:

 // ================= Declarations =================
float timer;
float ref_old;
float ref;
bool newPulse = false;
int i = 0;                 // Counter
float ts = 1/80.5;           // Sampling period

// Encoder
const int PinCLK = 2;           // Encoder CLK (White)
const int PinDT = 3;            // Encoder DT (Brown)
int pos_last = 0;               // Last position
volatile int pos = 0;             // Current position

// Motor
int Pin1 = 8;              // Driver pin 1 (Yellow) 
int Pin2 = 9;              // Driver pin 2 (Orange) 
int Pin3 = 10;             // Driver pin 3 (Green) 
int Pin4 = 11;             // Driver pin 4 (Blue)
int vel = 2;               // Motor speed (1 max speed)

// ================= Functions =================

void idle (){
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
}
  
  void CCKW (){
 // 1
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 2
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay (vel);
 // 3
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 4
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 5
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 6
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, HIGH);
 delay (vel);
 // 7
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(vel);
 // 8
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(vel);
}

void CKW(){
 // 1
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 2
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay (vel);
 // 3
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 4
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 5
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 6
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, HIGH);
 delay (vel);
 // 7
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(vel);
 // 8
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(vel);
}

// Interrupt
void isr ()  {
  static unsigned long t_interrupt_last = 0;
  unsigned long t_interrupt = millis();
    // If interrupts come faster than 5ms, assume it's a bounce and ignore
  if (t_interrupt - t_interrupt_last > 5) {                                                           
    if (digitalRead(PinDT) == LOW)
    {
      newPulse = true;
      pos-- ;
    }
    else {
      pos++ ;
    }
  }
  // Keep track of when we were here last (no more than every 5ms)
  t_interrupt_last = t_interrupt;
}
// Track: If the current rotary switch position has changed then update everything
void track() {
  if (newPulse == true) {
     noInterrupts() ;
        pos_last = pos ;  // read the volatile in a critical section
        newPulse = false;
    interrupts() ;
  }
}  
  // ================= Setup =================

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

  // Encoder
  pinMode(PinCLK,INPUT);
  pinMode(PinDT, INPUT);
  // Motor
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);
  pinMode(Pin3, OUTPUT);
  pinMode(Pin4, OUTPUT);

  // Attach the routine to service the interrupts
  attachInterrupt(digitalPinToInterrupt(PinCLK), isr, LOW);

     for(i=0;i<8051;i=i+1) { // Iterate through array 
    track(); // void function that uses interrupts to check when the 
             // rotary encoder changed position and updates its value if it did
    timer = i*ts;
    ref_old = ref;
    ref = 20*sin(0.05*PI*timer);         
    Serial.println(pos_last);
    if(ref_old-ref<0) {
      CKW(); // Turn 1 stepper step clockwise
    }
    if(ref_old-ref>0) {
      CCKW(); // Turn 1 stepper step counter-clockwise
    }   
    else {
      idle(); // Do not move
    }  
  }
}

  // ================= Loop =================

void loop() {

The original code with the millis() function, now updated again to limit the sensor's debounce, is still not working. My goal is to get this to work. I will post this in the next message due to the character limit.

Why use LOW for your interrupt condition?

How long does the signal spend at LOW?

UPDATED code using millis() - NOT WORKING:

 // ================= Declarations =================
float timer;
float ref_old;
float ref;
bool newPulse = false;

// Encoder
const int PinCLK = 2;           // Encoder CLK (White)
const int PinDT = 3;            // Encoder DT (Brown)
int pos_last = 0;               // Last position
volatile int pos = 0;             // Current position

// Motor
int Pin1 = 8;              // Driver pin 1 (Yellow) 
int Pin2 = 9;              // Driver pin 2 (Orange) 
int Pin3 = 10;             // Driver pin 3 (Green) 
int Pin4 = 11;             // Driver pin 4 (Blue)
int vel = 2;                     // Motor speed (1 max speed)

// ================= Functions =================

void idle (){
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
}
  
  void CCKW (){
 // 1
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 2
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay (vel);
 // 3
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 4
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 5
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, LOW);
 delay(vel);
 // 6
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin4, HIGH);
 delay (vel);
 // 7
 digitalWrite(Pin1, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(vel);
 // 8
 digitalWrite(Pin1, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin4, HIGH);
 delay(vel);
}

void CKW(){
 // 1
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 2
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay (vel);
 // 3
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 4
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, HIGH);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 5
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, LOW);
 delay(vel);
 // 6
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, HIGH);
 digitalWrite(Pin1, HIGH);
 delay (vel);
 // 7
 digitalWrite(Pin4, LOW);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(vel);
 // 8
 digitalWrite(Pin4, HIGH);
 digitalWrite(Pin3, LOW);
 digitalWrite(Pin2, LOW);
 digitalWrite(Pin1, HIGH);
 delay(vel);
}

// Interrupt
void isr ()  {
  static unsigned long t_interrupt_last = 0;
  unsigned long t_interrupt = millis();
    // If interrupts come faster than 5ms, assume it's a bounce and ignore
  if (t_interrupt - t_interrupt_last > 5) {                                                           
    if (digitalRead(PinDT) == LOW)
    {
      newPulse = true;
      pos-- ;
    }
    else {
      pos++ ;
    }
  }
  // Keep track of when we were here last (no more than every 5ms)
  t_interrupt_last = t_interrupt;
}
// Track: If the current rotary switch position has changed then update everything
void track() {
  if (newPulse == true) {
     noInterrupts () ;
        pos_last = pos ;  // read the volatile in a critical section
        newPulse = false;
    interrupts () ;
  }
}  
  // ================= Setup =================

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

  // Encoder
  pinMode(PinCLK,INPUT);
  pinMode(PinDT, INPUT);
  // Motor
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);
  pinMode(Pin3, OUTPUT);
  pinMode(Pin4, OUTPUT);

  // Attach the routine to service the interrupts
  attachInterrupt(digitalPinToInterrupt(PinCLK), isr, LOW);
}

  // ================= Loop =================

void loop() {
    track(); // void function that uses interrupts to check when the 
             // rotary encoder changed position and updates its value if it did
    timer = 0.001*millis();
    ref_old = ref;
    ref  = 20*sin(0.05*PI*timer); 
    if(ref-ref_old<0) {
      CKW(); // Turn 1 stepper step clockwise
    }
    if(ref-ref_old>0) {
      CCKW(); // Turn 1 stepper step counter-clockwise
    }   
    else {
      idle(); // Do not move
    }
}

TheMemberFormerlyKnownAsAWOL:
How long does the signal spend at LOW?

The servo is slow with a much smaller resolution compared to the encoder. I tried to measure it and it looks like the state is low between encoder steps, thus when the encoder is in the middle of a step. This could last about 0.5 s.

TheMemberFormerlyKnownAsAWOL:
Why use LOW for your interrupt condition?

Honest answer: That's what I found here on the forum. It should be FALLING right?

EDIT: By using the FALLING condition the operation does not stop! Hurray! However there is a catch: the encoder position data is wrong. I will research how to code for encoders using the FALLING (or RISING or CHANGING) condition, but if anyone has some suggestions or a good reference I would highly appreciate it

bohared:
Maybe I am missing something, but that's exactly what I did in my updated code, no?
I don't understand what you are trying to say. Is this wrong? It was suggested by Robin2.

Sorry. Just realised I have a mistake in the code in Reply #1 - it should be

void isr ()  {
  newPulse = true;                                                     
  if (digitalRead(PinDT) == LOW)
  {
    y-- ; 
  }
  else {
    y++ ; 
  }
}

And I'm pretty sure your ISR should be FALLING rather than LOW

...R

newPulse should be volatile.