如何使用 ESP32 做類比輸出?做個 80 年代的指針溫濕度表吧!

ESP32 相對於 Raspberry Pi 來說,最大的差異點之一是擁有類比輸出輸入(DAC, ADC)!可以讓我們把現實生活中的訊號(類比)與電路世界的訊號(數位)做一個橋樑。就讓我們為 如何用 ESP32 快速做溫溼度監測? 使用 DHT sensor 來達成智慧家居! 中一起做的溫濕度偵測器增加一個 80 年代的指針輸出吧!

這個專案有趣的地方在於,先透過 DHT sensor 把類比溫濕度轉換成數位後進入 ESP32 中處理,再將數值轉換成類比電壓大小輸出,並掛上負載電阻,透過指針電流計測量電流大小顯示溫濕度。因為轉換兩次可能會損失一些精准度,但卻是一個有趣的概念性專案,就讓我們一起來實作吧!

為了方便講解,以下我們以一個類比輸出來顯示濕度作為範例。

Step 1:準備硬體元件

這次製作需要準備的材料為:

  1. ESP32 (這邊以 NodeMCU-ESP32 為例)
  2. 3.3k 電阻
  3. 電流錶頭,最大值為 1mA

註:先前偵測溫濕度的元件就不再註明了,詳細可以參考 如何用 ESP32 快速做溫溼度監測? 使用 DHT sensor 來達成智慧家居!

Step 2:硬體線路

線路非常簡單

  1. 將 VIN 拉到 Vcc,方便起見我們可以直接用 USB 供電
  2. 以 GPIO 25 作為類比輸出 pin,拉到 3.3k 電阻的一端
  3. 電流計串連電阻,再拉到地
如何使用 ESP32 做類比輸出?做個 80 年代的指針溫濕度表吧!

為什麼我們要選用 3.3k 電阻呢?有以下原因

  1. ESP32 analog output 最大電壓是 3.3V
  2. 我希望最大輸出電流 1mA
  3. 簡單計算一下 V = IR,可以得到電阻應該選用 3.3k
  4. 因此電流錶頭用最大值為 1mA 的規格

Step 3:如何寫 DAC 程式

首先我們學習如何使用 analog output (DAC)。

在 ESP32 arduino framework 中,使用 dacWrite() 這個函數做輸出。第一個參數給定 pin,第二個參數給定要輸出的電壓的值。其中:

  1. 對應的 pin 不用特別宣告他的型態,也就是說不需要透過 pinMode() 函數在 setup 階段做宣告,直接使用 dacWrite() 函數即可
  2. 給定輸出的值範圍是 0~255,可以得知他將 3.3V 分成 255 份。255 時輸出 3.3V,3.3 * 128 / 255 的話約為 1.65V
#include <Arduino.h>
#define OUTPUT_PIN 25

void setup() {}

void loop() {
    int value = 128;
    dacWrite(OUTPUT_PIN, value);
}

拿一片尚未接線的 ESP32 跑起來後可以用三用電錶點一下看看是不是 1.65V 左右,如果是表示成功!

Step 4:開始寫程式

我們接續 如何用 ESP32 快速做溫溼度監測? 使用 DHT sensor 來達成智慧家居! 的程式範例繼續寫:

  1. 增加 define 三個常數,HUMIDITY_PIN, MAX_HUMIDITY 以及 DAC_MAX_VALUE
  2. 增加 displayHumidity() 函數,傳入目前濕度值,轉換 0 ~ 100 的濕度範圍為 0 ~ 255 後寫入 DAC
  3. loop() 函數中,成功從 DHT22 取得溫濕度,呼叫 displayHumidity() 函數將數值送出
#include <Arduino.h>
#include "DHTesp.h"

// 新增 define
#define HUMIDITY_PIN 25
#define MAX_HUMIDITY 100.0
#define DAC_MAX_VALUE 255

DHTesp dht;

// 新增顯示濕度函數
void displayHumidity(float humidity) {
     int value = (int)(humidity / MAX_HUMIDITY * DAC_MAX_VALUE);
     dacWrite(HUMIDITY_PIN, value);
}

void setup() [
    dht.setup(27, DHTesp::AM2302);
}

void loop() {
    TempAndHumidity data = dht.getTempAndHumidity();

    if (dht.getStatus() != 0) {
        Serial.println("DHT sensor error status: " + String(dht.getStatusString()));
    
    } else if (isnan(data.humidity) || isnan(data.temperature)) {
        Serial.println("Data is NaN!");

    } else {
        Serial.print("Humidity: ");
        Serial.print(data.humidity);
        Serial.print("%  Temperature: ");
        Serial.println(data.temperature);
 
        // 呼叫顯示濕度函數,將濕度傳入
        displayHumidity(data.humidity);
    }

    delay(2000);
}

溫度的部分就留給大家自行嘗試看看囉!

Step 5:上電測試

成功的話會看到電流表指針移動到對應電流值,可以簡單回推一下電壓是否正確,就能驗證程式是否有寫錯。

如何使用 ESP32 做類比輸出?做個 80 年代的指針溫濕度表吧!

電流表頭裡面的刻度可以自行重新印一張正確的覆蓋上去,以後讀取就不用再腦中計算電壓反推拉!

延伸閱讀:如何用 ESP32 快速做溫溼度監測? 使用 DHT sensor 來達成智慧家居!

Written by J
雖然大學唸的是生物,但持著興趣與熱情自學,畢業後轉戰硬體工程師,與宅宅工程師們一起過著沒日沒夜的生活,做著台灣最薄的 intel 筆電,要與 macbook air 比拼。 離開後,憑著一股傻勁與朋友創業,再度轉戰軟體工程師,一手扛起前後端、雙平台 app 開發,過程中雖跌跌撞撞,卻也累計不少經驗。 可惜不是那 1% 的成功人士,於是加入其他成功人士的新創公司,專職開發後端。沒想到卻在採前人坑的過程中,拓寬了眼界,得到了深層的領悟。