我有一个运动和接近传感器连接到树莓派。我想要发生的是当运动传感器检测到一个动作时,它从接近传感器获取一个读数,看看该人的距离......一旦该人进入一定距离,就会显示一条消息。
正在触发运动传感器并且我从接近传感器获得读数,然而,接近传感器陷入循环并且值不会更新(即使有人在右上方它)。
动议: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
};
接近度:
toggle()
我需要做些什么才能让它正常工作而不会陷入无限循环?
答案 0 :(得分:2)
你不能做一个while循环,期望运行一些其他代码并改变你正在测试的变量。 Javascript是单线程的,只要你在while循环中,就不会运行其他代码,所以你的变量永远不会改变,因此你有一个无限循环。
所以,像这样:
fib = fn
a,b,0 -> a
a,b,n -> fib.(b, a+b, n-1)
end
IO.puts Enum.sum(Enum.filter(Enum.map(1..50, fn n -> fib.(0,1,n) end), even and fn(x) -> x < 4000000 end))
如果undefined function fib/0
(elixir) src/elixir_fn.erl:33: anonymous fn/3 in :elixir_fn.expand/3
(stdlib) lists.erl:1238: :lists.map/2
(stdlib) lists.erl:1238: :lists.map/2
(elixir) src/elixir_fn.erl:36: :elixir_fn.expand/3
开始while (echo.value === 0) {
start = new Date().getTime() / 1000;
console.log('Echo is ' + echo.value);
}
,则是一个无限循环。只要echo.value
循环正在运行,=== 0
永远不会更改其值 - 因此它最终会产生无限循环。这是单线程性和事件驱动性的本质。
Javascript是一种事件驱动语言。当前执行线程一直运行直到完成,然后(并且只有那时)JS引擎从事件队列中提取下一个事件并运行与该事件关联的代码。因此,等待某些外部代码更改某些变量的while
循环在Javascript中永远不会起作用,因为只要echo.value
循环正在运行,外部代码就永远无法运行。
相反,您应该使用本机触发事件或使用while
每隔一段时间轮询一次值(这取决于您的感应界面的工作方式)。
此外,还有一行代码:
while
绝对没有。首先,setInterval()
需要两个参数。第一个应该是将来某个时候打电话的功能。第二个参数应该是以ms为单位的时间值。并且,setTimeout(500);
根本不会暂停执行。它所做的就是安排计时器在将来激活一段时间,然后立即执行下一行代码。在Javascript中没有等待。相反,您计划在将来的某个时间运行一些回调。
这里正确的解决方案取决于接近传感器接口的工作原理(在您的问题中未完全描述的内容)。如果它本身是事件驱动的(这将是理想的),那么你可以只订阅它的一个事件,每次事件触发时,你可以检查值并决定应该执行什么操作。这不涉及任何计时器或任何循环。您可能希望保存某个状态,以便在下一个事件触发时,您知道最近发生了什么,但如果事件是由事件驱动的,则不会进入循环或使用计时器。
如果接口不是事件驱动的,那么您可能需要使用定期setTimeout()
计时器“轮询”该状态。在这种情况下,您选择一些时间间隔(例如每秒),然后检查接近值,然后根据您看到的值确定要采取的操作。 setTimeout()
的作用如下:
setInterval()
答案 1 :(得分:0)
因为它被卡在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()。