覆盆子pi邻近检测nodejs

我有一个运动和接近传感器连接到树莓派。 我想要发生的事情是,当运动传感器检测到运动时,它从接近传感器获取读数以查看人的距离。一旦人进入一定的距离,就会显示一条消息。

运动传感器正在被触发,我正从接近传感器读取数据,但接近传感器陷入一个循环,数值不会更新(即使有人在其上)。

议案:

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 }; 

我需要做什么才能正确工作,而不会陷入无限循环?

你不能做一个while循环期待其他代码运行,并改变你正在testing的variables。 Javascript是单线程的,只要你在while循环中,没有其他代码会运行,所以你的variables永远不会改变,因此你有一个无限循环。

所以,这样的事情:

 while (echo.value === 0) { start = new Date().getTime() / 1000; console.log('Echo is ' + echo.value); } 

是一个无限循环如果echo.value开始了=== 0 。 只要while循环正在运行, echo.value永远不会改变它的值 – 因此它最终会导致一个无限循环。 这是单线程性和事件驱动性的本质。

Javascript是一种事件驱动的语言。 当前的执行线程一直运行直到完成,然后(并且只有这样)JS引擎才从事件队列中拉取下一个事件并运行与该事件相关的代码。 因此, while循环等待一些外部代码来改变一些variables在Javascript中永远不会工作,因为只要while循环运行,外部代码就永远不会运行。

相反,您应该使用本机触发的事件或使用setInterval()每隔一段时间轮询一次值(这取决于您的接近界面如何工作)。


另外,这样一行代码:

 setTimeout(500); 

完全没有。 首先, setTimeout()需要两个参数。 第一个应该是将来某个时间调用的函数。 第二个参数应该是以ms为单位的时间值。 而且, setTimeout()根本不会暂停执行。 它所要做的就是安排一个定时器,以便在将来触发一段时间,然后立即执行下一行代码。 在Javascript中没有等待。 相反,您将安排一些callback以便将来运行。


这里的正确解决scheme取决于您的接近传感器接口如何工作(在您的问题中没有完全描述的东西)。 如果是,事件驱动(这将是理想的),那么你可以订阅它的一个事件,每当事件触发时,你可以检查这个值并决定应该执行什么操作。 这不涉及任何定时器或任何循环。 您可能想要保存某个状态,以便在下一个事件触发时知道最近发生的事情,但是如果事件是事件驱动的,则不会进入循环或使用计时器。

如果接口不是事件驱动的,则可能需要使用定期的setInterval()定时器来“轮询”状态。 在这种情况下,您可以select一些时间间隔(比如说每秒),然后检查接近度值,然后根据所看到的值确定要采取的操作。 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 

因为它在while循环中被卡住了,所以你可以定义一个函数,每秒钟(或者任何间隔)recursion调用它来检查echo的值。

你只需要把你的while循环replace成下面的例子。

 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循环的地方)时,确保至less调用一次checkEchoValue()。