Raspberry Pi Pico でバーサライタ製作 (C/C++) ーRaspberry Pi Picoへの道6ー
前回はフォトリフレクタによる割り込みでLED制御を試しました。
今回はついにRaspberry Pi Pico でバーサライタを製作しました。
目次
バーサライタ構成
構成はこれまで製作してきたハンディーバーサライタ PovRanianと同様です。
モータを安定化電源(1V)で給電して回転部を回します。回転部には24セルのLEDのほかに回転を検出するフォトリフレクタとRaspberry Pi Picoが載っており、給電にはワイヤレスチャージモジュールを使用しています。
フォトリフレクタとRaspberry Pi Pico間にはチャタ防止にフィルタとシュミットトリガを挿入しています。
部品
- Raspberry Pi Pico
- SPI 入力LEDテープ
- フォトリフレクタ QTR-1A
- シュミットトリガ
- ワイヤレスチャージモジュール
- マブチモーター RS-540SH
バーサライタ分解能
Raspberry Pi Pico によるバーサライタができましたので、1周の分割数をどれほど大きくできるか試してみます。
これによりRaspberry Pi Pico の実力を測れるのではないかと考えました。
Cコード
フォトリフレクタで1周の時間を計測し、その時間を変数Divで分割して色分け(RGBYの4色)してLEDを点灯させるプログラムをです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
#include <stdio.h> #include "pico/stdlib.h" #include "hardware/pio.h" #include "apa102.pio.h" #define PIN_CLK 2 #define PIN_DIN 3 #define N_LEDS 24 #define Div 4 #define SERIAL_FREQ (30 * 1000 * 1000) // Global brightness value 0->31 #define BRIGHTNESS 3 uint32_t color[] ={ 0xFF0000, 0x00FF00, 0x0000FF, 0x00FFFF }; unsigned long rotTime, timeOld, timeNow; int numRot = 0; int stateDiv = 0; int numDiv = 0; int num = 0; void gpio_callback() { timeNow = time_us_64(); rotTime = timeNow - timeOld; timeOld = timeNow; numRot++; if(numRot >= Div ) numRot = 0; } void put_start_frame(PIO pio, uint sm) { pio_sm_put_blocking(pio, sm, 0u); } void put_end_frame(PIO pio, uint sm) { pio_sm_put_blocking(pio, sm, ~0u); } void put_bgr888(PIO pio, uint sm, uint32_t c) { pio_sm_put_blocking(pio, sm, 0x7 << 29 | // magic (BRIGHTNESS & 0x1f) << 24 | // global brightness parameter c ); } int main() { stdio_init_all(); gpio_set_irq_enabled_with_callback(22, GPIO_IRQ_EDGE_RISE, true, &gpio_callback); PIO pio = pio0; uint sm = 0; uint offset = pio_add_program(pio, &apa102_mini_program); apa102_mini_program_init(pio, sm, offset, SERIAL_FREQ, PIN_CLK, PIN_DIN); while (true) { if(stateDiv == 1 && time_us_64() - timeOld > rotTime / Div * (numDiv)){ stateDiv = 0; } if(stateDiv == 0 && time_us_64() - timeOld < rotTime / Div * (numDiv + 1)){ stateDiv = 1; put_start_frame(pio, sm); for (int i = 0; i < N_LEDS; ++i) { put_bgr888(pio, sm, color[num]); } put_end_frame(pio, sm); numDiv++; if(numDiv >= Div ) numDiv = 0; num++; if(num > 3 ) num = 0; } } } |
4分割
まずは Div = 4で動作確認しました。
Raspberry Pi Pico でバーサライタ
とりあえず1周 4分割これからどんどん分割数をあげて
Raspberry Pi Pico の性能を体で感じたい。実感として
SPIクロックもどれほど上げれるのかも感じたい#RaspberryPiPico #パイピコ #PiPico pic.twitter.com/4qm4RACBhO— HomeMadeGarbage (@H0meMadeGarbage) February 12, 2021
400分割
Div = 400 まで増加させても問題なく点灯動作を確認できました。
SPIのクロックSERIAL_FREQ は30MHzとしました。これ以上大きくするとLED表示が正常に実施されませんでした。
いきなり1周400分割いけた。
回転数は750~800 rpm
SPIクロック 30 MHz
クロックはこれ以上にすると点灯がおかしくなる。
おそらくLED側の制約か?まだマルチコアとかやってないのにこの分割数は凄いような。
とにかくPIOが何してるかわからないので断定的なことが言えない。#RaspberryPiPico pic.twitter.com/v1hhpaQDWA
— HomeMadeGarbage (@H0meMadeGarbage) February 12, 2021
Raspberry Pi PicoのIO は非常に高速に動作できるのだと実感できました。
画像表示
このままRGBYの4色で分割数上げてもよくわからなくなってきたのでアニメ画を表示してみます。
回転速度 960rpmで1周1000分割でも余裕でアニメ表示ができました!!
回転方向の分解能が大きくてもLEDが24セルですので少し寂しいですね 🙄
性能指数
これまでいろいろなマイコンでバーサライタを製作してきましたので、独自の性能指数を設けております。
性能指数 [hPOV(ヘクトポブ)] = LED数 × 回転数 × 一周の分解能 ÷ 100
現状 Raspberry Pi Picoの性能指数は
LED 24個 × 回転速度 960rpm × 1000分解能 ÷ 100 = 230,400 hPOV
となりました。
以下が過去のその他マイコンの実績値ですので、Raspberry Pi Picoの性能がうかがい知れます。
- Teensy 4.0:LED 64個 × 回転速度 530rpm × 200分解能 ÷ 100 = 67,840 hPOV
- ESP32(デュアルコア):LED 58個 × 回転速度 730rpm × 220分解能 ÷ 100 = 93,148 hPOV
- SPRESENSE(3コア):LED 57個 × 回転速度 730rpm × 400分解能 ÷ 100 = 166,440 hPOV
おわりに
Raspberry Pi Pico によって信じられないほど回転方向の分解能の高いバーサライタ動作を確認することができました。
今後はLEDのセル数を増やすべくSPIの複数出力やマルチコア動作を検討したいと思います。
それでは次の道でお会いしましょう!
次の記事
Raspberry Pi Pico バーサライタ解像度向上 (C/マルチコア) ーRaspberry Pi Picoへの道7ー