Go Down

Topic: An Alternative to a Hypothetical Delay in Interrupt (Read 1 time) previous topic - next topic

Erasermaster

I am currently working on a robot arm project for school. The arm will be autonomous and be able to sense objects and pick them up using SONAR and touch sensing. If at any time during the operating time that the arm fails I want to be able to manually control the arm at any time at the push of a button. I was thinking that an interrupt would work but I have noticed that they don't take delay functions. I would need a delay function to regulate the speed of the servo motors that I am using. What I need is a manual override button that when pressed, the arm will go into a loop where I can input values from buttons "1s and 0s" to control the different joints on the arm. I don't want to have to continuously check for a button press after every line in the code. What kind of alternative would there be to compensate for this?

The following code is what I tried to upload onto my Arduino UNO for the manual override of a single servo motor. At first it is just sweeping back and forth and then I push the override button and I have control.

Code: [Select]
#include <Arduino.h>
#include <Servo.h>

int interruptPin = 0; // attached to pin 2
volatile int servoPos = 180; // servo position angle
int rightButton = 13; // pin 13
int leftButton = 12; // pin 12
Servo servo; // 180 servo
void manual();

void setup(){
  attachInterrupt(interruptPin, direction, FALLING);
  servo.attach(6);
  pinMode(rightButton, INPUT);
  pinMode(leftButton, INPUT);
}

void loop(){
  for(servoPos = 180; servoPos > 1; servoPos--){
    servo.write(servoPos);
    delay(10);
  }
  for(servoPos = 1; servoPos < 180; servoPos++){
    servo.write(servoPos);
    delay(10);
  }
}

void manual(){
  if(digitalRead(rightButton) == 1){
    servoPos++;
    servo.write(servoPos);
    delay(10);
  }else{
    servo.write(servoPos);
  }
  if(digitalRead(leftButton) == 1){
    servoPos--;
    servo.write(servoPos);
    delay(10);
  }else{
    servo.write(servoPos);
  }
}

WizenedEE

You'll just want to get rid of every delay in your code. You will probably have to replace it with something like the blink without delay example and a state machine:
Code: [Select]

enum states {SERVO_UP, SERVO_DOWN, MANUAL} state = SERVO_UP;
int servopos;

void loop() {
  static unsigned long prevTime;
  unsigned long curTime = millis();
  if (digitalRead(overridebtn)) state = MANUAL;
  if (curTime - prevTime >= 10) {
    prevTime = curTime;
    switch(state) {
    case SERVO_UP:
      servopos++;
      break;
    case SERVO_DOWN:
      servopos--;
      break;
    case MANUAL:
      if (digitalRead(upbtn)) servopos++;
      else if (digitalRead(downbtn)) servopos--;
      break;
    }
    servo.write(servopos);
  }
}

PaulS

What you need to do in your ISR is set a flag - a boolean called manualOverrideInEffect, perhaps. Initialize that flag to false. Set it to true in the ISR. Then, in loop, check that flag. Do the automatic thing if false, and the manual thing if true.

PeterH

I guess you're thinking to use the interrupt to detect the button press. That's not necessary or (IMO) sensible for this problem.

Just poll the button to detect button presses and update a state variable when the button press is detected. The state variable would indicate whether the sketch is in automatic or manual mode.
I only provide help via the forum - please do not contact me for private consultancy.

Erasermaster

I will definitely look into state machines. I think this is what I need. Thanks!

Go Up