Fork me on GitHub

Arduino和processing实现串口通信


Arduino和processing是一对好基友。。。

1.通过串口将Arduino的输出传递给Processing进行输出。

Arduino代码:

1
2
3
4
5
6
7
8
9
10
int data=12345;
void setup()
{
Serial.begin(9600);//rate
}
void loop()
{
Serial.println(data); //send data, end up with '\n'
delay(1000);
}

Processing代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import processing.serial.*;
String message;
String temp;
Serial myPort;
void setup(){
myPort = new Serial(this,"COM3",9600); //Set Serial Port
}
void draw(){
if(myPort.available()>0){
temp = myPort.readString(); //temp for read bytes
for(int i = 0; i < temp.length(); i++){
//if meet the end mark
if(temp.charAt(i) == '\n'){
println(message);
message = ""; //clean string
}
else
message += temp.charAt(i); //store byte
}
}
}

注意:

由于串口流通的数据都是bytes而没有字符串概念,所有发送数据都会按一个byte一个byte缓存,不论是否是连续字符串;而读取时会取走所有缓存bytes,不论它们是否是一个、半个还是多个字符串。

Arduino和Processing的数据收发速度是不一样的。如果用Arduino延时较长时间,Processing可能读取一个字符串或字符串的一部分。如果Arduino延时较短,Processing可能读取多个字符串,但不一定完整。在读取字符串的时候,无法确定上一个字符串是否被读取了,当前字符串是否缓存完毕,因为字符串都已经切成了bytes,连成一串。这个问题是串口通信本身造成的,一定会出现。

一种解决方法是,通过在接收端缓存数据来解决这个问题。为传输数据设置一个结束标记,如’\n’(换行符),就能在接收到的数据流中识别到一个字符串的结尾。当未遇到结束标记,就一直将串口数据保存在一个buffer变量中,继续接收,当遇到结束标记,即完成缓存。

2.通过串口将rotation sensor的转动角度发送给Processing,并绘制出可视化的图形。

Arduino代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int potPin = 0; // 电位器第二针脚接在模拟口0上
void setup() {
// 启动串口,波特率为9600
Serial.begin(9600);
}
void loop() {
// 读取电位器电压
int sensorValue = analogRead(potPin);
// 因为processing的serial.read()只支持0-255之间的数值,所以需要把0-1023数值除以4,缩放到0-255之间
Serial.write(sensorValue/4);
delay(100);
}

Processing代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import processing.serial.*;
Serial serial;
int sensorValue;
void setup() {
// 设置画布大小为 305 x 200
size(305, 200); //设置305的原因是arduino ADC口输入过来的数值是0-255,加上圆形半径50,刚好305.
// 打开串口,设置波特率为9600
serial = new Serial(this, "COM3", 9600);
}
void draw() {
if ( serial.available() > 0) {
// 读取从串口产过来的Sensor数值。
sensorValue = serial.read()+25; //+25的原因是后面设置圆形半径为50,为了让圆形起点与重点贴边,就需要+25半径。
println(sensorValue);
// 在画布内画一个
background(255); // 背景为白色
fill(255,0,0); // 圆形内填充为红色
ellipse(sensorValue, 100, 50, 50);
}
}

知识点补充:

ellipse:(圆形)

ellipse(x,y,width,height)
x,y是圆形坐标点,指的是圆心。
width是圆的水平直径
height是圆的垂直直径
比如120,60这样画出来的就是一个椭圆了。

rect:(矩形)
rect(x,y,width,height)
x,y指的是矩形坐标点,是左上角那个点。
width是矩形宽度
height是矩形高度
默认模式是CORNER。
画矩形有三种模式:
1、CORNER:rect(左上x,左上y,宽,高)
2、CENTER:rect(中心x,中心y,宽,高)
3、CORNERS:rect(左上x,左上y,右下x,右下y)

例子:
rectMode(CENTER);
rect(150,150,200,200)

PS:貌似还是把代码当作Java显示高亮效果更好。

donate the author