FC2ブログ
2018-06-18 21:44 | カテゴリ:PIC応用回路
多数のLEDスロー点滅をテストしています。


前回までに3個のLEDスロー点滅が、なんとか実用的になるところまで来ましたので、LEDの個数を増やして、テストしています。
とりあえず、16個までの点滅にトライします。


いつも使用している「ブレッドボード」に、9個のLEDをセットしました。


(SLEDM2-01)
SLEDM2-01.jpg




続きは、、、



動作自体は、3個の時と同じような処理で行けると踏んでいるのですが、3個から9個に増えたことにより、処理時間がほぼ3倍くらいかかりますので、果たしてソフトPWMがちゃんとそれらしく見えるかがポイントです。
適当にパラメータをセットしてまずはテストです。


(9LED_Slow)


とりあえず動作しましたが、

1)動作が遅い

2)従ってPWMのチラつきが大きい(ビデオではわかりにくいですが、かなりチラついています)



という状態でした。
ビデオでは、シャッター速度の関係で、ちらつきが目立ちませんが、リアルタイムで見ると、チラチラして、実用になりません。
どうにかして、処理の速度を上げて、PWMの周期をちらつきが目立たない所まで上げなければいけません。

main関数の中の、PWM処理の部分のLOOPの中を整理して、余分な処理を無くすように検討しました。



(SLEDM06)
SLEDM06.jpg

(SLEDM07)
SLEDM07.jpg

(SLEDM08)
SLEDM08.jpg


まず、プログラムを見やすく、かつ、書きやすくするために処理の最初と最後に長い配列変数の記述を一般の変数に代入させて、それをまた、戻す作業をしていましたが、そこを配列の記述のままにしました。
MPLABXのタイマーで計測してら、この部分で数百マイクロ秒も消費していました。(びっくりです)


以下を削除

//-----------------------------------------
// 該当LEDのパラメータを変数に一旦取り込む
//-----------------------------------------
Para_a = LED_Para[LED_No][Ptrn];
Para_b = LED_Para[LED_No][Port];
Para_c = LED_Para[LED_No][Freq];
Para_d = LED_Para[LED_No][LED_ON_sts];
Para_e = LED_Para[LED_No][LED_TGT];
Para_f = LED_Para[LED_No][LED_DTY];
Para_g = LED_Para[LED_No][DTY_cnt];
Para_h = LED_Para[LED_No][Status];
Para_i = LED_Para[LED_No][Syc_cnt];
Para_j = LED_Para[LED_No][Syc_SPD];
Para_k = LED_Para[LED_No][DTY_max];
Para_m = LED_Para[LED_No][OnOff_counter];



//--- 各パラメータを配列に戻す -----------
LED_Para[LED_No][Ptrn] = Para_a;
LED_Para[LED_No][Port] = Para_b;
LED_Para[LED_No][Freq] = Para_c;
LED_Para[LED_No][LED_ON_sts] = Para_d;
LED_Para[LED_No][LED_TGT] = Para_e;
LED_Para[LED_No][LED_DTY] = Para_f;
LED_Para[LED_No][DTY_cnt] = Para_g;
LED_Para[LED_No][Status] = Para_h;
LED_Para[LED_No][Syc_cnt] = Para_i;
LED_Para[LED_No][Syc_SPD] = Para_j;
LED_Para[LED_No][DTY_max] = Para_k;
LED_Para[LED_No][OnOff_counter] = Para_m;


続いて、処理の途中で、for文を次に進める際に、 goto EXITで EXITに記述した continue 文に飛ばしている部分を
直接、 continue 文に入れ替えました


一例です。

//--- LED Duty Counter を-1する ------
Para_g = Para_g - 1;
if (Para_g > 0) {
goto Exit;  ===> continue へ変更
}

//--- 該当LEDがONかOFFかチェック ----
if (Para_d == 0) {
LED_on(LED_No); // LED on
Para_d = ON;
Para_g = Para_f;
goto Exit;  ===> continue へ変更
}
LED_off(LED_No); // LED off
Para_d = OFF;
Para_g = Para_k - Para_f;

//--- サイクルカウンター減算 -----

Para_i = Para_i - 1;
if (Para_i > 0) {
goto Exit;  ===> continue へ変更
}


その他、無駄な代入文も整理しました。

また、PWMの設定パラメータも併せて見直して、
スロー点滅が現認できるぎりぎりのPWM設定パラメータとして、PWMの分解数や、繰り返し数を何度も試行錯誤を行って、煮詰めました。


16個のLED接続設定で、このくらいのちらつきのものが

(16LED_DM30)




この程度まで改善できました。
PWMの段階は10段階まで絞りました。

(16LED_DM10)




12-13だともう少し、スロー感が出ます。
また、LEDが暗めの方が、やはりスロー感が出やすいようです。


あとは、使用者の希望するスロー感になるようにパラメータを調節していただければと思います。
下記を参考にしていただいて、使用するLEDの個数分の設定パラメータを配列に定義して、コンパイルしてください。
もちろん、プログラム中で随時パラメータを変更しつつ実行してもだいじょうぶです。

また、下記のSP、SKなどのパラメータはテスト時に多数のLED用に個別に設定するのが面倒なので、一括して変数で指定していますが、すべてのLEDについて個別に指定する事が出来ますので、配列を直接設定してください。



//----------------------------------------------------------------------------
// 以下LED点滅時のパラメータを初期化
//----------------------------------------------------------------------------
//
//------- LEDの数が16個の場合のおすすめ設定 -------------------------------------
Max_LED_No = 15; // 接続するLED数-1を設定する
SP = 0; //Dutyカウントを何回したらDutyを変化させるかの指定。大きくするとゆっくりに。
SK = 1; // 基本的な点滅の周期の設定(RAND点滅も含む)1以上にすると処理が遅くなる
DM = 10; // Dutyの最大カウント。大きくするとゆっくり変化するが、大きすぎると表示が乱れる
SYC = 10; // カウントをまとめて処理する回数。DMと同じにすると、OFF->ON、ON->OFFが同期する
// 完全に点灯する前に次の消灯のタイミングになり、LEDが暗くなることがある。
// 特にシリアル点滅の時
//----------------------------------------------------------------------------

//------- LEDの数が9個の場合のおすすめ設定 -------------------------------------
//Max_LED_No = 8; // 接続するLED数-1を設定する
//SP = 0; //Dutyカウントを何回したらDutyを変化させるかの指定。大きくするとゆっくりに。
//SK = 1; // 基本的な点滅の周期の設定(RAND点滅も含む)1以上にすると処理が遅くなる
//DM = 30; // Dutyの最大カウント。大きくするとゆっくり変化するが、大きすぎると表示が乱れる
//SYC = 30; // カウントをまとめて処理する回数。DMと同じにすると、OFF->ON、ON->OFFが同期する
// 完全に点灯する前に次の消灯のタイミングになり、LEDが暗くなることがある。
// 特にシリアル点滅の時
//----------------------------------------------------------------------------

//------- LEDの数が16個で少しゆっくりする場合のおすすめ設定 -------------------------------------
//Max_LED_No = 15; // 接続するLED数-1を設定する
//SP = 0; //Dutyカウントを何回したらDutyを変化させるかの指定。大きくするとゆっくりに。
//SK = 1; // 基本的な点滅の周期の設定(RAND点滅も含む)1以上にすると処理が遅くなる
//DM = 13; // Dutyの最大カウント。大きくするとゆっくり変化するが、大きすぎると表示が乱れる
//SYC = 13; // カウントをまとめて処理する回数。DMと同じにすると、OFF->ON、ON->OFFが同期する
// 完全に点灯する前に次の消灯のタイミングになり、LEDが暗くなることがある。
// 特にシリアル点滅の時
//----------------------------------------------------------------------------


LED_Para[LED_No][Ptrn] = 999;// 注意 999は適当な数字をセットしてください
LED_Para[LED_No][Port] = 999;
LED_Para[LED_No][Freq] = 999;
LED_Para[LED_No][LED_ON_sts] = 999;
LED_Para[LED_No][LED_TGT] = 999;
LED_Para[LED_No][LED_DTY] = 999;
LED_Para[LED_No][DTY_cnt] = 999;
LED_Para[LED_No][Status] = 999;
LED_Para[LED_No][Syc_cnt] = 999;
LED_Para[LED_No][Syc_SPD] = 999;
LED_Para[LED_No][DTY_max] = 999;
LED_Para[LED_No][OnOff_counter] = 999;

最後に今回のソースを上げておきます。(main関数部分です)
他のPICを使用される場合は、クロックやPINの入出力設定を main関数 に追加してください。


PICは、16F18857です。
クロックは、内部発振で、32MHz

RA0-RA5 = 出力設定
RB0-RB7 = 出力設定
RC0-RC7 = 出力設定

RA6-RA7 = 入力設定(SWなどを各自設定ください)

他のPICを使用される場合は、クロックやPINの入出力設定を main関数 に追加してください。


下記はGoogleのマイドライブで、MPLABXのプロジェクトフォルダー形式の圧縮になっています。
ダウンロードして解凍すれば、MPLABXで読み込めると思います。

LED_Manager_Slow_Blink13.zip

https://drive.google.com/open?id=1wP6Vdm_5ZCdAXg1NIitATO5ua6h83YAB


素人工作なので課題は山ほどありますが、割り込みを使用できなかった以上に、ソフトでのPWMで15個のLEDをスロー点滅させるには、32MHzのPICでは、力不足ということでしょうね。

おしまい!

関連記事

管理者のみに表示する