如何使用 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 做類比輸出 DAC?做個 80 年代的指針溫濕度表吧!如何使用 ESP32 做類比輸出 DAC?做個 80 年代的指針溫濕度表吧! 如何使用 ESP32 做類比輸出 DAC?做個 80 年代的指針溫濕度表吧!如何使用 ESP32 做類比輸出 DAC?做個 80 年代的指針溫濕度表吧! 如何使用 ESP32 做類比輸出 DAC?做個 80 年代的指針溫濕度表吧!如何使用 ESP32 做類比輸出 DAC?做個 80 年代的指針溫濕度表吧!

註:先前偵測溫濕度的元件就不再註明了,詳細可以參考 如何用 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% 的成功人士,於是加入其他成功人士的新創公司,專職開發後端。沒想到卻在採前人坑的過程中,拓寬了眼界,得到了深層的領悟。