【问题标题】:Write byte to Arduino from Ruby over serial通过串行从 Ruby 向 Arduino 写入字节
【发布时间】:2023-03-24 06:19:01
【问题描述】:

我正在尝试通过串行端口向我的 Ardunio 发送一个整数。然后芯片将在 LED 上显示二进制数字。但是,我在尝试通过串行端口将数据作为字节发送时遇到了很多麻烦,据我可以调试以下代码将其作为 ASC char 值发送。

谁能指出我正确的方向或发现错误?我真的很感激。很长一段时间以来,我一直在为此拔头发。

红宝石

require 'rubygems'  
require 'serialport' # use Kernel::require on windows, works better.  

#params for serial port  
port_str = "/dev/tty.usbserial-A700dZt3"  #may be different for you  
baud_rate = 9600  
data_bits = 8  
stop_bits = 1  
parity = SerialPort::NONE  

sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)  

i = 15

#just write forever  
while true do  
  sp.write(i.to_s(2))
  sleep 10
end

阿杜诺

int ledPin = 10;
int ledPin1 = 11;
int ledPin2 = 12;
int ledPin3 = 13;

byte incomingByte;  // for incoming serial data

void setup() {
  pinMode(ledPin, OUTPUT);  // initialize the LED pin as an output:
  pinMode(ledPin1, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin2, OUTPUT); // initialize the LED pin as an output:
  pinMode(ledPin3, OUTPUT); // initialize the LED pin as an output:
  Serial.begin(9600);   
  Serial.println("I am online"); 
}

void loop() {
 // send data only when you receive data:
if (Serial.available() > 0) {
    incomingByte = Serial.read();
            Serial.println(incomingByte, DEC);

   int value = (incomingByte, DEC) % 16;
   digitalWrite(ledPin, (value >> 0) % 2);
   digitalWrite(ledPin1, (value >> 1) % 2);
   digitalWrite(ledPin2, (value >> 2) % 2);
   digitalWrite(ledPin3, (value >> 3) % 2); // MSB

}

}

【问题讨论】:

  • 您是否尝试过使用终端程序而不是 Ruby?这是您的第一次设置还是您已经有一些工作?

标签: ruby serial-port arduino


【解决方案1】:

我猜您正在尝试写入值 15 以便一次点亮所有 LED。但是,15.to_s(2) 是“1111”。字符 '1' 的 ASCII 值是 49,所以不是一次写 15,而是快速连续写四次 49。

因此,您要查找的写入命令可能是 sp.putc(i)。这只会写入一个具有给定二进制 的字符(= Arduino 机器可读),而不是二进制表示的值的 ASCII 字符串表示形式(= 人类可读)。

所以保持其他一切不变,将 Ruby 代码中的 while 循环替换为:

loop do
  sp.putc(i)
  puts 'Wrote: %d = %bb' % [ i, i ]
  i = (i == 15) ? 0 : (i + 1)
  sleep(10)
end

如果您想阅读 Arduino 的回复,您可以使用例如sp.gets 获取一行文本,例如尝试将puts 'Arduino replied: ' + sp.gets 放在sleep 之前的循环中(并在循环之前放置一个puts sp.gets 以读取首次建立连接时发送的“我在线”)。

编辑: 我刚刚在您的代码中发现了另一个问题,在 Arduino 方面:value = (incomingByte, DEC) % 16; 总是导致值 10,因为 (incomingByte, DEC) 的值是 DEC(即 10) .您应该改用value = incomingByte % 16;。或者完全取消 value 并修改 incomingByte 本身,例如incomingByte %= 16;.

【讨论】:

  • 作为微控制器的一个小优化,您的引脚分配 10-13 您也可以用(一个)PORTB = ((incomingByte & 0x0F) << 2) | (PORTB & 0xC3); 替换 digitalWrite 行。
  • 我赞同这个答案,它包含了我要说的大部分内容。不过,digitalWrite(ledPin, (value >> 0) % 2); 行也可能是个问题。我不知道假设 HGIH 和 LOW 映射到 1 和 0 是否安全。通常引脚 13 是一个不确定的引脚,因为它有一个内置电阻。
  • 是的,HIGHLOW 映射到 0 和 1。=) 安全的假设是 PORTB 中的位映射到特定的物理但这只是在移动到不同的 µC 时才会出现的问题,在这种情况下,物理连接也可以移动。 (如果PORTB上对应的管脚可用。)
【解决方案2】:

您的问题可能是由缓冲引起的。要禁用缓冲,您可以执行以下操作之一:

【讨论】:

  • 或者在端口打开后立即设置sp.sync = true
  • 感谢我添加 sp.sync = true 的建议,但它似乎仍然无法正常工作
【解决方案3】:

我已经很久没有用串口做任何事情了,我在那里无能为力,但我确实看到了一件事。

>> 15.to_s #=> "15"

>> 15.to_s(2) #=> "1111"

我想如果你想发送二进制值,你会想要"\xf""\u000F"


从以下位置更改您的代码:

while true do  
  sp.write(i.to_s(2)) # <-- this sends a multi-character ASCII representation of the "i" value, NOT the binary.
  sleep 10
end

到:

while true do  
  sp.write(i.chr) # <-- this sends a single byte binary representation of the "i" value, NOT the ASCII.
  sleep 10
end

为了显示差异,这里是输出字符串的长度:

>> 15.to_s(2).size #=> 4
>> 15.chr.size #=> 1

以及组成字符串的字节的十进制值:

>> 15.to_s(2).bytes.to_a #=> [49, 49, 49, 49]
>> 15.chr.bytes.to_a #=> [15]

【讨论】:

  • 感谢我用 sp.write 9.to_s(2) 尝试过的建议,但它似乎仍然不想工作。
  • 嗯,9.to_s(2) 不是 9 的二进制表示。它是一个字符串表示。您必须使用"\x9""\x0009"[9].pack('c') 之类的东西。在视觉上看起来像二进制表示和二进制之间是有区别的。
【解决方案4】:

我之前有过这段 Ruby 代码的工作

while true do
  printf("%c", sp.getc)
end

而不是使用sp.write(i.to_s)。看起来您正在将其显式转换为字符串,这可能是您出现问题的原因。

我找到了我使用的原始博客文章: http://www.arduino.cc/playground/Interfacing/Ruby

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2021-09-20
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多