2010-11-06 40 views
7

我想通过串口发送一个整数给我的Ardunio。芯片然后将在LED上以二进制显示数字。不过,我试图通过串口将数据作为字节发送时遇到了很多麻烦,只要我可以调试以下代码将其作为ASC char值发送。从串口写入字节到红宝石的Arduino

任何人都可以指向正确的方向或发现错误吗?我真的很感激它。很长一段时间以来,我一直在拉我的头发。

红宝石

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 

} 

} 
+0

你有没有尝试过使用终端程序,而不是Ruby?这是你的第一次设置还是你已经有一些工作? – 2010-11-06 18:00:14

回答

5

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

您正在查找的写入命令因此可能是sp.putc(i)。这只写了一个字符,其中给定的二进制值的值为(= Arduino的机器可读取的),而不是用二进制表示的值(对您来说是人为可读的)的ASCII字符串表示。

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

如果你想读的Arduino的响应,可以使用例如:

因此保持一切一样,用替换while循环在你的Ruby代码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;

+0

作为微控制器的一个小优化,与您的引脚分配10-13你也可以用(一)替换'digitalWrite'线, PORTB =((incomingByte&0x0F)<< 2)| (PORTB&0xC3);'。 – Arkku 2010-11-16 21:07:59

+0

我赞同这个答案,它具有我要说的大部分内容。此外,'digitalWrite(ledPin,(value >> 0)%2)'行可能是一个问题。我不知道假设HGIH和LOW映射为1和0是否安全。并且通常引脚13是可用的引脚,因为它具有内置电阻。 – 2010-11-20 13:22:58

+0

是的,'HIGH'和'LOW'映射到0和1. =)什么是不安全的假设是'PORTB'中的位映射到特定的物理引脚,但这只是一个问题,如果移动到一个不同的μC这种情况下物理连接也可以移动。 (如果'PORTB'上的相应引脚可用。) – Arkku 2010-11-20 13:29:27

1

我收到

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

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

我发现原来的博客帖子我用: http://www.arduino.cc/playground/Interfacing/Ruby

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 

而且字节comp的十进制值上升字符串:

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

感谢您对sp.write 9.to_s(2)的尝试,但它仍然似乎不想工作。 – 2010-11-06 17:26:07

+1

那么'9.to_s(2)'不是9的二进制表示。它是一个字符串表示。你必须使用''\ x9“'或''\ x0009”'或'[9] .pack('c')''。视觉上看起来像二进制表示和*正在二进制之间是有区别的。 – 2010-11-06 17:56:47

1

您的问题可能是由缓冲引起的。 (之前写)创建后

+0

或者在打开端口后立即设置'sp.sync = true'。格雷格,谢谢, – 2010-11-06 16:59:43

+0

谢谢。编辑。 – 2010-11-06 17:08:34

+0

感谢您的建议家伙添加sp.sync = true,但它似乎仍然没有正常工作 – 2010-11-06 17:25:15