查看: 864|回复: 5

[入门教程] ESP32与掌控板IO接口编程入门 | ESP32学习之旅-Arduino版

[复制链接]
本帖最后由 铁熊 于 2020-5-20 17:20 编辑

banner_green.png


本系列历史文章目录:



本期给大家带来的是:掌控板IO接口编程入门,教你用 Arduino IDE 学会掌控板 IO 接口的简单编程操作。IO 就是 INPUT 与 OUTPUT 的缩写,即输入与输出。

微信封面.png

其实本篇是这个系列的入门篇之一,但是由于我一直偷懒,这篇一直放着没写,先写了一些进阶的内容。本篇比较简单,所以就不放案例演示视频了。

# 概述 #

掌控板的 IO 口主要是用来连接外部传感器、执行器等相关外设的。平时我们使用最多最常见的一些外设,一般都是数字量或模拟量的,传感器一般都是输入设备、执行器一般都是输出设备。所以,一般情况下学习一个主控板的 IO 口基本操作,我们都是从数字输入、数字输出、模拟输入、模拟输出这个 4 个方面来进行学习的,本篇也不例外。

这里需要注意的是,输入和输出是相对主控板来说的

  • 当信号是由主控板向外设发送时,相应的外设就是主控板的输出设备;
  • 当信号是由外设向主控板发送时,也就是主控板去读取外设的信号时,相应的外设就是主控板的输入设备。

所以:

  • 大部分传感器都是输入设备,因为他们的功能是测量数据,然后主控板去读取他们的数据;
  • 大部分执行器都是输出设备,因为是主控板向他们发送信号、控制他们完成相应的操作。


# 数字输入 #

数字输入(或数字量输入)设备是生活中最常见的设备,比如房间里的开关、按钮、楼道里的人体感应设备,这些设备有一个共同的特点,即只有 2 中情况:有或无、开或关、1 或 0,这些只有 2 种情况的设备,一般称为数字量设备。相应地,如果他们是传感器,则称为数字输入设备,或数字输入传感器。

掌控板上的按键 A 和 B,其实就是数字输入传感器。所以本节就以读取掌控板上的按键 A 和 B 为例,教你对数字输入设备编程。

先来先一下完整的程序:

[C++] 纯文本查看 复制代码
// 设置掌控板按键 A 的引脚编号
const int buttonAPin = P5;

// 设置按键 A 的状态值变量
int buttonAState = 0;

void setup() {
  // 初始化串口监视器
  Serial.begin(9600);

  // 初始化按键 A 对应的引脚为输入模式
  pinMode(buttonAPin, INPUT);
}

void loop() {
  // 读取按键 A 的值
  buttonAState = digitalRead(buttonAPin);

  // 如果按键 A 被按下了,串口监视器输出信息
  if (buttonAState == LOW) {
    Serial.println("Button A pressed");
  }

  delay(100);
}


这个程序很简单,程序中也有相应的注释了,我们简单来讲解一下。

首先在程序开头定义了两个变量,buttonAPin 用来定义按键 A 对应的引脚,buttonAState 用来存储按键 A 的状态。

[C++] 纯文本查看 复制代码
// 设置掌控板按键 A 的引脚编号
const int buttonAPin = P5;

// 设置按键 A 的状态值变量
int buttonAState = 0;


这里讲一下命名变量的小技巧,变量一般要命名成方便用户辨别、并且有一定实际字面意义的名称,这样当程序比较长的时候更加容易读懂。尽量不要命名成 a、b 这些没有太多实际字面意义的名称,当然特殊情况除外。

那么我们是如何知道按键 A 对应的引脚编号是 P5 呢

实际上掌控板官方 Wiki 上提供了非常详细的说明和电路图,我们阅读相应的文档,就可以知道掌控板上的板载资源对应的引脚了。我们可以直接点击下方链接,查看掌控板官方 Wiki 资料。

https://mpython.readthedocs.io/zh/master/board/hardware.html

在上面的网页中,我们可以查到一张表格,上面记录了掌控板上所有板载资源对应的引脚。从这里我们可以查到按键 A 对应的引脚编号为 P5。

掌控板引脚说明表.png

接下来在初始化程序 setup() 中,我们可以看到下面两句代码,分别用来对串口监视器进行初始化、以及设定按键 A 引脚的模式。对串口监视器初始化时,我们要设定串口波特率,常用的波特率是 9600 和 115200,设置波特率的作用是让电脑和掌控板保持相同的通信速率,以便可以互相收发信息。引脚模式,最常用的一般为输入模式 INPUT 和输出模式 OUTPUT,我们知道按键是数字输入传感器,所以要设置为输入模式 INPUT。

[C++] 纯文本查看 复制代码
  // 初始化串口监视器
  Serial.begin(9600);

  // 初始化按键 A 对应的引脚为输入模式
  pinMode(buttonAPin, INPUT);


这里顺便再提一下,在 Arduino IDE 中编程,一般会有两个自带的函数,分别为初始化函数 setup() 和循环函数 loop()。setup() 函数的功能是在程序开始前做相应的设置,设备上电后(或者按下 RESET 按键之后)只执行一次;loop() 函数是在 setup() 运行完成之后开始运行的,它的功能是不断重复执行其中的代码,因此需要重复运行的代码或任务,一般放在 loop() 函数中,比如不断读取按键的状态。当然也有一些特殊情况,比如中断的设置等,是不用放在 loop() 中的,这部分等讲到相应内容的时候再来展开。

接下来在 loop() 函数中,首先读取按键 A 的状态值,并且赋值给变量 buttonAState。读取数字量输入的程序为 digitalRead(),跟变量命名一样,程序中函数命名也是带有一定的意义、简单易读的。

[C++] 纯文本查看 复制代码
// 读取按键 A 的值
buttonAState = digitalRead(buttonAPin);


然后根据按键 A 的状态值,通过串口监视器打印出相应的信息。这里需要注意的是,一般情况下,按键弹起时的默认值为 LOW(或 0),当按键被按下时,按键的值变为 HIGH(或 1)。但是这不是绝对的,跟电路设计有关,掌控板的按键值与按键状态,就正好相反。所以当掌控板的按键 A 被按下时,它的状态值为 LOW。为了防止程序运行太快,导致串口监视器一下子输出太多信息,我们这里加了一个延时函数:delay(100),让程序每次都延时 100 毫秒再去运行下一次循环任务。

[C++] 纯文本查看 复制代码
// 如果按键 A 被按下了,串口监视器输出信息
if (buttonAState == LOW) {
    Serial.println("Button A pressed");
}

delay(100);


在工具菜单中,将主控板选为掌控板,并选择正确的串口号,上传程序。然后打开串口监视器,我们看看程序运行的效果。在串口监视器中将波特率设置为 9600,然后按下掌控板上的按键 A。每按下一次按键 A,串口监视器中就会输出相应的信息,说明程序编写成功!

数字输入监视器.png


试一试:改写程序,让程序同时也可以读取按键 B 的状态,并在串口监视器输出相应的信息。你会了么?

# 数字输出 #

学会了数字输入,我们再来学一学数字输出。我们生活中最常见的电灯,一般情况下,都是数字输出设备。数字输出也是只有 2 种控制状态的设备,高或低、1 或 0。这里以控制 LED 灯为例,来学习一下数字输出的程序编写。我们现在掌控板的 P0 端口外接一个 LED 灯,这里你可以选择自己喜欢的任意扩展板。电路比较简单,所以这里不放电路图了。

来看一下完整的程序:

[C++] 纯文本查看 复制代码
// 设置掌控板按键 A 的引脚编号
const int buttonAPin = P5;

// 设置 LED 灯的引脚编号
const int ledPin = P0;

// 设置按键 A 的状态值变量
int buttonAState = 0;

void setup() {
  // 初始化串口监视器
  Serial.begin(9600);

  // 初始化按键 A 对应的引脚为输入模式
  pinMode(buttonAPin, INPUT);

  // 初始化 LED 对应的引脚为输出模式
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // 读取按键 A 的值
  buttonAState = digitalRead(buttonAPin);

  // 如果按键 A 被按下了,点亮 LED 灯,否则熄灭 LED 灯
  if (buttonAState == LOW) {
    Serial.println("Button A pressed");
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

  delay(100);
}


仔细观察,我们发现这个程序跟上一节数字输入中的程序非常类似,我们只是在这基础之上加了几行代码。这里只讲差异部分。

首先在程序开头,定义了 LED 灯的引脚编号,我们将 LED 灯通过扩展板接在掌控板的 P0 引脚,这个与定义按键 A 引脚编号的方法一致。

[C++] 纯文本查看 复制代码
// 设置 LED 灯的引脚编号
const int ledPin = P0;


然后在 setup() 初始化函数中设置了 LED 连接的引脚为输出模式 OUTPUT,这个与设置按键 A 的方法也一样,只不过一个是 LED 设置为输出模式、按键 A 设置为输入模式。

[C++] 纯文本查看 复制代码
// 初始化 LED 对应的引脚为输出模式
pinMode(ledPin, OUTPUT);


然后在 loop() 函数中,当检测到按键 A 被按下时,点亮 LED,否则熄灭 LED 灯。点亮 LED 灯的代码为:

[C++] 纯文本查看 复制代码
digitalWrite(ledPin, HIGH);


熄灭 LED 灯的代码为:

[AppleScript] 纯文本查看 复制代码
digitalWrite(ledPin, LOW);


将程序上传到掌控板,按下按键 A,看看 LED 灯是否点亮了呢?松开按键 A 呢?

试一试:改写程序,实现:按下按键 A,点亮 LED 灯;按下按键 B,熄灭 LED 灯。

# 模拟输入 #

讲完数字输入、数字输出,我们再来看一看模拟输入。模拟输入是相对数字输入来说的,数字输入只要 2 种状态,但是模拟输入有很多种连续的状态,比如各种旋钮、温度值等。

在掌控板上也有 2 个模拟输入传感器:声音传感器与光线传感器。下面我们以声音传感器为例,讲一讲模拟输入的程序编写方法。

[C++] 纯文本查看 复制代码
// 设置掌控板声音传感器引脚编号
const int soundPin = P10;

// 设置声音大小值变量
int soundValue = 0;

void setup() {
  // 初始化串口监视器
  Serial.begin(9600);

  // 初始化声音传感器引脚为输入模式
  pinMode(soundPin, INPUT);
}

void loop() {
  // 读取声音传感器的值
  soundValue = analogRead(soundPin);

  // 串口监视器中打印声音传感器的值
  Serial.println(soundValue);

  delay(10);
}


这个程序与数字输入部分的程序也是非常类似的。

在程序开头,定义了两个变量,用来设置声音传感器的引脚编号、声音传感器的值。

[C++] 纯文本查看 复制代码
// 设置掌控板声音传感器引脚编号
const int soundPin = P10;

// 设置声音大小值变量
int soundValue = 0;


接着在 setup() 初始化函数中,初始化串口监视器和声音传感器的引脚模式:

[C++] 纯文本查看 复制代码
// 初始化串口监视器
Serial.begin(9600);

// 初始化声音传感器引脚为输入模式
pinMode(soundPin, INPUT);


接着在 loop() 函数中读取声音的值,并且在串口监视器中打印出来。读取模拟量的函数为 analogRead()。

[C++] 纯文本查看 复制代码
// 读取声音传感器的值
soundValue = analogRead(soundPin);

// 串口监视器中打印声音传感器的值
Serial.println(soundValue);

delay(10);


将程序上传到掌控板中,打开串口监视器,对着声音传感器说话,我们看看效果。

模拟输入绘图器.png

我们还可以以曲线图的形式,将声音传感器数据的变化展现出来。在 Arduino IDE 菜单栏中,依次点击:工具 → 串口绘图器,打开串口绘图器,对着声音传感器说话,看看曲线图变化吧。

![模拟输入绘图器](images/模拟输入绘图器.png)

试一试:改写程序,让程序同时也可以读取光线传感器的值,看看串口绘图器会输出什么信息呢?

# 模拟输出 #

你有没有注意到,有些人家里的电灯,亮度是可以调节的?这个其实就是模拟输出。相比于数字输出只有两种状态,模拟输出可以有连续的多种状态。

由于在 Arduino IDE 中,用掌控板自带的函数功能实现模拟输出比较复杂。因此我们这里调用别人做好的适用于掌控板 ESP32 的模拟输出函数库。函数库下载地址为:

https://github.com/ERROPiX/ESP32_AnalogWrite

我们要先将这个库导入到 Arduino IDE 中。这个库的功能是可以让掌控板像 Arduino 一样,方便的使用模拟输出功能,有个这个库,掌控板模拟输出的语法,就跟 Arduino 完全一样了。

这里以控制 LED 灯实现呼吸灯效果为例,完整的程序如下:

[C++] 纯文本查看 复制代码
#include <Arduino.h>
#include <analogWrite.h>

// 设置 LED 灯引脚编号
const int ledPin = P0;

void setup() {
  // 初始化 LED 灯引脚为输出模式
  pinMode(ledPin, OUTPUT);
}

void loop() {
  for (int brightness = 0; brightness <= 255; brightness++) {
    analogWrite(ledPin, brightness);
    delay(5);
  }

  for (int brightness = 255; brightness >= 0; brightness--) {
    analogWrite(ledPin, brightness);
    delay(5);
  }
}


在程序最开始,我们先引入两个头文件,在头文件中定义了实现模拟输出相关的功能函数。然后定义了 LED 灯的引脚编号。

[C++] 纯文本查看 复制代码
#include <Arduino.h>
#include <analogWrite.h>

// 设置 LED 灯引脚编号
const int ledPin = P0;


接着在 setup() 函数中设置 LED 灯引脚为输出模式。

然后在 loop() 函数中,通过 for 循环结构,控制 LED 灯由暗变亮,再由亮变暗。亮度通过局部变量 brightness 来设置。

[C++] 纯文本查看 复制代码
for (int brightness = 0; brightness <= 255; brightness++) {
    analogWrite(ledPin, brightness);
    delay(5);
}

for (int brightness = 255; brightness >= 0; brightness--) {
    analogWrite(ledPin, brightness);
    delay(5);
}


将程序上传到掌控板中,LED 灯是不是呈现呼吸灯闪烁变化的样子?说明程序编程成功了。


# 总结 #

在本章中,我们学习了:

  • 如何查阅掌控板各引脚相应的资源配置;
  • 数字量与模拟量的区别;
  • 简单的数字输入、数字输出、模拟输入、模拟输出的程序编写;
  • Arduino IDE 的基本使用方法。

学习了这些基础内容之后,就可以学习后面更加进阶的内容啦,其实进阶内容与入门内容类似,都是由一个个小功能组成的,有了这些基础功能的组合,通过不同的排列组合和逻辑设置,就可以实现各种好玩的创意啦!


# 欢迎关注 #

最后,欢迎关注公众号:铁熊玩创客,不定期更新创客制作、技术教程、创客教育等相关内容。


微信二维码引导2.png





小刚郭  初级技师

发表于 2020-4-20 20:49:27

不错的帖子啊
能不能讲讲一些高级的io食用
比如io寄存器,rmt
回复

使用道具 举报

1528  见习技师

发表于 2020-4-20 21:28:21

初学者,学习了,学习了,学习了,学习了!
回复

使用道具 举报

铁熊  初级技神
 楼主|

发表于 2020-4-20 21:30:51

小刚郭 发表于 2020-4-20 20:49
不错的帖子啊
能不能讲讲一些高级的io食用
比如io寄存器,rmt

有时间会慢慢更新的
回复

使用道具 举报

gada888  版主

发表于 2020-4-27 11:18:26

内容好全
回复

使用道具 举报

20060606  高级技匠

发表于 2020-7-17 05:10:37

太高端了,看不懂
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2020 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail