Help with interupt

Hi all Im trying to get an interrupt working in this program that will completely reset the program on the rising edge of a input pin connected to digital pin 3. Ive looked at online examples' and I think that digital pin 3 is interrupt 1. Ive tried coding it a couple different ways Identifying the input pin and also identifying the interrupt number. the sketch uploads fine but a look at the Arduino Uno board while the program is running allows me to confirm that the pin 3 is indeed receiving a rising edge and when it dose the reset function is not running. I suspect im not creating the interrupt properly

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//   as of 5/28/2025 this version works but the next version should activly send the shifter to nutral
//       on activation of the interupt 
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <AccelStepper.h>
#include <Servo.h>
#define motorInterfaceType 1
Servo throttleServo;                // create servo object to control a throttleServo
//******************************************************PINS*************************************************************
#define startIndicator 2             //     just a switch to ground pin 9 should be ok to bounce a little as in
                                    // this case the loop is interupted a bunch of times but will settle in an actual state
                                   //   the chattering noise of the servo on start swich activation cretes an audible noise
                                  // helping the operator to know they are in start mode kind of like a your blinker
                                 //is on
#define magnetSwitchStepper 3              //     this is the shifter mag switch on the shifter stepper motor .its an input,
             //     this is because mag switch operates the nutral sence relay
            //      and the relay feeds 5 volts to  a debounce circut.thru its comon and
           //     NC contaacts.When voltage falls below  5 volt threshold a 2n2222 transistor
          //      that was holding pin 3 down turns off thus interup should activate on rising
         //      edge
#define servoPin 4                    //     
#define stepperDirecton 10           //   
#define outputA 5                   //   output of the rotry encoder input to the ardrino
#define outputB 7                  //   output of the rotry encoder input to the ardrino
#define stepperEnable 8           //   OUTPUT from pin 8 to stepper driver 5 volts high 
#define stepperMove 6            //   
//************************************************************************************************************************
int currentStateA;
int lastStateA;// one of the 2 outputs from the rotery encoder
int controlMultiplier = 1; ; //various spots throuout program. The  counter will be amplified
                          //to result in less or more control travel for same control movment
                       // so far counter Multipliers are F,R,FN,RN when the program first begins
                   // controlMultiplier will be one so no amplification needed
               // forward, reverse,between forward and nutral and between reverse and nutral
float   F = 3.4;
float   R = 3.4;// changed from 4.4 to 3.4 on 5/27/2024 1103 pm
float   FN = 1;// changed from 2 to one 5/28/2025
float   RN = 1;// changed from 2 to one 5/28/2025
float   counter;// esentually the rotery encoder posision
AccelStepper ForwardReverseStepper(motorInterfaceType, stepperMove, stepperDirecton);
//#####################################################################
int  diagnosticMode = 0; // change to 1 to enter diagnostic test mode
//####################################################################
// the next 4 lines are map constants
float   X = 500;   // servo throtle in forward "From High" portion of map instruction
float   Y = 4900;  // servo throtle in forward "to High" portion of map instruction
float   Z = 500;  // stepper control between reverse and Nutral also forward and nutral "from high"
float   D = 4900; // stepper control between reverse and Nutral also forward and nutral "to thgh"
      // the next 2 lines are the exzact number of steps away from 0 that we want to be in gear
      // so figue out the exzact number of steps to forward
      //to be perfectly in forward from Nutral vise versa from 0 to Reverse
      // then reverse then probibly be a good idea to change expectedCCWCurrentStepperPosision
      // to somthing more understandable like absoluteForwardGearlocationincounter
int  expectedCCWCurrentStepperPosision = 1300; //expectedCWCurrentStepperPosision
int  expectedCWCurrentStepperPosision =  -1300;//expectedCCWCurrentStepperPosision
float   A;
float   B;
float   C ;
         // the next line is the highest the servo will travel set to  prevent exceding
         //max throttle in miliseconds
int fullThrottleServoPosision  = 2500;
         // the next line is the lowest  the servo will travel
         //set to  prevent exceding idle throttle in miliseconds too low engine may die or overheat
int  IdleRPMhServoPosision  = 1000;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//#################################################################################################
//#################################################################################################
// The shifter stepper has to be kept below a certin
//point to not shift past forward gear also
// this next line is a (counter point ,point at wich it moves into gear) it  must be set high
//enough so that the manual control feeling is still there..
//you are controling the stepper speed and direction manually up intill  this number. Hit this number and
// it just takes over and shifts for you. So if not set high enough it will feel like
// it slamed into gear before you wanted it  to.. too low and you will have no or not enough travel of the lever
//between forward
//  and nutral.. set this number corectly and during boat operation it will feel like this number dosent need to exsist
//the way it works is  the stepper stops at this point for a milisecond and without throtle movment
// procedes  to an exzact number of steps that we want for our gear posision to be in forward,aka
// "expectedForwardCurrentStepperPosision",
//it's that secondary number that actually determins that gear
// posision. If you change this you must first change
//the other to be just above or below this,and you
// must convert forom counter to number of steps to change the other not being carful can really create
// a back and forth situation right before the shift.KEEP TRACK of old settings and watch for over
// adjusting of the numbers. //
// any time you change a number note the date and time of the change and the old number like this example below
//  5/21/2025 10 am changed high stepper posision from -900 to -800 EXPEREMENT to alter shift posision
//#################################################################################################
//#################################################################################################
int  highStepperPosision = -900 ;  //  5/21/2025 10 am changed high stepper posision from -900 to -800 EXPEREMENT to alter shift posision
          // Like above only backwards the next line
         // is the (counter pointer) that the stepper
        //will stop moving under
       // control of the lever
      // and begin to advance to "'or retreat to'" the reverse posision .Furthermore
     // the actual posision is
    //expressed in steps and determind by  "expectedCCWCurrentStepperPosision"  // it is not yet known if ccw and cw are inverted
int  LowhstepperPosision = 900;
int  ForwardGearStop = 60;   //   gear shifting the spot at wich you have gone into
                            //forward gear or out
                           //of forward gear ...
                          // Just like above the Reverse gear stop is were we wish to stop controling gears and advance the
                        // trottle  instead of shifter on motor. likwise  stop controling the throtle and
                      //change gears instead depending on how you look at it
int ReverseGearStop = -60;   //   gear shifting the spot at wich you have gone into R gear or out
                            //of reverse
int  forwardThrotleStart = 49; //This is a counter pointer for the beginning of throtle movment in forward
int  reverseThrottleStart = -49 ; //This is a counter pointer for the beginning of throtle movment in reverse
int  startServoPosision = 1000;//Kind of self explanitory its were we want the throtle
                              //to be set when we pull on the starter rope.its going to need an input to tell it the engine
                             // needs starting and the same input to delete this action and revert to lever posision comands.
int  currentStepperPosision = 0;// 1500 microseconds is writen as 1500. Every time the program starts
                               // we assume the stepper is in 0 or Nutral center
int  currentServoPosision = IdleRPMhServoPosision;// we will start this at idle
                                                 //unless the start swich is closed
int comingOutofNutralTowardsForward = 12;
int comingOutofNutralToReverse = -12;
int forceToNutralLowSpot = -8;
int forceToNutralHighSpot = 8;
void(* resetFunc) (void) = 0;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void setup() {
  void(* resetFunc) (void) = 0;//declare reset function at address 0
 attachInterrupt(digitalPinToInterrupt(1), weAreinNutral, RISING);//CHANGED FROM FALLING 5/21/2025 138PM
  ForwardReverseStepper.setMaxSpeed(3900);
  ForwardReverseStepper.setAcceleration(3900);
  ForwardReverseStepper.setSpeed(3900);
  ForwardReverseStepper.moveTo(0);
  pinMode(magnetSwitchStepper, INPUT_PULLUP);
  pinMode(stepperEnable, OUTPUT);
  pinMode(stepperDirecton, OUTPUT);
  pinMode(stepperMove, OUTPUT);
  pinMode(startIndicator, INPUT_PULLUP);
  pinMode(outputA, INPUT_PULLUP);// this is output from the encoder input to the controler
  pinMode(outputB, INPUT_PULLUP);// this is output from the encoder input to the controler
  // previus 2 lines switched from input to input pull up 5/22/2025 omron encoder replaced with teass encodernew encoder
  // usses apn open colector output
 // Serial.begin(1200);// comented out 5/27/2025 1045 pm
   //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  // Read the initial state of outputA on the rotory encoder and declare
  //it to be identical to to the last state of A
  lastStateA = digitalRead(outputA);
}
//**************************************************************************************************************
void loop()
//*********************************************************************************************************************
{
  if (diagnosticMode != 1  ) {
    theMainprogram();
  }
  // diagnostic mode can be here
}
void theMainprogram()
{
  currentStateA = digitalRead(outputA);// program started
  // Read A again did it change?
  if (currentStateA != lastStateA  && currentStateA == 1) {
    if (digitalRead(outputB) != currentStateA) {
      counter = (counter + controlMultiplier); //
    } else {
      // Encoder is rotating CW so increment
      counter  = (counter - controlMultiplier); //
    }
  }

  //**********************************************************************************
  // the servo control for throtle in forward ............. ie rotating  CW Blue 7 White 6
  //***********************************************************************************
  if (counter > forwardThrotleStart) {
    controlMultiplier = F;
    // next 3 lines are to give the stepper a last chance to
    //get that stepper to the desired gear if
    // it did not make it there due to uncounted
    //steps ie moving lever too fast!!
    // right now however were all about
    //throtle control for servo in forward
    // and these 3 lines are ancalary
   // ForwardReverseStepper.moveTo(expectedCWCurrentStepperPosision);
  //  while (ForwardReverseStepper.currentPosition() != expectedCWCurrentStepperPosision)
    //  ForwardReverseStepper.run();
    // previous 3 lines are acounting for
    //uncounted steps/missed steps. (stepper motor has no closed loop operation)
    // it will loose steps its inevatable
    //during a while comand.
    //Proper adjustment of forward gear stop (forwardGearStop)
    //and (expectedCWCurrentStepperPosision)  is criticaly dependant on one another
    // they need to be close together but not too close. you have to plan for how
    //many steps wont get counted and set the (expectedCWCurrentStepperPosision)
    //to the exzact posision. leaving the forward gear stop to be some number chosen
    // a little below the target so that as long as you count enough steps to get above the target
    // the software gets you the rest of the way there
    //Idealey (LowhstepperPosision) and (highStepperPosision)should
    //be determind after (expectedCWCurrentStepperPosision) and(expectedCCWCurrentStepperPosision)
    // map function eqasion ahould be solved backwards to compute the counter posision.
    // or just play with it but do document changes I just played with it but crazy control inputs
    // could mess things up thats why there is a nutral lock that resets the counter each time you go thru or into nutral
    digitalWrite(stepperEnable, HIGH);// disable the shifter stepper .High disables. We
    //are now about  to throtle up in forward
    throttleServo.attach(servoPin);  // enable throttle servo attaches the servo on pin servoPin
    //exmap(counter, fromLow, fromHigh, toLow, toHigh)
    A = map(counter, 0 , X, 0, Y);// should amplify the throttle posision a higher
    //"to high"moves throtle faster
    //might help it stay cought up but the more you
    //amplify  the more you amplify the error result from
    // lost steps
    B = A - 1 ;       // I thought this was going to be  b = a minus the
    // reverse gear stop so throttle 0 would be counter zero its not
    // wkg why ?so just droped in a 0 to make it work
    // leaving in in case will need.
    //
    // Next linelimits range of  values
    //to between Idle rpm and full throtle
    B = constrain(B, IdleRPMhServoPosision , fullThrottleServoPosision);
    currentServoPosision = B; // a declaration
    throttleServo.writeMicroseconds(currentServoPosision);  // moves the servo position according
    //    to the
    //    scaled
  }

  //**************************************************************************************
  // Servo control for throtle in reverse......................
  // ****************************************** ******************************************

  if (counter <= reverseThrottleStart) {
    controlMultiplier = R;
                        // next 3 lines are a last chance to get that stepper to the desired gear
   // ForwardReverseStepper.moveTo(expectedCCWCurrentStepperPosision);// this variable
                        //must be set carfully
                          // see coments control multiplier
   // while (ForwardReverseStepper.currentPosition() != expectedCCWCurrentStepperPosision)
   //   ForwardReverseStepper.run();
    digitalWrite(stepperEnable, HIGH); //disable stepper, High disables we
    //are soon to throtle up in reverse
    throttleServo.attach(servoPin);  // enable throttle servo
                            // this  attaches the
                         //servo on pin servoPin
    A = map(counter, 0 , X, 0, -Y);
    B = A - 0;// I thought this was going to be  B equal to "a minus
                    //reverse gear stop" so throttle 0 would be counter zero seems not matter
                   // next linelimits range of  values to between Idle rpm and full throtle
    B = constrain(B, IdleRPMhServoPosision , fullThrottleServoPosision);
    currentServoPosision = B;
    throttleServo.writeMicroseconds(currentServoPosision);
  }

  //***********************************************************************
  // (Stepper) control between   Forward and  nutral
  // **********************************************************************

  if ((counter <= ForwardGearStop ) && (counter > comingOutofNutralTowardsForward))  {
    controlMultiplier = FN; // more agressive travel amplitude less agresive travel amplitude
    digitalWrite(stepperEnable, LOW);// low enables
    throttleServo.writeMicroseconds(currentServoPosision); //one last chance to get that
    //throtle servo to the Idle posision
    throttleServo.detach();// disable servo
    //   exmap(counter, fromLow, fromHigh, toLow, toHigh)
    C = map(counter, 0 , Z, 0, D); //stepper should respond faster as tolow and to high
    // get farther appart  this in conjunction with control multiplier sets responsivness
    //  next linelimits range of  values to between forward and Nutral
    C = constrain(C, LowhstepperPosision , highStepperPosision); //
    digitalWrite(stepperEnable, LOW);// stepper Low Enables we
    //are soon to move gears
    currentStepperPosision = C;
    ForwardReverseStepper.moveTo(currentStepperPosision);
    ForwardReverseStepper.run();
  }
  //***********************************************************************
  // (Stepper) control between  reverse and  nutral
  // **********************************************************************
  if ((counter >= ReverseGearStop ) && (counter < comingOutofNutralToReverse))  {
    controlMultiplier = RN; // more agressive travel amplitude less agresive travel amplitude
    digitalWrite(stepperEnable, LOW);// low enables
    throttleServo.writeMicroseconds(currentServoPosision); //one last chance to get that
    ///throtle servo to the Idle posision
    throttleServo.detach();// disable servo
                 //   exmap(counter, fromLow, fromHigh, toLow, toHigh)
    C = map(counter, 0 , -Z, 0, -D); //stepper should respond faster as "fromhigh" and "tohigh"
                                    // get farther appart
                                      //  next linelimits range of  values to between reverse and Nutral
    C = constrain(C, LowhstepperPosision , highStepperPosision); //
    currentStepperPosision = C;
    ForwardReverseStepper.moveTo(currentStepperPosision);
    ForwardReverseStepper.run();
  }

  //***********************************************************************
  // (Stepper) control between  comingOutofNutralToReverse and 0
  // **********************************************************************
  if ((counter >= comingOutofNutralToReverse ) && (counter <= forceToNutralLowSpot))
  {
    digitalWrite(stepperEnable, LOW);// low enables
    while (ForwardReverseStepper.currentPosition() != 0) {
      ForwardReverseStepper.moveTo(0);
      ForwardReverseStepper.run();
      digitalWrite(stepperEnable, LOW);// low enables
      counter = 0;
      controlMultiplier = 1;
    }
  }
  //***********************************************************************
  // (Stepper) control between  0 and comingOutofNutralToForward
  // **********************************************************************
  if ((counter >= forceToNutralHighSpot ) && (counter <= comingOutofNutralTowardsForward))
  {
    digitalWrite(stepperEnable, LOW);// low enables
    while (ForwardReverseStepper.currentPosition() != 0) {
      ForwardReverseStepper.moveTo(0);
      ForwardReverseStepper.run();
      counter = 0;
      controlMultiplier = 1;
    }
  }
  lastStateA = currentStateA;
  startCheck;
}
void startCheck() {
  digitalRead (startIndicator);
  if (startIndicator  == 0)// changed to 0 from 1 5/21/2025 1117 am also line 345 while start indicator
  {
    throttleServo.attach(servoPin);  // attaches the servo on pin servoPin

    while (startIndicator  == 0) {
      throttleServo.writeMicroseconds(startServoPosision);// in microseconds
    }
  }
  throttleServo.writeMicroseconds(IdleRPMhServoPosision);// in microseconds
  throttleServo.detach();// disable servo
}
//_______________________________________________________________________
//__________________________ISR____________________________________
//_______________________________________________________________________
//ISR function
void weAreinNutral () {
  
  counter = 0;
    resetFunc();  //c
}
//__________________________________________________________________________
//____________THE END_____________
//__________________________________________________________________________

Best to get the interrupt working with a simple example, and to understand the code before adding it to some other project.

Here is an excellent tutorial on Arduino Uno interrupts:

It is a good idea to consult the Arduino reference guide on what Arduino-specific functions do, and how they are to be used, to avoid making fatal mistakes like this one:

attachInterrupt(digitalPinToInterrupt(1)

https://docs.arduino.cc/language-reference/en/functions/external-interrupts/attachInterrupt/

1 Like

The code you posted won't compile, it's incomplete because resetFunc() isn't defined.

Can you please explain why you want to use an interrupt for this purpose? Is it because your coding skills have not yet advanced beyond writing blocking code? If so, the forum can help you advance.

1 Like

the code is running for me it just isn't triggering the interrupt for me .Im doing something wrong im not sure what .

I think I know.

can please share what code is blocking i wish to create a block in my program at the interrupt im attempting to create . thats the only place

It is very important that you first understand the working principle of a hardware interrupt.

"The ISR to call when the interrupt occurs; this function must take no parameters and return nothing." im having trouble understanding the above . I think this means I cannot change a variable during the ISR but something like issuing a reset command is ok

No, it is telling you that an interrupt is just like any other function, except for the passing of parameters and the returning of a value. Just what is says and what it means. Do not add assumptions to the description.
The interrupt code has the same access to all global variables as do all other functions.

What do you think a reset command is? I don't recall such an instruction in the Arduino Cook Book.

Rather than guess, why not study the linked tutorial and actually learn something?

I believe I do and its a good choice to have blocking code if you will protect from expensive hardware damage with a simple interrupt. I suspect im making a simple mistake somewhere . The ISR runs the program attempts to return to where it was but never dose because its been reset as it dose . so far thats the plan I need the mistake spotted for me if you have got a second .

I believe its a hardware interrupt of its own

Do you realize that interrupts are disabled during the execution of interrupt code?

I suspect your while-loops are blocking. Not all while loops are blocking, but I suspect your while-loops are.

During the time that these loops are executing, no other tasks can be done, including checking pins to see if the signals have changed. That's why you are seeing interrupts as a potential solution. But they might fix one problem and cause 2 new problems.

Better to avoid blocking code so that interrupts are not necessary.

You may experiment the following simple interrupt process on DPin-3 (INT1, Fig-1) to find out the problem of your sketch.


Figure-1:

The MCU will be continuously blinking L at 1-sec interval as a Mainline Program (MLP). When the user gently presses K2, the MCU will be interrupted by the falling edge of the triggering signal. The MCU goes to the ISR Routine named ISRINT1, sets a flag to inform the loop() function that ISRINT1's task of blinking LED2 at 2-sec interval for five times would be done in the loop() function.

Test Sketch:

#define INT1 3
#define L 13
#define LED2 9
volatile bool flag = false;

void setup()
{
    Serial.begin(9600);
    pinMode(L, OUTPUT);
    pinMode(LED2, OUTPUT);    
    pinMode(INT1, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(INT1), ISRINT1, FALLING);
    interrupts();
}

void loop()
{
    if(flag == false)
    {
        digitalWrite(L, HIGH);
        delay(500);
        digitalWrite(L, LOW);
        delay(500);
    }
    else
    {
        for(int i = 0; i < 5; i++)
        {
            digitalWrite(LED2, HIGH);
            delay(1000);
            digitalWrite(LED2, LOW);
            delay(1000);
        }
        flag = false;
    }
}

void ISRINT1()
{
    flag = true;
}

You may be interested to read the attached file on inerrupt process of ATmega328P MCU.
Ch-9 IRQLec.pdf (469.5 KB)

1 Like

The attachInterrupt() function does not contain the argument that you have wanted.

One of the fatal mistakes was pointed out in the first reply. Good luck with your project!

Sounds like an XY Problem.
If your issue is "I fear my program gets stuck" ... fix the problem.
If you can't fix the problem, use the functionality of a Watchdog.

Why do you ask ?

This may be correctly defining a function which when called will start at 0, causing reset, or some of what reset does at least:

void(* resetFunc) (void) = 0;//declare reset function at address 0

but it shouldn't be local to setup().

Move that line out of setup() so it can be seen everywhere,

a7