2010-11-06 26 views
7

Tôi đang cố gửi một số nguyên qua cổng nối tiếp tới Ardunio của mình. Chip sau đó sẽ hiển thị số nhị phân trên đèn LED. Tuy nhiên tôi đang gặp rất nhiều rắc rối khi cố gắng gửi dữ liệu dưới dạng một byte trên cổng nối tiếp, đến mức tôi có thể gỡ lỗi mã sau gửi nó như là các giá trị char ASC.Viết byte vào Arduino từ Ruby qua nối tiếp

Có ai có thể chỉ cho tôi đúng hướng hoặc phát hiện lỗi không? Tôi thực sự đánh giá cao nó. Tôi đã kéo mái tóc của tôi ra ngoài trong một thời gian dài.

của Ruby

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

Bạn đã thử sử dụng chương trình đầu cuối thay vì Ruby chưa? Đây có phải là thiết lập đầu tiên của bạn hay bạn đã có thứ gì đó hoạt động không? –

Trả lời

5

Tôi đoán bạn đang cố viết giá trị 15 để chiếu sáng tất cả các đèn LED cùng một lúc.Tuy nhiên, 15.to_s(2) là "1111". Giá trị ASCII của ký tự '1' là 49, vì vậy thay vì viết 15 khi bạn đang viết 49 bốn lần liên tiếp nhanh chóng.

Lệnh ghi mà bạn đang tìm kiếm có thể là sp.putc(i). Điều này chỉ viết một ký tự với giá trị nhị phân cho trước (= máy có thể đọc được đối với Arduino) thay vì biểu diễn chuỗi ASCII của giá trị được biểu thị bằng nhị phân (= người có thể đọc được cho bạn).

Vì vậy, việc giữ mọi thứ khác nhau, thay thế while vòng lặp trong mã Ruby của bạn với:

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

Nếu bạn muốn đọc các câu trả lời từ Arduino, bạn có thể sử dụng ví dụ sp.gets để nhận một dòng văn bản, ví dụ: thử đặt puts 'Arduino replied: ' + sp.gets vào vòng trước sleep (và một puts sp.gets trước khi vòng lặp để đọc "Tôi trực tuyến" được gửi khi kết nối được thiết lập lần đầu).

Edit: Tôi chỉ phát hiện một vấn đề khác trong mã của bạn, ở phía bên Arduino: value = (incomingByte, DEC) % 16; luôn dẫn đến giá trị 10 vì (incomingByte, DEC) có giá trị DEC (đó là 10). Bạn nên sử dụng value = incomingByte % 16; để thay thế. Hoặc loại bỏ hoàn toàn value và sửa đổi incomingByte chính nó, ví dụ: incomingByte %= 16;.

+0

Là một tối ưu hóa nhỏ trên vi điều khiển, với bài tập pin của bạn 10-13 bạn cũng có thể thay thế các dòng 'digitalWrite' với (một) 'PORTB = ((đếnByte & 0x0F) << 2) | (PORTB & 0xC3); '. – Arkku

+0

Tôi ủng hộ câu trả lời này, nó có hầu hết những gì tôi định nói. Ngoài ra, mặc dù, 'digitalWrite (ledPin, (value >> 0)% 2);' dòng có thể là một vấn đề. Tôi không biết nếu nó là an toàn để giả định HGIH và LOW bản đồ đến 1 và 0. Và thường pin 13 là một pin iffy để sử dụng, bởi vì nó có một điện trở được xây dựng trong. –

+0

Có, bản đồ 'HIGH' và' LOW' tới 0 và 1. =) Điều gì là _not_ an toàn để giả định là các bit trong bản đồ 'PORTB' cho các chân vật lý cụ thể nhưng đây chỉ là vấn đề nếu chuyển sang một µC khác trong trường hợp đó các kết nối vật lý cũng có thể được di chuyển. (Nếu các chân tương ứng trên 'PORTB' có sẵn.) – Arkku

1

Tôi đã có mã công việc này của Ruby trước

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

hơn là sử dụng sp.write(i.to_s). Có vẻ như bạn đang chuyển đổi nó thành một chuỗi rõ ràng, điều này có thể là nguyên nhân gây ra sự cố của bạn.

Tôi tìm thấy bài đăng blog ban đầu tôi đã sử dụng: http://www.arduino.cc/playground/Interfacing/Ruby

1

Đã quá lâu kể từ khi tôi đã làm bất cứ điều gì với cổng nối tiếp mà tôi không thể giúp đỡ đó, nhưng tôi thấy một điều.

>> 15.to_s #=> "15" 

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

Tôi nghĩ rằng nếu bạn muốn giá trị nhị phân để được gửi cho bạn sẽ muốn "\xf" hoặc "\u000F".


Thay đổi mã của bạn từ:

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 

tới:

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

Để hiển thị sự khác biệt, đây là chiều dài của chuỗi đang được đầu ra:

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

Và giá trị thập phân của byte comp tăng các chuỗi:

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

Cảm ơn bạn đã gợi ý tôi đã thử nó với sp.write 9.to_s (2) nhưng nó vẫn không có vẻ muốn làm việc. –

+1

Vâng, '9.to_s (2)' không phải là biểu diễn nhị phân của 9. Nó là biểu diễn chuỗi. Bạn sẽ phải sử dụng một cái gì đó như '" \ x9 "' hoặc '" \ x0009 "' hoặc '[9] .pack ('c')'. Có một sự khác biệt giữa hình ảnh trực quan giống như biểu diễn nhị phân và * là * nhị phân. –

1

Sự cố của bạn có thể do đệm. Để vô hiệu hóa bộ nhớ đệm, bạn có thể làm một trong các cách sau:

+0

Hoặc đặt 'sp.sync = true' ngay sau khi cổng được mở. –

+0

Cảm ơn, Greg. Đã chỉnh sửa. –

+0

Cảm ơn các gợi ý guys ive thêm sp.sync = true nhưng nó vẫn không hoạt động chính xác –

Các vấn đề liên quan