Closed Guttata closed 6 years ago
I try the code for the "Measure distance with a HC-SR04 ultrasonic sensor" and it's working. Thanks for that.
You're welcome :smile:
We declare an async anonymous function with a callback function inside the echo.on ?
There are two anonymous functions in the code posted above. Neither of them is async. echo.on
is however async. The second parameter passed to echo.on
is a callback function. On the screen it may look like this callback function is "inside the echo.on" but this isn't the case.
How can i retrieve the distance from outside this callback function and anonymous function ?
Below is a modified variant of the example program form the readme. It implements an async function called measureDistance
which expects a callback function as a parameter. When called, measureDistance
will measure the distance and call the callback with the measured distance. I hope this makes things a little clearer.
var Gpio = require('../').Gpio,
trigger = new Gpio(23, {mode: Gpio.OUTPUT}),
echo = new Gpio(24, {mode: Gpio.INPUT, alert: true});
// The number of microseconds it takes sound to travel 1cm at 20 degrees celcius
var MICROSECDONDS_PER_CM = 1e6/34321;
trigger.digitalWrite(0); // Make sure trigger is low
function measureDistance(callback) {
var startTick;
function alertHandler(level, tick) {
var endTick,
diff;
if (level == 1) {
startTick = tick;
} else {
endTick = tick;
diff = (endTick >> 0) - (startTick >> 0); // Unsigned 32 bit arithmetic
callback(diff / 2 / MICROSECDONDS_PER_CM);
echo.removeListener('alert', alertHandler);
}
}
echo.on('alert', alertHandler);
trigger.trigger(10, 1); // Set trigger high for 10 microseconds
}
// Trigger a distance measurement once per second
setInterval(function () {
measureDistance(function (distance) {
console.log(distance + 'cm');
});
}, 1000);
Hi fivdi,
Thanks for the quick reply, it clarifies things.
I managed to do what a want just before your reply... but i'm still in trouble with this new paradigm...ASYNC.
I'am building an autonomous car. I manage without problem to pilot it in manual mode (no sensor measurement). But i'am facing a wall with the autoPilot mode.
function Car () {
//Motor engine instanciation
...
//Ultrason sensor instanciation
this.FrontUltrasonicSensor = new UltrasonicSensor (constants.FRONT_ULTRASONIC_SENSOR_ECHO_GPIO, constants.FRONT_ULTRASONIC_SENSOR_TRIG_GPIO);
this.FrontRightUltrasonicSensor = new UltrasonicSensor (constants.FRONT_RIGHT_ULTRASONIC_SENSOR_ECHO_GPIO, constants.FRONT_RIGHT_ULTRASONIC_SENSOR_TRIG_GPIO);
this.FrontLeftUltrasonicSensor = new UltrasonicSensor (constants.FRONT_LEFT_ULTRASONIC_SENSOR_ECHO_GPIO, constants.FRONT_LEFT_ULTRASONIC_SENSOR_TRIG_GPIO);
this.BackUltrasonicSensor = new UltrasonicSensor (constants.BACK_ULTRASONIC_SENSOR_ECHO_GPIO, constants.BACK_ULTRASONIC_SENSOR_TRIG_GPIO);
this.autoPilotOn = false;
}
function UltrasonicSensor (echoGpio, trigGpio){
this.echo = new Gpio(echoGpio, {mode: Gpio.INPUT, alert: true});
this.trigger = new Gpio(trigGpio, {mode: Gpio.OUTPUT});
this.distance = 0;
}
I manage to take the sensor value with this function. It stores the distance value inside the distance attribute of the sensor object passed in param.
Car.prototype.measureDistance = function (sensor){
sensor.trigger.digitalWrite(0); // Make sure trigger is low
var startTick;
var distance;
// The number of microseconds it takes sound to travel 1cm at 20 degrees celcius
var MICROSECDONDS_PER_CM = 1e6/34321;
sensor.echo.on('alert', function (level, tick) {
var endTick,
diff;
if (level == 1) {
startTick = tick;
} else {
endTick = tick;
diff = (endTick >> 0) - (startTick >> 0); // Unsigned 32 bit arithmetic
distance = diff / 2 / MICROSECDONDS_PER_CM;
sensor.distance = distance;
console.log("sensor distance:", sensor.distance);
}
});
sensor.intervalObj = setInterval(function(){
sensor.trigger.trigger(10, 1); // Set trigger high for 10 microseconds
}, 1000);
}
I'm calling this function this way in my WebSocket Server:
client.on('AUTO PILOT', () => {
myCar.measureDistance(myCar.FrontUltrasonicSensor);
myCar.measureDistance(myCar.FrontRightUltrasonicSensor);
myCar.measureDistance(myCar.FrontLeftUltrasonicSensor);
myCar.measureDistance(myCar.BackUltrasonicSensor);
myCar.autoPilot();
});
So that it starts asynchronous measurement, and then i call my autoPilot function.
Car.prototype.autoPilot = function (){
this.autoPilot = true;
while (autoPilotOn) {
while (!frontObstacleDetected) {
this.moveUp();
}
// ....
}
}
PROBLEM: As soon as i enter inside the first While loop. It seams that my async measure stops.
I tried to remove the While loop and calling the function this way:
client.on('AUTO PILOT', () => {
myCar.measureDistance(myCar.FrontUltrasonicSensor);
myCar.measureDistance(myCar.FrontRightUltrasonicSensor);
myCar.measureDistance(myCar.FrontLeftUltrasonicSensor);
myCar.measureDistance(myCar.BackUltrasonicSensor);
//myCar.autoPilot();
myCar.intervalObj = setInterval(function(){myCar.autoPilot();}, 1000);
});
First advantage i manage to stop the autoPilot on socket event by clearing the intervalObj but now with this i get a lot more distance measurement. As if new myCar.measureDistance were called in addition to the previous one. Maybe because i don't have the echo.removeListener in my code ?
Thanks to help a complete beginner in the complexity of the multiple async paradigm
Typically, does this can work (in term of callback ...) ?
Car.prototype.measureDistance = function (sensor, callback) {
sensor.trigger.digitalWrite(0); // Make sure trigger is low
var startTick;
var distance;
// The number of microseconds it takes sound to travel 1cm at 20 degrees celcius
var MICROSECDONDS_PER_CM = 1e6/34321;
sensor.echo.on('alert', function (level, tick) {
var endTick,
diff;
if (level == 1) {
startTick = tick;
} else {
endTick = tick;
diff = (endTick >> 0) - (startTick >> 0); // Unsigned 32 bit arithmetic
distance = diff / 2 / MICROSECDONDS_PER_CM;
sensor.distance = distance;
calback();
}
});
sensor.trigger.trigger(10, 1); // Set trigger high for 10 microseconds
}
Car.prototype.measureDistances = function(callback) {
this.measureDistance(this.FrontUltrasonicSensor, callback);
this.measureDistance(this.FrontRightUltrasonicSensor, callback);
this.measureDistance(this.FrontLeftUltrasonicSensor, callback);
this.measureDistance(this.BackUltrasonicSensor, callback);
}
Car.prototype.autoPilot= function() {
this.autoPilotOn = true;
if (!this.frontObstacle())
{
this.moveUp();
} else {
var direction = this.chooseDirection();
switch direction:
//code
}
}
//websocket.js
client.on('STOP', () => {
if (myCar.autoPilotOn) {
console.log("STOP AUTOPILOT");
clearInterval(myCar.intervalObj);
myCar.autoPilotOn = false;
}
myCar.stop();
});
client.on('AUTO PILOT', () => {
myCar.intervalObj = setInterval(function () {
myCar.measureDistances(function () {
myCar.autoPilot();
});
}, 1000);
});
Thanks a lot again.
Code like the following is no-go as it will block all async code from executing.
Car.prototype.autoPilot = function (){
this.autoPilot = true;
while (autoPilotOn) {
while (!frontObstacleDetected) {
this.moveUp();
}
// ....
}
}
In Node.js there is only one thread that executes JavaScript code and it will get stuck in the (potentially infinite) while loop above. None of the async code will get a chance to execute.
Maybe because i don't have the echo.removeListener in my code ?
The echo.removeListener
is essential.
Code like the following isn't a good idea:
this.measureDistance(this.FrontUltrasonicSensor, callback);
this.measureDistance(this.FrontRightUltrasonicSensor, callback);
this.measureDistance(this.FrontLeftUltrasonicSensor, callback);
this.measureDistance(this.BackUltrasonicSensor, callback);
This code will start a measurement on four ultrasonic sensors at the same time. The ultrasonic sound pulses from the different sensors are likely to interfere with each other and give incorrect readings. The readings will need to be performed one after another.
I'm afraid there are too many questions above that I don't fully understand. To be honest, you may be trying to achieve too much in one step initially. The first thing is to understand how is Node.js is supposed to work. What async code is hand how it works. Without grasping this it's going to be difficult to impossible to achieve what you would like to achieve.
I'm going to go ahead and close this issue as there are no to-dos for pigpio. Good luck with the autonomous car.
Hi,
Thanks again for your help. I will test step by test.
For your information, the "echo.removeListener" is not mentioned inside the readme and the published example.
Hi, i'm sorry it is not a issue but more an help request. I am new to the NODE JS and javascript world. I try the code for the "Measure distance with a HC-SR04 ultrasonic sensor" and it's working. Thanks for that.
Nevertheless, i don't understand the syntax of this part of code: We declare an async anonymous function with a callback function inside the echo.on ?
How can i retrieve the distance from outside this callback function and anonymous function ? A struggle few hours on this. Thanks a lot.