processing 与arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章...

12
2 Processing Arduino 通信 2.1 串口简介 Processing 平台开发的是计算机应用程序,而 Arduino 开发板是电子硬件,将 计算机应用程序与电子硬件连接起来进行相互通信,实现各种控制功能,需要用到一 个接口作为沟通的桥梁,这个桥梁就是串口。 串行接口简称“串口”,是采用串行通信方式的扩展接口。串口出现在 1980 前后,初期是为了实现连接计算机外 设的目的,一般用来连接鼠标和外置 Modem,以及老式摄像头和写字板等设 备,常见的有一般计算机应用的 RS-232 接口,如图 2-1 所示。后来还衍生出工 业计算机应用的半双工 RS-485 与全双工 RS-42由于串口的速度较慢,且目前家庭 常用的电子设备都逐渐转为 USB 接口,因此很多家用计算机和笔记本电脑逐渐取消 了这个接口。但是由于串口简单易用,在单片机、嵌入式系统和物联网等领域有着广 泛的应用,工业控制行业也有着巨大的保有量。为了方便产品开发者、电气工程师和 电子爱好者的使用,市面上出现了 USB 转串口的数据线,如图 2-2 和图 2-3 所示。 2-2 采用的是 RS232 标准的接口,图 2-3 采用的是 TTL 电平的串口,两者的 电气特性是不同的。RS232 的电气特性为:逻辑 1 电压为 -3 -15V,逻辑 0 电压 2-1 计算机主板上的串口

Upload: others

Post on 31-Mar-2021

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

第 2 章

Processing 与 Arduino 通信

2.1 串口简介

在 Processing 平台开发的是计算机应用程序,而 Arduino 开发板是电子硬件,将

计算机应用程序与电子硬件连接起来进行相互通信,实现各种控制功能,需要用到一

个接口作为沟通的桥梁,这个桥梁就是串口。

串行接口简称“串口”,是采用串行通信方式的扩展接口。串口出现在 1980 年

前后,初期是为了实现连接计算机外

设的目的,一般用来连接鼠标和外置

Modem,以及老式摄像头和写字板等设

备,常见的有一般计算机应用的 RS-232

接口,如图 2-1 所示。后来还衍生出工

业计算机应用的半双工 RS-485 与全双工

RS-42。

由于串口的速度较慢,且目前家庭

常用的电子设备都逐渐转为 USB 接口,因此很多家用计算机和笔记本电脑逐渐取消

了这个接口。但是由于串口简单易用,在单片机、嵌入式系统和物联网等领域有着广

泛的应用,工业控制行业也有着巨大的保有量。为了方便产品开发者、电气工程师和

电子爱好者的使用,市面上出现了 USB 转串口的数据线,如图 2-2 和图 2-3 所示。

图 2-2 采用的是 RS232 标准的接口,图 2-3 采用的是 TTL 电平的串口,两者的

电气特性是不同的。RS232 的电气特性为:逻辑 1 电压为 -3 ~ -15V,逻辑 0 电压

图 2-1 计算机主板上的串口

Page 2: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

第 2 章 Processing 与 Arduino 通信 9

为 +3 ~ +15V。而 TTL 电平的 +5V 或 +3.3V 等价于逻辑 1,0V 等价于逻辑 0。一般

RS232 用于连接外部设备,TTL 电平可以直接连接单片机,两种接口不能直接对接,

需通过 MAX232 芯片进行电平转换。

图 2-2 USB 转串口数据线 图 2-3 USB 转串口 TTL 电平串口

Arduino UNO 开发板上自带了 USB 转串口功能,该功能是依靠 AVR 单片机

Mega16U2 实现的,如图 2-4 所示。

使用者只需要将 USB 数据线与 Arduino 接上,并连接至计算机,在 Arduino 开发

环境目录下的 drivers 文件夹中找到驱动程序,单击“下一步”按钮,直到完成驱动程

序安装,如图 2-5 所示。COM12 指的是分配给 Arduino 板的端口号是 12。

图 2-4 Mega16U2 单片机实现 USB 转串口 图 2-5 在设备管理器中查看 USB

转串口设备所对应的串口号

Page 3: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

10 第一篇 入 门 篇

2.2 Processing 串口编程

Processing 的串口通信是由 serial 库提供的,可以通过调用成员函数来实现。串

口通信函数的功能如表 2-1 所示。

表 2-1 Processing 串口通信函数

函数名 功  能

available() 检查串口是否接收到数据

read() 从串口读入数据,数据为字节类型,范围为 0 ~ 255

readChar() 从串口读入数据,返回字符类型数据

readBytes() 从串口读入数据,返回字节类型数据

readBytesUntil() 从串口读入数据,返回字节类型数据,当遇到校验字符时停止读取数据

readString() 从串口读入数据,返回字符串类型数据

readStringUntil() 从串口读入数据,返回字符串类型数据,当遇到校验字符时停止读取数据

buffer() 设置缓冲区大小

bufferUntil() 从串口读取数据,遇到特定字符才会停止读取数据

last() 以字节类型返回读取到的最后一个数据

lastChar() 以字符类型返回读取到的最后一个数据

write() 向串口写入数据

clear() 清空缓冲区数据

stop() 停止串口数据传输

list() 返回能使用的串口

serialEvent() 自定义一个串口接收事件

使用串口时,我们首先导入串口的库函数,再实例化一个对象。下面的实例代码

运行后,会将计算机现有的串口全部显示出来。

import processing.serial.*; // 导入 serial 库

Serial myPort; // 实例化一个 Serial 对象

println(Serial.list()); // 显示计算机已有的全部串口

执行程序后,显示的结果如图 2-6 所示。

图 2-6 显示串口端口号

Page 4: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

第 2 章 Processing 与 Arduino 通信 11

笔者的 Arduino 板分配的端口号是 12。通过下面的例子,可以实现往 COM12 发

送数据。

示例:Processing 向串口发送数据。

import processing.serial.*; // 导入 serial 库

Serial port; // 实例化一个 Serial 对象

String message;

void setup(){

message="c";

port= new Serial(this,"COM12",9600);

// 初始化 port,第 2 个参数是端口号,第 3 个参数是比特率

}

void draw(){

port. write(message); // 发送数据

}

执行程序后,我们可以看到 Arduino 板载的 RX 灯一直亮起,说明有数据在不停

地发送过去。关闭程序后,RX 灯熄灭。

注意 比特率是串口通信的速率,9600 指的是每秒发送 9600 比特的数据,即

9600bps。该参数可以更改,常用的比特率为 9600bps、19 200bps、57 600bps 和

115 200bps。将 Processing 与 Arduino 的比特率设置为一致方可通信,否则会出现乱

码,无法正常接收。

2.3 Arduino 串口编程

Arduino 的串口通信是通过在头文件 HardwareSerial.h 中定义一个 HardwareSerial

类的对象 serial,然后直接使用类的成员函数来实现的。串口通信函数的功能如表

2-2 所示。

表 2-2 Arduino 串口通信函数

函数名 功  能

Serial.begin() 用于设置串口的比特率,除以 8 可得到每秒传输的字节数

Serial.end() 停止串口通信

Page 5: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

12 第一篇 入 门 篇

函数名 功  能

Serial.available() 用来判断串口是否收到数据,该函数返回值为 int 型,不带参数

Serial.setTimeout()使用 Serial.readBytesUntil()、Serial.readBytes()、Serial.parseInt() 或 Serial.parseFloat().

时,设置读取数据超时时间,单位是毫秒,默认是 1000 毫秒

Serial.readBytesUntil()从串口读入字符,存入一个数组中。当遇到校验字符时或读取超时时停止读取

数据

Serial.readBytes()从串口读取字符,存入一个数组中。当读取够指定数目的字符或读取超时时停止

读取数据

parseInt() 用于从串口读取整型数据,当遇到字符型数据或读取超时时停止读取数据并返回 0

Serial.parseFloat()用于从串口读入浮点数据,返回第一个浮点型数据。当遇到第一个字符或读取超

时时停止读入数据

readString() 从串口读入字符串

readStringUntil() 从串口读入字符串,当遇到校验字符时停止读取

Serial.read() 用于从串口读入数据,该函数返回值为 int 型的串口数据,不带参数

peek() 从串口读入数据,与 read() 不同的是,peek() 读取完后不会清空串口缓冲数据

Serial.fi nd() 从串口读入数据,当遇到目标字符串时停止读取并返回 true

Serial.fi ndUntil()从串口读入数据,当遇到目标字符串时停止读取并返回 true,当遇到校验字符时

或者读取超时时返回 false

Serial.print() 用于从串口输出数据,数据可以是变量,也可以是字符串

Serial.println() 与 Serial.print 函数类似,都是从串口输出数据,只是多了回车换行功能

serialEvent() 定义一个串口读入事件

示例:从串口输出“The char I have received:”字符。

int c=0;

void setup()

{

Serial.begin(9600); // 比特率 9600

}

void loop()

{

if(Serial.available())

{

c=Serial.read();

Serial.print("The char I have received:");

Serial.printl(nc,DEC); // 输出并换行

}

delay(200);

}

(续)

Page 6: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

第 2 章 Processing 与 Arduino 通信 13

打开 Arduino 界面的串口监视器,输入任意字符,单片机接收到会返回该字符的

ASCII 码,如图 2-7 所示。

图 2-7 串口监视器显示界面

2.4 Processing 与 Arduino 通信编程

本书将通过几个小例子让读者快速地掌握 Processing 与 Arduino 的通信编程。

实例一:在 Processing 界面上画一个矩形,当用鼠标单击矩形内的时候,Arduino

板载的 LED 灯(与数字引脚 13 相连)点亮,单击矩形外的时候,Arduino 板载的

LED 熄灭。

Processing 代码:

import processing.serial.*; // 导入 serial 库

Serial port; // 实例化一个 Serial 对象

void setup(){

port= new Serial(this,"COM12",9600);

Page 7: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

14 第一篇 入 门 篇

// 初始化 port(根据 Arduino 分配的端口号填写)

size(300,300);

}

void draw(){

rect(100,100,50,50); // 绘制矩形

}

void mouseClicked()

{ if((mouseX>=100)&(mouseX<=150)&(mouseY>=100)&(mouseY<=150))

// 当鼠标在矩形区域内单击时

{ println("LED turn ON!");

port.write("a"); // 往串口发送小写字母 a

}

else

{println("LED turn OFF!");

port.write("b"); // 当在矩形区域外单击时,往串口发送小写字母 b

}

}

Arduino 代码:

int c=0;

void setup()

{

Serial.begin(9600); // 比特率 9600

pinMode(13,OUTPUT); // 设置数字引脚第 13 脚为输出模式

digitalWrite(13,LOW); // 设置该引脚的初始值为低电平

}

void loop()

{

if(Serial.available())

{

c=Serial.read();

if(c==97) // 如果接收到字母 a(ASCII 码值为 97)

digitalWrite(13,HIGH); // 第 13 引脚置高电平,LED 灯亮

else

if (c==98) // 如果接收到字母 b(ASCII 码值为 98)

digitalWrite(13,LOW); // 第 13 引脚置低电平,LED 灯灭

}

}

如图 2-8 所示,当单击白色矩形内时,Processing 提示 LED 已经打开(见图 2-9),

板载 LED 点亮(见图 2-10)。

Page 8: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

第 2 章 Processing 与 Arduino 通信 15

图 2-8 执行效果图 图 2-9 提示灯打开 图 2-10 板载 LED 点亮

当单击白色矩形外时,Processing 提示 LED 已经关闭(见图 2-11),板载 LED 熄

灭(见图 2-12)。

图 2-11 提示灯熄灭 图 2-12 板载 LED 熄灭

实例二:将一个开关连接到 Arduino 上的 + 引脚,如图 2-13 所示,接线如表 2-3

所示。长按开关,Processing 上的圆形变成红色;松开开关,Processing 上的圆变成

绿色。初始为绿色。

图 2-13 按键连接 Arduino 开发板

Page 9: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

16 第一篇 入 门 篇

表 2-3 接线表

序  号 模块引脚 Arduino 引脚 序  号 模块引脚 Arduino 引脚

1 S D8 3 - GND

2 + 5V

Processing 代码:

import processing.serial.*; // 导入 serial 库

Serial myPort; // 实例化一个 Serial 对象

void setup()

{ size(300,300);

fill(0,255,0);

ellipse(100, 100, 100, 100);

myPort = new Serial(this, "COM12", 9600);

// 初始化 myPort(根据 Arduino 分配的端口号填写)

}

void draw()

{

while (myPort.available() > 0) // 监听端口

{

char inByte = myPort.readChar(); // 读取字节

println(inByte); // 显示接收到的字节

switch(inByte)

{case 'a': fill(0,255,0); // 当接收到的字母为 a时填充红色

ellipse(100, 100, 100, 100); // 重绘圆

break;

case 'b': fill(255,0,0); //当接收到的字母为 b 时填充绿色

ellipse(100, 100, 100, 100); // 重绘圆

break;

default: break;

}

}

}

Arduino 代码:

boolean button; // 定义一个布尔型的变量

void setup() {

button=false; // 初始值为假

pinMode(8,INPUT); // 定义数字第 8 引脚为输入模式

Page 10: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

第 2 章 Processing 与 Arduino 通信 17

Serial.begin(9600); // 设置比特率为 9600bps

}

void loop() {

button=digitalRead(8); // 读取数字第 8 引脚

if(button)

{ Serial.write("a"); // 当读取到为高电平时(按下按钮),发送字母 a

}

else

{Serial.write("b"); // 当读取到为低电平时(释放按钮),发送字母 b

}

}

实例三:前面两个例子演示了如何从 Processing 发送数据到 Arduino,也演示了

如何从 Arduino 发送数据到 Processing。下面的这个例子演示了如何实现双向收发。

结合实例一,在 Processing 里画一个矩形,当在矩形区域内单击时,向 Arduino

发送字母 a。Arduino 收到后点亮板载的 LED 灯,同时向 Processing 发送“ The

light turn ON”;Processing 收到后显示在屏幕的左上角。当单击矩形框外时,

Processing 向 Arduino 发送字母 b,Arduino 板载的 LED 灯熄灭,与此同时 Arduino

向 Processing 发送“ The light turn OFF”, Processing 收到这串字符后显示在屏幕的左

上角。

Processing 代码:

import processing.serial.*; // 导入 serial 库

Serial myPort; // 实例化一个 Serial 对象

int lf = 10; // 换行符号的 ASCII 码值

String myString = null; // 定义一个字符串变量

void setup()

{

size(300,300); // 设置画布大小

background(125); // 设置画布背景颜色

myPort = new Serial(this, "COM14", 9600);

// 初始化 myPort(根据 Arduino 分配的端口号填写)

myPort.clear();

}

void draw()

{

Page 11: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

18 第一篇 入 门 篇

rect(100,100,50,50); // 绘制矩形

while (myPort.available() > 0) // 监听端口

{ myString = myPort.readStringUntil(lf);

// 读字符串,直到出现换行符号后,将字符串赋值给 myString 变量

if(myString!=null)

{ background(125); // 每次清空屏幕

text(myString,10,30); // 灯光开启、关闭提示显示在屏幕左上角

}

}

}

void mouseClicked()

{ if((mouseX>=100)&(mouseX<=150)&(mouseY>=100)&(mouseY<=150))

// 当鼠标在矩形区域内单击时

{ myPort.write("a"); // 往串口发送字母 a

}

else

{ myPort.write("b"); //当在矩形区域外单击时,往串口发送字母b

}

}

Arduino 代码:

int c=0;

void setup()

{

Serial.begin(9600); // 比特率 9600

pinMode(13,OUTPUT); // 设置数字引脚第 13 脚为输出模式

digitalWrite(13,LOW); // 设置该引脚的初始值为低电平

}

void loop()

{

if(Serial.available())

{

c=Serial.read();

if(c==97) // 如果接收到字母 a(ASCII 码值为 97)

{digitalWrite(13,HIGH); // 第 13 引脚置高电平,LED 灯亮

Serial.println("The light turn ON");

// 向 Processing 发送灯已开启的字符串,结尾处有换行符号

}

else

if (c==98) // 如果接收到字母 b(ASCII 码值为 98)

Page 12: Processing 与Arduino 通信images.china-pub.com/ebook4945001-4950000/4946916/ch02.pdf第2 章 Processing 与Arduino 通信 9为+3 ~+15V。而TTL 电平的+5V 或+3.3V 等价于逻辑1,0V

第 2 章 Processing 与 Arduino 通信 19

{ digitalWrite(13,LOW); // 第 13 引脚置低电平 ,LED 灯灭

Serial.println("The light turn OFF");

// 向 Processing发送灯已关闭的字符串,结尾处有换行符号

}

}

}

注意 该程序使用了 readStringUntil() 函数 , 该函数能一直读取字符串,直到出现事

先约定好的终止符号,使用该函数能完整地读取整个字符串。若使用 readString() 函

数则可能会出现读取不到完整的字符串,或者只读取一半的情况。读者可以自行尝

试,体验两个函数的差异。