本文將採用《超圖解Python物聯網實作入門:使用ESP8266與MicroPython》書本裡的範例,介紹Raspberry Pi Pico RP2040(以下簡稱Pico)、ESP8266和ESP32的MicroPython程式,在讀取類比輸入以及輸出PWM訊號的異同。
本文實驗需要的零件:
- 樹莓派Pico開發板,一片。
- 類比搖桿模組,一個(或者兩個10KΩ可變電阻)。
- 9G伺服馬達,兩個。
Pico麵包板示範接線如下,搖桿的VRx與VRy腳分別接Pico的腳27(ADC1)和腳26(ADC0),兩個伺服馬達的訊號線則分別接腳17和16:
MicroPython讀取類比輸入
ESP8266晶片的ADC(類比數位轉換器)的解析度(位元深度)是10位元,所以ESP8266的ADC物件的read()方法的傳回值介於0~1023。底下的程式片段將在ESP8266上每隔0.5秒讀取A0類比輸入:
from machine import Pin, ADC import time adc = ADC(0) while (1): print(adc.read()) time.sleep(0.5)
ESP32的ADC解析度為9~12位元可調,相關說明請參閱《使用ESP32控制板(三):MicroPython的類比輸入、UART序列埠以及觸控開關》貼文,底下的程式採12位元解析度,所以ADC物件的read()傳回值介於0~4095。
from machine import Pin, ADC import time adc = ADC(Pin(32)) adc.atten(ADC.ATTN_11DB) adc.width(ADC.WIDTH_12BIT) while (1): print(adc.read()) time.sleep(0.5)
由於MicroPython支援多款微控器,每個晶片的ADC解析度可能都不同,為了讓程式在不同晶片都能取得一致的類比輸入數值範圍,MicroPython 1.12版的ADC類別新增了read_u16()方法,它將統一傳回16位元,介於0~65535的類比輸入值。
Pico的RP2040晶片的ADC解析度也是12位元。read_u16()方法將把數值放大,例如,假設在ESP8266使用read()讀取到的類比值是512,改用read_u16()讀取,將變成32768。
Pico的RP2040晶片的ADC類別不支援read()方法,必須使用read_u16()。底下的程式片段將在Pico板每隔0.5秒顯示腳26的類比輸入值:
from machine import Pin, ADC import time adc = ADC(Pin(26)) while (1): print(adc.read_u16()) time.sleep(0.5)
MicroPython輸出PWM訊號:控制伺服馬達
ESP8266和ESP32的PWM輸出程式寫法一樣,所以《超圖解Python物聯網實作入門:使用ESP8266與MicroPython》第10章的自訂伺服馬達控制類別(servo.py檔)可直接複製到ESP32執行。
但是同樣的程式檔在Pico的RP2040晶片會產生錯誤。首先是Pico的MicroPython版本,PWM()不接受freq(頻率)和duty(工作週期)參數。底下的敘述可在ESP8266和ESP32運行無誤:
from machine import Pin, PWM servo = PWM(Pin(15), freq=50, duty=60)
PWM物件可用freq()和duty()方法設定頻率和工作週期:
from machine import Pin, PWM servo = PWM(Pin(15)) servo.freq(50) servo.duty(60)
在Pico板控制PWM輸出時,要採用上面的語法,duty()也要改用duty_u16(),而工作週期的輸入值範圍也改成0~65535。ESP8266和ESP32目前不支援duty_u16()方法。
底下是修改自第10章的servo.py伺服馬達自訂類別檔,適用於Pico板:
from machine import PWM, Pin class Servo: def __init__(self, pin, min=500, max=2400, range=180): self.servo = PWM(Pin(pin)) self.servo.freq(50) self.period = 20000 self.minDuty = self.__duty(min) self.maxDuty = self.__duty(max) self.unit = (self.maxDuty - self.minDuty)/range def __duty(self, value): return int(value/self.period * 65535) def rotate(self, degree=90): val = round(self.unit * degree) + self.minDuty val = min(self.maxDuty, max(self.minDuty, val)) self.servo.duty_u16(val)
請參閱《使用Thonny Python IDE編寫MicroPython程式(二):上傳程式與管理開發板的快閃記憶體內容》貼文的說明,使用Thonny編輯器把servo.py檔案存入Pico板的快閃記憶體,即可執行底下的程式,透過類比搖桿控制兩個伺服馬達:
from machine import ADC from servo import Servo servo_x = Servo(17) servo_y = Servo(16) scale = 0.00275 vr_x = ADC(27) vr_y = ADC(26) while True: servo_x.rotate(int(vr_x.read_u16() * scale)) servo_y.rotate(int(vr_y.read_u16() * scale))
請問老師會出 Raspberry Pi Pico微控制板的書嗎?
拍謝,目前沒有計畫,謝謝!