2023年1月4日 星期三

MicroPython 學習筆記 : Wemos D1 mini pro 測試

昨晚為了找 ESP32 開發板翻箱倒櫃在零件箱中找到四塊 D1 mini pro, 其中兩塊是有附購 SMA 外接天線的, 另兩塊沒有 (使用板上內建的陶瓷天線), 另外還找到一個 0.91 吋與 0.96 吋的 SSD1306 OLED 顯示器各一個, 其中 0.91 吋的前端玻璃有裂痕, 不確定有沒有壞掉. 查詢之前的網購資料, 應該是 2020/3/31 向 Aliexpress 買的 : 


先用三秒膠把針腳黏在 D1 mini pro 板子上, 今天晚上焊接後進行測試. 

D1 mini pro 與 D1 mini 一樣都有 5V 輸出, 這在做實驗時很方便. 

首先接上 USB 後在 "控制台/裝置管理員/連接埠" 檢查此板所連接的 COM 埠 : 




可見此板 USB 晶片用的是 CP2102, 然後按照下面這篇中的指令用 esptool 燒錄韌體 : 


值得注意的是, 與 D1 mini 不同的是, D1mini pro 燒錄韌體前不須要把 D3 (GPIO0) 接地, 直接燒錄即可 (把 D1 接地反而會無法燒錄), 先查詢 Flash 資訊 : 

D:\ESP8266>esptool.py --port COM12 flash_id   
esptool.py v2.6
Serial port COM12
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
MAC: 68:c6:3a:f8:cd:a3
Uploading stub...
Running stub...
Stub running...
Manufacturer: 20
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...

可見這塊是 4MB Flash. 

接著是抹除 Flash 記憶體內容 :

D:\ESP8266>esptool.py --chip esp8266 --port COM12 erase_flash    
esptool.py v2.6
Serial port COM12
Connecting....
Chip is ESP8266EX
Features: WiFi
MAC: 68:c6:3a:f8:cd:a3
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 9.6s
Hard resetting via RTS pin...

如果像 D1 mini 那樣把 D0 接地, 反而會出現如下 Failed to connect to ESP8266 的錯誤訊息 : 

D:\ESP8266>esptool.py --chip esp8266 --port COM12 erase_flash     
esptool.py v2.6
Serial port COM12
Connecting........_____....._____....._____....._____....._____....._____....._____

A fatal error occurred: Failed to connect to ESP8266: Timed out waiting for packet header

然後就可以燒錄韌體了 : 

D:\ESP8266>esptool.py --port COM12 --baud 115200 write_flash --flash_size=detect -fm dio 0 esp8266-20220618-v1.19.1.bin   
esptool.py v2.6
Serial port COM12
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
MAC: 68:c6:3a:f8:cd:a3
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0240
Compressed 634844 bytes to 419808...
Wrote 634844 bytes (419808 compressed) at 0x00000000 in 37.1 seconds (effective 136.9 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

這樣就燒錄完成了. 

接著參考下面這篇, 測試剛焊好接腳的 0.91 吋與 0.96 吋 OLED 顯示器 : 


0.91 吋的程式如下 : 

import ssd1306
from machine import Pin, I2C
i2c=I2C(scl=Pin(5), sda=Pin(4))
oled=ssd1306.SSD1306_I2C(128, 32, i2c)
oled.fill(1)
oled.show()

結果不行, 0.91 吋的裂痕似乎傷到裡面電路, 完全黑屏, 廢了. 

0.96 吋的程式改用 SoftI2C 測試 : 

from machine import Pin, SoftI2C
import ssd1306
i2c=SoftI2C(scl=Pin(5), sda=Pin(4)) 
oled=ssd1306.SSD1306_I2C(128, 64, i2c)
oled.fill(1)
oled.show()

結果 0.96 吋的 OK : 




原來以前不知不覺買了蠻多零組件, 現在要開始活化資產.

2023年1月3日 星期二

說好的 300M

年前中華電信打來說鄉下家的光世代要升速到 300M/100M, 今天看手機才發現 12/29 就簡訊通知已完工, 要求重開光世代數據機測試, 早知道昨天我還在鄉下就可以試了. 




晚上打電話給爸, 請他拔掉電源再插回去, 我遠端連線鄉下家的樹莓派 Pi 3, 連上台大網速測試網站, 發現下載速度居然連 1M 都不到 : 





哇, 這結果太令我傻眼, 原先 60M 時起碼還有 40M~50M, 這麼一調適連 1M 都沒有, 我還指望在光世代上架站呢, 這一定是哪裡設定有問題 (雖然簡訊說要用網路線直連, 因為透過 WiFi 會有誤差, 但我不要求精確 300M, 至少要跑出 200M 吧?), 每次升速都這樣, 都還要麻煩師傅跑一趟. 

2023-01-05 補充 : 

今天師傅去鄉下家裡測試, 調整後數據機端已可達 312M, 但他說我的信舟無線基地台太舊了, 透過 WiFi 連線速度會受限, 叫我去買支援 300M 以上, 有 WiFi 6 功能的基地台. 我遠端連線 Pi 3 用台大測速發現有 7M 以上 :




看來要去燦坤走一趟了. 

2023-01-07 補充 :

晚上回到鄉下用筆電測試結果如下 :





若用桌電直連數據機, 以中華電信測速程式去跑可達 280M : 




好, 那下周就來去買新的 WiFi 路由器. . 

天堂果實「木虌果」

去年底問樓下同事是否有木虌果種子, 上週竟然直接給了我一顆木虌果, 說回家切開就能取得種子.我看果皮呈橘紅色表示已經熟成, 但按壓表皮還沒軟化, 放了一周元旦前帶回鄉下煮排骨湯. 




對切頗開後可見外層是黃色果肉, 內層是被艷紅色種囊包覆的種子 :




用湯匙將紅色種囊舀到盆子中, 然後將果肉挖下來煮湯 : 




用大湯匙不斷攪拌種囊, 直到裡面的黑色種子脫離後, 將種子撈起來放在另一個盆子中清洗 :






搓洗時種子外面一層薄薄淡黃色的種衣會脫落, 這也要收集起來一起煮湯 :




我把紅色的種囊漿全倒入鍋湯中, 湯汁紅通通 :




洗好的木虌果種子, 很像一隻隻小鱉, 這也是其名字的由來 : 




木虌果營養價值很高, 主要有 : 
  • 茄紅素是番茄的 25 倍
  • beta 胡蘿蔔素比胡蘿蔔還高
  • 果肉有大量膳食纖維與不飽和酯肪酸
參考 : 


MicroPython 學習筆記 : 1602 LED 顯示器測試 (一)

去年底重做 SSD1306 測試後, 又從零件箱中找出傳統 2*16 的 1602A LCD 顯示器, 趁著元旦假期也重測看看以前的函式庫是否還能用, 參考我在 2017 年寫的這篇 :


本系列全部文章參考 :


參考書籍 :

# 超圖解 Python 物聯網 (旗標, 趙英傑)
# Python 感測器大應用 (旗標, 創客自造者)

本篇仍是以 D1 mini 開發板進行測試, 用 ESP8266 驅動 1602A 需要下列兩個函式庫 :


也可以從原作者的 GitHub 下載 : 


將此兩個函式庫上傳到 ESP8266 開發板即可開始進行測試. 

在這之前要先將 1602A 與 D1 mini 透過 1602 I2C 模組用 I2C 介面連接起來. 也可以直接用 1602A 與 ESP8266 連接, 但那要用掉 ESP8266 八個 GPIO 埠來直接傳送資料給 1602A 的 D0~D7 腳, 而且還有其他接腳須要控制, 連接起來很麻煩, 一般都會用一個 1602  I2C 模組介面板插在 1602A 針腳上, 然後用上面那兩個 I2C 函式庫去控制, 這樣只要用兩個 GPIO 埠即可. 這個 1602 12C 模組其實是利用 PCF8574 多工器 IC 將 IO 埠集縮並轉成 I2C 介面以節省輸出入腳與簡化操作方式, 接線圖重貼如下 :





上圖中 1602 I2C 模組上有 VCC, GND, SCL, 與 SDA 四支腳, VCC 與 GND 分別接到 D1 min 的 3.3V 與 GND 腳, SCL 接到 D1 腳 (GPIO5), 而 SDA 則接到 D2 腳 (GPIO4), 這兩個 GPIO 埠是 ESP8266 的預設 I2C 輸出入埠, 但也可以用其他任何 GPIO 埠, 因為最新版的 MicroPython 韌體已經改用軟體 I2C 類別 SoftI2C 來處理 I2C 通訊, 取代原本的內建 I2C 類別, SoftI2C 可用任何 GPIO 腳模擬為 SCL 與 SDA 腳. 

其次要注意的是, 1602A 有 3.3V 與 5V 兩種電壓, 兩種板子的差別在於 3.3V 款的背板有一顆位準轉換 IC 與電容, 圖片重貼如下 : 




我使用的是上方的 3.3V 款, 可直接從 D1 mini 的 3.3V 與 GND 腳取得電源. 接好電源後 1602A 的藍色背光就會亮起來, 接著就可匯入函式庫來輸出字串到 1602A 顯示幕, 先使用 I2C 類別 : 

>>> from machine import I2C, Pin   
>>> from esp8266_i2c_lcd import I2cLcd   

然後呼叫內建的 I2C 類別建構函式來建立 I2C 物件 : 

>>> i2c=I2C(scl=Pin(5), sda=Pin(4), freq=400000)   
>>> type(i2c)  
<class 'SoftI2C'>     
>>> dir(i2c)  
['__class__', 'readinto', 'start', 'stop', 'write', 'init', 'readfrom', 'readfrom_into', 'readfrom_mem', 'readfrom_mem_into', 'scan', 'writeto', 'writeto_mem', 'writevto']
>>> 

可見 I2C() 會建立一個 SoftI2C 物件 (新版 MicroPython 韌體), 它提供了低階的讀寫方法. 但通常不會直接使用這些讀寫方法來通訊, 而是使用上面從 esp8266_i2c_lcd 模組匯入的 I2cLcd 類別. 此處 freq 參數設定 I2C 匯流排通訊速率為 400K bps, scl 與 sda 參數設定 GPIO5 與 GPIO4 為 I2C 通訊接腳, 此為 ESP8266 預設的 I2C 埠, 參考 : 



 板子腳位 ESP8266 腳位 功能
 D0 GPIO16 IO
 D1 GPIO5 IO, SCL 
 D2 GPIO4 IO, SDA 
 D3 GPIO0 IO, 內建 10K 上拉電阻
 D4 GPIO2 IO, 內建 10K 上拉電阻與 LED
 D5 GPIO14 IO, SCK
 D6 GPIO12 IO, MISO
 D7 GPIO13 IO, MOSI
 D8 GPIO15 IO, SS, 內建 10K 上拉電阻
 TX TXD UART 送端
 RX RXD UART 收端
 A0 ADC 類比輸入 (0~3.3V)

 
接著呼叫 SoftI2C 物件的 scan() 方法掃描目前 I2C 匯流排上有哪些設備 (I2C 是一對多協定), 它會傳回設備的 10 位址串列 :
 
>>> i2c.scan()    
[39] 

此處只有 1601 I2C 模組這一個 I2C 設備, 其位址為 39, 此乃十進制, 須將其轉為二進制 0x27, 因為接下來要呼叫 I2cLcd 類別之建構函式 I2cLcd() 時要傳入此二進制位址做為第二參數, 此函式之參數結構如下 :

I2cLcd(i2c, i2c_addr, num_lines, num_columns)

第一參數為上面建立之 SoftI2C 物件, 第二參數為 I2C 設備之二進制位址, 第三參數為 LCD 顯示幕列數 (1602A 為 2), 第四參數為 LCD 顯示行數 (1602A 為 16) :

>>> lcd=I2cLcd(i2c, 0x27, 2, 16)     
>>> type(lcd)   
<class 'I2cLcd'>   

可見 I2cLcd() 會建立一個 I2cLcd 物件, 檢視其內容 : 

>>> dir(lcd)   
[object_link_for_thonny=1073677440]['__class__', '__init__', '__module__', '__qualname__', 'clear', '__dict__', 'i2c', 'i2c_addr', 'num_lines', 'num_columns', 'hal_write_init_nibble', 'LCD_FUNCTION_RESET', 'LCD_FUNCTION', 'LCD_FUNCTION_2LINES', 'hal_write_command', 'hal_backlight_on', 'hal_backlight_off', 'backlight', 'hal_write_data', 'LCD_CLR', 'LCD_HOME', 'LCD_ENTRY_MODE', 'LCD_ENTRY_INC', 'LCD_ENTRY_SHIFT', 'LCD_ON_CTRL', 'LCD_ON_DISPLAY', 'LCD_ON_CURSOR', 'LCD_ON_BLINK', 'LCD_MOVE', 'LCD_MOVE_DISP', 'LCD_MOVE_RIGHT', 'LCD_FUNCTION_8BIT', 'LCD_FUNCTION_10DOTS', 'LCD_CGRAM', 'LCD_DDRAM', 'LCD_RS_CMD', 'LCD_RS_DATA', 'LCD_RW_WRITE', 'LCD_RW_READ', 'cursor_x', 'cursor_y', 'display_off', 'backlight_on', 'hide_cursor', 'display_on', 'show_cursor', 'blink_cursor_on', 'blink_cursor_off', 'backlight_off', 'move_to', 'putchar', 'putstr', 'custom_char']

它提供了許多方法來顯示字串, 重貼如下 :


 I2cLcd 物件的方法 說明
 move_to(x, y) 移動游標至座標 (x, y)
 putchar(str) 從游標目前位置開始顯示字串 str, 然後將游標移到字串結束之下一位置
 putchar(char) 從游標目前位置開始顯示字元 char, 然後將游標移到下一位置
 custom_char(location, charmap) 將字元圖樣 charmap 寫入 CGRAM 記憶體位址 location=0~7 
 clear() 清除 LCD 螢幕並將游標移至左上角座標 (0, 0)
 show_cursor() 顯示游標 (底線)
 hide_cursor() 隱藏游標
 blink_cursor_on() 開啟游標閃爍功能
 blink_cursor_off() 關閉游標閃爍功能
 display_on() 開啟顯示功能
 display_off() 關閉顯示功能 (即顯示白屏)
 backlight_on() 開啟背光
 backlight_off() 關閉背光


其中最常用的是 putstr() 方法, 它會從目前游標位置開始顯示字串, 例如 : 

>>> lcd.putstr("Hello World!\nIt's working!")    

注意, 傳入字串中可用 '\n' 表示換列, 結果如下 : 




完整程式碼如下 : 

# main.py
from machine import I2C, Pin   
from esp8266_i2c_lcd import I2cLcd   
i2c=I2C(scl=Pin(5), sda=Pin(4), freq=400000)   
lcd=I2cLcd(i2c, 0x27, 2, 16)     
lcd.putstr("Hello World!\nIt's working!")    

由於新版 MicroPython 韌體另外內建了 SoftI2C 類別可模擬任何 GPIO 腳做 I2C 通訊, 所以上面程式碼改為從 machine 匯入 SoftI2C 類別, 並改為呼叫 SoftI2C() 建構式建立 SoftI2C 物件也是可以的 (因 I2C 類別未來將廢棄, 故建議改用 SoftI2C), 例如 : 

# main.py
from machine import SoftI2C, Pin   
from esp8266_i2c_lcd import I2cLcd   
i2c=SoftI2C(scl=Pin(5), sda=Pin(4), freq=400000)   
lcd=I2cLcd(i2c, 0x27, 2, 16)     
lcd.putstr("Hello World!\nIt's working!")    

結果是一樣的. 

接下來測試 SoftI2C 是否能將任何 GPIO 腳模擬成 I2C 的 scl 與 sda, 以下選定 D0 (GPIO 16) 當作 scl, D8 (GPIO15) 當作 sda : 

# main.py
from machine import SoftI2C, Pin   
from esp8266_i2c_lcd import I2cLcd   
i2c=SoftI2C(scl=Pin(16), sda=Pin(15), freq=400000)   
lcd=I2cLcd(i2c, 0x27, 2, 16)     
lcd.putstr("Hello World!\nIt's working!")    

更改 scl 與 sda 接線後在 Thonny 輸入

MicroPython v1.19.1 on 2022-06-18; ESP module with ESP8266

Type "help()" for more information.
>>> from machine import SoftI2C, Pin    
>>> from esp8266_i2c_lcd import I2cLcd   
>>> i2c=SoftI2C(scl=Pin(16), sda=Pin(15), freq=400000)   
>>> type(i2c)   
<class 'SoftI2C'>   
>>> lcd=I2cLcd(i2c, 0x27, 2, 16)     
>>> lcd.putstr("Hello World!\nIt's working!")   

結果與上面相同. 

參考 : 


2023年1月2日 星期一

在 MCU 上運行的機器學習模型 : TensorFlow Lite Micro

今天在搜尋樹莓派 Pico 資料時找到樹莓派 Pico 的 TensorFlow Lite Micro 版本 : 


TensorFlow Lite 是谷歌深度學習框架 TensorFlow 的手機或迷你電腦 (例如樹莓派) 版, 而 TensorFlow Lite Micro 則是給微控制器開發板 (例如 Arduino, ESP32, 樹莓派 Pico 等) 用的, 主要是考量記憶體大小與 CPU 執行效能而做的瘦身工程. 這些開發板幾乎都是基於 ARM Cortex-M 架構的 32 位元 MCU. 參考 :


在 MCU 上運行 TensorFlow Lite Micro 的程序是先在 Colab 上用 TnsorFlow 以 32 位元浮點數訓練模型, 然後將訓練好的模型降為 8 位元整數, 用 TensorFlow Lite 直譯器載入模型運行, 與在 Colab 上的結果比較, 若損失沒有明顯惡化, 即可使用工具程式將減化的模型轉成 model.cc 的 C 語言格式 (即 TFLM 格式), 最後用 MCU 的 SDK 將 model.cc 與 MCU 的原始碼一起編譯成韌體燒錄至 MCU 即可, 參考 :


關於 TinyML 的書目前不多, 我只找到下面兩本 : 



Source : 博客來


此書譯自 Oreilly 2020 年出版的 "TinyML: Machine Learning with TensorFlow Lite on Arduino and Ultra-Low-Power Microcontrollers", 好消息是 : 市圖與母校圖書館都有這本書 , Nice, :).




Source : 天瓏


此書譯自 Packt 2022 年出版的 "TinyML Cookbook: Combine artificial intelligence and ultra-low-power embedded devices to make the world smarter", 中譯本 2023/1/13 即將由基峰出版, 書中範例檔可在 GitHub 下載 :


2023年1月1日 星期日

2023 年第 1 周記事

今天是 2023 年元旦, 水某上個月訂了海港, 因為我是當日壽星有 85 折, 二哥 10 月份正忙著碩班推甄與專題報告, 他生日也沒時間聚餐, 加上水某是 11 月, 爸是 1 月 10 日, 通通合併起來. 只是姊姊的同學要從高雄上台北找她跨年, 車票與行程已訂好無法回來. 她跟菁菁的生日宴要合併在 1/20 小年夜. 吃到一半菁說接下來是小禮物登場, 原來是三組扇形紅包, 給我, 水某, 與爸, 哈哈, 她每次都會想出這些小點子 : 




本周說是 2023 第一周, 其實只有今天才是 2023, 周二辦公大樓舉辦退休同仁聯合歡送會, 本單位有兩個老同事退休, 由於沒有補新人, 故也牽動來年工作調整以分擔遺留工作, 我個人也要寫新的軟體來輔助我完成新增的工作職掌. 周二晚上尾牙在福華五樓麗香苑, 我抽到 1000 元現金. 我呢小獎不斷, 幾乎每年都抽到還可以的獎, 但就是統一發票與樂透總是槓龜, 哈哈. 

老妹阿蘭住院已三周, 排便不順似乎尚未解決, 醫院周四打電話回報說要照腹部斷層以確定是否有出血性腸阻塞, 故下班後跑了一趟醫院簽同意書. 照護機構年底通知說因應基本薪資調整, 2023 年 1 月要調漲照護費, 因為外籍看護工的薪資其實就是基本薪資. 

昨天看到新聞報導李鍾碩與 IU 交往 ing 中, 令我感到非常驚訝, 我追韓劇這麼久好像沒看過他們有合演過戲劇, 加上兩人身高差距有點大, 沒想過兩人會是一對. 


Source : Yahoo 新聞


他們都是我最喜愛的演員之一, 我是在看 "死的詠嘆" 時第一次注意到李鍾碩, 後來又看了與秀智演的 "當你沉睡時" 印象更深, 最近看的作品是與潤娥合作的 "黑話律師". IU 則是看 "我的大叔" 開始關注的, 據說她非常寵粉. IU 與金裕貞都是我非常欣賞與看好的演員.

露天購買 TypeC 傳輸充電線與手機架

因為之前買的磁吸線接觸不理想, 常變成慢速充電甚至不過電, 所以打算直接用手機本身的 Type C, 但手邊的 Type C 陸續被二哥與水某拿去用了, 只好重新買. 賣家要 299 才免運, 看到賣場有一個汽車手機架就順便買了湊一湊 :





免運並領了 19 元折扣碼, 實付 346 元. 

年底至今已瞎拚好多東西了, 好爽. 


2023-01-05 補充 :

今日取貨測試 Type C 可以順利連上手機傳送資料. 
 

好站 : 資料科學工作者的學習路徑

今天在 Youtube 看到張維元老師的資料科學教學影片, 非常值得一看 : 






Good Bye 2022, Welcome 2023

今天是 2023 年元旦, 我以前是元旦寶寶, 昨晚特地在 11:50 開電視看公視轉播台北 101 煙火秀, 覺得真是好看. 蔣萬安上台致詞簡單大方, 希望新的一年他真的能兌現政治支票. 其實, 我們的新年願望也是一張支票, 能否兌現就看自己的努力了. 

回顧過去一年, 在學習研究方面雖然努力進取, 但進度仍未達理想 (資料科學 Pandas 未完成), 雖說取乎上得乎中乃正常現象, 但願今年更加自律追求卓越. 2023 學習重心如下 : 
  • 傳統機器學習
  • 深度學習深化 
  • 自然語言處理 (RNN, LSTM, Trasformer, GPT-3)
  • PyTorch 
  • MicroPython 物聯網 (ESP32-CAM/樹莓派 Pico W) 
  • Flask/Django 後端網頁
  • Ubuntu 架站
  • LineBot 
檢視去年願望, 大概只有資料科學較有進度 (完成 Matplotlib, Numpy, 只差 Pandas 尚未學完).  Python 金融資訊系統根本沒動 (等自架網站完成才能做), 物聯網專案中的 No.1 網路時鐘材料已備齊就缺時間. 深度學習看完幾本書也實作, 但總覺得不夠熟練. 新的一年想回頭看傳統機器學習與學學 PyTorch. 

2022 的上半年主要投入資料科學與深度學習, 尤其 5/18 因菁菁確診我開始居家上班到 10/13 日, 期間參加了許多線上的內訓課程收穫滿滿. 另外下半年周末投入獨立型太陽能系統安裝建置, 斷斷續續忙了四個月才完成, 雖然沒列入物聯網專案, 但監控與擷取發電用電資料也要用到物聯網甚至機器學習. 總之, 雖然學習未達標, 但還是進步不少. 

光世代升速至 300M/100M

週五中華電信打電話通知說鄉下老家的光世代要升速為下行 300M, 上行 100M, 我說年中 (五月初) 才剛從 35M 升到 60M, 怎麼又要升速, 他說因為設備換新, 現在輪到我們村裡, 若調試 OK 就可升速, 我問可以不升嗎? 他說這樣可能資料傳遞優先順序會被排擠.

這聽起來似乎不升不行了, 既然如此那就拿來架站唄, 反正我租了 10 年的英國 Hostinger 明年底到期不再續租了, 那就用鄉下老家的光世代自己架站好了, 畢竟我做各種實驗與物聯網專案都需要一台能自己控制的網站伺服器.