Arduino interrupt not working as id like

okay so in my code i have a function called drawarea() that's moves two servos motor holding a Lazer pointer to draw and area.
i have also a lcd menu in this project and an encoder.
what i am experiencing: when the drawarea() function is running if i try and activate my interrupt function doencoder() by rotating the encoder nothing happens and the drawarea() function keeps running.
what i expect to happen: when the drawarea() function is active and i am rotating the encoder i will exit the drawarea function and will go to the doencoder() function.
this is my full code :

#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Wire.h>
#include <Servo.h>
// all the servo stuff intelazing 
Servo x_servo;  
Servo y_servo;
int min_x = 40;
int max_x = 95;
int min_y = 106;//was 115 
int max_y = 180;//was 180
int area=0;
int Play=0;
int min_freeze = 200;
int max_freeze = 3000;
float minimal_movement = 5;
int random_delay;
float x_position = min_x + (max_x - min_x)/2;
float y_position = min_y + (max_y - min_y)/2; 
float x_old_position = x_position;
float y_old_position = y_position;
float x_new_position;
float y_new_position;
float x_speed;
float y_speed;
int movement_time;
// all the servo stuff intelazing 
//all screen stuff
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET     4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//all screen stuff
// Define pins for the encoder
const int encoderPinA = 2;
const int encoderPinB = 3;
const int buttonPin =4 ;
const int lazser= 7;
//define pins
//menu stuff
int menuIndex = 0;
int minValue = 0;
int maxValue = 180;
int* menuItemValues[] = {&min_x, &max_x, &min_y, &max_y, &area, &Play};
//menu stuff
//rotarty stuff
volatile int valRotary, lastValRotary, encoder0Pos;
//rotarty stuff
void setup() {
  y_servo.attach(10);  // attaches the y servo on pin 10 to the servo object
  x_servo.attach(9); 
  y_servo.write(y_position); 
  x_servo.write(x_position);
  delay(1000);
  Serial.begin(9600);
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(lazser,OUTPUT);
  digitalWrite(lazser, HIGH);
  attachInterrupt(0, doEncoder, CHANGE);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);//init lcd
  display.setTextSize(2);//init lcd
  display.setTextColor(WHITE);//init lcd
  display.display();
 }

void loop() {
  displayMenu();
  MenuLogic();
}
void MenuLogic() {
    if (valRotary != lastValRotary) {
        if (menuIndex == 4 || menuIndex == 5) {
            *menuItemValues[menuIndex] = (valRotary > lastValRotary) ? 1 : 0;
        } else {
            *menuItemValues[menuIndex] += valRotary - lastValRotary;
            *menuItemValues[menuIndex] = constrain(*menuItemValues[menuIndex], minValue, maxValue);
        }

        displayMenu();
    }

    if (digitalRead(buttonPin) == LOW) {
        menuIndex = (menuIndex + 1) % 6;
        displayMenu();
        delay(150);
    }
  
    if (1 == *menuItemValues[4] && menuIndex==4 ) {
        drawArea();
        *menuItemValues[4]=0;
    }

    if (1 == *menuItemValues[5] && menuIndex==5) {
        play();
    }

    lastValRotary = valRotary;
}

void play()
{
  generateRandomMovement();
  adjustForSmallMovement(y_new_position, y_old_position);
  adjustForSmallMovement(x_new_position, x_old_position);
  x_speed = (x_new_position - x_old_position) / movement_time;
  y_speed = (y_new_position - y_old_position) / movement_time;
  for (int pos = 0; pos < movement_time; pos += 1)
  {
    x_position = x_position + x_speed;
    y_position = y_position + y_speed;
    x_servo.write(x_position);
    y_servo.write(y_position);
    delay(10);
  }
  x_old_position = x_new_position;
  y_old_position = y_new_position;
  delay(random_delay);
}
void generateRandomMovement() {
  movement_time = random(10, 40);
  random_delay = random(min_freeze, max_freeze);
  x_new_position = random(min_x + minimal_movement, max_x - minimal_movement);
  y_new_position = random(min_y + minimal_movement, max_y - minimal_movement);
}
void adjustForSmallMovement(float& newPos, float& oldPos) {
  if (abs(newPos - oldPos) < 5) {
    newPos += (newPos > oldPos) ? minimal_movement : -minimal_movement;
  }
}
void drawArea() {
  int adj_delay = 40;  // Adjust the delay as needed
  unsigned long previousMillis = 0;  // Variable to store the last time the servo was updated
  unsigned long interval = adj_delay;  // Interval between servo updates

  // Move the laser to the top-left corner of the square
  y_servo.write(min_y);
  int x = min_x;
  while (x <= max_x) {
    if (millis() - previousMillis >= interval) {
      x_servo.write(x);
      previousMillis = millis();
      x++;
    }
  }

  // Move the laser to the top-right corner of the square
  x_servo.write(max_x);
  int y = min_y;
  while (y <= max_y) {
    if (millis() - previousMillis >= interval) {
      y_servo.write(y);
      previousMillis = millis();
      y++;
    }
  }

  // Move the laser to the bottom-right corner of the square
  y_servo.write(max_y);
  x = max_x;
  while (x >= min_x) {
    if (millis() - previousMillis >= interval) {
      x_servo.write(x);
      previousMillis = millis();
      x--;
    }
  }

  // Move the laser to the bottom-left corner of the square
  x_servo.write(min_x);
  y = max_y;
  while (y >= min_y) {
    if (millis() - previousMillis >= interval) {
      y_servo.write(y);
      previousMillis = millis();
      y--;
    }
  }
}

void displayMenu() {
  display.clearDisplay();
  display.setCursor(0, 0);
  // Menu items 0 to 3: Min and Max Values
    if (menuIndex == 0) {
      display.print("Min_x:");
      display.println(*menuItemValues[0]);
      x_servo.write(*menuItemValues[0]);
    }
    if (menuIndex == 1) {
      display.print("Max_x=");
      display.println(*menuItemValues[1]);
      x_servo.write(*menuItemValues[1]); 
    }
    if (menuIndex == 2) {
      display.print("min_y=");
      display.println(*menuItemValues[2]);
      y_servo.write(*menuItemValues[2]);
    }
    if (menuIndex == 3) {
      display.print("Max_y=");
      display.println(*menuItemValues[3]);
      y_servo.write(*menuItemValues[3]); 
    }
    if (menuIndex == 4) {
      display.print("Area=");
      display.println(*menuItemValues[4]);
    }
    if (menuIndex == 5) {
      display.print("Play=");
      display.println(*menuItemValues[5]);
    }
  display.display();
}

void doEncoder()
{
 // unsigned long currentMillis = millis();
  if (digitalRead(encoderPinA) == digitalRead(encoderPinB))
  {
  encoder0Pos++;
  }
  else
  {
  encoder0Pos--;
  }
  valRotary =- encoder0Pos/2.5;
  if (valRotary<lastValRotary)
  {

    *menuItemValues[4]=0;
    *menuItemValues[5]=0;
  }
  
}

Your topic has been moved. Please do not post in "Uncategorized", see the sticky topics in Uncategorized - Arduino Forum.

Thanks for using code tags in your first post :+1:

Welcome to the forum

Assuming that you are using an AVR based board such as a Uno or Nano, what is connected to pin 2 of the Arduino ?

If you are using a different board then which one is it ?

i am using an Arduino uno.
and pin 2 of my Arduino board is the s2 of the encoder.

It's probably time they renamed "Uncategorized" to what it is - "BEGINNER TRAP HERE!"

2 Likes

At a glance it looks like you don't understand how interrupts work.

The encoder thing is probably taking the interrupts and updating the variables it should, but there is nothing in the area function that pays any attention to that.

An interrupt is completely invisible to the interrupted code. It is only through changes the interrupt function makes that it might even be known to have happened.

Usually interrupts are brief and make changes that must be looked for in the non-interrupt code.

Interrupts are good for tracking an encoder, but recognizing changes to the encoder positions is only going to happen if you code that explicitly.

For example you could print the value the encoder maintains, and as you twist the encoder, the printed values would change. The encoder ISR is happening by stealing little bits of the attention your code will still appear to be getting all of.

I can't google for the best article, but

 using interrupts Arduino

turned this up, which looks competent

Interrupts are usually not the answer to the real problem you are experiencing. I know how to use them, and aside from their appearance in library code have had almost no occasion to need them myself. A common misconception is that they are a panacea, the more you know the more you will see they are not.

Use a good encoder library, leave interrupts off your own table until you have a problem that cannot be solved otewise.

a7

1 Like

Though often brevity-to-the-max, Nick Gammon is rarely off-target. Every word should be considered and re-read as often as necessary.

Thank you for your advice
do you have any encoder library that you recommend ?

Yes. I know it otherwise, and it happens to be the one what turns if you just google

Arduino encoder library

which means you can install the library with the IDE library management tools.

So without reservation

You can use it with two, one or zero interrupt capable pins, which speaks to the general claim that interrupts aren't always necessary for thing like that.

I suspicion that you'll still have the problem you began with, how when doing one thing can a program be made to stop that and do some other thing.

Intrrruptrs or no, you will have to adjust your code so it either constantly checks while it is busy doing the one thing, or write code that is bob-blocking, which is to say has no loops or other tcode that hogs the resource which is processing time.

So say a few words about how you want all the things your sketch will do to get along with each other and be easily switched amongst.

a7

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