通过串口从 Ruby 将字节写入 Arduino
我正在尝试通过串行端口向我的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我猜您正在尝试写入值 15 以便同时点亮所有 LED。但是,
15.to_s(2)
是“1111”。字符“1”的 ASCII 值为 49,因此不要一次写入 15,而是快速连续写入 49 次四次。因此,您正在寻找的写入命令可能是
sp.putc(i)
。这只会使用给定的二进制值(= Arduino 机器可读)写入一个字符,而不是用二进制表示的值的 ASCII 字符串表示形式(= 人类可读)。因此,保持其他所有内容相同,将 Ruby 代码中的
while
循环替换为:如果您希望读取 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: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 placingputs 'Arduino replied: ' + sp.gets
in the loop beforesleep
(and oneputs 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 valueDEC
(which is 10). You should usevalue = incomingByte % 16;
instead. Or do away withvalue
altogether and modifyincomingByte
itself, e.g.incomingByte %= 16;
.您的问题可能是由缓冲引起的。要禁用缓冲,您可以执行以下操作之一:
spsp.sync = true
write
之后Your problems may be caused by buffering. To disable buffering, you can do one of the following:
sp
to unbuffered after creating it (before writing):sp.sync = true
write
我已经很久没有用串口做过任何事情了,我无能为力,但我确实看到了一件事。
我
认为如果您想要发送二进制值,您需要
"\xf"
或"\u000F"
。将代码从: 更改
为:
为了显示差异,这里是输出的字符串的长度:
以及组成字符串的字节的十进制值:
It's been so long since I did anything with serial ports that I can't help there, but I do see one thing.
and
I think if you want the binary value to be sent you'll want
"\xf"
or"\u000F"
.Change your code from:
to:
To show the difference, here's the length of the strings being output:
And the decimal values of the bytes comprising the strings:
我之前曾使用过此 Ruby 代码,
而不是使用
sp.write(i.to_s)
。看起来您正在将其显式转换为字符串,这可能是导致问题的原因。我找到了我使用的原始博客文章:
http://www.arduino.cc/playground/Interface/Ruby
I've had this Ruby code work before
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