Go Down

Topic: SR04 Something is wrong(Totally solved) (Read 426 times) previous topic - next topic

Frédéric_Plante

Jun 03, 2014, 12:57 am Last Edit: Jun 03, 2014, 06:43 pm by Frédéric_Plante Reason: 1
The module does work, got it working with the Newping library just before posting this. The code does detect some sort of distance, like some multiple of 172.41 but not centimeter. I really do know what the hick is wrong any one feel like helping a bit.

Code: [Select]


#define broche_Trig 12
#define broche_Echo 3

unsigned long last_detection = 0;
const int Ping_interval = 150;

const double k_Mach = 0.0029;

int duration;
double distance;

void setup() {

 attachInterrupt(1, got_echo, FALLING);
 
 pinMode(broche_Trig, OUTPUT);
 pinMode(broche_Echo, INPUT);

 Serial.begin (115200);
 
}

void loop() {

 if(millis() - last_detection >= Ping_interval) {
 
   digitalWrite(broche_Trig, HIGH);
   delayMicroseconds(5);
   digitalWrite(broche_Trig, LOW);
   last_detection = millis();  
   
 }
 
}

void got_echo(){
 
    duration = millis() - last_detection ;
    distance = 0.5 * (duration / k_Mach)   ;
    Serial.println((String)distance + F(" cm"));

}
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

#1
Jun 03, 2014, 02:06 am Last Edit: Jun 03, 2014, 06:17 am by Frédéric_Plante Reason: 1
Ah! I get it...

172.41 * 0.0029 = 0.499989, that is the 1/2 of the distance that the ping does when it hit some thing. So duration must = 1. That mean that my time resolution is not precise enogh.

Ok so millis() is to big, so I changed millis() to micros(),

Code: [Select]

#define broche_Trig 12
#define broche_Echo 3
#define broche_Piezo 8

volatile unsigned long last_detection = 0;
unsigned long last_detection2 = 0;
const int Ping_interval = 150;

const double k_Mach = 29.4117647;

int duration;
double distance;

void setup() {

 attachInterrupt(1, got_echo, FALLING);
 
 pinMode(broche_Trig, OUTPUT);
 pinMode(broche_Echo, INPUT);

 Serial.begin (115200);
 
}

void loop() {
 
 if(millis() - last_detection >= Ping_interval) {
 
   digitalWrite(broche_Trig, HIGH);
   delayMicroseconds(5);
   digitalWrite(broche_Trig, LOW);
   last_detection = millis();  
   last_detection2 = micros();
   
 }
 
 
}

void got_echo(){
 
    duration = micros() - last_detection2 ;
    distance = (0.5  *(duration / k_Mach)) - 8  ; // - 8 ???
    Serial.println((String)distance + F(" cm"));

}



I really don't get why i need to do the "- 8", but this work:
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

Can some one else try my code and tel me if he get the right distance or if there is a 8 cm difference from reality. Who know maybe my module is busted...
As we fight our way northward into the great unknown, only that one thing remains certain...

jremington

Ultrasonic sensors send out several pulses in a burst, so there is some ambiguity about which of the pulses might be received as an echo. Also, with some types of sensors, there is a time lag after the pulse is sent before the receiver is turned on (otherwise it is activated instantly). Do as you've done and calibrate your sensor against a range of distances. If it seems to be working but you come up with a constant offset, that is fine.
"It seems to run on some form of electricity"

Frédéric_Plante

Actually, at 1 meter, it read 108 cm and at 3 cm it read 11cm. This 8 cm is constant. That is ok, i dont really care, i still get a accurate reading if i calculate that constant offset.

The fact that it is constant make me wounder if I should not just associate a constant to it and just declare it at the begining of the code.

Any way, the second code work great. And it does not use pulseIn(). Not using pulseIn() was the chalenge I got from some guy on the French board,

So mission accomplished.
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

#5
Jun 03, 2014, 06:15 am Last Edit: Jun 03, 2014, 07:08 am by Frédéric_Plante Reason: 1
But still that - 8 bug my mind. The math guy in me don't like it

I like when my function are

f(x) = ax

And not

f(x) = ax + b

We are talking about 8 full centimeter that appered out of no where and that were not present in my first code. That is strange.
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

#6
Jun 03, 2014, 06:28 pm Last Edit: Jun 03, 2014, 06:44 pm by Frédéric_Plante Reason: 1
Thanx to B@tto for his patience, this one is totally solved. The constant extra 8 centimetres were caused by the fact that I was using only one interrupt and only on FALLING. In fact we have to measure the time between RISING and FALLING not the time between sending the PING and the end of the receive.


So this code totally work. And it is more instructive the the library, since you can see the whole process on the same page

Code: [Select]

#define broche_Trig 12
#define broche_Echo 3
#define broche_Piezo 8

volatile unsigned long derniere_mesure = 0;
unsigned long debut_ping = 0;
const word interval_mesure = 150;

const double k_Mach = 29.4117647;

double duree;
byte distance;

void setup() {

 
 pinMode(broche_Trig, OUTPUT);
 pinMode(broche_Echo, INPUT);

 Serial.begin (115200);
 
}

void loop() {
 
 if(millis() - derniere_mesure >= interval_mesure) {
 
   digitalWrite(broche_Trig, HIGH);
   delayMicroseconds(10);
   digitalWrite(broche_Trig, LOW);
   derniere_mesure = millis();  
   attachInterrupt(1, echo_percue, RISING);
 
 }
 
}


void echo_percue(){
 
 debut_ping = micros();
 detachInterrupt(1);
 attachInterrupt(1, echo_terminee, FALLING);

}  


void echo_terminee(){
 
 duree = micros() - debut_ping ;
 distance = ((0.5 / k_Mach) * duree );//f(x) = ax + b
 
 if (!(distance >= 150 || distance <= 0)){
   
   Serial.println((String)distance + F(" cm"));
   tone(broche_Piezo, 10500, 5);
   
 }
 
 detachInterrupt(1);
 

}



Also, the ping as to be 10 micro-second long, minimally. It was pinging 5 micro-second, It should not of work at all.
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

So, the Unit need a certain time beteween the moment the trig pin get to HIGH and the moment it send the Ping. Basically this can be calculate this way, in the case of my SR04.

Code: [Select]


~8cm ÷ Mach

OR

~8cm ÷ 340m/s

OR

~0,08m/s  ÷ 340m

So

~0.00024s

Or

~2.4 ?s




Now the next step will be to remove the Time base sending and change it for a Boolean base sending. This way It will not send a Ping before it has ended the process of receiving the Ping it as send before.
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

#8
Jun 03, 2014, 07:20 pm Last Edit: Jun 03, 2014, 08:48 pm by Frédéric_Plante Reason: 1
Now the process is so fast that I have to put a delay(100) so the Serial port doesn't hang cause it has to much data to send. lol

So this is my final brew. If you have any question, just Ask

Code: [Select]

#define broche_Trig 12
#define broche_Echo 3
#define broche_Piezo 8

unsigned long debut_ping = 0;

const double k_Mach = 29.4117647;

byte distance;
bool en_attente = false;

void setup() {

 
 pinMode(broche_Trig, OUTPUT);
 pinMode(broche_Echo, INPUT);

 Serial.begin (115200);
 
}

void loop() {
 
 
 if(en_attente == false) {

   delay(100);
   digitalWrite(broche_Trig, HIGH);
   delayMicroseconds(10);
   digitalWrite(broche_Trig, LOW);
   attachInterrupt(1, echo_percue, RISING);
   en_attente = true;
   
 }
 
}

void echo_percue(){
 
 debut_ping = micros();
 detachInterrupt(1);
 attachInterrupt(1, echo_terminee, FALLING);

}  

void echo_terminee(){
 
 distance = ((0.5 / k_Mach) * (micros() - debut_ping)); // f(x) = ax -> x = ?t
 
 if (!(distance >= 150 || distance <= 0)){
   
   Serial.println((String)distance + F(" cm"));
   tone(broche_Piezo, 10500 / distance , 5);
   
 }
 
 detachInterrupt(1);
 en_attente = false;

}
As we fight our way northward into the great unknown, only that one thing remains certain...

Go Up