始终从串行端口以及从接口

时间:2019-02-16 12:28:58

标签: ruby multithreading arduino

我正在尝试使用RoR设置Web应用程序,以便能够使用Web界面控制Arduino。我的方法可能是这里出了问题,因为在发送命令时,我很难读取arduino在串行上所说的内容。我的主要目标和未来目标是将串行端口列出(流式传输)到我的Web界面,并在服务器端进行响应(如果在串行端口上给出了一些特定命令)。

我已经尝试了什么?我虽然使用Threads是个好主意,但是我遇到了一些问题。首先,我通过创建一个新的Thred并使用.join尝试了最简单的方法。由于serial.gets正常运行了一段时间却无法解决,所以我的服务器一直挂在那里。

即使最终没有满足我的需求,我也会通过运行10次来限制我真正的出路(如代码所示)。

我的arduino代码(有效):

char receivedChar;
boolean newData = false;

void setup() {
 Serial.begin(9600);
 pinMode(LED_BUILTIN, OUTPUT);
 Serial.println("<Arduino is ready>");
}

void loop() {
 recvOneChar();
}

void recvOneChar() {
 if (Serial.available() > 0) {
  receivedChar = Serial.read();
  if (receivedChar == '1') {
   digitalWrite(LED_BUILTIN, HIGH);
   Serial.println("LED IS ON");
  }else if (receivedChar == '2' ){
   digitalWrite(LED_BUILTIN, LOW);
   Serial.println("LED IS OFF");
  }
 }
}

RoR上的控制器:

def blink_led
  puts "blink_led action called"
  t1 = Thread.new do
    Setting.blink_led
  end
  Setting.read_board
  t1.join
end

RoR模型:

@port_str = "/dev/tty.usbmodem14201"
@baud_rate = 9600
@data_bits = 8
@stop_bits = 1
@parity = SerialPort::NONE


def self.read_board
    puts "INSIDE READ METHOD"
    sp = SerialPort.new(@port_str, @baud_rate, @data_bits, @stop_bits, @parity)

    i = 0
    while i < 10 do
      message = sp.gets
      if message
        message.chomp!

        puts message
      end
      i += 1
    end
end

def self.blink_led
    puts "INSIDE BLINK METHOD"
    sp = SerialPort.new(@port_str, @baud_rate, @data_bits, @stop_bits, @parity)

    #just read forever
    i = 0
    while i < 5
        sp.write('1');
        sleep(1)
        sp.write('2');
        sleep(1)
        i += 1
    end

    sp.close
end

根据我的幼稚经验,我希望一旦我使用一个按钮调用控制器方法,就能看到LED闪烁(它闪烁),同时又能在服务器上看到PUTS上说LED亮/关(期望一切正常运行) 嗯,那并没有发生,我得到了一些奇怪的结果:

在我的服务器上运行1次正常(我第一次按下按钮)时,在我的计数器上添加i之前,这之后很奇怪。 第一次运行:

blink_led action called
INSIDE READ METHOD
INSIDE BLINK METHOD
Completed 200 OK in 6015ms (ActiveRecord: 0.0ms)

IS D ISIS OLS ONLED IS OFF
LED IS ON
LED IS OFF
LED IS ON
LED IS OFF

它只是挂在那里。

现在,在while循环上使用get计数器,它确实不执行我想要的操作,我希望它一直运行(如果发生某些情况),我还将数据从另一个源发送到串行(一个小的ruby脚本),并希望我的服务器能够对其进行检查/反应。

blink_led action called
INSIDE READ METHOD
INSIDE BLINK METHOD
LED IS LED IS OFF
Completed 200 OK in 6013ms (ActiveRecord: 0.0ms)

LED IS ON
LED IS OFF
LED IS ON
LED IS OFF
LED IS ON
LED IS OFF
LED IS ON
LED IS OFF

消息至少正确显示,但是我的服务器仍然挂起。

我在这里走的路都错吗?什么是实现我想要实现的最佳方法?最后,我希望我的服务器能够一直运行串行读取命令,同时对从串行端口读取的内容做出反应,并对接口上的输入做出反应,例如按下按钮。完成此操作后,我希望能够将串行端口“流式传输”(不知道这是否是正确的词)。

EDIT1:更正了一些拼写错误,并学习了如何在每次挂起时终止服务器进程

Edit2:明确我的问题。我正在寻找一种2路通信,一种是从接口/服务器到arduino的通信,另一种是从arduino到我的服务器的通信。我正在寻找一种可以将命令发送到arduino并从中读取答案的东西。到目前为止,我有一个动作/方法,该命令向arduino发送闪烁命令,发送“ 1”或“ 2”,arduino“ LED亮”对它进行响应,“ LED灭”。但这(到目前为止)仅在我的服务器知道它将得到答案时才可行。

我有一个小的ruby脚本,它发送相同的命令来打开和关闭LED,而我所缺少的是我的服务器能够注意到在Serialport上写了一些东西(在这种情况下,来自当此事件是由另一个来源触发时,arduino说“ LED亮” /“ LED灭”。

1 个答案:

答案 0 :(得分:0)

您可以将read_board方法更改为无休止的后台线程。当收到消息时,它可以调用其他方法,并使用websockets / action cable更新前端。

  # app/models/setting.rb

  def self.read_board
    sp = SerialPort.new(@port_str, @baud_rate, @data_bits, @stop_bits, @parity)
    Thread.new do

      loop do
        message = sp.gets # This will probably wait for input
        if message
          message.chomp!
          message_received(message)
        end
      end

    end
  end

  def self.message_received(message)
    # Alert clients of message using websockets / actioncable.
  end

从某个地方调用此方法(只需调用一次)

# config/initializers/read_board.rb

Setting.read_board

您需要填写message_received方法。如果您不想弄乱动作电缆/ websocket,可以创建一个存储新消息的数组,并从前端弹出的循环中发送查询,该循环从列表中弹出。但是,使用websockets是更好的选择。不幸的是,要解释此答案中的设置有点太复杂了,但是如果您四处搜寻,就会发现很好的教程。

我会说尝试为websockets / actioncable制作一个演示项目(只是一个简单的聊天室,有大量的教程),然后再尝试为arduino项目改编代码。

相关问题