2010-11-06 78 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