【问题标题】:Asynchronous function not producing immediate result inside while loop异步函数在while循环内不立即产生结果
【发布时间】:2017-01-09 01:45:42
【问题描述】:

我是 nodejs 的新手,我所做的是将 LCD 面板和 4x4 膜矩阵键盘连接到 Raspberry Pi,并使用 Node.js 对其进行了编程。我想要实现的是,无论何时按下一个键,它都应该立即显示在 LCD 面板上,当我按下 # 时,它应该停止输入。

为此,我使用了 LCD https://www.npmjs.com/package/lcd 和 RPIO https://github.com/jperkin/node-rpio 包,因为我必须不断检查用户输入,所以我已将用于接收输入的代码放入 while 循环和其中,我已经编写了 print 语句,并且问题出在哪里。当我在键盘上按一个键时液晶面板不显示任何字符,但当我按#时,程序退出并且所有字符都显示在液晶面板上。

我写的代码如下。

var rpio = require('rpio');
var Lcd = require('lcd'),//This is asynchronous function
    lcd = new Lcd({
        rs: 18,
        e: 23,
        data: [24, 17, 27, 22],
        cols: 8,
        rows: 2
    });
var matrix=[[1,2,3,'A'],
            [4,5,6,'B'],
            [7,8,9,'C'],
            ['*',0,'#','D']]
var row=[37,35,33,31];
var col=[29,23,40,38];
for (var i = 0; i < 4; i++) {
    rpio.open(col[i], rpio.OUTPUT, rpio.HIGH);
}
for (var i = 0; i < 4; i++) {
    rpio.open(row[i], rpio.INPUT, rpio.PULL_UP);
}
var code="";
var comeout=0;
lcd.on('ready', function() {
    lcd.setCursor(0, 0);
    //start of keypad code
    while(true){
        for (var j = 0; j < 4; j++) {
            rpio.write(col[j],rpio.LOW);
            for (var i = 0; i < 4; i++) {
                if(rpio.read(row[i])==0){
                    console.log(matrix[i][j]);
                    lcd.print(matrix[i][j]);
                    if(matrix[i][j]=='#'){
                        comeout=1;
                        break;
                    }
                    while(rpio.read(row[i])==0);
                }
            }
            if(comeout==1)
                break;
            else
                rpio.write(col[j],rpio.HIGH);
        }
        if(comeout==1)
            break;
    }
    //end of keypad code
});

// If ctrl+c is hit, free resources and exit.
process.on('SIGINT', function() {
    lcd.clear();
    lcd.close();
    process.exit();
});

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 我建议将您的代码分解成小块并专注于问题。
  • 你不能在 JS 中那样使用while(true) 循环。这就是为什么您有一些事件需要引起注意,例如按键。查看rpio.poll()。由于我不完全了解您的两个 for 循环是如何工作的以及您在那里使用的 rpio.write()rpio.read(),因此我无法重写您的代码
  • 我猜colrow 包含某种位掩码!?
  • 您将引脚 23 用于 LCD 启用和col[1];也许这就是问题所在。使用 while(true) 没有任何问题,因为您在不使用任何中断或其他事件源的情况下扫描您的键矩阵(行和列)。
  • @PeterPaulKiefer,是的。这就像在 JS 中使用 while(true) 来检查更改(键盘/鼠标)按钮状态。它基本上是一个无限循环,永远不会中断以使任何其他 JS 代码能够执行;就像lcd.print() 背后的代码一样,似乎堆积如山。直到此循环终止(按#)。然后刷新堆栈并执行所有(待处理的)异步代码。这正是他所描述的问题。

标签: javascript node.js npm raspberry-pi


【解决方案1】:

根据上面与@Thomas 的讨论,我建议您使用setImediate 调用模拟while(true) 循环,在该循环中请求矩阵并执行LCD.print。这是因为 LCD.print 将操作添加到 javascripts 事件队列。但是事件队列的操作是阻塞的,直到实际操作完成。只要您处于while(true) 循环中,它就永远不会完成。

因此,您必须结束活动操作并给予事件循环控制权,该控制权依次执行打印命令。但同时您必须确保在不按“#”键的情况下再次扫描键矩阵。

这是一个例子:

lcd.on('ready', function() 
{
  lcd.setCursor(0, 0);
  setImediate(
  function scanMatrix()
  {
    for (var j = 0; j < 4; j++) 
    {
      rpio.write(col[j],rpio.LOW);
      for (var i = 0; i < 4; i++) 
      {
        if(rpio.read(row[i])==0)
        {
          console.log(matrix[i][j]);
          lcd.print(matrix[i][j]);
          if(matrix[i][j]!='#')
          {
            setImmediate(scanMatrix);
          }
          while(rpio.read(row[i])==0);
        }
      }
      rpio.write(col[j],rpio.HIGH);
    }
  });
});

代码没有经过测试,因为我这里没有 raspi。它应该给你一个如何解决问题的想法。

一个非常酷的 ;-) 解决方案是将微控制器(MSP430,...)添加到键矩阵。 MC 扫描矩阵并通过 SPI 或 I2C 将按键传输到 raspi。 ....好吧,好吧,好吧,别打我;-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多