4914| 5
|
[入门教程] ESP32与掌控板IO接口编程入门 | ESP32轻松学 |
本帖最后由 铁熊 于 2021-2-7 20:14 编辑 本系列历史文章目录: 本期给大家带来的是:掌控板IO接口编程入门,教你用 Arduino IDE 学会掌控板 IO 接口的简单编程操作。IO 就是 INPUT 与 OUTPUT 的缩写,即输入与输出。 其实本篇是这个系列的入门篇之一,但是由于我一直偷懒,这篇一直放着没写,先写了一些进阶的内容。本篇比较简单,所以就不放案例演示视频了。 # 概述 # 掌控板的 IO 口主要是用来连接外部传感器、执行器等相关外设的。平时我们使用最多最常见的一些外设,一般都是数字量或模拟量的,传感器一般都是输入设备、执行器一般都是输出设备。所以,一般情况下学习一个主控板的 IO 口基本操作,我们都是从数字输入、数字输出、模拟输入、模拟输出这个 4 个方面来进行学习的,本篇也不例外。 这里需要注意的是,输入和输出是相对主控板来说的:
所以:
# 数字输入 # 数字输入(或数字量输入)设备是生活中最常见的设备,比如房间里的开关、按钮、楼道里的人体感应设备,这些设备有一个共同的特点,即只有 2 中情况:有或无、开或关、1 或 0,这些只有 2 种情况的设备,一般称为数字量设备。相应地,如果他们是传感器,则称为数字输入设备,或数字输入传感器。 掌控板上的按键 A 和 B,其实就是数字输入传感器。所以本节就以读取掌控板上的按键 A 和 B 为例,教你对数字输入设备编程。 先来先一下完整的程序: [mw_shl_code=cpp,false]// 设置掌控板按键 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); }[/mw_shl_code] 这个程序很简单,程序中也有相应的注释了,我们简单来讲解一下。 首先在程序开头定义了两个变量,buttonAPin 用来定义按键 A 对应的引脚,buttonAState 用来存储按键 A 的状态。 [mw_shl_code=cpp,false]// 设置掌控板按键 A 的引脚编号 const int buttonAPin = P5; // 设置按键 A 的状态值变量 int buttonAState = 0;[/mw_shl_code] 这里讲一下命名变量的小技巧,变量一般要命名成方便用户辨别、并且有一定实际字面意义的名称,这样当程序比较长的时候更加容易读懂。尽量不要命名成 a、b 这些没有太多实际字面意义的名称,当然特殊情况除外。 那么我们是如何知道按键 A 对应的引脚编号是 P5 呢? 实际上掌控板官方 Wiki 上提供了非常详细的说明和电路图,我们阅读相应的文档,就可以知道掌控板上的板载资源对应的引脚了。我们可以直接点击下方链接,查看掌控板官方 Wiki 资料。 https://mpython.readthedocs.io/zh/master/board/hardware.html 在上面的网页中,我们可以查到一张表格,上面记录了掌控板上所有板载资源对应的引脚。从这里我们可以查到按键 A 对应的引脚编号为 P5。 接下来在初始化程序 setup() 中,我们可以看到下面两句代码,分别用来对串口监视器进行初始化、以及设定按键 A 引脚的模式。对串口监视器初始化时,我们要设定串口波特率,常用的波特率是 9600 和 115200,设置波特率的作用是让电脑和掌控板保持相同的通信速率,以便可以互相收发信息。引脚模式,最常用的一般为输入模式 INPUT 和输出模式 OUTPUT,我们知道按键是数字输入传感器,所以要设置为输入模式 INPUT。 [mw_shl_code=cpp,false] // 初始化串口监视器 Serial.begin(9600); // 初始化按键 A 对应的引脚为输入模式 pinMode(buttonAPin, INPUT);[/mw_shl_code] 这里顺便再提一下,在 Arduino IDE 中编程,一般会有两个自带的函数,分别为初始化函数 setup() 和循环函数 loop()。setup() 函数的功能是在程序开始前做相应的设置,设备上电后(或者按下 RESET 按键之后)只执行一次;loop() 函数是在 setup() 运行完成之后开始运行的,它的功能是不断重复执行其中的代码,因此需要重复运行的代码或任务,一般放在 loop() 函数中,比如不断读取按键的状态。当然也有一些特殊情况,比如中断的设置等,是不用放在 loop() 中的,这部分等讲到相应内容的时候再来展开。 接下来在 loop() 函数中,首先读取按键 A 的状态值,并且赋值给变量 buttonAState。读取数字量输入的程序为 digitalRead(),跟变量命名一样,程序中函数命名也是带有一定的意义、简单易读的。 [mw_shl_code=cpp,false]// 读取按键 A 的值 buttonAState = digitalRead(buttonAPin);[/mw_shl_code] 然后根据按键 A 的状态值,通过串口监视器打印出相应的信息。这里需要注意的是,一般情况下,按键弹起时的默认值为 LOW(或 0),当按键被按下时,按键的值变为 HIGH(或 1)。但是这不是绝对的,跟电路设计有关,掌控板的按键值与按键状态,就正好相反。所以当掌控板的按键 A 被按下时,它的状态值为 LOW。为了防止程序运行太快,导致串口监视器一下子输出太多信息,我们这里加了一个延时函数:delay(100),让程序每次都延时 100 毫秒再去运行下一次循环任务。 [mw_shl_code=cpp,false]// 如果按键 A 被按下了,串口监视器输出信息 if (buttonAState == LOW) { Serial.println("Button A pressed"); } delay(100);[/mw_shl_code] 在工具菜单中,将主控板选为掌控板,并选择正确的串口号,上传程序。然后打开串口监视器,我们看看程序运行的效果。在串口监视器中将波特率设置为 9600,然后按下掌控板上的按键 A。每按下一次按键 A,串口监视器中就会输出相应的信息,说明程序编写成功! 试一试:改写程序,让程序同时也可以读取按键 B 的状态,并在串口监视器输出相应的信息。你会了么? # 数字输出 # 学会了数字输入,我们再来学一学数字输出。我们生活中最常见的电灯,一般情况下,都是数字输出设备。数字输出也是只有 2 种控制状态的设备,高或低、1 或 0。这里以控制 LED 灯为例,来学习一下数字输出的程序编写。我们现在掌控板的 P0 端口外接一个 LED 灯,这里你可以选择自己喜欢的任意扩展板。电路比较简单,所以这里不放电路图了。 来看一下完整的程序: [mw_shl_code=cpp,false]// 设置掌控板按键 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); }[/mw_shl_code] 仔细观察,我们发现这个程序跟上一节数字输入中的程序非常类似,我们只是在这基础之上加了几行代码。这里只讲差异部分。 首先在程序开头,定义了 LED 灯的引脚编号,我们将 LED 灯通过扩展板接在掌控板的 P0 引脚,这个与定义按键 A 引脚编号的方法一致。 [mw_shl_code=cpp,false]// 设置 LED 灯的引脚编号 const int ledPin = P0;[/mw_shl_code] 然后在 setup() 初始化函数中设置了 LED 连接的引脚为输出模式 OUTPUT,这个与设置按键 A 的方法也一样,只不过一个是 LED 设置为输出模式、按键 A 设置为输入模式。 [mw_shl_code=cpp,false]// 初始化 LED 对应的引脚为输出模式 pinMode(ledPin, OUTPUT);[/mw_shl_code] 然后在 loop() 函数中,当检测到按键 A 被按下时,点亮 LED,否则熄灭 LED 灯。点亮 LED 灯的代码为: [mw_shl_code=cpp,false]digitalWrite(ledPin, HIGH);[/mw_shl_code] 熄灭 LED 灯的代码为: [mw_shl_code=applescript,false]digitalWrite(ledPin, LOW);[/mw_shl_code] 将程序上传到掌控板,按下按键 A,看看 LED 灯是否点亮了呢?松开按键 A 呢? 试一试:改写程序,实现:按下按键 A,点亮 LED 灯;按下按键 B,熄灭 LED 灯。 # 模拟输入 # 讲完数字输入、数字输出,我们再来看一看模拟输入。模拟输入是相对数字输入来说的,数字输入只要 2 种状态,但是模拟输入有很多种连续的状态,比如各种旋钮、温度值等。 在掌控板上也有 2 个模拟输入传感器:声音传感器与光线传感器。下面我们以声音传感器为例,讲一讲模拟输入的程序编写方法。 [mw_shl_code=cpp,false]// 设置掌控板声音传感器引脚编号 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); }[/mw_shl_code] 这个程序与数字输入部分的程序也是非常类似的。 在程序开头,定义了两个变量,用来设置声音传感器的引脚编号、声音传感器的值。 [mw_shl_code=cpp,false]// 设置掌控板声音传感器引脚编号 const int soundPin = P10; // 设置声音大小值变量 int soundValue = 0;[/mw_shl_code] 接着在 setup() 初始化函数中,初始化串口监视器和声音传感器的引脚模式: [mw_shl_code=cpp,false]// 初始化串口监视器 Serial.begin(9600); // 初始化声音传感器引脚为输入模式 pinMode(soundPin, INPUT);[/mw_shl_code] 接着在 loop() 函数中读取声音的值,并且在串口监视器中打印出来。读取模拟量的函数为 analogRead()。 [mw_shl_code=cpp,false]// 读取声音传感器的值 soundValue = analogRead(soundPin); // 串口监视器中打印声音传感器的值 Serial.println(soundValue); delay(10);[/mw_shl_code] 将程序上传到掌控板中,打开串口监视器,对着声音传感器说话,我们看看效果。 我们还可以以曲线图的形式,将声音传感器数据的变化展现出来。在 Arduino IDE 菜单栏中,依次点击:工具 → 串口绘图器,打开串口绘图器,对着声音传感器说话,看看曲线图变化吧。 ![模拟输入绘图器](images/模拟输入绘图器.png) 试一试:改写程序,让程序同时也可以读取光线传感器的值,看看串口绘图器会输出什么信息呢? # 模拟输出 # 你有没有注意到,有些人家里的电灯,亮度是可以调节的?这个其实就是模拟输出。相比于数字输出只有两种状态,模拟输出可以有连续的多种状态。 由于在 Arduino IDE 中,用掌控板自带的函数功能实现模拟输出比较复杂。因此我们这里调用别人做好的适用于掌控板 ESP32 的模拟输出函数库。函数库下载地址为: https://github.com/ERROPiX/ESP32_AnalogWrite 我们要先将这个库导入到 Arduino IDE 中。这个库的功能是可以让掌控板像 Arduino 一样,方便的使用模拟输出功能,有个这个库,掌控板模拟输出的语法,就跟 Arduino 完全一样了。 这里以控制 LED 灯实现呼吸灯效果为例,完整的程序如下: [mw_shl_code=cpp,false]#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); } }[/mw_shl_code] 在程序最开始,我们先引入两个头文件,在头文件中定义了实现模拟输出相关的功能函数。然后定义了 LED 灯的引脚编号。 [mw_shl_code=cpp,false]#include <Arduino.h> #include <analogWrite.h> // 设置 LED 灯引脚编号 const int ledPin = P0;[/mw_shl_code] 接着在 setup() 函数中设置 LED 灯引脚为输出模式。 然后在 loop() 函数中,通过 for 循环结构,控制 LED 灯由暗变亮,再由亮变暗。亮度通过局部变量 brightness 来设置。 [mw_shl_code=cpp,false]for (int brightness = 0; brightness <= 255; brightness++) { analogWrite(ledPin, brightness); delay(5); } for (int brightness = 255; brightness >= 0; brightness--) { analogWrite(ledPin, brightness); delay(5); }[/mw_shl_code] 将程序上传到掌控板中,LED 灯是不是呈现呼吸灯闪烁变化的样子?说明程序编程成功了。 # 总结 # 在本章中,我们学习了:
学习了这些基础内容之后,就可以学习后面更加进阶的内容啦,其实进阶内容与入门内容类似,都是由一个个小功能组成的,有了这些基础功能的组合,通过不同的排列组合和逻辑设置,就可以实现各种好玩的创意啦! # 欢迎关注 # 最后,欢迎关注公众号:铁熊玩创客,不定期更新创客制作、技术教程、创客教育等相关内容。 |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed