google-site-verification: google3bd66dd162ef54c7.html
fc2ブログ

チャーリープレクシングでクリスマスツリー用LEDイルミネーションを作る(ダイナミック点灯プログラムの作成)

◆まえがき
Arduinoでクリスマスツリー用LEDイルミネーションを作る話の続きです。前回の記事で回路図が出来たので、今回は点灯させたいLEDを簡単に指定出来るようにします。LEDの数が多いので、このような場合はダイナミックに点灯させるのが定石です。

具体的には、配列に点灯パターンをセットするだけで、その通りにLEDを点灯させるプログラムを作ります。

◆テストに使用した回路
・外観
LEDを仮付けしてテスト
手持ちの白色LEDをかき集め、6段にしました。

・回路図(図をクリックで別窓に拡大図)
Arduinoでクリスマスツリーイルミネーションの回路図
ポートをまたいだ物を作っておいた方が、後で拡張したくなった時に楽なので、D2からD8までを使いました。使ったポートは合計7つで、LEDの数は42個になります。なお、この図はLED面から見た図なので、配線する時は左右逆に配線します。

・裏面
仮配線
仮配線なのでLEDの足は切らないで使っています。

・先端の緑色LED
てっぺんの緑のLEDにはダイオードを入れた
てっぺんのLEDを緑色にしたので、Vfをできるだけ揃えるためにここだけダイオードを直列に入れています。チャーリープレクシングでは狙った場所以外のLEDを2個以上通過するパスが発生し、電圧によってはそのLEDがうっすらと光ることがあります。緑色LEDのVfは白色LEDより低いので、そのような問題が起こらないための対策です。

◆駆動ソフト
1. 動作確認(配線確認)用ソフト
最終的にはLEDをダイナミック点灯させますが、誤配線や部品の不良があるとその位置を特定するのが難しくなります。そんなことで、ポートを一つづつ駆動してスタティックに点灯させるプログラムで確認を行いました。

スタティック駆動プログラム:20201205_TrianglePlexingTest-1.txt

ポートを一つづつHighにし、その時にLEDを点灯さるポートにはLowを出力、点灯させないポートは入力に設定するようになっています。ポートは7個あるので順番にLEDを点灯させていきます。なお、点灯させるLEDの位置は、配列のpM[ ] を使ったビットマップで指定するようになっています。

ここがチャーリープレクシングの駆動プログラムのキモなので、例を使って詳しく説明しておきます。以下はポートのD4に対する処理ルーチンを抜き出したものです。
void d4High() {                   // D4ポートからHighを出力し、指定のLEDを点灯
ledOff(); // LEDポートを初期化(入力でLowに設定)
if ( pM[5] & 0b0000000000100000 ) DDRD |= B00000100; // 該当ビットを出力にアサイン
if ( pM[4] & 0b0000000000010000 ) DDRD |= B00001000;
if ( pM[3] & 0b0000000000010000 ) DDRD |= B00100000;
if ( pM[3] & 0b0000000001000000 ) DDRD |= B01000000;
if ( pM[3] & 0b0000000100000000 ) DDRD |= B10000000;
if ( pM[3] & 0b0000010000000000 ) DDRB |= B00000001; // ここからBポート
DDRD |= B00010000; // D4を出力にアサイン
PORTD |= B00010000; // D4をHigh(これでLEDが光る)
}

void ledOff() { // 全LED消灯(LED接続ピンを全て入力/Lowに設定)
PORTD &= B00000011; // D2-7をLOW
PORTB &= B11111110; // D8をLOW
DDRD &= B00000010; // D2-7を入力にアサイン
DDRB &= B11111110; // D8を入力にアサイン
}
D4をHighにした時に、点灯させたいLEDを指定するポート( = Lowを出力するポート)を If 文でパターンメモリー( pM[ ] )から選択するようになっています。

このプログラムを通過する時に点灯するLEDを回路図で示すと次のようになります。

駆動ピンとLEDの関係
D4にプラスの電圧をかけた場合、赤丸の位置のLEDを点灯あるいは非点灯させることになります。

2. ダイナミック点灯確認ソフト
ここまで出来たら、次はLEDをダイナミック点灯させます。やり方はいろいろありますが、MsTimer2を使ったタイマー割り込みでやって見ました。2ms周期でタイマー割り込みを掛け、ポートを一つづつスキャン。ポートは7個あるので、14msで1回分のスキャンを完了することになります。つまり、1つのLEDに着目すると、1秒間に約71回点滅していることになります。

ダイナミック点灯のテストプログラム 20201205_TrianglePlexingTest-2.txt

せっかくなので、簡単に出来るイルミネーションの事例として、水平線、垂直線、斜め線の移動と、徐々に明るさを変化させるプログラムを入れてみました。明るさの変化は、ダイナミック点灯の点灯時間を変えることで実現しています。

◆動画
スタティック駆動のテスト(Test-1)と、ダイナミック駆動のテスト(Test-2)を実行している様子です。


◆まとめ
これで準備は出来たので、次の作業はクリスマスツリーに取り付けられるようなハード作りです。ただ、AliExpress に発注している白色のLEDがまだ届いていません。ということで、続きはそのLEDが届いてから始めることになります。たぶんあと1週間はかかりそうな感じです。

◆プログラムで気になる点
プログラムの中で16ビットの二進数を、0b0000000000100000 と書いていますが、これはArduinoのリファレンスには書かれていない表現方法なので将来問題が起こるかも知れません。

Arduinoで二進数の定数を表現したい場合は、B10101010 と書くのが正しい作法です。ただ、最大8ビットまでなので、16ビットの定数は表現できません。どうしてもやりたい場合、リファレンスによると (B11001100 * 256) + B10101010 と書くのだそうですが、これって実行速度が遅くなりそうだしスマートではありません。

あと、割り込み処理ルーチンの中 delayMicroseconds( ); とやっていますが、これが何か副作用、例えばタイマーの誤差の原因にならないかちょっと心配です。まあ、クリスマスツリーならタイマーが多少狂っても問題は無いのですが、、
関連記事

コメントの投稿

管理者にだけ表示を許可する

タイマー割り込みでLEDのダイナミック点灯

タイマー2を使った例です。
http://igarage.cocolog-nifty.com/blog/2020/12/post-4c28b8.html

割り込み内で「delayMicroseconds」が気になるということで、これを回避する手段です。

re:タイマー割り込みでLEDのダイナミック点灯

アドバイスありがとうございます。

なるほど、タイマー2にはこんな機能があるんですね。早速やってみます。

今の私のやり方、つまりdelayMicroseconds()を使う方法だと、LEDを明るくするためには割り込みルーチンの中にいる時間が長くなってしまって良くないですよね。
カレンダー
02 | 2024/03 | 04
- - - - - 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 - - - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。
記事の内容のご利用は読者の自己責任でお願いします。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード