電子專案》使用 iPhone 的 Touch ID 搭配 Arduino Nano 33 解鎖自己的電腦

最近把以前一個用 B4i 寫的 iOS app 用 Swift 重寫,功能是:用 iPhone 的 Touch ID 解鎖自己的電腦。這個程式的原理很簡單,是用一塊 arduino 模擬成 HID Keyboard,然後 iOS app 透過 BLE 把密碼傳送給 arduino 裝置,接著 arduino 裝置再把密碼輸入到電腦,利用這種方式解鎖電腦。

HID Keyboard 的部分,以前是用 Blend Micro 來做,這次則改用 Arduino Nano 33 IoT 來做。

左邊紅色的電路板是 Blend Micro,中間深藍色電路板是 Arduino Nano 33 IoT。

以下是 Demo 影片與 Source code 連結:

詳細情況請看:https://github.com/kyumdbot/AutoPass

給定一個正規表達式,找出符合這個正規表達式的所有字串

唐鳳在 FLOLAC’14 的演講裡有提到這個為 Apple Siri 寫的 Haskell 套件:https://github.com/audreyt/regex-genex,作用是給定一個正規表達式,找出符合這個正規表達式的所有字串,我想找找看 Python 跟 R 裡頭有沒有類似的套件,有搜尋到 Python 裡有類似的套件:https://github.com/google/sre_yield

目前還沒找到 R 的版本,希望有人知道的話能告訴我,感謝!

老 MacBook 裝 x86 Raspbian

最近把老舊的 MacBook 2010 的 RAM 加到 8GB,然後把作業系統改裝 Raspberry Pi Desktop (x86 Raspbian),有這台機器又活起來的感覺!嗯…也許是我還蠻習慣 Raspbian 的關係吧 (?

不過因為 MacBook 的螢幕太亮,而 LXDE 沒有內建調整螢幕亮度的軟體,所以需要自己手動更改螢幕亮度值,螢幕亮度的設定檔通常會放在 /sys/class/backlight/{顯卡類型之類的}/ 目錄裡面,例如我的 MacBook 2010 的螢幕亮度設定檔就放在 /sys/class/backlight/nv_backlight/ 裡,設定檔名稱通常是叫做 brightness,同個目錄下還會有一個叫做 max_brightness 的檔案,這個檔案可以看亮度最大值是多少,像我的 max_brightness 裡的數值是 100,所以我在修改 /sys/class/backlight/nv_backlight/brightness 的數值時,範圍就是 0 ~ 100。

要更改螢幕亮度時,用 nano 或是 vim 開啟設定檔,然後修改數值即可:

$ sudo nano /sys/class/backlight/nv_backlight/brightness

不過每次這樣改好像有點不直覺 (其實是我都會忘記設定檔的目錄路徑 XD),所以我寫了一個 GUI 小程式,用來調整我的 MacBook 2010 的螢幕亮度:https://github.com/kyumdbot/rpd-brightness

衝動型購物

我最近寫了一個 Python 小程式來查看我每年都在天瓏網路書店消費了多少錢,結果嚇屎我了… 尤其是 2018 å¹´…

看了這些圖表後,我希望明年開始,以後每年在天瓏的花費可以壓到兩萬以下… XD #新年願望

程式碼在此:https://github.com/kyumdbot/tenlongbar

Kotlin’s Nullable vs. Swift’s Optional

最近在學 Kotlin 與重學那個學過但沒有學會過的 Swift,發現 Kotlin 的 nullable 與 Swift 的 Optional 非常像,大概有 87 分像吧 (不能再低了)? 所以我做了個對照表:

補充說明:

  1. 使用 ?. 或 as? 運算子時,傳回值的型態一樣會是 nullable (Kotlin) / Optional (Swift),所以對傳回值的後續處理一樣要用 nullable (Kotlin) / Optional (Swift) 的方式對待之。 (心法:只要傳回值有可能出現空值 ( null / nil ),那個傳回值就會是一個 nullable / Optional 。)
  2. Swift Optional 的驚嘆號 ( ! ) 表示直接把 Optional 變數解包並當成有值去對待,所以當變數是空值 (nil) 的時候,對空值調用方法 (或者說:發送訊息) 時當然會當掉,因為空值無法響應那個方法。例如這行程式:str!.uppercased(),當 str 裡是一個 String 的時候,對它調用 .uppercased() 方法是沒問題的,可是當 str 裡是 nil 的時候,這時就會出錯了,因為 nil 沒有 .uppercased() 這個方法,所以會當掉。Kotlin 的 !! 符號是非空斷言 (Not-Null Assertion),告訴編譯器這個地方出現的值不會是 null,所以編譯器會把它當成非空型態去處理,但是,如果這個值不幸是 null 的話,就會拋出一個例外。
  3. Kotlin nullable 與 Swift Optional 不一樣的地方在於:Kotlin nullable 不是一個實際的 Type,例如這行 Kotlin 程式:var str : String? 表示 str 實際上的 Type 會有兩種情況:String 或 null,所以 str 變數的值有可能是一個字串,也有可能是一個空值。但是在 Swift 裡,這行程式:var str : String? 表示 str 的 Type 是一個 Optional,str 變數的值就是一個 Optional,只是這個 Optional 裡的內容可能是一個字串,也可能是一個 nil。也就是説:當一個變數的值可能出現空值時,Swift 用 Optional 去封裝那個變數;但在 Kotlin 裡,把變數宣告成 nullable 的型態時,只是在告訴編譯器,這個變數有可能出現空值 (所以這個變數的 Type 實際上可能會出現兩種情況),然後編譯器就會對這個變數做可空型態的檢查,確保程式碼裡有把出現空值的情況考慮進去。

Haskell 筆記》Currying function

在一般 C-like 的程式語言裡,如果想寫一個函數把兩個整數相加,並傳回相加後的結果,通常會這樣寫:

int add(int a, int b) { 
    return a + b; 
}
function add(a, b) {
    return a + b;
}

但是在 Haskell 裡會這樣寫:

add :: Int -> Int -> Int
add a b = a + b

第一行的 add :: Int -> Int -> Int 是描述函數的型別,第二行的 add a b = a + b 是函數的主體。

我第一次看到這種寫法時,覺得這種寫法看起來很怪,尤其是第一行,為何前兩個參數的分隔符號是用 -> 呢?

Haskell 的 -> 符號的含義: -> 符號表示一個函數,這個函數接受左側型別的參數,並返回右側型別的值。

後來才明白這種寫法的奇妙之處,因為這個函數是一個柯里化函數 (Currying function)。

先在 GHCi 裡輸入並執行這個函數:

:t 是 :type 的縮寫,這個指令可以查看一個值的型別,這裡可以看到 x 的型別是 Int,add 函數的型別是:Int -> Int -> Int 。

當給 add 函數兩個整數時,會傳回兩數相加的結果,但是,我們可以嘗試只給 add 函數一個整數:

由上圖可以看到,我只給 add 函數一個參數(8),並將回傳結果存到 f,然後查看 f 的型別,會發現 f 是一個函數,型別是:Int -> Int。

這裡的 f 是一個「接受一個 Int 參數並傳回一個 Int 值」的函數,f 會把傳給它的整數加 8,並回傳相加的結果。

如下圖所示,當給 add 函數兩個參數時,傳回一個 Int 值:

如下圖所示,只給 add 函數一個參數時,傳回一個函數:

Haskell 用這種語法描述函數,真的很精妙啊!

試玩 Coral USB Accelerator

我不久前買了 Google 出的 Edge TPU 裝置:Coral USB Accelerator 來玩玩看,覺得這玩意非常不錯,台幣兩千多元,可以跑 TensorFlow Lite 格式的模型,我個人是覺得還蠻划算的。

我先用 Raspberry Pi 3 Model B+ 來測試 Pose Detection 模型,一開始使用預設的解析度:640×480,繪製的速度不是很理想,影片如下:

然後我把解析度設定成:480×360,繪製的速度有加快,但還是不盡理想,所以後來我改用一台 2013 年買的小筆電來跑,這次繪製的速度就相當不錯了,影片如下:

這台小筆電的規格為:CPU 是 Intel Celeron(R) CPU 847 @ 1.10GHz,記憶體 4GB,作業系統是 Debian 10 (buster) amd64 版,且有 USB 3 的插孔。

Raspberry Pi 3 Model B+ 除了 CPU 速度較慢之外,也沒有 USB 3 的插孔,所以整體上慢了一大截。但是前陣子出的 Raspberry Pi 4 Model B 有 USB 3 插孔,我已經訂了一台 Pi 4,等收到貨後再測試看看繪製速度是否有提升。

# 2019 年 11月 3 日補充: 我在 Raspberry Pi 4 (4GB 記憶體版本) 上測試了 Coral PoseNet,測試結果請看以下影片,TrueFPS 維持在 20.x 以上:

然後我還有嘗試 Object detection 與 MiniGo 圍棋:

Coral å®˜æ–¹ç¶²ç«™ä¹Ÿæä¾›äº†å¥½å¹¾å€‹å·²ç·¨è­¯å¥½çš„模型讓人下載:https://coral.withgoogle.com/models/ ,可以先從這些模型開始玩起。

感想:這種 Edge TPU 裝置可以做很多有趣的應用,而且價格不算貴,有興趣的人快去買來玩玩看!

IchigoJam BASIC RPi 初體驗

IchigoJam BASIC RPi 是一個運作在 Raspberry Pi 上的 OS,這個 OS 很有趣,開機後會顯示一個黑白畫面的 BASIC 終端機,完全沒有 GUI,直接寫 BASIC 控制 Raspberry Pi,彷彿就像是 30 多年前的個人電腦。

下方是我嘗試用 IchigoJam BASIC RPi 控制 Pin 輸出的影片:

Raspberry Pi 上的 BASIC 解譯器

整理一下,目前 Raspberry Pi 上可用的 BASIC 有:

其中 RTB 與 BBC BASIC for SDL 2.0 可直接在 Raspbian 上安裝與執行,IchigoJam BASIC RPi 與 RISC OS 則是獨立的 OS。

電子專案》Closed Eye Alarm

我寫了個 Android app,利用 Google Play Services Vision 的 FaceDetector 偵測人臉位置與眼睛打開的機率,然後只要發現有人的眼睛可能是閉上的,就傳送訊息給 micro:bit (透過 BLE) ,micro:bit 上接了一個 speaker,收到訊息就會逼逼叫。上方是 Demo 影片。

圖:micro:bit 與 speaker