Arduino motror controller using interruptions

hi I need to write a code for motor controller using interruptions.
I have to main code but has zero idea how to use interruptions in the code itself.

heres what i must do,can someone explain me how to use interruptions

Re-implement the software using
interrupts so that the controller buttons are not blocked during the ramp-up and ramp-down phases
of the operating cycle.
There are two buttons, start/stop on pin 3 and E-Stop on pin 2. The controller takes 10 seconds to
ramp from zero to full power. Pressing the start/stop button causes the ramp up to commence, after
that if the stop button is pressed the controller will ramp back down to zero from whatever power
level it is currently at. If the E-Stop button is pressed the controller will immediately stop the motor.

#define DEBUG_MODE
#define MOTOR_DRIVE 11 // Motor output PWM on Pin 11
#define E_STOP 2 // Emergency Stop on Pin 2
#define RUN_STOP 3 // Start/Stop on Pin 3
#define PMAX 255 // MAX Power 100%
#define RAMP_DELAY int(10000/PMAX) // Ten Second Ramp Time

It would be better to re-write the code so that it does not block at any time. Using interrupts like that is a band aid (at best) and not a good use of interrupts.

Non-blocking timing tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

Post the code you are using currently and we can help fix it (and most likely not use interrupts)

Yes ,Thanks. I was told to use interrupts for this code.

I got this so far #define DEBUG_MODE
#define MOTOR_DRIVE 11
#define RUN_STOP 3
#define E_STOP 2
#define PMAX 255                         // MAX Power 100%
#define RAMP_DELAY int(5000/PMAX)        // Five Second Ramp Time

volatile bool motorState = 0;

void setup() {
  // put your setup code , to run once:
 #ifdef DEBUG_MODE
 Serial.begin(9600);
 Serial.println("%D DEBUG Starting Setup");
 #endif

/* Configure Inputs and Outputs */
 pinMode(MOTOR_DRIVE,OUTPUT);
 analogWrite(MOTOR_DRIVE,0);
 
 pinMode(RUN_STOP,INPUT_PULLUP);
 pinMode(E_STOP,INPUT_PULLUP);
 
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Finished Setup");
 #endif
}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.print("Run Stop");
  if (digitalRead(RUN_STOP)==LOW) 
  {   motorState = !motorState;
      if (motorState) rampUp(); else rampDown();
  }
  if (digitalRead(E_STOP)==LOW) 
  {   
    stopMotor();
    motorState = 0;
  }
 } // Loop

void rampUp()
{
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Commencing Ramp UP");
 #endif
  for (int i = 0; i < PMAX; i++)
  {
    analogWrite(MOTOR_DRIVE,i);
    delay(RAMP_DELAY);
  }
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Finished Ramp UP");
 #endif
}

void rampDown()
{ 
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Commencing Ramp DOWN");
 #endif
 
 for (int i = PMAX; i > 0; i--)
  {
    analogWrite(MOTOR_DRIVE,i);
    delay(RAMP_DELAY);
  }
  #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Finished Ramp DOWN");
 #endif 
}

void stopMotor()
{ 
 #ifdef `DEBUG_MODE`
  Serial.println("%D DEBUG Emergency Stop Entry");
 #endif
  analogWrite(MOTOR_DRIVE,0);``
  #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Emergency Stop Exit");
 #endif 
}

but if there is a better way with no interrupts I would like to learn it

Start by browsing the forum guidelines and putting your code in code tags. How to get the best out of this forum - Using Arduino / Installation & Troubleshooting - Arduino Forum

It helps people help you. With code tags, people can copy & paste your code with 2 clicks, exactly as-is.

1 Like

As for your code, you need to let loop() do its thing as fast as possible. This means getting rid of your for() loops inside your ramp functions as well as those delays().

Do do that, you call you call your ramp function every time through loop(). Inside the function, you track elapsed time since the last step, and if enough time has passed, you do the next step. If not, return without doing anything.

Also, every time through loop() you check the state of your buttons are react accordingly. You might also have to keep track of what state you are in - ramping up, ramping down, steady-state, idle, etc.

Start with the references @groundFungus provided.

1 Like

thank You ,I will try.

Please edit your posts to add code tags ("</>" forum editor button).

Write non-blocking code (no delays, no waits for any action to complete, etc.) and simply read the button pins along with other actions. This method is much more reliable than using interrupts.

1 Like

I dont really know how to do this yet.I think I need to use interrupts cause thats the requirement

So lets say I MUST use interrupts,where will I implement them in the code

Where does that requirement come from? Is this a school assignment?

If your instructor is insisting on using interrupts to read the button switches, they are doing you a disservice by making you use bad programming practices.

Along with the non blocking timing tutorials, look up state machine programming to implement the strategy mentioned by @blh64 above.

It is.
And I am not trained in arduino code much at this point.
"check the state of your buttons are react accordingly" how do I do this.
And how do I block the times?

Please answer questions.

We will help you if you are willing to do some work, but i doubt that anyone will write the code for you.

Have you played with the code from the tutorials? Do you understand how the millis() timing works?

I did answer it is for school. I don't want to get a code from someone I want to understand how to implement interrupts in the code and do it. I did not have any arduino tutorials.All I know is from Yt videos which isn't much.We havent cover any coding in our course and the teacher in this course simply expects us to know this.I am not able to learn how to code in 5 days without any help.

I dont understand how the millis() timing works,I am using YT playlist to learn and it didn't cover this yet.

Seems like a pretty tall order from your instructor to jump right into interrupts without any other training...

what is wrong in here :frowning:


#define DEBUG_MODE
#define MOTOR_DRIVE 11
#define RUN_STOP 3
#define E_STOP 2
#define PMAX 255                         // MAX Power 100%
#define RAMP_DELAY int(10000/PMAX)        // Ten Second Ramp Time

volatile bool motorState = 0;

void setup() {
  // put your setup code here, to run once:
 #ifdef DEBUG_MODE
 Serial.begin(9600);
 Serial.println("%D DEBUG Starting Setup");
 #endif
 attachInterrupt(digitalPinToInterrupt(RUN_STOP), rampUp, RISING)
 attachInterrupt(digitalPinToInterrupt(RUN_STOP), rampDown, FALLING)
/* Configure Inputs and Outputs */
 pinMode(MOTOR_DRIVE,OUTPUT);
 analogWrite(MOTOR_DRIVE,0);
 
 pinMode(RUN_STOP,INPUT_PULLUP);
 pinMode(E_STOP,INPUT_PULLUP);
 
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Finished Setup");
 #endif
}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.print("Run Stop");
  if (digitalRead(RUN_STOP)==LOW) 
  {   motorState = !motorState;
      if (motorState) rampUp(); else rampDown();
  }
  if (digitalRead(E_STOP)==LOW) 
  {   
    stopMotor();
    motorState = 0;
  }
 } // Loop

void rampUp()
{
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Commencing Ramp UP");
 #endif
  for (int i = 0; i < PMAX; i++)
  {
    analogWrite(MOTOR_DRIVE,i);
    delay(RAMP_DELAY);
  }
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Finished Ramp UP");
 #endif
}

void rampDown()
{ 
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Commencing Ramp DOWN");
 #endif
 
 for (int i = PMAX; i > 0; i--)
  {
    analogWrite(MOTOR_DRIVE,i);
    delay(RAMP_DELAY);
  }
  #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Finished Ramp DOWN");
 #endif 
}

void stopMotor()
{ 
 #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Emergency Stop Entry");
 #endif
  analogWrite(MOTOR_DRIVE,0);
  #ifdef DEBUG_MODE
  Serial.println("%D DEBUG Emergency Stop Exit");
 #endif 
}

type or paste code here

tl;dr: Start with the references @groundFungus provided. In post #2.


You have interrupt service routines that you also call as regular functions. That's not necessarily wrong, but it is not common.

You use delay() in those functions, which means they won't work as ISRs because… delay() does not work when interrupts are off.

You do some printing from within the ISRs. This is generally not a good idea.

You are split between holding the button down makes it go one way, releasing the button makes it go the other way, and another set of code lines reverse direction with each press.

Too many interpretations of the button.

Your functions used as regular functions still block, that is to say that once started, they will not return until finiched, which means your button won't be read, which means you'll have no response to pressing. Ccertainly not the response it seems you and teach are looking to implement.

This only needs interrupts if there is someone standing between you and your letter grade who insists that you use them.

Start with the references @groundFungus provided. In post #2. Do this without interrupts, everything you learn making that happen will prepare you for a day that may never come, when you have a problem that would best be solved using interrupts.

You say you are following a video guide. Which one, please post a link to Chapter 1, Verse 1 of this.

It is hard to believe your teacher throws this at you when you so not quite ready for it. What is s/he teaching, what assignments has]ve you successfully finiched and turned in as done?

Share the previous assignment and the sketch you wrote to do it, maybe we can figure out where teach's head is at. Some of us may have formed an opinion about that aready…

a7

FYR,

#define E_STOP A1       // Emergency Stop
#define RUN_STOP A0     // Start/Stop
#define MOTOR_DRIVE 11  // Motor output PWM
#define PMAX 255        // MAX Power 100%
#define SMAX 100.0      // MAX Setpoint

float setPoint = 0.0;
float rampRate = 10.0;
float rampValue = 0.0;

bool runningState;
bool prevRunningState;

// Declare Function
float Scale(int inputValue, float minEU = 0, float maxEU = PMAX);
float Ramp(float currentValue, float Setpoint,  float Rate);

void setup() {
  pinMode(RUN_STOP, INPUT);       // Set Pint to Input Mode
  pinMode(E_STOP, INPUT_PULLUP);  // Set Pint to Input Mode with Pull-Up
  pinMode(LED_BUILTIN, OUTPUT);   // Set Pint to Output Mode
}

void loop() {
  prevRunningState = runningState;          // Store Previous Running Status

  bool startState = digitalRead(RUN_STOP);  // Read PB Start Status
  bool emerState = digitalRead(E_STOP);     // Read PB Stop/E-Stop Status
  runningState = (startState | runningState) & emerState;

  if (runningState & ! prevRunningState) {
    setPoint = 100.0; // Start
  } else if (!runningState & prevRunningState) {
    setPoint = 0.0;   // Stop
  }

  rampValue = Ramp(rampValue, setPoint, rampRate);    // Get Ramp Value
  int pwmValue = Scale(rampValue, 0.0, SMAX, 0.0, PMAX);  // Engineering Value to RAW Value
  analogWrite(MOTOR_DRIVE, pwmValue);                 // PWM Output

  // Ramping Status
  if (rampValue == setPoint) {
    digitalWrite(LED_BUILTIN, LOW);
  } else {
    digitalWrite(LED_BUILTIN, HIGH);
  }
}


//============================================================
// Function: Ramp
// Input:
//    currentValue : Current Value
//    Setpint      : Setpoint
//    Rate         : Rate/Second
// Output:
//  ControlValue : Update Control Value every cycle;
//============================================================


float Ramp(float currentValue, float Setpoint,  float Rate) {
  unsigned long _deltaTime;
  static unsigned long _currTime;

  unsigned long _prevTime = _currTime;
  _currTime = micros();
  _deltaTime = _currTime - _prevTime;

  float _controlValue = currentValue;

  if (_controlValue < Setpoint ) {
    _controlValue += (Rate * (float)_deltaTime * 0.000001);
    if (_controlValue > Setpoint) {
      _controlValue = Setpoint;
    }
  }
  else if (_controlValue > Setpoint) {
    _controlValue -= (Rate * (float)_deltaTime * 0.000001);
    if (_controlValue < Setpoint) {
      _controlValue = Setpoint;
    }
  }
  return _controlValue;
}

float Scale(float const inputValue, float const rawMin, float const rawMax, float const euMin, float const euMax) {
  return ((inputValue - rawMin) / (rawMax - rawMin)) * (euMax - euMin) + euMin ;
}