YAS's VB.NET Tips
 
ラズベリーパイ活用
ラズベリーパイ活用
123
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
2021/11/01

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

| by:YAS
 前回に引き続き、Arduino用のTFT液晶をRaspberry Pi PICOにつなぎ、240 x 320ピクセルのBitmapを表示してみました。前回はSIOにmem32でアクセスしたのですが、Bitmap画像を表示するのに18.2秒もかかってしまいました。今回は、PIOを使って高速化を図ってみます。
 24bitBitmapを16bitBitmapに変換するのはPythonで行い、GPIOへの出力部分をPIOを使って行いました。
 その結果、前回と同じ画像を4.5秒で表示できました。(関数デコレーターに@micropython.nativeを指定した場合は、2.8秒!)4倍の高速化!PIOは強力ですね。
 しかし、4.5秒でも実用的とは言えないので、次回はさらにPIOに処理を移してみたいと思います。
 
 下のコードは,MicroPython1.17をインストールしたRaspberry Pi PICOで作成・動作確認をしています。(同じフォルダに240 x 340ピクセル、24bitカラーの画像を「sample.bmp」という名前で配置してください。)


00:36
2021/10/31

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

| by:YAS
 Arduino用のTFT液晶をRaspberry Pi PICOにつなぎ、240 x 320ピクセルのBitmapを表示してみました。このLCDは5Vで動作しますが、横のCON1のピンを使うことで、3.3Vでも使うことができるようです。詳しくは、ELEGOOの製品ページに情報があります。
 今回は、下のようにPICOと接続しました。
 LCD Raspberry Pi PICO
 LCD_D0 GPIO0 (1pin)
 LCD_D1 GPIO1 (2pin)
 LCD_D2 GPIO2 (4pin)
 LCD_D3 GPIO3 (5pin)
 LCD_D4 GPIO4 (6pin)
 LCD_D5 GPIO5 (7pin)
 LCD_D6 GPIO6 (9pin)
 LCD_D7 GPIO7 (10pin)
 LCD_RD GPIO8 (11pin)
 LCD_WR GPIO9 (12pin)
 LCD_RS GPIO10 (14pin)
 LCD_CS GPIO11 (15pin)
 LCD_RST GPIO12 (16pin)
 GND GND (38pin)
 CON1の3.3V 3.3V (36pin)

 TFTに付属のArduinoのサンプル_9341uno.inoとShowBMP.inoを参考に、MicroPythonでBitmap画像を表示しました。LCDの初期化は_9341uno.inoの処理をそのまま使いました。ShowBMP.inoによると、ビットマップデータは赤5bit・緑6bit・青5bitの16bitで、上位8bitを先に、下位8bitを後に送信するようです。
 今回は、mem32でSIOのGPIO_OUT(0xd0000010)に書き込むことで、パラレル出力を制御しました。しかし、これでは1画面を更新するのに18.2秒かかりました。また、関数デコレーターに@micropytnon.nativeを指定しても、16.9秒かかり、実用的ではありません。(ArduinoUNOではSDカードの画像を11秒くらいで表示する。これも遅いけど。)だからと言ってC++を使うのは面倒くさいので、今後、PIOやDMAを使った高速化に挑戦したいと思います。

 下のコードは,MicroPython1.17をインストールしたRaspberry Pi PICOで作成・動作確認をしています。(同じフォルダに240 x 340ピクセル、24bitカラーの画像を「sample.bmp」という名前で配置してください。)


23:09
123