0

I'm working on my first arduino project, Sumo Robot, therefore i dont know much about programming yet. We are supposed to use two IR sensors one on the front of the robot other on its back to avoid crossing the black line of the arena. I wrote this simple code to control the motors. But i have been asked to use interrupts to raise the efficiency of my code.

So do you guys have an idea of how i can use interrupts with the L298n motor driver to move my dc motors forward and backward.

Here is my code

int fIR=7;
int bIR=8;
int fIR_value;
int bIR_value;      
const int trigPin = 9;
const int echoPin = 11;

long duration;
int distance;

int IN1 = 4;
int IN2 = 5;
int IN3 = 6;
int IN4 = 12;

void setup() {
  Serial.begin(9600);
  pinMode(fIR,INPUT);
  pinMode(fIR,INPUT);
  pinMode(trigPin,OUTPUT);
  pinMode(echoPin,INPUT);
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);


}

void loop() {

  fIR_value = digitalRead(fIR);
  Serial.print("Front IR:");
  Serial.print(fIR_value);
  Serial.print(" , ");

  bIR_value = digitalRead(bIR);
  Serial.print("Back IR:");
  Serial.print(bIR_value);
  Serial.print(" , ");

  digitalWrite(trigPin, LOW);
  delayMicroseconds(10);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);  
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration*0.034/2;
  Serial.print("Distance: ");
  Serial.println(distance);
  delay (500);

  if(distance<30&&fIR_value==HIGH&&bIR_value==LOW){
    STOP();
    delay(50);
    BACKWARD(); 
//    Serial.print("1");
  }
  else if(distance<30&&fIR_value==LOW&&bIR_value==HIGH){
    STOP();
    delay(50);
    FORWARD();
//    Serial.print("2");

  }
  else if(distance<30&&fIR_value==LOW&&bIR_value==LOW){
    STOP();
    delay(50);
    FORWARD();
//    Serial.print("3");

  }
    else if(distance>30&&fIR_value==LOW&&bIR_value==LOW){
    STOP();
    delay(50);
    ROTATE();
//    Serial.print("4");

  }
   else if(distance>30&&fIR_value==HIGH&&bIR_value==LOW){
    STOP();
    delay(50);
    BACKWARD();
//    Serial.print("5");

  }
   else if(distance>30&&fIR_value==LOW&&bIR_value==HIGH){
    STOP();
    delay(50);
    FORWARD();
//    Serial.print("6");

  }
}

void FORWARD(){

  digitalWrite(IN1,200);
  digitalWrite(IN2,0);
  digitalWrite(IN3,0);
  digitalWrite(IN4,200);
}
void BACKWARD(){

  digitalWrite(IN1,0);
  digitalWrite(IN2,200);
  digitalWrite(IN3,200);
  digitalWrite(IN4,0);
}
void ROTATE(){

  digitalWrite(IN1,200);
  digitalWrite(IN2,0);
  digitalWrite(IN3,200);
  digitalWrite(IN4,0);
}
void STOP(){

  digitalWrite(IN1,0);
  digitalWrite(IN2,0);
  digitalWrite(IN3,0);
  digitalWrite(IN4,0);
}
New contributor
Saba Jayyusi is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • don't you think that you should use interrupts for the sensors? – jsotola 2 days ago
  • if you didnt use interrupts with the sensors, then what would be the source of interrupts from the L298n? – jsotola 2 days ago
  • Oh that's smart 🙃 – Saba Jayyusi 2 days ago
  • How can I DM you.. Im new to this – Saba Jayyusi 2 days ago
  • learn how to use an interrupt on one pin ... use an interrupt with one sensor to light an LED – jsotola 2 days ago
0

As jsotola already suggested in the comments, using interrupts for driving the motors does not make sense. With a L298N you simply set the outputs and then leave them alone until you think they should stop.

Instead you could use interrupts for your sensors.

Though I would argue, that using interrupts would not be really necessary, when you implement your code the right way, means non-blocking. You use a lot of delay() calls. where the Arduino does not do anything, just twiddling thumbs. Instead you could use the principle from the BlinkWithoutDelay example, that comes with the Arduino IDE, to write the code non-blocking. In that case every bit of code would only do something, if it needs to, and otherwise return fast. That would make your code run way faster. You would also need to set a lower timeout for the pulseIn() function, as it's standard timeout is 1s (ultrasonic sensors like you are using one normally can only sense up to 3m, would would correspond to 20ms max pulse duration, if I'm doing the math correctly).

If using interrupts is a mandatory part of your excercise, you can decide, where to use interrupts:

  • The simplest way would be for the IR sensors. You could use the attachInterrupt() function to set up an Interrupt Service Routine (ISR) for the corresponding pin. If you want the interrupt to trigger, when the IR sensors go HIGH, you can use RISING, otherwise you can use FALLING. Keep in mind, that ISRs should be as small and fast as possible. You cannot use delay() there. Normally one would only set simple (1 byte) variables in the ISR, and then react with longer actions in the main code by checking these variables. You have you set every variable, that can be changed in an ISR, as volatile:

    volatile byte flag;
    
  • For the ultrasonic sensor, you have more than one way to go. I will outline 2 ways. For both of them you need to either directly manipulate the Special Function Registers of the microcontroller, or find a library, that does that for you (don't know, if such libraries exist, but you can search for them):

    1. You could use the Pin Change Interrupt. It triggers everytime, when a pin from a full pin port (group of up to 8 pins) changes it's state. You can mask away unused pins, so that they will not influence the interrupt. In the ISR you can check the state of the pin. If it is high, the start of the pulse just happened. Save a timestamp of that moment with the micros() function. The next ISR (where the pin will be LOW) will mark the end of the pulse. Now you can calculate the time difference between the timestamp and the current micros() value. You should use a 1-byte variable as flag, to trigger the processing the the pulse duration in the main function (or, if you want to directly use the time difference variable, you need to turn of the interrupt, while you are using the variable).

    2. If you want to show off, you could use a hardware Timer in Input Capture mode (this is the more complex, then the other possibilities). The timer is a counter, that is connected to the system clock (through a prescaler, where you can change the count frequency in a coarse way). The timer starts and when the Input Capture pin ICP1 (in case of Timer1) changes it's state, the current value of the timer will be saved in an extra register and an interrupt is fired. This timer value is like a timestamp. If you record the timestamps for the rising and the falling edge of the pulse, you can take the difference and calculate the time difference/distance from this. This part works similar to the first way above. The notes about interrupts also apply here.

Your Answer

Saba Jayyusi is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.