ESP32與掌控板IO接口編程入門 | ESP32開發之旅-Arduino版

衆所周知,掌控板在創客教育中用的非常廣泛,它是一塊基於 ESP32 的學習開發板。大家對掌控板編程,用的比較多的都是圖形化編程的方式,比如 mPython、Mind+ 等。但是,既然掌控板是基於 ESP32 芯片的,所以我們也可以用 Arduino 軟件對其編程。所以,有時間的話,我準備給大家分享一系列用 Arduino 代碼對掌控板(ESP32)編程的教程:用Arduino玩轉ESP32與掌控板系列

本系列歷史文章目錄:

本期給大家帶來的是:掌控板IO接口編程入門,教你用 Arduino IDE 學會掌控板 IO 接口的簡單編程操作。IO 就是 INPUT 與 OUTPUT 的縮寫,即輸入與輸出。
微信封面
其實本篇是這個系列的入門篇之一,但是由於我一直偷懶,這篇一直放着沒寫,先寫了一些進階的內容。本篇比較簡單,所以就不放案例演示視頻了。

概述

掌控板的 IO 口主要是用來連接外部傳感器、執行器等相關外設的。平時我們使用最多最常見的一些外設,一般都是數字量或模擬量的,傳感器一般都是輸入設備、執行器一般都是輸出設備。所以,一般情況下學習一個主控板的 IO 口基本操作,我們都是從數字輸入數字輸出模擬輸入模擬輸出這個 4 個方面來進行學習的,本篇也不例外。

這裏需要注意的是,輸入和輸出是相對主控板來說的

  • 當信號是由主控板向外設發送時,相應的外設就是主控板的輸出設備;
  • 當信號是由外設向主控板發送時,也就是主控板去讀取外設的信號時,相應的外設就是主控板的輸入設備。

所以:

  • 大部分傳感器都是輸入設備,因爲他們的功能是測量數據,然後主控板去讀取他們的數據;
  • 大部分執行器都是輸出設備,因爲是主控板向他們發送信號、控制他們完成相應的操作。

數字輸入

數字輸入(或數字量輸入)設備是生活中最常見的設備,比如房間裏的開關、按鈕、樓道里的人體感應設備,這些設備有一個共同的特點,即只有 2 中情況:有或無、開或關、1 或 0,這些只有 2 種情況的設備,一般稱爲數字量設備。相應地,如果他們是傳感器,則稱爲數字輸入設備,或數字輸入傳感器。

掌控板上的按鍵 A 和 B,其實就是數字輸入傳感器。所以本節就以讀取掌控板上的按鍵 A 和 B 爲例,教你對數字輸入設備編程。

先來先一下完整的程序:

// 設置掌控板按鍵 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 的狀態。

// 設置掌控板按鍵 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。
掌控板引腳說明表
接下來在初始化程序 setup() 中,我們可以看到下面兩句代碼,分別用來對串口監視器進行初始化、以及設定按鍵 A 引腳的模式。對串口監視器初始化時,我們要設定串口波特率,常用的波特率是 9600 和 115200,設置波特率的作用是讓電腦和掌控板保持相同的通信速率,以便可以互相收發信息。引腳模式,最常用的一般爲輸入模式 INPUT 和輸出模式 OUTPUT,我們知道按鍵是數字輸入傳感器,所以要設置爲輸入模式 INPUT。

  // 初始化串口監視器
  Serial.begin(9600);

  // 初始化按鍵 A 對應的引腳爲輸入模式
  pinMode(buttonAPin, INPUT);

這裏順便再提一下,在 Arduino IDE 中編程,一般會有兩個自帶的函數,分別爲初始化函數 setup() 和循環函數 loop()。setup() 函數的功能是在程序開始前做相應的設置,設備上電後(或者按下 RESET 按鍵之後)只執行一次;loop() 函數是在 setup() 運行完成之後開始運行的,它的功能是不斷重複執行其中的代碼,因此需要重複運行的代碼或任務,一般放在 loop() 函數中,比如不斷讀取按鍵的狀態。當然也有一些特殊情況,比如中斷的設置等,是不用放在 loop() 中的,這部分等講到相應內容的時候再來展開。

接下來在 loop() 函數中,首先讀取按鍵 A 的狀態值,並且賦值給變量 buttonAState。讀取數字量輸入的程序爲 digitalRead(),跟變量命名一樣,程序中函數命名也是帶有一定的意義、簡單易讀的。

// 讀取按鍵 A 的值
buttonAState = digitalRead(buttonAPin);

然後根據按鍵 A 的狀態值,通過串口監視器打印出相應的信息。這裏需要注意的是,一般情況下,按鍵彈起時的默認值爲 LOW(或 0),當按鍵被按下時,按鍵的值變爲 HIGH(或 1)。但是這不是絕對的,跟電路設計有關,掌控板的按鍵值與按鍵狀態,就正好相反。所以當掌控板的按鍵 A 被按下時,它的狀態值爲 LOW。爲了防止程序運行太快,導致串口監視器一下子輸出太多信息,我們這裏加了一個延時函數:delay(100),讓程序每次都延時 100 毫秒再去運行下一次循環任務。

// 如果按鍵 A 被按下了,串口監視器輸出信息
if (buttonAState == LOW) {
    Serial.println("Button A pressed");
}

delay(100);

在工具菜單中,將主控板選爲掌控板,並選擇正確的串口號,上傳程序。然後打開串口監視器,我們看看程序運行的效果。在串口監視器中將波特率設置爲 9600,然後按下掌控板上的按鍵 A。每按下一次按鍵 A,串口監視器中就會輸出相應的信息,說明程序編寫成功!
數字輸入監視器

試一試:改寫程序,讓程序同時也可以讀取按鍵 B 的狀態,並在串口監視器輸出相應的信息。你會了麼?

數字輸出

學會了數字輸入,我們再來學一學數字輸出。我們生活中最常見的電燈,一般情況下,都是數字輸出設備。數字輸出也是隻有 2 種控制狀態的設備,高或低、1 或 0。這裏以控制 LED 燈爲例,來學習一下數字輸出的程序編寫。我們現在掌控板的 P0 端口外接一個 LED 燈,這裏你可以選擇自己喜歡的任意擴展板。電路比較簡單,所以這裏不放電路圖了。

來看一下完整的程序:

// 設置掌控板按鍵 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 引腳編號的方法一致。

// 設置 LED 燈的引腳編號
const int ledPin = P0;

然後在 setup() 初始化函數中設置了 LED 連接的引腳爲輸出模式 OUTPUT,這個與設置按鍵 A 的方法也一樣,只不過一個是 LED 設置爲輸出模式、按鍵 A 設置爲輸入模式。

// 初始化 LED 對應的引腳爲輸出模式
pinMode(ledPin, OUTPUT);

然後在 loop() 函數中,當檢測到按鍵 A 被按下時,點亮 LED,否則熄滅 LED 燈。點亮 LED 燈的代碼爲:

digitalWrite(ledPin, HIGH);

熄滅 LED 燈的代碼爲:

digitalWrite(ledPin, LOW);

將程序上傳到掌控板,按下按鍵 A,看看 LED 燈是否點亮了呢?鬆開按鍵 A 呢?

試一試:改寫程序,實現:按下按鍵 A,點亮 LED 燈;按下按鍵 B,熄滅 LED 燈。

模擬輸入

講完數字輸入、數字輸出,我們再來看一看模擬輸入。模擬輸入是相對數字輸入來說的,數字輸入只要 2 種狀態,但是模擬輸入有很多種連續的狀態,比如各種旋鈕、溫度值等。

在掌控板上也有 2 個模擬輸入傳感器:聲音傳感器與光線傳感器。下面我們以聲音傳感器爲例,講一講模擬輸入的程序編寫方法。

// 設置掌控板聲音傳感器引腳編號
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);
}

這個程序與數字輸入部分的程序也是非常類似的。

在程序開頭,定義了兩個變量,用來設置聲音傳感器的引腳編號、聲音傳感器的值。

// 設置掌控板聲音傳感器引腳編號
const int soundPin = P10;

// 設置聲音大小值變量
int soundValue = 0;

接着在 setup() 初始化函數中,初始化串口監視器和聲音傳感器的引腳模式:

// 初始化串口監視器
Serial.begin(9600);

// 初始化聲音傳感器引腳爲輸入模式
pinMode(soundPin, INPUT);

接着在 loop() 函數中讀取聲音的值,並且在串口監視器中打印出來。讀取模擬量的函數爲 analogRead()。

// 讀取聲音傳感器的值
soundValue = analogRead(soundPin);

// 串口監視器中打印聲音傳感器的值
Serial.println(soundValue);

delay(10);

將程序上傳到掌控板中,打開串口監視器,對着聲音傳感器說話,我們看看效果。
模擬輸入監視器
我們還可以以曲線圖的形式,將聲音傳感器數據的變化展現出來。在 Arduino IDE 菜單欄中,依次點擊:工具 → 串口繪圖器,打開串口繪圖器,對着聲音傳感器說話,看看曲線圖變化吧。
模擬輸入繪圖器

試一試:改寫程序,讓程序同時也可以讀取光線傳感器的值,看看串口繪圖器會輸出什麼信息呢?

模擬輸出

你有沒有注意到,有些人家裏的電燈,亮度是可以調節的?這個其實就是模擬輸出。相比於數字輸出只有兩種狀態,模擬輸出可以有連續的多種狀態。

由於在 Arduino IDE 中,用掌控板自帶的函數功能實現模擬輸出比較複雜。因此我們這裏調用別人做好的適用於掌控板 ESP32 的模擬輸出函數庫。函數庫下載地址爲:

https://github.com/ERROPiX/ESP32_AnalogWrite

我們要先將這個庫導入到 Arduino IDE 中。這個庫的功能是可以讓掌控板像 Arduino 一樣,方便的使用模擬輸出功能,有個這個庫,掌控板模擬輸出的語法,就跟 Arduino 完全一樣了。

這裏以控制 LED 燈實現呼吸燈效果爲例,完整的程序如下:

#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 燈的引腳編號。

#include <Arduino.h>
#include <analogWrite.h>

// 設置 LED 燈引腳編號
const int ledPin = P0;

接着在 setup() 函數中設置 LED 燈引腳爲輸出模式。

然後在 loop() 函數中,通過 for 循環結構,控制 LED 燈由暗變亮,再由亮變暗。亮度通過局部變量 brightness 來設置。

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 的基本使用方法。

學習了這些基礎內容之後,就可以學習後面更加進階的內容啦,其實進階內容與入門內容類似,都是由一個個小功能組成的,有了這些基礎功能的組合,通過不同的排列組合和邏輯設置,就可以實現各種好玩的創意啦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章