我有一个运动和接近感应器连接到树莓派上。我想要发生的是,当运动传感器检测到运动时,它会从接近感应器获得读数,以查看该人在特定距离内is...once该人有多近,就会显示一条消息。
运动传感器被触发,我从接近传感器获得读数,然而,接近传感器陷入循环,值永远不会更新(即使有人在它上面)。
运动:
import gpio from 'gpio';
import proximity from './proximity';
const gpio4 = gpio.export(4, {
direction: 'in',
});
// bind to the "change" event
gpio4.on('change', (val) => {
// value will report either 1 or 0 (number) when the value changes
if (val === 1) {
console.log('checking proximity');
proximity.getDistance();
}
});接近度:
import gpio from 'gpio';
// pin 38 GPIO 20 - for trigger
const trig = gpio.export(38, {
direction: 'out'
});
// pin 37 GPIO 26 - for echo
const echo = gpio.export(37, {
direction: 'in'
});
function getDistance() {
const speedSound = 34000;
// resetting trigger
trig.set(0);
setTimeout(500);
console.log("initial trig value (0): " + trig.value); // should be 0
responsiveVoice.speak('');
const timestamp = moment().add(30, 's');
let start = 0;
let end = 0;
trig.set();
setTimeout(10);
trig.set(0);
while (echo.value === 0) {
start = new Date().getTime() / 1000;
console.log('Echo is ' + echo.value);
}
while (echo.value === 1) {
end = new Date().getTime() / 1000;
console.log('Echo is ' + echo.value);
let timeDiff = end - start;
let distance = (timeDiff * speedSound) / 2;
console.log('Distance = ' + distance);
if (distance < 60) {
console.log('User is within 2 ft. Enable voice');
return true;
} else {
return false;
}
}
}
module.exports = {
getDistance
};我需要做什么才能在不陷入无限循环的情况下正确地工作呢?
发布于 2016-06-18 03:11:29
您不能执行while循环,期望其他代码运行并更改您正在测试的变量。Javascript是单线程的,只要您在while循环中,就不会运行其他代码,因此您的变量永远不会更改,因此您会有一个无限循环。
所以,就像这样:
while (echo.value === 0) {
start = new Date().getTime() / 1000;
console.log('Echo is ' + echo.value);
}是一个无限循环,如果echo.value启动=== 0的话。只要那个while循环还在运行,echo.value就永远不会改变它的值--因此它最终会变成一个无限循环。这就是单一三位一体和事件驱动的本质。
Javascript是一种事件驱动语言。当前执行线程一直运行到完成,然后(也只有在那时) JS引擎从事件队列中拉出下一个事件,并运行与该事件关联的代码。因此,等待某些外部代码更改某些变量的while循环在Javascript中永远不会工作,因为只要while循环还在运行,外部代码就永远不会运行。
相反,您应该使用本地触发的事件或使用setInterval()每隔一段时间轮询该值(这取决于您的邻近接口是如何工作的)。
另外,下面这样一行代码:
setTimeout(500);什么都不做。首先,setTimeout()需要两个参数。第一个应该是在将来某个时候调用的函数。第二个参数应该是以毫秒为单位的时间值。而且,setTimeout()根本不会暂停执行。它所做的就是安排一个计时器在将来的某个时间触发,然后它会立即执行下一行代码。在Javascript中没有等待。相反,您可以安排一些回调在将来的某个时候运行。
正确的解决方案取决于您的接近感应器接口是如何工作的(在您的问题中没有完全描述)。如果它本身是事件驱动的(这将是理想的),那么你可以只订阅它的一个事件,每次该事件触发时,你可以检查该值并决定应该执行什么操作。这将不涉及任何计时器或任何循环。你可能想保存一些状态,这样当下一个事件触发时,你就知道最近发生了什么,但如果事情是事件驱动的,你就不会进入循环或使用计时器。
如果接口不是事件驱动的,那么您可能需要使用循环的setInterval()计时器“轮询”状态。在这种情况下,您选择某个时间间隔(例如每秒),然后检查接近度值,然后根据您看到的值决定采取什么操作。setInterval()的工作原理是这样的:
// poll once per second
setInterval(function() {
// put some code here that will run every second
}, 1000);
// code here will run immediately - the timer callback runs some time in the future发布于 2016-06-18 03:14:12
因为它被困在while循环中,所以您可以定义一个每秒(或任何时间间隔)递归调用自身的函数来检查echo的值。
您只需要将while循环替换为如下所示的内容。
while (echo.value === 0) {
start = new Date().getTime() / 1000;
console.log('Echo is ' + echo.value);
}
while (echo.value === 1) {
end = new Date().getTime() / 1000;
console.log('Echo is ' + echo.value);
let timeDiff = end - start;
let distance = (timeDiff * speedSound) / 2;
console.log('Distance = ' + distance);
if (distance < 60) {
console.log('User is within 2 ft. Enable voice');
responsiveVoice.speak('Hello, I am Jarvis; welcome to Cardinal Solutions. Please check in.');
return true;
} else {
return false;
}
}变成了
function checkEchoValue() {
if(echo.value === 0) {
console.log("Echo value is zero.");
start = new Date().getTime() / 1000;
} else {
console.log('Echo value is non-zero');
end = new Date().getTime() / 1000;
let timeDiff = end - start;
let distance = (timeDiff * speedSound) / 2;
console.log('Distance = ' + distance);
if (distance < 60) {
console.log('User is within 2 ft. Enable voice');
responsiveVoice.speak('Hello, I am Jarvis; welcome to Cardinal Solutions. Please check in.');
}
}
setTimeout(checkEchoValue, 1000);
//calls this method again in a second
}当您真正想要开始检查值时(可能是while循环现在所在的位置),请确保至少调用一次checkEchoValue()。
https://stackoverflow.com/questions/37888457
复制相似问题