上篇文章瞭解如何在 Arduino IDE 開發環境下,撰寫 C 語言控制 Pico,包括初始設定方法及編譯上傳程式的步驟,之後仍繼續 MicroPython 相關的實作,日後有時間再回來深入瞭解 Arduino IDE 搭配 Pico 開發環境的用法。LCD的顯示功能在微控制器的開發上,是很重要的,本篇要實作將日期、時間及開發板的溫度感測值顯示在 LCD1602 螢幕上。這裡同時也會用到呼叫其他程式的功能,透過函式呼叫控制 LCD1602 的各項功能,如顯示、移動游標等,讓撰寫程式變的簡單些。
Pi Pico的開發板上有個溫度傳感器,連接到 ADC(Analog-to-digital converter,或稱 A/D 或 A to D) 類比數位轉換的特殊引腳,在規格圖上,可以看到 Pin 31-35 標記 ADC0, ADC1, AGND, ADC2 和 ADC_VREF(或稱 ADC3,偵測硬體電壓用)從外部接 ADC。Pico 開發板上的溫度傳感器沒有實體的引腳,但可以透過存取 ADC4 得到數值。
ADC 的存取方式和一般的 GPIO 不同,原因是 GPIO 僅顯示高電位和低電位兩種狀態,而 ADC 會取得不同的電壓數值。Pico 的 ADC 使用 12 位元來計算數值,表示偵測的值可以從 0 到 4095。但是 MicroPython 將 ADC 值擴充到 16 位元範圍,有效值從 0 到 65535。Pico的電壓以 3.3V 運行,這表示 ADC 引腳在 3.3V 電壓時,將傳回 65535 的值,若無電壓的情況下,傳回數值 0。當引腳施加的電壓介於 0 至 3.3V 之間時,將獲得介於兩者之間的值。
根據 Pico 開發板上的傳感器規格,溫度在攝氏 27 度時會提供 0.706V 的電壓,每升高攝氏 1 度,電壓就會降低 1.721 毫伏特,即 0.001721 伏特。可以用這個數值來換算當時 ADC 的電壓所得到的溫度。
程式中用到 utime 的 localtime()函式,說明如下:
Pi Pico的開發板上有個溫度傳感器,連接到 ADC(Analog-to-digital converter,或稱 A/D 或 A to D) 類比數位轉換的特殊引腳,在規格圖上,可以看到 Pin 31-35 標記 ADC0, ADC1, AGND, ADC2 和 ADC_VREF(或稱 ADC3,偵測硬體電壓用)從外部接 ADC。Pico 開發板上的溫度傳感器沒有實體的引腳,但可以透過存取 ADC4 得到數值。
ADC 的存取方式和一般的 GPIO 不同,原因是 GPIO 僅顯示高電位和低電位兩種狀態,而 ADC 會取得不同的電壓數值。Pico 的 ADC 使用 12 位元來計算數值,表示偵測的值可以從 0 到 4095。但是 MicroPython 將 ADC 值擴充到 16 位元範圍,有效值從 0 到 65535。Pico的電壓以 3.3V 運行,這表示 ADC 引腳在 3.3V 電壓時,將傳回 65535 的值,若無電壓的情況下,傳回數值 0。當引腳施加的電壓介於 0 至 3.3V 之間時,將獲得介於兩者之間的值。
根據 Pico 開發板上的傳感器規格,溫度在攝氏 27 度時會提供 0.706V 的電壓,每升高攝氏 1 度,電壓就會降低 1.721 毫伏特,即 0.001721 伏特。可以用這個數值來換算當時 ADC 的電壓所得到的溫度。
from machine import ADC temper_sensor = ADC(4) temper_volts = temper_sensor.read_u16()將 temper_volts 的電壓值,換算成 12 位元對應的數值。
temper_volts = temper_volts * 3.3 / 65535將取得的電壓跟攝氏 27 度時的電壓相減,所得的電壓差,再除以每1度溫度的電壓變化值,就可以算出當時 Pico 開發板上的溫度。
celsius_degrees = 27 - (temper_volts - 0.706) / 0.001721若要換算成華氏溫度,可以套用以下公式:
fahrenheit_degrees = celsius_degrees * 9 / 5 + 32LCD1602若要以 I2C 通訊,需要外接一個模組 PCF8574,若不知道這個介面使用的 I2C 編號,可以執行以下程式取得,但是這個值是 10 進位。若要用在程式中,需再換算成 16 進位。
import machine sda=machine.Pin(0) scl=machine.Pin(1) i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000) print(i2c.scan())以 LCD1602 為例,得到的是 39,換算成 16 進位為 27,稍後的程式中會用到這個值。
[材料]
- Raspberry Pi Pico x1
- LCD1602液晶顯示器 x1
- PCF8574 LCD連接模組 x1
- 麵包板 x1
- 排線 n 條
[接線圖]
LCD1602 需要5V電壓供電,而 Pico 提供的是 3.3V ,LCD1602 可以顯示,但字體及背景亮度不足;但是有一個替代的方案,是接 Pin40 的VBUS,根據「pico-datasheet」的描述,VBUS 是 micro-USB 的輸入電壓,連接到 micro-USB Port 的 Pin 1,通常是 5V,如果沒有接 USB 時,電壓為 0V。Pi Pico接腳 | LCD1602 I2C接腳 |
---|---|
Pin 1(GP0) | SDA |
Pin 2(GP1) | SCL |
Pin 38(GND) | GND |
Pin 40(VBUS) | VCC |
[程式]
LCD1602函式庫,我參考 Github 開發人員 Tyler Peppy 的函式,如要執行以下的程式,需要再下載 RPI-PICO-I2C-LCD 的 lcd_api.py 及 pico_i2c_lcd.py 兩個程式。將三個檔案放在同一個目錄內,可以是電腦目錄或 Pico 的虛擬磁碟。要特別注意檔名的大小寫要跟以下程式寫的一模一樣,否則呼叫程式時會出現錯誤,建議是全部都小寫,避免混淆。程式中用到 utime 的 localtime()函式,說明如下:
- utime.localtime(secs):取得系統的日期及時間。
import machine import utime from machine import ADC from machine import I2C from lcd_api import LcdApi from pico_i2c_lcd import I2cLcd I2C_ADDR = 0x27 #LCD1602的I2C位址 I2C_NUM_ROWS = 2 #LCD1602列數 I2C_NUM_COLS = 16 #LCD1602行數 i2c = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000) #設定I2C lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS) utime.sleep(2) to_volts = 3.3 / 65535 temper_sensor = ADC(4) #從ADC(4)取得溫度感測器的電壓值 while True: lcd.clear() time = utime.localtime() # 顯示日期及時間 lcd.putstr("{month:>02d}/{day:>02d} {HH:>02d}:{MM:>02d}:{SS:>02d}".format( month=time[1], day=time[2], HH=time[3], MM=time[4], SS=time[5])) temper_volts = temper_sensor.read_u16() * to_volts #取得當時溫度的電壓 celsius_degrees = 27 - (temper_volts - 0.706) / 0.001721 #計算攝氏溫度 # fahrenheit_degrees = celsius_degrees * 9 / 5 + 32 #計算華氏溫度 lcd.move_to(0,1) #游標跳至第二列第一行 lcd.putstr('TEMP:') lcd.putstr(str(round(celsius_degrees,3))) lcd.putstr(' oC') #用小寫O代替度的符號 utime.sleep(3) #暫停3秒鐘
接線圖有誤
回覆刪除Pin39 & Pin40 為 VSYS 與 VBUS 非 I2C 的 SDA 及 SCL
非常感謝您的指正。我看一下原來的接線圖也覺得不太對勁,使用 VBUS 5V的電源,SDA 及 SCL 改接 Pin0 及Pin1,重新接線後 LCD1602 顯示正常,執行程式也沒問題。已經將接線圖、照片及影片更新。謝謝您!!
刪除張貼留言