この記事について
データドリブンなLチカという言葉をご存知だろうか?実はこの記事のために作った造語だ。今回はデータドリブンなLチカの意味ついて説明する。さらにRaspberry Pi picoを使ってTensorflow Lite for MicrocontrollerのLチカデモを実行する方法について説明する。データドリブンなLチカって言ってみたかっただけなのでネタ半分で読んで欲しい。そして、Raspberry Pi picoが積み基板化している方にぜひチャレンジしていただき、新時代へのパラダイムシフトを体験することを願っている。
Lチカとは(おさらい)
Lチカとはマイコンに接続したLEDを点滅させるHelloWorld的なプログラムのことだ。sleep命令やタイマー割り込み、PWM出力といったマイコンの機能を使い倒してLEDの点滅間隔をプログラムする。例えば蛍のようなゆっくりとした点滅パターンを作りたい場合、sin関数を使ってPWMの出力を変化させる。
Lチカの明滅パターンをデータで定義する
データドリブンなLチカはLEDの点滅パターンをデータによって定義する。先ほどの例と同様の点滅を作る場合はsin関数の出力をデータとして記録する。その記録したデータを学習させたニューラルネットワークを使ってPWMの出力を変化させる。
後述するデータドリブンなL チカのデモを実行した様子がこちら。見た目は普通のLチカと違いはない。
綺麗なPi picoのLチカだろ。。。Tensorflow lite for microcontroller(NN)で近似させたSin波で点滅してるんだぜ、これ。。。 pic.twitter.com/DaV0ZdCNon
— masato_ka (@masato_ka) 2021年2月11日
上記ツイートの例だと実行速度がはやく普通の点滅に見えるため、sin波の変化がわかりやすいように調整してみた。
Raspberry Pi pico led blink with neural network that approximates a sine wave.
データドリブンなLチカが示すパラダイムシフト
データドリブンなLチカの利点は点滅パターンを作り出す関数を定義せずともその点滅を実装できることだ。ニューラルネットワークはデータさえあれば任意の関数を近似(まね)できる特性がある。この特性を利用することで、データから任意の点滅を実装することができる。元の関数が不明でも問題ない。
つまり、データドリブンなLチカは実装という作業を「アルゴリズムを考えてコードに落としこむ」から「アルゴリズムを定義するデータを集める」に変化させたのだ。処理の実装ではなくデータの収集、これがデータドリブンなLチカが示すパラダイムシフトだ。
このように処理を記述するプログラミングに代わって、データによって機能を定義するソフトウェア開発をSoftware2.0と呼ぶ。マイコンの世界もついにSoftware2.0が到来したというわけだ。
sin波のような単純な関数では旨味はないが、一見、不規則に見えるような点滅など複雑な点滅を実装する場合はどちらが良いだろうか。
Raspberry Pi picoでデータドリブンなLチカを実行する。
実際にデモを体験してみよう。Raspberry Pi picoでデータドリブンなLチカを実現するためにはニューラルネットワークを実装する必要がある。Raspberry Pi picoではTensorFlow Lite for microcontroller(以下TF Lite micro)という、TensorFlow の組み込み向け実装がポーティングされている。
前出のLチカ動画はTF Lite microのhello_worldデモを実行したものだ。このサンプルではsin関数を学習したニューラルネットワークを使い、LEDの点滅を制御している。今回はこのデモの実行方法を説明する。
事前準備
公式のGetting Startedドキュメントを参考にコンパイラ、cmakeといったツールチェインとpico-sdkをダウンロードしておく。pico-sdkは環境変数PICO_SDK_PATHにパスを通しておく。わからない場合はぐぐると丁寧に解説した記事が出てくるのでそちらを参考にして欲しい。
続いて、TF Lite microのリポジトリをローカルにクローンしておく。
>git clone https://github.com/raspberrypi/pico-tflmicro.git
hello_worldサンプルの修正
2021年2月14日現在、pico-tflmicroのhello_worldのコードはそのままでは動かない。ビルドするとタイポに起因するエラーが発生する。pico-tflmicro/example/hello_world/rp2/output_handler.cpp
を適当なエディタで開き修正する。
- 34行目
pwm_clear_irq(pwm_gpio_to_slice(PICO_DEFAULT_LED_PIN));
pwm_clear_irq(pwm_gpio_to_slice_num(PICO_DEFAULT_LED_PIN));
- 41,42行目
reset_block(RESETS_RESET_PWM_RST_N_BITS); unreset_block_wait(RESETS_RESET_PWM_RST_N_BITS);
reset_block(RESETS_RESET_PWM_BITS); unreset_block_wait(RESETS_RESET_PWM_BITS);
- 45,47行目
// Tell the LED pin that the PWM is in charge of its value. gpio_funcsel(PICO_DEFAULT_LED_PIN, GPIO_FUNC_PWM); // Figure out which slice we just connected to the LED pin pwm_inst_t slice = pwm_gpio_to_slice(PICO_DEFAULT_LED_PIN);
// Tell the LED pin that the PWM is in charge of its value. gpio_set_function(PICO_DEFAULT_LED_PIN, GPIO_FUNC_PWM); // Figure out which slice we just connected to the LED pin uint slice = pwm_gpio_to_slice_num(PICO_DEFAULT_LED_PIN);
- 52,54行目
// Mask our slice's IRQ output into the PWM block's single interrupt line, // and register our interrupt handler pwm_clear_irq(slice); pwm_enable_irq(slice, true); irq_set_exclusive_handler(PWM_IRQ_WRAP, on_pwm_wrap); irq_enable(PWM_IRQ_WRAP, true);
// Mask our slice's IRQ output into the PWM block's single interrupt line, // and register our interrupt handler pwm_clear_irq(slice); pwm_set_irq_enabled(slice, true); irq_set_exclusive_handler(PWM_IRQ_WRAP, on_pwm_wrap); irq_set_enabled(PWM_IRQ_WRAP, true);
- 60行目
pwm_config_divider(&config, 4.f);
pwm_config_set_clkdiv(&config, 4.f);
- 85行目
エラーは出ないが、LEDの点滅速度調整のため、修正する。
sleep_ms(10);
sleep_ms(50);
hello_worldサンプルをビルド
以下のコマンドでサンプルをビルドする。
>cd pico-tflmicro >mkdir build >cd build >cmake .. >cd example/hello_world >make -j4
ビルドが終わったらRaspberry Pi picoをPCにつなぎ、hello_world.uf2をコピーする。しばらくするとRaspberry Pi picoの基板に乗っているLEDが点滅し始める。
ようこそ、データドリブンなSoftware 2.0の世界へ。
まとめ
データドリブンなLチカでは、プログラムではなくデータによってLチカの点滅パターンを定義することができる。さらに、Raspberry Pi picoはTF Lite microのデモを実行することで簡単にこのデータドリブンなLチカを体験することができる。
Lチカだけでなく、センサの値を入力としたり、出力をモータに変えてみたりと、データドリブンな処理定義はその応用範囲が広く、マイコン工作の可能性を広げてくれる。TF Lite microの使い方やそのほかの応用事例は以下の過去記事を参照して欲しい。