Arduino / ESP 的 LED 沙漏

qedqed6
5 min readSep 30, 2022

--

前陣子在 IG 上看到了一個非常漂亮的 Arduino Hourglass 專案。

因為覺得非常漂亮,就決定自己也來做一個。

材料

  • 控制板:Arduino 系列 (ATMEGA 2560) 或是 ESP 系列 (ESP32 DEVKit v1)
  • 顯示:8 x 8 LED 矩陣顯示器含 MAX7219 IC 的模組,共兩個。
  • 感測器:陀螺儀和加速度計的 MPU 6050。

電路圖

MAX 7219 可以幫助我們輕鬆地透過串流資料來控制 LED 矩陣的每一個點的亮或是暗。

最有趣的地方是,它可以與其它的 MAX 7219 進行鏈接,這代表可以用固定數量的 GPIO 來控制多個 LED 矩陣。

因此我們將 LED 沙漏的上半部分與下半部分鏈接起來,並將串流資料的相關腳位接到 ESP32 控制器。

感測器部分使用 MPU 6050, 內建加速度計和陀螺儀。

為了模擬沙漏中的沙子受到地球重力影響而下落的物理特性,所以要透過加速度計來偵測重力作用在沙漏上的方向。

ESP32 DEVKIT V1 開發板上的 ESP-WROOM-32 MCU 上的程式碼要負責:

  • 建立 LED 矩陣沙漏的抽象資料模型
  • 接收 MPU 6050 的加速度計資料,並判斷當前重力作用在沙漏的方向
  • 將資料模型的資料顯示在兩個 MAX 7219 的 LED 矩陣上。

LED 矩陣沙漏的資料模型

LED 沙漏分成上下兩個區塊,無論是哪一個區塊,其中的沙粒都要表現出受到重力的影響,使得砂粒下落的行為。

因此只要建立好一個區塊資料模型並重覆使用即可,因為無論是上或是下的區塊,表現出的概念都是相同的;給予區塊重力方向,使得沙粒向下落下。

首先將代表沙漏某一個區塊的 LED 矩陣放在直角坐標系內。如果以實際的視覺效果會像是下圖這樣:

假定有一(藍色)沙粒在座標 (7, 7) ,則它受重力的影響會有三種可能性(紅色)分別是:

  • 正下方座標 (6, 6)
  • 右下方座標 (7, 6)
  • 左下方座標 (6, 7)

實際上,假設不考慮其它物理特性的話,在這裡傾向的做法是,若正下方沒有其它沙粒存在,優先讓沙粒從 (7, 7) 移動到 (6, 6),這樣子的表現會更像實物。

而左下和右下的方向,若是兩邊也都沒有沙粒存在,則亂數決定其落下方向,避免總是讓沙粒呈現固定的行為。

而若是只有一邊沒有沙粒存在,就讓它往沒有沙粒的方向落下。

最後,三個方向都有沙粒的存在的話,就不動作。

依此邏輯,依序遍歷每一個座標並作處理,就可以產生沙粒落下的一個幀 (frame) 畫面。

假設當前沙粒座標為 (x, y) 則:

  • 正下方座標 (x-1, y-1)
  • 右下方座標 (x, y-1)
  • 左下方座標 (x-1, y)

不斷地重覆去執行 “遍歷每一個座標” 的循環,可以產生無數個幀,並依序且按照設定好的時間間隔 (fps),將每一個座標的沙粒狀態顯示在 LED 矩陣上,就可以呈現出沙粒落下的動畫。

沙漏可能豎放也可能橫放,也就是重力會作用在沙漏的上下左右,共四個方向。

在此我們只要將基礎座標系進行對應的旋轉後,依然可以使用上面提到的處理方法來呈現沙粒重力方向移動的畫面。就像下圖這樣:

當重力作用在沙漏的右側時,我們將基礎座標系旋轉 90度產生新的參考座標系後,繼續使用上面提到的方法遍歷參考座標係,即可讓沙粒向右移動。

也就是說重力作用在沙漏的:

  • 由上到下的方向:參考座標系 = 基礎座標系旋轉 0 度
  • 由下到上的方向:參考座標系 = 基礎座標系旋轉 180 度
  • 由左到右的方向:參考座標系 = 基礎座標系旋轉 90 度
  • 由右到左的方向:參考座標系 = 基礎座標系旋轉 270 度

由基礎座標系的座標求出參考座標系的座標,可以使用矩陣的旋轉和平移達成。

重力方向

重力的方向偵測,則由 MPU 6050 在每一幀畫面產生前,讀取加速度計的 X, Y, Z 三個方向的加速度值判斷。

原始碼

LED 沙漏程式碼請參考:

--

--

qedqed6

吾乃阿克西斯教教義信奉者!汝,勿要忍耐。想喝的時候就喝,想吃的時候就吃便好。因為明天並不見得還能吃得到。