Attic or Garret

M5Stackを使ってみる (MicroPython編)

Introduction

M5Stack/M5Camera/M5Stick/M5Atom/M5Stamp
それぞれコンパクトなケースに沢山の機能が詰まった魅力的なIoTデバイス
マイコン世代のひとはM5と聴くとSORD m5を思い出すはずw
内容はIndexにまとめています。お好みの内容をまったりとご覧下さい。(^_^)
ほぼ備忘録です。バージョンなどの違いによって使い方が変わっている可能性もあるのでご注意ください。
長くなったのでハード編は別ページにまとめました。

公開している内容を著者に無断で転載あるいは商業目的で利用することを禁止します。 改造等は個人の責任のもとに行って下さい。発生した事故、故障などに対して一切の責任を持ちません。 公開している内容のアイデアを流用した作品、および公開している独自の解析結果を含む情報を、SNS、ブログ、書籍などで発表する際はご一報ください。こちらのサイトへのリファレンス(リンク)を加えてください。

改造により電波法違反となる可能性があります。当サイトでは適時、ダミーロードなどの電波を微弱化する処置、および電磁波シールドを使用しての電磁波漏洩対策等を行っており電波法の適用範囲内で実験しています。改造は自己責任でお願いします。 技適(工事設計認証)に関する情報

Index

MicroPython編

ハード編

M5Stack / M5Stick / M5Camera / M5Atom[S3] / M5Stamp[S3] をMicroPythonで使ってみる。

M5Stack / M5Stick / M5Camera / M5Atom[S3] / M5Stamp[S3] で使えるMicroPythonのファームウェアは複数の種類があります。さらにビルドに使ったESP-IDF(CPU開発元の公式SDK)のバージョンによっても機能が異なってきます。
MicroPythonの種類ベースバージョンidf関連サイトソースコードM5ハード対応
originalオリジナル/本家v5.0.4micropython.orgソースコード
originalリビルド版v1.22.0v5.0.4このページで解説
loborisv1.9.4ソースコード
loborisリビルド版loborisこのページで解説
UIFlowv1.12flow.m5stack.com非公開
UIFlow2v1.22v5.0.4flow2.m5stack.comソースコード
(ローカル版)
Core2forAWS-MicroPythonv1.12?ソースコードCore2forAWSのみ
最終確認 2024/02/20
  • ・ 最新のMicroPythonの情報はリリースノートで確認してください。Releases
  • ・ カスタム機能を説明するときは[ originalリビルド版 ][ loborisリビルド版 ][ loboris ]と記載をしています。
  • MicroPythonの種類やバージョンにより、それぞれ機能が実装されていなかったり、文法が異なります。
  • 違いがあっても機能が実装されていれば、そのまま、もしくは若干の手直しで対応できる場合があります。
  • [ loborisリビルド版 ]は高機能な[ loboris ]にさらに機能を追加しています。ベースは古くなっていますが安定度も高いので用途によってはまだまだ使えます。Bluetooth Classicに唯一対応しています。
  • ・ PythonのIDEとしてuPyCraft を使っています。
    Thonnyはファイル(画像などのバイナリ含め)のドラックドロップ転送が使えないので使っていません。
  • ・ M5Stack公式ではUIFlowを推奨しています。
  • UIFlowはREPLからほぼ通常のMicroPythonとしても使えます。

MicroPython [ originalリビルド版 ]Index

最新のオリジナルMicroPython(v1.22.0)をM5Stack(Core2/Fire/M5Atom[S3]/M5Stamp[S3])に最適化してリビルドしました!これから機能を充実させてゆきます。

追加した機能

@ M5Stack Core2 / Fire / M5Atom[S3] / M5Stamp[S3] / M5StickC[PLUS/2] のハードウェアに対応

A MP3ファイルの再生に対応(バックグラウンド再生に対応 [スレッドセーフ] )

B Madgwickフィルタに対応(Cプログラムなので高速)

C Bluetoothに対応 (BLE HIDを簡単に使えるようにしました)

D I2SのサウンドでPDMに対応

E REPLでuPyCraftのバイナリ転送に対応

F PWMのパーセント指定に対応

  machine.PWM.reserve(percentage=True) を実行するとloboris互換になります。

MicroPython [ original ] ビルド済みイメージファイル

リビルド済みのイメージファイルを用意しました!
MicroPython[ originalリビルド版 ] M5Stack[Fire/Core2/Basic]/M5Atom[S3]/M5Stamp[S3]/M5StickC[+2]/XiaoS3[C3]対応 ダウンロード

BOARD情報の作成

ボード情報を用意するとボードごとにビルドを分けることが出来るので便利です。boards以下にボード名のフォルダを作ります。

モジュールの追加

リビルド [玄人志向]

MicroPython [ loborisリビルド版 ]Index

現状ではどのMicroPythonでも使えない機能があるため、今のところ機能が豊富なloboris版をM5Stack(M5Sstick/M5Atom/M5Stamp)に最適化してリビルドしました!

追加した機能

@ M5Stack / M5Stick / M5Atom / M5Stamp のハードウェアに対応

A MP3ファイルの再生に対応(再生中にSD、LCDの同時アクセスが可能)

B Madgwickフィルタに対応

C Bluetoothに対応 (btstackの一部の機能)

D バッファに格納されたイメージデータの表示に対応

E readintoを使ったときにデータ格納位置をオフセット指定できる。

F WAVファイルの再生時にバッファー容量を指定できる。

MicroPython [ loboris ] ビルド済みイメージファイル

MicroPython[ loborisリビルド版> ] ダウンロード
  • ※ 実験中のリビルド版であることをご理解のうえでお使いください。
  • ※ 書き込みはハード編のファームウェアのバックアップ / リストアを参照してください。
  • ※ FLASHサイズ/SPI速度/PSRAM別になっています。
  • ※ 名前にbtstackがあるファイルはBluetoothの一部機能が使えますが実験バージョンです。btstackがメモリを占有するため利用可能メモリが減っています。(PSRAMが搭載されていないとWiFiが使えません)

リビルド [玄人志向]

MP3ファイルを再生するIndex

MP3ファイルの再生機能を追加しました。バックグラウンド再生も出来るので再生中も処理を継続できます。

初期化

I2S[PDM] [ originalリビルド版 ]
NS4168 (M5Stack Core2 / M5Atom Echo) [ originalリビルド版 ]
DAC (M5Stack) [ loborisリビルド版 ]
NS4168 (M5Stack Core2 / M5Atom Echo) [ loborisリビルド版 ]
  • ※ I2Sのチャンネルは2チャンネルありますが、再生/録音ではチャンネル0しか使えません。また再生/録音は同時には使えません。

再生

import audio
audio.play_mp3('ファイル名.mp3') ファイルディスクリプタの指定も出来ます
オプション(省略可、値は初期値)
    port_id=0,
    buffsize=1940, リードバッファ(socketストリームからの再生時など、音切れする際は増やします)
    bg_play=False, stacksize=4096, priority=2, core=1, バックグラウンド再生の指定
    bit=32, I2Sで扱うビットサイズ(音質向上用)
    stream=False, True にするとヘッダを読み込まない
    end_mute=False, 再生後の消音(ノイズ対策)
    button=None, button_on=False 停止ボタン、停止ボタンON条件

audio.check_play() 再生確認
audio.stop() 再生停止

audio.interrupt_in() 子スレッドのファイルアクセスを停止
audio.interrupt_out() 子スレッドのファイルアクセスを再開
オプション [ loborisリビルド版 ]
バックグラウンド再生中でも親スレッドでファイルアクセスが出来ます!
  • ※ バックグラウンド再生する際はファイル名ではなくファイルディスクリプタを使う必要があります。
  • ※ esp32の標準ビルドされたファイルシステムはスレッドセーフではありません。
    スレッドセーフに対応するためにソースコードを改変しています。
競合が発生しないように改良していますが、ハードウェアでファイルシステムとリソースを共有しているデバイスがあると競合が発生します(M5StackのSDカードとLCDの関係など) 詳しくは Partitions APISPI Flash API を参照してください。 この場合は interrupt_in() により子スレッドのファイルアクセスを停止することで競合を避けることが出来ます。下記ご注意ください。
  • ※ 出来るだけ短時間で割り込み処理を終了させます。
  • ※ 再生中に実行されるフォアグラウンドのプログラムによっては予期せぬ動作をする可能性があります。
mp3ファイルはモノラルに変換してください。
変換ツールはEcoDecoTooL114を使っています(Fraunhofer/CBR/128kbps)

WAVEファイルを再生するIndex

import audio
audio.play_wave('ファイル名.wav') ファイルディスクリプタの指定も出来ます
オプション(省略可、値は初期値)
    port_id=0,
    buffsize=1024, バッファーサイズ
    bg_play=False, stacksize=4096, priority=2, core=1, バックグラウンド再生の指定
    bit=32, I2Sで扱うビットサイズ(音質向上用)
    repeat=0, リピート再生回数
    end_mute=False 再生後の消音(ノイズ対策)
    button=None, button_on=False 停止ボタン、停止ボタンON条件

audio.check_play() 再生確認
audio.stop() 再生停止
バックグラウンド再生についてはMP3ファイルを再生するを参照してください。
M5Stack [ loborisリビルド版 ]

マイクを使うIndex

初期化

SPM1423[ESP32-S3 PDM] (M5Capsule) [ originalリビルド版 ]
  • ※ I2Sのチャンネルは2チャンネルありますが、再生/録音ではチャンネル0しか使えません。また再生/録音は同時には使えません。

録音

音に反応して自動で録音します。録音開始に必要な音量はローパス、マイクレベルで設定します。
録音データはファイルにも保存できます(レスポンスが落ちます)
import wave

buff = bytearray(framerate*10+44) # 10 Sec
rec_size= wave.mic_recording_auto(mic, 録音データの格納場所(メモリ / ファイル名)buff,
                                                              フレームレート12000, ローパス8, マイクレベル6)
オプション(省略可、値は初期値)
    chunk_size=6000, 録音の最小単位(フレームレートの半分を指定すれば0.5秒)
    block_size=48000, 音声認識処理される最小単位ブロック単位(通常フレームレートの4倍)
    sc=3, nc=2, debug=False, cv=False, shift=0

液晶ディスプレイを使う [ originalリビルド版 ]Index

初期化

描画などの使い方はこちらを参照してください。→ ST7789 Driver for MicroPython
M5Stack Core2 / FireはLCDとSDが同じSPIバスに接続されているので、共用出来るように"russhughes/st7789_mpy"を修正しています。
マルチプラットフォームなのでM5Stackのハードウェアに特化していないのだと思われます。

液晶ディスプレイを使う [ loborisリビルド版 ]Index

初期化

描画

tft.set_bg(tft.WHITE)
tft.set_fg(tft.BLACK)
tft.clear()
tft.rect(1, 1, 158, 78) 端から端まで線を引く
tft.font(tft.FONT_Ubuntu) フォント指定
tft.text(0, 0, 'test', tft.BLACK) テキストの表示
詳しくは… display・loboris/MicroPython_ESP32_psRAM_LoBo Wiki・GitHub

液晶ディスプレイを使う (framebuf)Index

初期化

液晶ディスプレイを使う [ loborisリビルド版 + LovyanGFX ] (2020/08/07-)Index

lovyan03さん製作の超高速グラフィックライブラリLovyanGFXをMicroPythonでも使えるようにしました。
displayモジュールと共存出来ません、別途リビルドが必要です。
MicroPython[loboris+lovyan03リビルド版] ダウンロード (実験バージョン)
  • ※ MicroPython対応にあたってlovyan03さんにご対応頂きました。この場を借りて感謝申し上げます。

初期化

LovyanGFXでイメージデータを表示する

lgfx.drawJpgFile('イメージファイル名', 0, 0) x, yの位置指定が出来ます
lgfx.drawJpg(data, 0, 0) バッファに格納されたイメージデータ,x, yの位置指定が出来ます
  • ※ LovyanGFXのsprite機能には対応中…
  • ※ printfは実装していません
  • ※ PSRAMを使う場合は40MHz駆動にする必要があります。
  • ※ PSRAMとLovyanGFXとBluetooth(BTSTACK)を組み合わせて使うとIRAMが不足します。SPIのIRAM使用を停止することでビルドできます。
  • ※ LovyanGFXとBluetooth(BTSTACK)を組み合わせた状態でFTPを使うと転送速度が落ちます。

イメージデータを連続表示する (2019/04/09-)Index

M5Stack [ loborisリビルド版 ]

上の動画は内蔵フラッシュメモリーに保存した画像ファイル(jpeg)を連続表示して実現しています。 全画面(320×240)にjpeg画像1枚を表示する時間を測定すると約0.1ミリ秒でした。 全画面表示はLCD(ILI9341)のアクセススピードより、画像データ保管場所からの転送スピードに影響されます。

SDカードをマウントするIndex

初期化

M5StickC [ loboris ]
実際の転送速度はSDカードとの相性によるようです。

SPIインターフェースを使う際のトラブル&対策Index

ESP32モジュールにはHSPI、VSPI(ESP32非C/SだとそれぞれSPI2_HOST=1、SPI3_HOST=2)の2系統のSPIインターフェースが用意されています。(FlashとpsRAM用は別)

M5Stack Core2 / Fire / Basic

SDカードスロットとLCDはインターフェース(VSPI)を共有しています。外部用SPI端子もVSPIに接続されます。
SDカードとLCDを同時にアクセスする際には注意が必要。

MicroPython [ loboris ] でのSPIとDMA

SPIはDMAも使用しておりMicroPython [ loboris ] では現状下記に固定されています。
  • ・ LCD (DMA1)
  • ・ SDスロット (DMA2)
  • ・ 外部SPI機器 (DMA1)
このためLCDと外部SPI機器は同時に使用出来ず、次のエラーが発生します。
spi_master: spi_bus_initialize(96): dma channel already in use
[SPI_UTILS]: spi initialization failed with rc=0x103

ジャイロ、加速度、地磁気センサを使うIndex

なるべく共通化できるようにプログラムを記述しています。設定値は各センサーの仕様によります。

Madgwickフィルタを使う [ originalリビルド版 / loborisリビルド版 ]Index

Madgwickフィルタを使う事によりロール、ピッチ、ヨー角が高精度に取得できます。
  • ※ センサーがキャリブレーションされていないとドリフトします。

Bluetooth(Classic)を使う [ loborisリビルド版 + btstack ] (2019/08〜)Index

Bluetoothに関する情報は少ないのでMicroPythonに実装するのは苦労しました。モジュールさえ作ってしまえばあとの扱いは簡単です。 いまのところbtstackとの組み合わせがとても安定してます。btstackは登場からかなり経っていることもあり情報もそこそこあってソースコードも読みやすく、サンプルコードも充実しています。でもAPI構成(BLE ANCS Client API)が独自なのでMicroPythonのモジュールにするのはちょっと面倒です。
公式MicroPython(ESP32)がBluetooth(BLE)に対応しました。クラシックには対応してないようです。だんだんbtstackを使う必要性が薄れてくるかもしれません。
  • ※ Callbackルーチン内でのメモリ確保はエラーの要因になります。globalの使用を推奨します。
  • ※ run_loop_execute()を使うとPythonに制御が戻らないため、run_noloop_execute(timeout_ms)を追加

sixaxis (DUALSHOCK3)

DUALSHOCK3のデータを直接取得することが出来ます。
  • ※ DUALSHOCK3をPlayStation以外で使うためには事前の準備が必要です。
    Windowsの場合は、株式会社ベストテクノロジーさんのSIXAXISの設定が詳しいです。
    上記リンクから取得できる sixpair を使ってホスト側(M5xxxxx)のMACアドレスを DUALSHOCK3に書き込みます。 ホスト側のMACアドレスは下記の sixaxis.read_mac() で取得できます。
    USB 入力デバイスで認識されているときはDUALSHOCK3として認識されていません、うまく接続出来ないときはDUALSHOCK3をリセットします。

spp[Server] (Serial Port Profile)

仮想シリアルポートとして動作します。PC側の設定は着信(デバイスが接続を開始する)

spp[Client] (Serial Port Profile)

仮想シリアルポートとして動作します。PC側の設定は発信(コンピュータが接続を開始する)

hid (Wii Remote/Other)

WiiリモコンなどのHIDタイプのゲームコントローラからデータを直接取得することが出来ます。

hid[Slave] (Keyboard/Mouse)

HIDのスレーブ動作をします。キーボード、マウスとして機能します。

hciパケットをAndroidでキャプチャして解析

Bluetooth(BLE)を使う [ originalリビルド版 ] (2023/04〜)Index

ESP32S3からClassicは非対応になりBLEのみ対応となりました。
APIもNimBLEベースになっています。

BLE Keyboard

AtomS3をBLE Keyboardにする例です。
Heerkog氏のhid_services.pyを組み込んでいます。
  • ※ MicroPython v1.20以降(v1.22でも確認)ではキーコードが送信できない問題が起きています。v1.19でお試しください。
    Don't work on micropython v1.20.0

オリジナルUUIDの生成

こちらで生成できます。version1を指定 https://www.uuidgenerator.net/version1

Wi-Fi アクセスポイントに接続するIndex

import time
import network
import setting SSID,PASSWARDを保存した設定ファイル
if 'ap_if' not in locals():
  ap_if = network.WLAN(network.STA_IF)
if not ap_if.isconnected():
  ap_if.active(True)
  ap_if.connect(setting.MY_SSID, setting.MY_PASSWARD)

while not ap_if.isconnected(): 接続待ち
  print(".", end='')
  time.sleep(0.1)

FTPサーバーに接続するIndex

[ originalリビルド版 ]

import ftp
ftp.ftpserver()
robert-hh氏のFTP-Server-for-ESP8266-ESP32-and-PYBDを組み込んでいます。
簡易バージョンです。クライアントがセッションを閉じると終了。1 つのセッションのみがサポートされます。

DeepSleepを使うIndex

DeepSleep中は消費電力を節約できます。
サンプルコード [ loboris ]

動作クロックを変更するIndex

動作クロックには2MHz, 80Mhz, 160MHz, 240MHzを指定できます。
import machine

machine.freq(240) 任意の動作クロックを指定、省略した場合は現在のクロックを返します。
  • ※ DeepSleepと違いクロック変更後でもそのままプログラムが動作します。ただし通信系の機能を使っている場合など影響が起きる可能性があります。
  • ※ originalではMHzの指定が出来ないようです。240MHzは240000000Hzになります。

PMICを使うIndex

MicroPythonからパワーマネジメントIC AXP192にアクセスする。
import axp192

i2c = machine.I2C(sda=21, scl=22)
pm=axp192.AXP192(i2c)

RTCを使うIndex

MicroPythonからリアルタイムクロックBM8563にアクセスする。
import bm8563

i2c = machine.I2C(sda=21, scl=22)
rtc=bm8563.BM8563(i2c)

rtc.GetBm8563Time() (年, 月, 日, 時, 分, 秒, 週)が戻ります。
rtc.GetTime() (時, 分, 秒)が戻ります。
rtc.SetTime(Hours, Minutes, Seconds) 時間を設定します。
rtc.GetData() (年, 月, 日, 週)が戻ります。
rtc.SetData(Year, Month, Date, WeekDay) 日付を設定します。

撮影データを取得するIndex

OV2640(M5Camera) [ loborisリビルド版 ] (2019/01/23)

DualShock/2を使うIndex

DualShock/2はSPIインターフェースで通信できます。
DualShock/2の資料はこちらが詳しくとても分かりやすいです。
プレイステーション2専用ローリングスイッチ技術資料

初期化

M5Stack [ loborisリビルド版 ] (2018/06/24)

readintoでデータ格納位置をオフセット指定する ( loborisリビルド版] )Index

sock.readinto(バッファ, 入力バイト数(省略可), オフセット(省略可))
MicroPythonオリジナルではmemoryviewが使えるようになったので、バッファのポインタ渡しができるようになりました。よってオフセット指定は不要になりました。

エラー定数 (int)Index

ESP_OK0
ESP_FAIL-1
ESP_ERR_NO_MEM0x101    |    ESP_ERR_TIMEOUT0x107    |    ESP_ERR_WIFI_BASE0x3000
ESP_ERR_INVALID_ARG0x102    |    ESP_ERR_INVALID_RESPONSE0x108    |    ESP_ERR_MESH_BASE0x4000
ESP_ERR_INVALID_STATE0x103    |    ESP_ERR_INVALID_CRC0x109    |    ESP_ERR_FLASH_BASE0x6000
ESP_ERR_INVALID_SIZE0x104    |    ESP_ERR_INVALID_VERSION0x10A    |    ESP_ERR_HW_CRYPTO_BASE0xc000
ESP_ERR_NOT_FOUND0x105    |    ESP_ERR_INVALID_MAC0x10B    |    ESP_ERR_MEMPROT_BASE0xd000
ESP_ERR_NOT_SUPPORTED0x106    |    ESP_ERR_NOT_FINISHED0x10C    |    
esp-idf/components/esp_common/include/esp_err.h

MicroPythonでWebAPIを使ってみる。 [ originalリビルド版 ]

WebAPIを使うことで可能性が加速的に拡がります。
サンプルコードの実行にはリビルド済みのイメージファイルが必要になります。
MicroPython [ original ] をリビルドするを参照してください。

Google Cloud Speech-to-Text をWebAPIで使う (2024/01〜)Index

waveデータの生成はマイクを使うを参照してください。
  • ※ 高速化のためメモリに格納したwaveデータをそのままBase64エンコードして転送しています。
    Base64エンコードをchunk_sizeごとに分割して行うことでメモリを大幅に節約しています。
  • ※ 録音時間を伸ばしたい、もしくは搭載メモリが少なければwaveデータをファイル経由で扱う必要があります。

ChatGPT AIチャットボットをWebAPIで使う (2023/04〜)Index

VOICEVOXをWebAPIで使う (2023/04〜)Index

VOICEVOXサーバーの起動 (Windows)

AppData\Local\programs\VOICEVOX\run.exe --host VOICEVOXサーバーのアドレス

VOICEVOXサーバーへのリクエスト

import urequests as requests
import webapi サポートモジュール

address="VOICEVOXサーバーのアドレス:50021/"
res1 = requests.post(address+'audio_query?text='+webapi.encode_url_string(content)+'&speaker=1&outputStereo=false')
res2 = requests.post(address+'synthesis?speaker=1&outputStereo=false',data = res1.text.encode("utf-8"))
キャラクターボイスを変えるときはspeakerの値を変えます。

webapi.play_wav(res2.raw, spk) # !caution instance variable インスタンス変数を参照しているので要注意
spkの初期化はMP3ファイルを再生するを参照してください。
  • ※ waveデータをバッファを介さずに直接I2Sに書き込みすることでメモリを節約して高速化しています。


各種改造は個人の責任のもとに行って下さい。改造により発生した事故,故障などに対し Attic or Garret では一切の責任を持ちません。また各種改造を施した製品は,各種保険及び保証を受ける権利を失う可能性があります。
Attic or Garret 中の各記事,写真及び改造内容を著者に無断で転載あるいは商業目的で利用することを禁じます。

Copyright © 1996-2021 Itoi.All Rights Reserved.