公開日:2024/03/30
title.png

29th Season


#29-8 ロボットカーを組み立てよう(演奏電飾)

 先日M5StickC Plusを使ってスマホからのラジオコントロールに対応したロボットカー(下図)に、遊び心を取り入れて見たいと思います。

a295_expr.jpg

 世の中、遊びが無いとギスギスとして、うまく回りませんから、大切な事だと思います。

電飾と音楽演奏機能の追加

 今回取り入れる遊び心は、音楽演奏機能と、イルミネイション(電飾)の追加です。
 まずは音楽演奏機能の使い道から検証して行きましょう。

 と、言う事で、ロボットカーにも、音楽を演奏する機能があると、上例の様な状況を模擬できて、愉快です。


 次に、電飾について考えてみましょう。
 電飾&車と言うと、デコトラ(decoration truck)等を想像しますか?今回は、そこまでの電飾はイメージしておらず、普通に自動車に備わっている、ヘッドライトやウインカ、パトランプ等の表現として、LEDを搭載しようと思います。

 まずは、ロボットカーに追加すべき周辺回路の設計を進めましょう。

追加回路の設計

 手持ち部品の中から、RGB LEDパネル、パッシブブザーを使い、また、「#29-5 ロボットカーを組み立てよう(無線操縦)」にて接続したラジオコントロール用のM5StickC Plusも含めて、以下の様な回路図となりました。

a298_schem.png

 詳しく見て行きましょう。

音楽演奏用パッシブブザー

 忘れてしまいがちなのですが、実のところ、パッシブブザー(下図)は電磁的な素子なのです。

ar37_buzzer.jpg

 このため、パッシブブザーはモータなどと同様、ON/OFFする時に逆起電力が発生します。こうした逆起電力からマイコンのI/Oポートを保護するため、データシートには推奨回路例が示されています。

  パッシブブザーの推奨回路例:

 実装面積の限られたロボットカーの制御基板(ブレッドボード)に搭載するには、1)は素子数も多く、配線も複雑なため、使い難いです。2)で1〜2[kΩ]もの抵抗を繋いでしまうと、電流が絞られて十分な音量を確保できません。と、言う事で3)を採用して見ました。
 ただし、推奨回路3)には、ダイオードを接続した場合にもダンピング抵抗が接続されていて、抵抗値については明確な記載がありません。2)と同じ抵抗値では音量が確保できないのは同じ事なので、もっと小さめの抵抗値としました。具体的な抵抗値については、各自ご判断ください。心配な方は、お手持ちのパッシブブザーの製造元にお問い合わせください。

電飾としてのRGB LEDパネル

 電飾に使ったのは、RGB LEDパネル(下図)です。

a191_rgbpnl.jpg

 WS2812Bという、シリアルRGB LEDチップが8個カスケードに接続されたモジュールです。使い方は、同じWS2812Bを搭載しているRGB LEDリングの記事でご確認ください(以下リンク、図)。

  「#11-2 円形配置RGB LED(WS2812B)を使う

a112_commu.png

 電源、GND以外は、シリアル通信線1本だけなので、適切なI/Oポートを割り当てて接続します。

WS2812Bの電源電圧

 と、ここで、RGB LEDパネルの電源電圧に問題発生です。
 WS2812Bのデータシートで確認すると、電源電圧は4.5〜5.5[V]と規定されています。つまり、5V定格なのね……。

 現在、制御用マイコン328duinoは3.3V駆動しており、WS2812Bの入力電圧規定(Vil,Vih)も厳し目に設定されているため、電圧レベルが合いません。
 実装スペースの限られたロボットカーにレベルシフタ(L/S)を配置するのも難儀な事なので、故意犯でRGB LEDパネルを3.3V駆動してみたところ、特に問題なく動作しました(1@_@;)。

 確かに、波長の短い青や緑などのLEDは順方向電圧Vfが大きめ(2〜3.3[V])なので、低電圧で明るく光らせるのは厳しいのだけど……。3.3V駆動しても特に違和感は、ありませんでした。それどころか、5V駆動ではLEDが明るすぎて扱い難かったのが、3.3Vに落としたことで、ちょうど良い明るさになって使い易くなりました。結果オ〜ライ(1^^;)v。

 理想ダイオードの場合、電圧がVfを超えない限り電流が流れないので、例えばVf=3.5VのLEDはVdd=3.3Vでは光りません。
 しかし、実在のダイオードは、Vf未満の電圧でも電流は流れ始めるので、多少暗くなりますが光ります。つまり、必ずしも「電源電圧をVf以上に上げないと光らない」って事は無いのです。

※しかも、LEDを構成するダイオードは、直接遷移型の化合物半導体(III-V属など)なので、そもそも、シリコン(Si、IV属)ダイオードの様な急峻なダイオード特性ですら、ありません。Vfより低い電圧でも、それなりに電流が流れて、光るんです。

 実際に3.3Vで駆動してみると、規定の4.5〜5.5[V]と言うのはコンサバ過ぎるのではないか?と思います。あるいは、何100個とカスケードに接続して、街路樹や建物の壁などに這わせて光らせる用途では、低電圧(3.3V等)では足りないので、コンサバになっているのかな?
 いずれにせよ、8ピクセル程のRGB LEDパネルでは全く問題なく、電源電圧が低下したことで、返って丁度良い明るさで使えるし、それに伴って消費電流量も低下するお陰で使い易くなりました。

 と、言う事で、本ページでは、RGB LEDパネルを3.3Vで駆動します(故意犯)。

※逆に、定格通りの5Vで使う場合、L/Sの挿入に加え、電流消費量が増える事による電源設計などについても、しっかり再検討してください。

ソフトウェアの設計

 続いてソフトウェアの設計を進めて行きます。

音楽演奏プログラム

 以下記事から始まって拡張してきた、MML(Music Macro Language)を使って音楽を演奏するプログラム(play_mml.ino)から、必要な関数(play_mml()関数など)をコピーしてきて、ロボットカーの制御プログラムに組み込みます。

  「#5-8 MMLで音楽を奏でる

 音階を演奏するためのPWM出力には、ATmega328の16ビットタイマ(TC1)ユニットを使っています。PWM出力のI/Oポートは、Arduino IDEの端子番号でD9(OC1A)です。
 割り込みを使って演奏していて、バックグラウンド演奏(【bgm】コマンド)も可能なので、モータなどの制御を中断したり邪魔したりせずに音楽演奏が可能です。

 ロボットカー制御プログラム(robot_car.ino)へ組み込むに当たって、以下の様なシリアルモニタコマンドで、MMLを使った音楽演奏を可能とします。

  MML演奏用シリアルモニタコマンド仕様:

 ロボットカーの制御マイコンに選択したUNO 3.3V化328duinoは、CPU動作周波数がArduino UNOの16MHzと比べて8MHzに低下していますが、パフォーマンス的には問題ないと思います。

 音楽演奏機能に関しては、必要な関数や関連するコードのコピー&ペーストで終了できました。楽チン。

WS2812B制御プログラム

 今回、前の節でリンクした記事(「#11-2 円形配置RGB LED(WS2812B)を使う」)で作成したプログラムを流用して使うことができませんでした。理由を以下にまとめます。

 ATmega328 @8MHzのC言語でプログラムして、I/Oポート直叩きで800kHzの高速通信を実現するのは無理だというのが結論となりました。

アセンブラで波形生成

 ここまで高速な通信だと、アセンブラでゴリゴリ組んでも無理かも??困ったぞ……。等と言っていても始まりません。C言語で無理なら、後はアセンブラでゴリゴリと押し進めるしか手は残っていないので、可能か否か、アセンブラプログラムの力業で試してみます。

 まず頭を整理するため、ATmega328のアセンブラ命令について簡単にまとめてみました。

 この様に、命令実行時間で調整しながら、I/Oポートを800kHzでトグルさせ、通信波形を生成しなくては、なりません。

 out命令でI/Oポートをトグルさせる以下のコードでは、1サイクル(=125ns)のHIGH幅と、1サイクル(=125ns)のLOW幅が2回繰り返されます。

  "out %[portd],%[pd3_1]\n\t"  // 1 cyc
  "out #[portd],%[pd3_0]\n\t"  // 1 cyc
  "out %[portd],%[pd3_1]\n\t"  // 1 cyc
  "out #[portd],%[pd3_0]\n\t"  // 1 cyc


 この応用で、400nsのHIGHレベル+850nsのLOWレベル、計1,250nsのPWM波形を生成するためには、以下の様なコードとなります。

  // HIGH=400ns=3.2cyc @8MHz
  "out %[portd],%[pd3_1]\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc
  // LOW=850ns=6.8[cyc] @8MHz
  "out #[portd],%[pd3_0]\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc
  "nop\n\t"  // 1 cyc


 nop命令1個当たり、F_CPU=8MHzでは1サイクル=125nsかかるので、この特徴を使って実時間を調整し、所望の波形を生成しました。要は、nop命令1個を125nsで換算し、nop命令の数で制御する方法です。
 1サイクル=125nsで量子化されるため、125nsの倍数になっていない、400nsや850nsは正確に表現することができないことには注意してください。WS2812Bの通信波形には、マージン(±150ns)が設定されているので、この範囲内に収まるように設計して行きます。

 上の例は、基本的な考え方として解説しました。実際のプログラムでは、ループを形成したり、ビット値0/1に従って、異なる波形を生成するために分岐したりする必要があるので、もっと複雑です。


 次回、上に示したアイディアを使って、実際のプログラムを実装してみたいと思います。果たして、328duino @8MHzでWS2812Bへのデータ送信が実現できるのか?


btn_arduino.png

btn_prev.png btn_next.png

home