通过串口从 Ruby 将字节写入 Arduino

发布于 2024-10-01 02:54:49 字数 1595 浏览 2 评论 0原文

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

谁能指出我正确的方向或发现错误?我真的很感激。我已经为此烦恼了很长时间。

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

}

}

I'm trying to send an integer over the serial port to my Ardunio. The chip is then going to display the number in binary on the LED's. However I'm having lots of trouble trying to send the data as a byte over the serial port, as far as I can debug the following code sends it as the ASC char values.

Can anyone point me in the right direction or spot the mistake? I'd really appreciate it. I've been pulling my hair out over this for a long time.

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

}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

海未深 2024-10-08 02:54:49

我猜您正在尝试写入值 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 来获取一行文本,例如尝试在 sleep 之前将 puts 'Arduino returned: ' + sp.gets 放入循环中(还有一个 puts sp.gets > 在循环之前读取首次建立连接时发送的“我在线”)。

编辑:我刚刚在 Arduino 端的代码中发现了另一个问题:value = (incomingByte, DEC) % 16; 总是导致值 10,因为 (incomingByte, DEC) 的值为 DEC(即 10)。您应该使用 value =传入Byte % 16; 来代替。或者完全删除value并修改incomingByte本身,例如incomingByte %= 16;

I'm guessing you are trying to write the value 15 in order to light all the LEDs at once. However, 15.to_s(2) is "1111". The ASCII value of the character '1' is 49, so instead of writing 15 once you are writing 49 four times in rapid succession.

The write command you are looking for is therefore probably sp.putc(i). This writes only one character with the given binary value (= machine-readable for Arduino) instead of an ASCII string representation of the value expressed in binary (= human-readable for you).

So keeping everything else the same, replace the while loop in your Ruby code with:

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

If you wish to read the responses from Arduino, you can use e.g. sp.gets to get one line of text, e.g. try placing puts 'Arduino replied: ' + sp.gets in the loop before sleep (and one puts sp.gets before the loop to read the "I am online" sent when the connection is first established).

Edit: I just spotted another problem in your code, on the Arduino side: value = (incomingByte, DEC) % 16; always results in the value 10 because (incomingByte, DEC) has the value DEC (which is 10). You should use value = incomingByte % 16; instead. Or do away with value altogether and modify incomingByte itself, e.g. incomingByte %= 16;.

雄赳赳气昂昂 2024-10-08 02:54:49

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

Your problems may be caused by buffering. To disable buffering, you can do one of the following:

活雷疯 2024-10-08 02:54:49

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

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

It's been so long since I did anything with serial ports that I can't help there, but I do see one thing.

>> 15.to_s #=> "15"

and

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

I think if you want the binary value to be sent you'll want "\xf" or "\u000F".


Change your code from:

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

to:

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

To show the difference, here's the length of the strings being output:

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

And the decimal values of the bytes comprising the strings:

>> 15.to_s(2).bytes.to_a #=> [49, 49, 49, 49]
>> 15.chr.bytes.to_a #=> [15]
何止钟意 2024-10-08 02:54:49

我之前曾使用过此 Ruby 代码,

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

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

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

I've had this Ruby code work before

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

rather than using sp.write(i.to_s). It looks like you are explicitly converting it to a string, which may be the cause of your problems.

I found the original blog post I used:
http://www.arduino.cc/playground/Interfacing/Ruby

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文