覆盆子pi接近检测nodejs

时间:2016-06-17 18:50:35

标签: javascript node.js raspberry-pi raspberry-pi2

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

正在触发运动传感器并且我从接近传感器获得读数,然而,接近传感器陷入循环并且值不会更新(即使有人在右上方它)。

动议:

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()

我需要做些什么才能让它正常工作而不会陷入无限循环?

2 个答案:

答案 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()。