ruby arduino hacking - 串口通讯

ruby和串口通讯可以通过[url=http://ruby-serialport.rubyforge.org/]serialport[/url]这个gem来实现,这个gem的用法很简单,先来看一个简单的串口输入输出例子:


require 'rubygems'
require 'serialport'

sp = SerialPort.new "/dev/ttyUSB0", 9600
sp.write "abcd"


2行代码,代表用9600的波特率连接/dev/ttyUSB0串口设备,往串口输入abcd

然后我们upload如下的代码,将串口接收到的数据通过串口输出:

int b = 0;

void setup() {
Serial.begin(9600);
}

void loop() {
if (Serial.available() > 0) {
b = Serial.read();

Serial.print("I received: ");
Serial.println(b, DEC);
}
}


我们可以通过arduino IDE的Serial Monitor来看到运行的结果,当然也可以再用serialport这个gem:

require 'rubygems'
require 'serialport'

sp = SerialPort.new "/dev/ttyUSB0", 9600
while r = sp.readlines
puts r
sleep 1
end


串口通讯常用来采集数据,比如这篇文章中的[url=http://www.danielandrade.net/2008/07/05/temperature-sensor-arduino/]LM35温度传感器[/url],我们只需将写少量ruby代码,就可以将串口的数据保存到数据库供后续使用。你还可以在这篇文章的基础上加上DSM501A粉尘传感器之类的,用weibo api每天定时发布自己家的PM2.5,或者添加更多的湿度,压力等传感器,就是一个小型的个人气象站了。


除了采集数据,接下去来看前一篇博客中提到的:
[quote]
将代码放在PC端运行,通过串口通讯写入和读取arduino上的各种输入输出口,这样的好处有2个:1复杂的控制代码(比如互联网,计算,数据库)可以不受限于arduino语言。 2方便快速调试,不需要编写,上传,烧入这样麻烦。
[/quote]

用一个蜂鸣器演奏乐曲来举例子,来看两只老虎的简谱:

[img]http://dl.iteye.com/upload/attachment/0074/6591/84ab8c38-f361-39d2-aa14-eeed902acb9b.png[/img]

如果直接upload代码,我们只需要反复调用[url=http://arduino.cc/en/Reference/Tone]tone[/url]函数就可以了,如需要演奏不同的乐曲,就upload不同的代码,这就是烧入一次,执行一次。
我们可以通过串口通讯和自定义协议,来实现演奏不同的乐曲。以上面的简谱为例子,我们定义数字1~7分别对应简谱的1~7,定义‘*’为1拍,‘-’为2拍,‘_’为1/2拍,‘.’为1又1/2拍。arduino代码如下:

#include "pitches.h"
int pitches[] = {
NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4
};
char c;

void setup() {
Serial.begin(9600);
pinMode(8, OUTPUT);
}

void loop() {
if (Serial.available() > 0) {
c = Serial.read();
if (c == '-') {
delay(1600);
} else if (c == '.') {
delay(600);
} else if (c == '*') {
delay(400);
} else if (c == '_') {
delay(200);
} else if (c == '0') {
noTone(8);
} else {
tone(8, pitches[c - '0']);
}
}
}


ruby代码如下:

require 'rubygems'
require 'serialport'

sp = SerialPort.new "/dev/ttyUSB0", 9600
string = "12311231345-345-5.6_5.4_315.6_5.4_31151-151-0"
string.scan(/\d[_|\-|\.]?/) do |i|
sp.write i.ljust(2, '*')
end

需要说明的是,因为不想在每个1拍的音符后面都加个*,所以代码多了2行,否则就是很简单的一个each block中依次串口输出就可以了。
我们如果需要换个歌曲,就将string的内容更换,重新执行一次即可,这样就实现了一次烧入,多次运行的效果。

在上面这个例子中,我们自定义了一个tone的协议,实际中用到最多的是digitalWrite/Read和analogWrite/Read,所以只要针对他们做一个简单协议,就能很方便地控制,https://github.com/HashNuke/arduino 就是这样的一个项目。而 https://github.com/chrismetcalf/ruby-firmata 则是针对[url=http://firmata.org/wiki/Main_Page]Firmata[/url]这个通用协议的ruby实现。

通过ruby控制arduino除了唱两只老虎哄哄小孩,还能做很多实用或者有趣的事情,请等待下篇...
<think>好的,我现在需要帮助用户实现Arduino和OpenCV之间的串口通信。首先,我得理清他们的需求。用户可能是在做一个项目,比如通过摄像头捕捉图像,用OpenCV处理后再通过串口发送指令给Arduino控制某些硬件,比如电机或传感器。或者反过来,Arduino发送传感器数据到OpenCV进行分析。 首先,我需要明确两者的通信方式。Arduino通常通过USB串口与电脑连接,而OpenCV运行在电脑上,所以通信的关键点在于如何在OpenCV所在的程序(比如Python或C++)中实现串口通信。 接下来,用户提到的引用中有几个相关的资料。引用[2]提到Python和Arduino串口通信,引用[4]则是关于VC++和Arduino的通信。所以用户可能使用Python或C++来编写OpenCV部分。我需要考虑这两种情况。 步骤一:硬件连接。确保Arduino通过USB连接到电脑,并安装正确的驱动程序。确认串口号,比如COM3(Windows)或/dev/ttyUSB0(Linux)。 步骤二:Arduino端的程序。需要编写一个串口通信的代码,监听来自电脑的指令,并可能发送数据回电脑。比如,当Arduino接收到特定字符串时执行动作,或者定时发送传感器数据。 步骤三:电脑端的OpenCV程序。这里需要用Python或C++的串口库,如Python的pyserial或C++的serial库,来与Arduino通信。同时,OpenCV处理图像后生成相应的控制指令,通过串口发送。 可能出现的问题包括串口端口选择错误、波特率不匹配、数据格式不一致导致的解析错误。需要确保双方使用相同的波特率,比如9600或115200,并且数据格式(如终止符)一致。 另外,数据交互的协议需要简单有效。比如,OpenCV发送字符'S'让Arduino停止电机,发送'F'前进,或者Arduino发送传感器数据作为字符串,OpenCV解析后显示或处理。 还要考虑实时性和稳定性。串口通信可能有延迟,特别是在大量数据传输时,需要优化数据包的大小和发送频率。可能采用校验和或确认机制来确保数据正确传输。 用户提供的引用中有示例代码,比如引用[3]中的Arduino串口例子和引用[4]中的C++代码,这些可以作为参考。在Python中,pyserial的使用相对简单,适合快速开发;而C++可能需要更底层的配置,但性能更好。 最后,测试环节很重要。先测试Arduino端的串口收发是否正常,再测试OpenCV端的程序是否能正确发送和接收数据,最后整合两者,确保整个流程无误。</think>### 实现Arduino与OpenCV串口通信的步骤 #### 1. 硬件连接与基础配置 -Arduino通过USB连接到计算机,并安装对应驱动。 - 确认Arduino串口号(Windows设备管理器中的`COMx`,Linux的`/dev/ttyACM0`或`/dev/ttyUSB0`)。 -Arduino IDE中测试基础串口通信功能(参考引用[3]的代码示例)。 #### 2. Arduino端代码编写 编写Arduino程序监听串口指令,并根据指令执行操作。例如: ```cpp void setup() { Serial.begin(9600); // 波特率需与OpenCV端一致 } void loop() { if (Serial.available() > 0) { String command = Serial.readStringUntil('\n'); // 以换行符为终止符 if (command == "detect") { // 执行动作(如控制LED或电机) } // 可发送传感器数据回传 Serial.println("ACK"); // 确认响应 } } ``` #### 3. OpenCV端代码编写(Python/C++) **Python方案(推荐)**: ```python import cv2 import serial import time # 初始化串口 arduino = serial.Serial(port='COM3', baudrate=9600, timeout=1) # OpenCV图像处理 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() # 图像处理逻辑(如物体检测) if 检测到目标: arduino.write(b'detect\n') # 发送指令 response = arduino.readline().decode().strip() print("Arduino响应:", response) cv2.imshow('Frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break arduino.close() cap.release() ``` **C++方案**(参考引用[4]): ```cpp #include <opencv2/opencv.hpp> #include <serial.h> // 使用第三方库如libserial int main() { cv::VideoCapture cap(0); SerialPort arduino("COM3", 9600); if (!arduino.isOpen()) return -1; while (true) { cv::Mat frame; cap >> frame; // 图像处理逻辑 if (检测到目标) { arduino.write("detect\n"); // 发送指令 std::string response = arduino.readline(); std::cout << "响应: " << response << std::endl; } cv::imshow("Frame", frame); if (cv::waitKey(1) == 'q') break; } return 0; } ``` #### 4. 通信协议设计建议 - **数据格式**:使用简单文本协议,如`指令\n`或`数据1,数据2\n`。 - **校验机制**:添加校验和(如`*CHECKSUM`后缀)或使用`ACK/NACK`确认。 - **同步机制**:避免数据冲突,可采用请求-响应模式(如OpenCV发送指令后等待Arduino响应)。 #### 5. 调试与优化 - **波特率匹配**:确保双方使用相同波特率(常用9600、115200)。 - **数据延迟**:减少单次传输数据量,或使用多线程分离图像处理和串口通信。 - **错误处理**:添加超时重发、数据完整性检查(参考引用[4]的调试方法)。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值