Ultrasonic gives wrong output

Hello
I have a robot with 2 motors and 5 ultrasonic sensors and 2 enchoder and more components

Every 1 weel turn enchoder gives 30750 pulses and due to this reason it need to be on interupt

The issue is when the motors start working the ulterasonics gives wrong values , looks like the intrupt is adding too much delay , what should i do ?
Im using arduino mega

#define encoderr 2
#define encoderl 3

#define echo1 64
#define echo2 66
#define echo3 68
#define trig1 65
#define trig2 67
#define trig3 69
#define echo4 41
#define echo5 31
#define trig4 43
#define trig5 33

#define motorr_p 7     // motor - and + conectors
#define motorr_m 5
#define motorl_p 8
#define motorl_m 4

 long int dispulser = 0;  // enchoder pulses till now 
 long int dispulsel = 0;


long duration, distance  ;
int rightsensor, midsensor, leftsensor ,right2sensor, mid2sensor, left2sensor;

 void ultra_sonics(int trigPin, int echoPin)
{
  digitalWrite(trigPin, 0);
  delayMicroseconds(2);

  digitalWrite(trigPin, 1);
  delayMicroseconds(10);
  digitalWrite(trigPin, 0);
  duration = pulseIn(echoPin, 1 , 26000);
  distance = distance;
  distance = duration * 0.034/2;
}


void enr()
{
    dispulser ++;
}

void enl()
{
    dispulsel ++ ;
}

void check_ul_sen()
{
  ultra_sonics(trig1, echo1);
  leftsensor = distance;

  ultra_sonics(trig2, echo2);
  rightsensor = distance;
  
  ultra_sonics(trig3, echo3);
  midsensor = distance; 
  
  ultra_sonics(trig4, echo4);
  right2sensor = distance;
  
  ultra_sonics(trig5, echo5);
  left2sensor = distance;
  

  

  
}

void setup() {
  // put your setup code here, to run once:
  pinMode(motorl_p , OUTPUT);
  pinMode(motorl_m , OUTPUT);
  pinMode(motorr_p , OUTPUT);
  pinMode(motorr_m , OUTPUT);

  pinMode(trig1, OUTPUT);
  pinMode(trig2, OUTPUT);
  pinMode(trig3, OUTPUT);
  pinMode(trig4, OUTPUT);
  pinMode(trig5, OUTPUT);
  pinMode(echo1, INPUT);
  pinMode(echo2, INPUT);
  pinMode(echo3, INPUT);
  pinMode(echo4, INPUT);
  pinMode(echo5, INPUT);

  Serial.begin(115200);
    
  attachInterrupt(digitalPinToInterrupt(encoderr), enr, RISING); 
  attachInterrupt(digitalPinToInterrupt(encoderl), enl, RISING); 

}

void loop() {
  // put your main code here, to run repeatedly:
  check_ul_sen();
  //analogWrite(motorl_p , 255);
  //analogWrite(motorl_m , 0);

  //analogWrite(motorr_p , 255);
 // analogWrite(motorr_m , 0);

  Serial.print('L');
  Serial.print(leftsensor);
  Serial.print(" R ");
  Serial.print(rightsensor);
  Serial.print(" M ");
  Serial.print(midsensor);
  Serial.print(" L2 ");
  Serial.print(left2sensor);
  Serial.print(" R2 ");
  Serial.println(right2sensor);
  Serial.print(" enl ");
  Serial.print(dispulsel);
  Serial.print(" enr ");
  Serial.println(dispulser);
  
  delay(300);
  
  


}

Code link

motors on

Motors off

Please help thanks

If you suspect it's an interrupt problem, try using a call to noInterrupts() before the reading and interrupts() after it:

void ultra_sonics(int trigPin, int echoPin)
{
  noInterrupts();
  digitalWrite(trigPin, 0);
  delayMicroseconds(2);

  digitalWrite(trigPin, 1);
  delayMicroseconds(10);
  digitalWrite(trigPin, 0);
  duration = pulseIn(echoPin, 1 , 26000);
  distance = distance;
  distance = duration * 0.034/2;
  interrupts();
}

Okay yes its intrupt i tested it with yoursuggestion but now enchoder is not counting, i want both enchoder and ulterasonics work together, is there any way that they can ?

try

#define encoderr 2
#define encoderl 3

const byte US_pins[5][2] = {
  {65, 64},
  {67, 66},
  {69, 68},
  {43, 41},
  {33, 31}
};

#define motorr_p 7     // motor - and + conectors
#define motorr_m 5
#define motorl_p 8
#define motorl_m 4

volatile uint32_t  dispulser = 0;  // encoder pulses till now
volatile uint32_t  dispulsel = 0;

enum Sensors {rightsensor, midsensor, leftsensor , right2sensor, left2sensor };

uint16_t ultra_sonics(byte sensor) {
  static uint32_t duration = 0;
  noInterrupts();
  digitalWrite(US_pins[sensor][0], 1);
  delayMicroseconds(10);
  digitalWrite(US_pins[sensor][0], 0);
  duration = pulseIn(US_pins[sensor][1], 1 , 26000);
  interrupts();
  return duration / 57;
}


void enr()
{
  dispulser ++;
}

void enl()
{
  dispulsel ++ ;
}

void setup() {
  pinMode(motorl_p , OUTPUT);
  pinMode(motorl_m , OUTPUT);
  pinMode(motorr_p , OUTPUT);
  pinMode(motorr_m , OUTPUT);

  for (byte i = rightsensor; i <= left2sensor; i++) {
    pinMode(US_pins[i][0], OUTPUT);
    pinMode(US_pins[i][1], OUTPUT);
  }

  Serial.begin(115200);

  attachInterrupt(digitalPinToInterrupt(encoderr), enr, RISING);
  attachInterrupt(digitalPinToInterrupt(encoderl), enl, RISING);
}

void loop() {

  //analogWrite(motorl_p , 255);
  //analogWrite(motorl_m , 0);

  //analogWrite(motorr_p , 255);
  // analogWrite(motorr_m , 0);

  char bufer[50];
  sprintf(bufer, "L%d R%d M%d L2%d R2%d enl%u enr%u\r\n",
          ultra_sonics(leftsensor),
          ultra_sonics(rightsensor),
          ultra_sonics(midsensor),
          ultra_sonics(left2sensor),
          ultra_sonics(right2sensor),
          dispulsel,
          dispulser
         );
  noInterrupts();
  for(byte i=0;i<sizeof(bufer);i++)Serial.print(bufer[i]);
  interrupts();
  delay(300);
}

Will this code miss any enchoder steps ??

The main problem should be "pulseIn()" wating for the pulse (up to 26 milliseconds), but looking at your full code, the only reason why encoders ISR could miss RISING state is in the variables you increase, missing the "volatile" keyword!
Try this (instead of the noInterrupts changes):

 volatile long int dispulser = 0;  // enchoder pulses till now 
 volatile long int dispulsel = 0;

PS: "Encoder" has no "h" inside...:wink:

1 Like

I suggest checking all the parts separately.

Capture

As you see it still gives wrong resalts when motor is on

What do you mean by that ?

Same , when motor is on valaues are wrong

it is not my code

So is there any way that i can fix this issue ?

Your encoders give 30,750 pulses per wheel turn, this is a high frequency for an Arduino to handle along with other tasks. Some motor controllers have built-in encoder inputs that can manage this without burdening the main CPU.
Try this "non-blocking code"

volatile long dispulser = 0;  // Make these volatile since they are modified in ISR
volatile long dispulsel = 0;

unsigned long lastTriggerTime = 0;
const unsigned long triggerInterval = 20;  // Interval to trigger new measurement in ms

void ultra_sonics_nonblocking(int trigPin, int echoPin, long &result) {
  unsigned long now = millis();
  if (now - lastTriggerTime >= triggerInterval) {
    // Trigger ultrasonic pulse
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    lastTriggerTime = now;
  }
  
  long duration = pulseIn(echoPin, HIGH, 26000);
  if (duration > 0) {
    result = duration * 0.034 / 2;
  }
}

void isrRight() {
  dispulser++;
}

void isrLeft() {
  dispulsel++;
}

void setup() {
  // youe existing code
}

void loop() {
  ultra_sonics_nonblocking(trig1, echo1, leftsensor);
  ultra_sonics_nonblocking(trig2, echo2, rightsensor);
  ultra_sonics_nonblocking(trig3, echo3, midsensor);
  ultra_sonics_nonblocking(trig4, echo4, right2sensor);
  ultra_sonics_nonblocking(trig5, echo5, left2sensor);
  
  // Rest of code
}

If i put arduino due will this problem get solved ??

It could help since clock speed, processor and ram are better. But you still have to address interrupts, motor control and sensor readings.

It gives an error

C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino: In function 'void loop()':
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:79:56: error: cannot bind non-const lvalue reference of type 'long int&' to an rvalue of type 'long int'
       ultra_sonics_nonblocking(trig1, echo1, leftsensor);
                                                        ^
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:27:10: note:   initializing argument 3 of 'void ultra_sonics_nonblocking(int, int, long int&)'
     void ultra_sonics_nonblocking(int trigPin, int echoPin, long &result) {
          ^~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:80:57: error: cannot bind non-const lvalue reference of type 'long int&' to an rvalue of type 'long int'
       ultra_sonics_nonblocking(trig2, echo2, rightsensor);
                                                         ^
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:27:10: note:   initializing argument 3 of 'void ultra_sonics_nonblocking(int, int, long int&)'
     void ultra_sonics_nonblocking(int trigPin, int echoPin, long &result) {
          ^~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:81:55: error: cannot bind non-const lvalue reference of type 'long int&' to an rvalue of type 'long int'
       ultra_sonics_nonblocking(trig3, echo3, midsensor);
                                                       ^
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:27:10: note:   initializing argument 3 of 'void ultra_sonics_nonblocking(int, int, long int&)'
     void ultra_sonics_nonblocking(int trigPin, int echoPin, long &result) {
          ^~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:82:58: error: cannot bind non-const lvalue reference of type 'long int&' to an rvalue of type 'long int'
       ultra_sonics_nonblocking(trig4, echo4, right2sensor);
                                                          ^
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:27:10: note:   initializing argument 3 of 'void ultra_sonics_nonblocking(int, int, long int&)'
     void ultra_sonics_nonblocking(int trigPin, int echoPin, long &result) {
          ^~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:83:57: error: cannot bind non-const lvalue reference of type 'long int&' to an rvalue of type 'long int'
       ultra_sonics_nonblocking(trig5, echo5, left2sensor);
                                                         ^
C:\Users\Lenovo\AppData\Local\Temp\.arduinoIDE-unsaved2023812-15724-ib5ykh.le98b\sketch_sep12a\sketch_sep12a.ino:27:10: note:   initializing argument 3 of 'void ultra_sonics_nonblocking(int, int, long int&)'
     void ultra_sonics_nonblocking(int trigPin, int echoPin, long &result) {
          ^~~~~~~~~~~~~~~~~~~~~~~~

exit status 1

Compilation error: cannot bind non-const lvalue reference of type 'long int&' to an rvalue of type 'long int'

The code


#define encoderr 2
#define encoderl 3
 
#define echo1 64
#define echo2 66
#define echo3 68
#define trig1 65
#define trig2 67
#define trig3 69
#define echo4 41
#define echo5 31
#define trig4 43
#define trig5 33
 
#define motorr_p 7     // motor - and + conectors
#define motorr_m 5
#define motorl_p 8
#define motorl_m 4

    volatile long dispulser = 0;  // Make these volatile since they are modified in ISR
    volatile long dispulsel = 0;

    int rightsensor, midsensor, leftsensor ,right2sensor, mid2sensor, left2sensor;
    unsigned long lastTriggerTime = 0;
    const unsigned long triggerInterval = 20;  // Interval to trigger new measurement in ms
     
    void ultra_sonics_nonblocking(int trigPin, int echoPin, long &result) {
      unsigned long now = millis();
      if (now - lastTriggerTime >= triggerInterval) {
        // Trigger ultrasonic pulse
        digitalWrite(trigPin, LOW);
        delayMicroseconds(2);
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);
        lastTriggerTime = now;
      }
     
      long duration = pulseIn(echoPin, HIGH, 26000);
      if (duration > 0) {
        result = duration * 0.034 / 2;
      }
    }
     
    void enr() {
      dispulser++;
    }
     
    void enl() {
      dispulsel++;
    }
     
    void setup() {
      // youe existing code// put your setup code here, to run once:
  pinMode(motorl_p , OUTPUT);
  pinMode(motorl_m , OUTPUT);
  pinMode(motorr_p , OUTPUT);
  pinMode(motorr_m , OUTPUT);
 
  pinMode(trig1, OUTPUT);
  pinMode(trig2, OUTPUT);
  pinMode(trig3, OUTPUT);
  pinMode(trig4, OUTPUT);
  pinMode(trig5, OUTPUT);
  pinMode(echo1, INPUT);
  pinMode(echo2, INPUT);
  pinMode(echo3, INPUT);
  pinMode(echo4, INPUT);
  pinMode(echo5, INPUT);
 
  Serial.begin(115200);
   
  attachInterrupt(digitalPinToInterrupt(encoderr), enr, RISING);
  attachInterrupt(digitalPinToInterrupt(encoderl), enl, RISING); 

    }
     
    void loop() {
      ultra_sonics_nonblocking(trig1, echo1, leftsensor);
      ultra_sonics_nonblocking(trig2, echo2, rightsensor);
      ultra_sonics_nonblocking(trig3, echo3, midsensor);
      ultra_sonics_nonblocking(trig4, echo4, right2sensor);
      ultra_sonics_nonblocking(trig5, echo5, left2sensor);
     
       analogWrite(motorl_p , 255);
  analogWrite(motorl_m , 0);
 
  analogWrite(motorr_p , 255);
  analogWrite(motorr_m , 0);
      // Rest of code
    }

Sorry i don't undrestand the second part so as the cpu speed is higher on arduino due , still there should be a delay for ulterasonics and as i said for 1 360 wheel turn my encoder gives around 30750 pulses witch is alot so will i still get wrong resalts ?

Is it better to just put an nano or uno for just ulterasonics ?

Try definining the sensors as "long" instead of "int".

Thanks , but i tested the code and it gives 99 insted of 137 still the values are wrong

Also due to using pwm , motor speed will get higher and lower in future .