通过串行从Ruby向Arduino写入字节

时间:2010-11-06 16:32:27

标签: ruby serial-port arduino

我正在尝试通过串口将一个整数发送到我的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

Arduino的

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

}

}

4 个答案:

答案 0 :(得分:5)

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

您正在寻找的写命令可能是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;

答案 1 :(得分:1)

我之前使用过这段Ruby代码

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

而不是使用sp.write(i.to_s)。看起来你明确地将它转换为字符串,这可能是你问题的原因。

我找到了我用过的原创博文: http://www.arduino.cc/playground/Interfacing/Ruby

答案 2 :(得分:1)

我用链接端口做了很长时间,我无法帮助,但我确实看到了一件事。

>> 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]

答案 3 :(得分:1)

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