Need help with interrupts. Kinda CNC software

Hello!

I am making a program on Arduino to control two stepper motors.
But at first forget about motors. :slight_smile:

The CNC head will move in two axis (each axis, each motor).
On the both side of both axis i will montage limit switches.
So when the CNC head hit the limit switch it have to change direction of the motor.
Example:
If the motor is running in forward direction and when it hits the limit switch, the program have to change the rotation of the motor and spin in backward direction. And again when hit the limit switch it have to change direction again, and so on and so on…

I though i should change the direction of motors with interrupts.

Because I will have some LCD display and several pushbuttons and potentiometers and ofcourse driving the motors, I CANT PUT ALL THE CODE AND READING THE INPUTS OF SWITCHES IN THE MAIN LOOP.

What do you recommend me to do? :slight_smile:

Instead of motors i am using two LEDs, one led for each direction.
And two pushbuttons.

Can I avoid checking the boolean state in main loop and let the interrupt do the work?

Here is the code:

#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x27 // <<----- Add your address here.  Find it from I2C Scanner
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

int ledPinLeft = 13; // LED is attached to digital pin 13
int ledPinRight = 11;


LiquidCrystal_I2C  lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);

//variables to keep track of the timing of recent interrupts
unsigned long button_time1 = 0;
unsigned long button_time2 = 0;
unsigned long last_button_time1 = 0;
unsigned long last_button_time2 = 0;
volatile boolean left_b=LOW;
volatile boolean right_b=LOW;
 int x = 0;

void setup() {
 //enable interrupt 0 which uses pin 2
 //jump to the increment function on falling edge
 attachInterrupt(0, isrLeft, RISING);
 attachInterrupt(1, isrRight, RISING);
 Serial.begin(9600);
 lcd.begin (20, 4);
 lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
 lcd.setBacklight(HIGH);
 lcd.home();
 lcd.print("Interrupt test");
 lcd.setCursor(-1, 1);
 lcd.print("Num. of ISR: ");
 lcd.print(x);

 pinMode(ledPinLeft, OUTPUT);
 pinMode(ledPinRight, OUTPUT);
 digitalWrite(ledPinLeft,LOW);
 digitalWrite(ledPinRight,LOW);
}


void loop() {

 //there will be main program
 
 if(left_b==HIGH)
 left();
 if(right_b==HIGH)
 right();
}

void left() {
 digitalWrite(ledPinLeft, HIGH);
 digitalWrite(ledPinRight, LOW);
 Serial.println(x);
 lcd.setCursor(14, 1);
 lcd.print(x);
 lcd.setCursor(0, 3);
 lcd.print("<-----");
 left_b=LOW;
 
}

void right() {
 digitalWrite(ledPinLeft, LOW);
 digitalWrite(ledPinRight, HIGH);
 Serial.println(x);
 lcd.setCursor(14, 1);
 lcd.print(x);
 lcd.setCursor(0, 3);
 lcd.print("----->");
 right_b=LOW;
 
}

// Interrupt service routine for interrupt 0
void isrLeft() {
 left_b=HIGH;
 button_time1 = millis();
 //check to see if increment() was called in the last 250 milliseconds
 if (button_time1 - last_button_time1 > 250)
 {
   x++;
   last_button_time1 = button_time1;
   
 }
}

void isrRight() {
 right_b=HIGH;
 button_time2 = millis();
 //check to see if increment() was called in the last 250 milliseconds
 if (button_time2 - last_button_time2 > 250)
 {
   x++;
   last_button_time2 = button_time2;
   
 }

}

:slight_smile:

I though i should change the direction of motors with interrupts.

I think not. While the motor is moving, what else is the Arduino doing? Monitoring a limit switch doesn't take much processing time/effort.

Because I will have some LCD display and several pushbuttons and potentiometers and ofcourse driving the motors, I CANT PUT ALL THE CODE AND READING THE INPUTS OF SWITCHES IN THE MAIN LOOP.

YES, YOU CAN!

I CANT PUT ALL THE CODE AND READING THE INPUTS OF SWITCHES IN THE MAIN LOOP.

WHY NOT ?

If you use interrupts you are going to need 4 of the, 2 for each axis.

Ignore the main loop :slight_smile:

PaulS:
I think not. While the motor is moving, what else is the Arduino doing? Monitoring a limit switch doesn't take much processing time/effort.
YES, YOU CAN!

But while the motor is running the program will all the time check the boolean state of interrupt..
That means: The program will make 1 microstep of the motor and 1 checking of the interupts, and then again 1 step of motor and again checking of interrupts?

Why interrupts then? If the program must check them? Isnt the point of interrupts that they automaticly reminds the arduino when it is necessary?

Isnt the point of interrupts that they automaticly reminds the arduino when it is necessary?

No. The point of interrupts is to deal with something that must be handled RIGHT NOW!, such as serial data arriving, the clock ticking, etc. These kind of things can't wait until you get around to checking on them.

Step, read a switch state, step, read a switch state, etc. CAN wait (to check the state of the switch) until the step is done.

If you persist with interrupts, all you will accomplish is, in the ISR, setting a flag that the interrupt happened. You still need to check the flag before stepping again. You might as well read the switch state.

PaulS:
No. The point of interrupts is to deal with something that must be handled RIGHT NOW!, such as serial data arriving, the clock ticking, etc. These kind of things can’t wait until you get around to checking on them.

Step, read a switch state, step, read a switch state, etc. CAN wait (to check the state of the switch) until the step is done.

If you persist with interrupts, all you will accomplish is, in the ISR, setting a flag that the interrupt happened. You still need to check the flag before stepping again. You might as well read the switch state.

But instead of using interrupts i could be using only if(digitalRead(pin)==HIGH) then… isnt that the same?

Can I use interrupts without checking the switch states in main loop each cycle? :slight_smile:

@burnley1: Please edit your post, select the code, and put it between [code] … [/code] tags.

You can do that by hitting the ‚ÄúCode‚ÄĚ icon above the posting area. It is the first icon, with the symbol: </>

Read this before posting a programming question


One thing that jumps out at me in your code is that you are updating the LCD every time through loop. That will be slow. Why not update it when something changes?

There is no constantly updating LCD in the main loop now. Now i edited the code (main loop). Before editing there was just some code in main loop to write numbers. Now its empy.
Please anwser on previous question people!
Thanks to everyone!

But instead of using interrupts i could be using only if(digitalRead(pin)==HIGH) then.. isnt that the same?

No. Using digitalRead() you decide where in the code and how often the reading of inputs takes place.

Interrupts can happen at any time, should contain as little code as possible, possibly just setting a flag to indicate that the interrupt has occurred and maybe saving the time that the interrupt took place if that is relevant. The flag is then reacted to in the main program, but if you are going to do that then you may just as well just read the input in the main program anyway.

Why complicate things by using interrupts when you don't need to.

But instead of using interrupts i could be using only if(digitalRead(pin)==HIGH) then.. isnt that the same?

Checking the state of a pin with digital read is not greatly different than checking if the flag variables left_b and right_b are set. The digitalRead() version helps you steer clear of problems which often occur when people are first learning to use interrupts. The fact that it looks like you are trying to perform some sort of debounce within the interrupt indicates to me that the digitalRead() with debounce is a better way to go.

Can I use interrupts without checking the switch states in main loop each cycle? :slight_smile:

No. You are really using the interrupts to execute the left() and right() functions. What those functions do can not be done within an ISR.