ALTERNATIVE TO INTERRUPTS

How can I detect a state from a Arduino digital port (HIGH or LOW) continuosly, without using Interrupts?
For example, I want to detect if one switch is activated and I use Interrupt to do it and direct my code to a function needed at that time! However, using Interrupts can cause some problems in my case, because during this routine made during Interrupt, I have to run a stepper motor.

So, the problem is that I need to do a certain sub-routine first than the rest of the code, but I can't use Interrupts to detect constantly the state of a digital port. How can I manage to monitoring this?

How can I detect a state from a Arduino digital port (HIGH or LOW) continuously, without using Interrupts?

You can’t. However, you need to work out how fast you need to detect the change. What is your application? What are you really trying to do? Why do you think it needs to be that fast?

PerryBebbington:
You can't. However, you need to work out how fast you need to detect the change. What is your application? What are you really trying to do? Why do you think it needs to be that fast?

For example, if you need to stop your stepper based on the switch state then you can check the state (or transition) of the switch every time you step the stepper motor (assuming you are doing that in a loop). If not, then you need to determine when the switch state is relevant and monitor accordingly.

luciocr:
For example, I want to detect if one switch is activated and I use Interrupt to do it and direct my code to a function needed at that time! However, using Interrupts can cause some problems in my case, because during this routine made during Interrupt, I have to run a stepper motor.

it sounds like you want to do different things in an interrupt service routine depending on the state of an input pin?

if this is correct, loop() captures the state of a digital input by reading it, and the ISR conditionally executes code depending on the value of state

not sure why the ISR couldn’t read the state of the pin (but it make sense to minimize ISR processing)

PerryBebbington:
You can't. However, you need to work out how fast you need to detect the change. What is your application? What are you really trying to do? Why do you think it needs to be that fast?

I'm developing a project about solar tracker. In this project, I'm including the switch to avoid the motor going beyond this range. So, there are two switches (in opposite sides) for axis (two axis).

Moreover, the switch is also used to calibrate the potentiometer. For this, these are the steps:

  1. switch is activated,
  2. Read the value of the potentiometer
  3. Compare the reading value of the potentiometer and a set value (stored in EEPROM).
  4. If this difference is greater than X value, I want to replace this value read to that stored in EEPROM.
  5. Change the direction of the motor
  6. Moves the motor until hit the switch (placed in the opposite side).
  7. Read the value from the potentiometer again (but,
  8. Change again the direction of the motor
  9. Move 90º degrees and stop

This aims to read the position from both switches (both sides from the same axis) , by using the potentiometer and calibrate this one.

This routine would be within Interrupt Service Routine, but it is much long and my routine requires some increment of time to run the motor.

And other problem: In the sixth step, the Interrupt is called again and instead of following to seventh step, it will call the Interrupt again and go back to the first step, but it isn't what I want.

Can I solve this? Which is the best way to calibrate potentiometer by using Switch, while I use the switch to limit movement too?

luciocr:
This routine would be within Interrupt Service Routine

That would be a huge design mistake. Never, ever have any tasks in an ISR that take more than a few microseconds to complete.

Actually, there is no reason why you need to use interrupts for anything at all, in your project as it has been presented. You do need to step the motor and check the limit switch and/or potentiometer, alternately (or concurrently, depending on your point of view). That can be done with the usual cooperative multitasking inside loop().

aarg:
That would be a huge design mistake. Never, ever have any tasks in an ISR that take more than a few microseconds to complete.

Actually, there is no reason why you need to use interrupts for anything at all, in your project as it has been presented. You do need to step the motor and check the limit switch and/or potentiometer, alternately (or concurrently, depending on your point of view). That can be done with the usual cooperative multitasking inside loop().

Thanks for broading my view about it! Good one!
But I still have one problem:

How do I replace "for loop" for millis?

Try a site search on 'solar tracker' to see if others may have already solved this.

luciocr:
Thanks for broading my view about it! Good one!
But I still have one problem:

How do I replace “for loop” for millis?

If you mean, “how do I implement…”, then decompose the for loop and use a state variable to make an implicit ‘while’ from an ‘if’.

So a

for(i=3; i<6; i++) {<somecode>}

decomposes as

i=3;
while (i<6) {
<somecode>
i++;
}

For the state machine you would do something like

if state == initialize
{
i=3;
state = run
}
else if (state == run and i<6 ) {
<somecode>
i++;
}
else
{
state = idle
}

To activate it, you just assert:

state = initialize

In practice you can often use a switch statement to perform the same logic, I just wanted to spell it out clearly (which I doubt, I guess…)

This aims to read the position from both switches (both sides from the same axis) , by using the potentiometer and calibrate this one.

This routine would be within Interrupt Service Routine, but it is much long and my routine requires some increment of time to run the motor.

While I've been asleep you've had some good answers. You don't need an interrupt for this and others have shown you how to go about it. I've nothing useful to add. Good luck.

aarg:
That would be a huge design mistake. Never, ever have any tasks in an ISR that take more than a few microseconds to complete.

Actually, there is no reason why you need to use interrupts for anything at all, in your project as it has been presented. You do need to step the motor and check the limit switch and/or potentiometer, alternately (or concurrently, depending on your point of view). That can be done with the usual cooperative multitasking inside loop().

How do I run the motor and check the limit switch at the same time (concurrently) ?

Is it something like:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void  numerodepassos(int nSteps, int newCustom, int nEixo) { // function to generate pulses acording to the information obtained from the function (positioning potentiometer and tracking)
    int passos; //variable to store number of steps      - nEixo is used to say which axis is on the movement

    if indicacaodefuncao=0  {//indicate the mode used (tracking)
      passos = newCustom; //number of steps that comes from the tracking function
    }
    if indicacaodefuncao =1 {//indicate the mode used (positioning potentiometer)
      passos = nSteps; // number of steps that comes form the positioning function
    }
    int contador=0; //variable to count the number of times that 
    
     do{ 
      
       unsigned long curMillis = millis(); //store the current time 
       
    if (curMillis - prevStepMillis >= stepDelayMotorVH[nEixo]) { //stepDelayMotor is used to set a time to each step of the motor
        prevStepMillis = curMillis; //uptade the previousStep to continue comparing before
        if (pinoDrive[0]== HIGH){ //if STEP is HIGH
        digitalWrite(pinoDrive[0], LOW); // alternate to LOW
         else (pinoDrive[0]== LOW){
        digitalWrite(pinoDrive[0], HIGH);
         }
         contador++; //increment the number of times 
        }
    }
     }while (contador<=passos); //we should continue run the motor until the counter reach the numbers of steps need
  }
 
   unsigned long currentMillisdelay = millis(); //variable to store the current time 
  
  if (currentMillisdelay - prevStepMillischecagem >2) { //set the frequency to read the switch pin 
       prevStepMillis = currentMillisdelay; //uptade the previousStep to continue comparing before
       swLeitura = digitalRead(pinoswitch); //read the switch pin
  }
  
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

several things at the same time

aarg:
If you mean, “how do I implement…”, then decompose the for loop and use a state variable to make an implicit ‘while’ from an ‘if’.

So a

for(i=3; i<6; i++) {<somecode>}

decomposes as

i=3;

while (i<6) {

i++;
}




For the state machine you would do something like



if state == initialize
{
i=3;
state = run
}
else if (state == run and i<6 ) {

i++;
}
else
{
state = idle
}




To activate it, you just assert:


state = initialize




In practice you can often use a switch statement to perform the same logic, I just wanted to spell it out clearly (which I doubt, I guess...)

Thank you so much, @aarg!
Another question: When I use switch case within a function that is outside the void loop, if I have a break (and I didn’t call another case of this switch case), will I go back to the loop to run the next line of the code?

void loop {

switch (mode) {

case START: 

runmotor();
mode = MIDDLE;

break;

case MIDDLE: 

check_potentiometer();
mode = END;
break;

case END:
calibrate();
break;

}

void runmotor(){

 switch (action) {
  
 break;

   case STEPS:
      steps ();
break;


  case DIRECTION:

       dir ();
 
break;

}

 void dir (){

   switch (set) {

  case NEW:
      do something;

break;

}

In this example, when I finish doing case NEW (within function dir) and I have a break, will I go back to the switch case DIRECTION of the function runmotor and before I return to the void loop and go to the line mode = END?

dougp:
several things at the same time

Thanks for your help!

When functions end either because the program runs to the end of the code in them or because an explicit return is encountered, the code execution continues from where the function was called

The break statements in a switch/case end execution of the current code block for the current case. If the switch/case is within a function the break does not explicitly cause the function to end although, of course, there may be no more code to execute in the function so it will return to where it was called.

To answer your question, I hope:

 void dir (){
   switch (set) {
  case NEW:
      do something;
       break;
}

is just:

 void dir (){
  if (set == NEW) {do something;}
}

So, no.