YAS's VB.NET Tips
 
ラズベリーパイ活用
ラズベリーパイ活用
123
2023/10/19

Raspberry Pi Picoで4桁7セグLED

| by:YAS
 秋月電子で見かけた、「4桁緑色7セグメントLED」をRaspberry Pi Picoで表示してみました。
 データシートによると、アノード共通で、ダイナミック点灯方式のLEDのようです。LEDのセグメントのA~GとDPを、470Ωの抵抗アレイを挟んで、GPIOの0~7に、また、LEDのDIG1~DIG4とD1・D2・D3を、GPIOの16~20に接続しました。
 MicroPythonで60Hz程度で更新するためには、GPIOを1つずつ操作していては間に合いませんので、mem32を使って一括で操作することにしました。240Hzのタイマー割り込みで1桁ずつ表示しているので、60Hzで4桁が表示されます。
 下のコードはLEDに0000~9999を表示するものです。詳しくは、コードを参照してください。
 
 下のコードは,MicroPython1.20.0をインストールしたRaspberry Pi Picoで作成・動作確認をしています。


00:19
2023/06/27

Raspberry Pi PicoのDC/DCコンバーターのモード変更

| by:YAS
 「Raspberry Pi Pico Datesheet」の18ページや「Raspberry Pi Pico W Datesheet」の14ページによると、Picoは「GPIO23」、Pico Wは「WL_GPIO1」のピンでPowerSaveの制御ができます。低負荷時に、PSピンが0のとき、レギュレーターはパルス周波数変調(PFMモード)、1のとき、パルス幅変調(PWMモード)になるようです。高負荷時には、PSピンの設定によらず、PWMモードになるようです。
 PWMモードでは、効率が悪い代わりに、リップルが低減し、電源経由のノイズが抑えられるようです。
 実際に、どのような波形になるのか、オシロスコープで確かめてみました。プローブは、36ピンの「3V3(OUT)」と38ピンの「GND」に接続しました。

【Pico 起動直後】


【Pico PS=0に設定】
machine.Pin(23, machine.Pin.OUT).value(0)

 起動直後と変わらないようです。PSはデフォルトで0なので、当然だと思われます。

【Pico PS=1に設定】
machine.Pin(23, machine.Pin.OUT).value(1)

 リップルが小さくなったように見えますが、2つの横線が見えます。2つの線の電圧の違いは0.02Vですので、気にする程ではないと思います。波形を拡大すると下の様になっています。


【Pico W 起動直後】

 PicoのDC/DCコンバーターは「RT6150」、Pico Wは「RT6154」のためか、起動時の波形が異なります。

【Pico W PS=0に設定】
machine.Pin("WL_GPIO1", machine.Pin.OUT).value(0)

 「WL_GPIO1」はデフォルトで0のはずなので、改めて0に設定しても変わらないと思うのですが、実際には波形が変わります。

【Pico W PS=1に設定】
machine.Pin("WL_GPIO1", machine.Pin.OUT).value(1)

 PWMモードでのリップルはPicoよりも小さいようです。

 PicoとPico Wは、WifiやBluetoothが付いた以外はほぼ同じで、互換性は高いと思っていましたが、細かいところで特性が異なっているところがあるようですね。
00:26
2022/11/17

Raspberry Pi Pico W から LINE に通知する

| by:YAS
 LINE Notifyを使って、Raspberry Pi Pico Wから自分のLINEに送信してみます。
 LINE Notify API Documentによると、https://notify-api.line.me/api/notifyに、application/x-www-form-urlencodedでPOSTすればよいようです。
 しかし、Pico WのMicroPythonには、URLエンコードができるモジュールはないようです。そこで、upipでurllib.parseモジュールをインストールすることにします。
 ところが、
最新版のPico W用MicroPythonには、upipがなく、mipというものに代わっているようなのです。そして、mipでは、urllib.parseをインストールできません。前回の投稿のWifiに接続するモジュールを使って下の様なコードを実行しても、エラーになってしまいました。
import wifi
wlan, ip = wifi.connect()
import mip
mip.install('urllib.parse')
Installing urllib.parse (latest) from https://micropython.org/pi/v2 to /lib Package not found: https://micropython.org/pi/v2/package/6/urllib.parse/latest.json Package may be partially installed
 upipが実行できるのは、古いバージョンのMicroPythonのようです。探してみると、
Raspberry Pi Datasheetsにある、soft/micropython-firmware-pico-w-290622.uf2では、upipが使えました。下のようなコードに変更すると、urllib.parseモジュールがインストールできました。
import wifi
wlan, ip = wifi.connect()
import upip
upip.install('urllib.parse')

Installing to: /lib/ Warning: micropython.org SSL certificate is not validated Installing urllib.parse 0.5.2 from https://micropython.org/pi/urllib.parse/urllib.parse-0.5.2.tar.gz Installing micropython-collections 0.1.2 from https://micropython.org/pi/collections/collections-0.1.2.tar.gz Installing micropython-collections.defaultdict 0.3 from https://micropython.org/pi/collections.defaultdict/collections.defaultdict-0.3.tar.gz Installing micropython-re-pcre 0.2.5 from https://micropython.org/pi/re-pcre/re-pcre-0.2.5.tar.gz Installing micropython-ffilib 0.1.3 from https://micropython.org/pi/ffilib/ffilib-0.1.3.tar.gz
 ようやくURLエンコードができるかと思いきや、import urllib.parseでエラーになってしまいます。
Traceback (most recent call last): File "", line 2, in File "/lib/urllib/parse.py", line 30, in File "/lib/re.py", line 11, in AttributeError: 'NoneType' object has no attribute 'func'
 これは、どうやらlibフォルダからffilib.pyとre.pyを削除して、内蔵のものを使うようにすればよいようです。それで、下のコードを実行できるようになりました。実行すると、無事、LINEに通知が送られました。
import urequests as requests
from urllib.parse import urlencode
from micropython import const

LINE_TOKEN = const('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
LINE_URL = const('https://notify-api.line.me/api/notify')

def line_notify(message):
    header = {
        'Content-Type' : 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer ' + LINE_TOKEN
    }
    contents = { 'message' : message}
    message = urlencode(contents)
    try:
        response = requests.post(LINE_URL, headers = header, data = message)
        print(message)
    except Exception as e:
        print(e)
    finally:
        if 'response' in locals():
            response.close()

if __name__ == '__main__':
    import wifi
    try:
        wlan, ip = wifi.connect()
        line_notify('テスト送信')
    except Exception as e:
        print(e)
    finally:
        if 'wlan' in locals():
            wifi.disconnect(wlan)


21:20
2022/11/16

Raspberry Pi Pico W を Wifi に接続する

| by:YAS
 Raspberry Pi Pico W をWifiに接続します。WIFI_SSIDにアクセスポイント名を、WIFI_PASSWORDにパスワードを定義してから connect_wifi関数を呼び出します。接続の3秒後に切断します。切断しなければ、プログラムを停止してもWifiの接続は継続するようです。

【参考文献】
Connecting to the Internet with Raspberry Pi Pico W
import network
from machine import Pin
from time import sleep
from micropython import const

#定数
WIFI_SSID = const('xxxxxxxxxx')
WIFI_PASSWORD = const('xxxxxxxxxx')
MAX_RETRY = const(10)

#グローバル変数
led = Pin('LED', Pin.OUT)

def connect():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(WIFI_SSID, WIFI_PASSWORD)
    retry = MAX_RETRY
    while retry > 0:
        print('Wifi接続中...')
        if wlan.status() < network.STAT_IDLE or wlan.status() >= network.STAT_GOT_IP:
            break
        retry -= 1
        led.toggle()
        sleep(1)
    if wlan.status() !=  network.STAT_GOT_IP:
        led.off()
        raise RuntimeError('Wifi接続失敗')
    else:
        led.on()
        print('Wifi接続完了')
        ip = wlan.ifconfig()[0]
        print(f'IPアドレス = {ip}')
    return wlan, ip

def disconnect(wlan):
    if wlan.isconnected():
        wlan.disconnect()
        led.off()
        print('Wifi切断')
       
if __name__ == '__main__':
    try:
        wlan, ip = connect()
        sleep(3)
    except Exception as e:
        print(e)
    finally:
        if 'wlan' in locals():
            disconnect(wlan)


23:01
2022/11/11

PICOでバッテリー残量確認

| by:YAS
 Raspberry Pi PICOでバッテリーの残量を取得するコードです。バッテリーの電圧を測って、残量を推測します。
from machine import Pin, ADC

PIN_BATTERY_VOLT = 29          #バッテリー電圧測定ピン
PIN_USB_POWER = 24             #USB電源検出ピン
BATTERY_CONV = 3.3 / 65535 * 3 #生の値 --> 電圧値 変換係数

usb_power = Pin(PIN_USB_POWER, Pin.IN)
battery_volt = Pin(PIN_BATTERY_VOLT, Pin.IN)
adc_battery = ADC(battery_volt)

#USB電源検出
def detect_usb_power():
    return usb_power.value()

#電源電圧取得
def measure_battery_volt():
    return adc_battery.read_u16() * BATTERY_CONV

#リチウムイオン電池残量割合取得
def battery_remaining():
    volt = measure_battery_volt()
    if volt >= 4.2:
        rate = 1
    elif volt >= 3.8:
        rate = 0.8
    elif volt >=3.6:
        rate = 0.6
    elif volt >= 3.3:
        rate = 0.4
    elif volt >= 2.7:
        rate = 0.2
    else:
        rate = 0
    return volt, rate

if __name__ == '__main__':
    print(f'USB電源:{"検出" if detect_usb_power() == 1 else "非検出"}')
    volt, rate = battery_remaining()
    print(f'電源電圧:{volt:.2f}V\n電池残量:{rate:.0%}')


23:14
2022/11/06

picozeroモジュールでボタン押下検知

| by:YAS
 picozeroモジュールを使うと、色々簡単にできるようです。割り込みでボタン押下を検知するには、以下のようになります。とても簡単です。GPIO15に接続したボタンを押下すると、内蔵のledが点いたり消えたりします。
from picozero import Button, pico_led

PIN_BUTTON = 15

def main():
    button = Button(PIN_BUTTON)
    button.when_pressed = led_toggle

def led_toggle():
    pico_led.toggle()

if __name__ == '__main__':
    main()

12:41
2022/08/31

Raspberry Pi PICOでWAVファイル再生

| by:YAS
①Raspberry pi PICOで音声を再生する
 下のページを参考に、wavファイルを再生することができました。
 http://serverarekore.blogspot.com/2021/07/raspberry-pi-picotpa2006dwav.html
 しかし、PWMをそのままD級アンプに入れると音質があまりに悪いので、ローパスフィルターで改善を図ってみました。

②PWMの出力を確認する


 テスト用データとして、橋本技術研究所のサイン波wavファイルの400Hzのファイルを使わせていただきました。
 再生した際の出力をロジックアナライザLA2016で表示したものが下図です。

 Channel0は左側スピーカーの出力、Channel1は仮想GNDの出力です。PWMのスイッチング周波数は実測で約122kHでした。プログラム上でも122kHzでしたので一致します。

③ローパスフィルタで復調する

 wavePlayer.pyの注釈(上図)の通りに、2kΩの抵抗と、0.1μFのキャパシタのローパスフィルタ(カットオフ周波数約796Hz)で復調したのが下図です。(簡易オシロスコープDSO Shellで測定)

 直流の成分を含んだ、サイン波が復調できました。


④カップリングコンデンサで直流成分を除去する
 GPIO4の仮想GNDをGNDにするか、下図のように2200pFのカップリングコンデンサを直列に入れて、直流成分を除去します。


 これにスピーカーを繋ぐと音が出ますが、音量がとても小さいのでD級アンプTPA2006を使って増幅してみます。

⑤D級アンプTPA2006で増幅する
 
 スピーカーで鳴らせるように、秋月電子で購入したTPA2006のモジュールを使ってみました。仕様書をざっと眺めると、スピーカーまでのケーブルが短い場合は出力フィルターはいらないと読み取れたのですが、出力をオシロスコープでみると、上の写真のようになってしまいました。

⑥出力フィルタを付けてみる
 下図のように、33μHのインダクタと、0.33μFのキャパシタのローパスフィルタ(カットオフ周波数約48kHz)を繋いでみました。また、ゲインを変えないのであれば、カップリングコンデンサはモジュールに内蔵のものがあるので、削除しました。

 オシロスコープの波形は正弦波になりました。気持ちはいいのですが、聞いた感じは、出力フィルタなしとあんまり変わらないような気もします。

 結論としては、アンプに入れる信号はローパスフィルターで復調してからの方が音質がかなりよくなります。しかし、出力フィルターはあっても無くてもそれほどかわらないと思いました。
 あと、3倍のゲインでは音量が小さめだと感じました。
01:22
2022/02/19

VBでRaspberry Pi PICOにファイルを転送する

| by:YAS
 Raspberry Pi PICOにファイルを転送するには、Thonnyなどを使えば簡単にできますが、PICOを使った自作VOCAにWAVEファイルを転送しようとすると、簡単にできる方法はなさそうです。バイナリ配列の内容をファイルを書き込むコードをREPLモードで実行してみましたが、メモリ不足のエラーが出て、ごく小さいファイルしか転送できませんでした。そこで、仮想COMポートのcom0comを使ってThonnyの通信内容を解読したところ、2kbyteずつ送信・書き込みを行っていることがわかりました。
 下のサンプルコードはtest.wavをPICOのルートディレクトリに転送します。コードをForm1にコピー・貼り付けすれば動作します。

Form1.vb

14:20
2021/11/01

ELEGOOのArduino用2.8インチTFT液晶にビットマップを表示する④(完結編)

| by:YAS
 前々前回に引き続き、Arduino用のTFT液晶をRaspberry Pi PICOにつなぎ、240 x 320ピクセルのBitmapを表示してみました。前回24bitBitmapを16bitBitmapに変換する処理とGPIOへの出力部分をPIOを使って作りました。残念ながら遅くなってしまいましたが、BitmapデータをPIOにそのまま流し込めるようになりましたので、今回は、DMAを使って画像データをPIOに転送してみました。
 その結果は、なんと0.094秒と、最初の18.2秒から193倍の速度になりました。すごいぞDMAとPIO!C++なんていらないじゃん!何でもMicroPythonで作れるんじゃない?
 DMAの利用は、myDMA.pyを使わせていただきました。下のページからコピペし、同じフォルダに入れておいてください。
 danjperron/PicoAudioPWM - GitHub
 DMAを使う際に注意する点として、フルスピードのDMAで転送するとPIOのFIFOがオーバーフローしてしまうので、DMAのクロックを1/5にしています。(この値は1/2,1/3…と試してみて、うまくいった値を使っています。適当です。)
 
 下のコードは,MicroPython1.17をインストールしたRaspberry Pi PICOで作成・動作確認をしています。(同じフォルダに240 x 340ピクセル、24bitカラーの画像を「sample.bmp」という名前で配置してください。)


01:34
2021/11/01

ELEGOOのArduino用2.8インチTFT液晶にビットマップを表示する③

| by:YAS
 前々回前回に引き続き、Arduino用のTFT液晶をRaspberry Pi PICOにつなぎ、240 x 320ピクセルのBitmapを表示してみました。前回はGPIOへの出力部分をPIOを使って高速化しました。今回は、24bitBitmapを16bitBitmapに変換する部分もPIOで行いました。
 その結果は、前回と同じ画像を5.9秒で表示と、前回の4.5秒よりも遅くなってしまいました。変換そのものは絶対にPIOの方が速いと思うので、StateMachineへのputが2byteから3byteに増えたところがボトルネックなのだと推測しています。(StateMachineへのputにそんなに時間がかかるとも思えないのですが…。不思議です。)
 今回のPIOの処理の追加で、Bitmap画像のデータをそのままStateMachineのFIFOへ流し込めばよくなったので、DMAが使えそうです。次回はさらにDMAを使ってPIOにデータを流し込んでみたいと思います。
 
 下のコードは,MicroPython1.17をインストールしたRaspberry Pi PICOで作成・動作確認をしています。(同じフォルダに240 x 340ピクセル、24bitカラーの画像を「sample.bmp」という名前で配置してください。)


01:02
123