ちょっと上いくLフワの作り方

  • 3
    いいね
  • 0
    コメント

少し上質なLフワ(LEDフワフワ)をやってみよう!、という記事です。
あるはずのmbed LPC1768が見当たらないのでmbed LPC1114FN28を使います。

ファームウェアをアップデート

無用なトラブルを避けるために、mbed LPC1114FN28を使う前にインターフェースのファームウェアをアップデートしておきましょう。
ファームウェアと手順はこちらです。

2016年8月に新しいファームウェアが出ています。
継続的に更新されていて、ありがたい。

Lフワ

LEDと(電流制限)抵抗を接続します。
PWMで明るさを変化させるので、"PwmOut"のピンに接続しなければいけません。今回は、dp18に接続します。

image.png

プログラムは、100ミリ秒毎に1%ずつON時間を増やして、(10秒経過して)100%になると0%になって、またON時間を増やすようにしました。

経過時間[秒] PWM出力値
0.0 0.00
0.1 0.01
0.2 0.02
0.3 0.03
... ...
10.0 1.00
10.1 0.00
10.2 0.01
... ...
main.cpp
#include "mbed.h"

PwmOut Led(dp18);

int main()
{
    for(;;) {
        for (int i = 0; i <= 100; i++) {
            Led = (float)i / 100;
            wait_ms(100);
        }
    }
}

実行!

image.png

うん、フワフワと...していますが...
Lチカとは明らかに違うものの、「ふわっ」という感じではなく、「ドカンッ」という感じの点灯具合です。(汗

さらに、デジカメで撮影すると、
Lフワ動画①
LEDが点滅して見えてしまいます。orz
これでは、せっかくのLフワもtwitter/Facebookで自慢が出来ないではありませんか!

問題点は以下の2つ。

  • 「ドカンッ」と点灯してしまう
  • デジカメで上手く撮影できない

デジカメで撮影できるように

デジカメで上手く撮影できないのは、シャッタースピードと比べて、PWM周期が遅かったり、近いのが原因です。デフォルトのPWM周期は、PwmOutの説明に書かれていました。

The default period is 0.020s, and the default pulsewidth is 0.

どれくらい速くすれば良いのか分からないので、適当に10マイクロ秒にして、デジカメで撮影してみます。

main.cpp
#include "mbed.h"

PwmOut Led(dp18);

int main()
{
    Led.period_us(10);  // PWM周期を10マイクロ秒に設定

    for(;;) {
        for (int i = 0; i <= 100; i++) {
            Led = (float)i / 100;
            wait_ms(100);
        }
    }
}

Lフワ動画②

デジカメで撮影できるようになりました(^O^)/

点灯具合を調整できるように

つぎは「ドカンッ」です。
明るさとON時間の関係を数式で表現するのは難しそうなので、調整できるようにすることで対処します。

明るさに対応するON時間の表を用意します。
Excelでデータを作って、サクラエディタにコピペして、キーボードマクロでC言語の配列に加工しました。

image.png

main.cpp
#include "mbed.h"

const float LedMap[] = {
    0.0000, 0.0001, 0.0004, 0.0009, 0.0016, 0.0025, 0.0036, 0.0049, 0.0064, 0.0081,
    0.0100, 0.0121, 0.0144, 0.0169, 0.0196, 0.0225, 0.0256, 0.0289, 0.0324, 0.0361,
    0.0400, 0.0441, 0.0484, 0.0529, 0.0576, 0.0625, 0.0676, 0.0729, 0.0784, 0.0841,
    0.0900, 0.0961, 0.1024, 0.1089, 0.1156, 0.1225, 0.1296, 0.1369, 0.1444, 0.1521,
    0.1600, 0.1681, 0.1764, 0.1849, 0.1936, 0.2025, 0.2116, 0.2209, 0.2304, 0.2401,
    0.2500, 0.2601, 0.2704, 0.2809, 0.2916, 0.3025, 0.3136, 0.3249, 0.3364, 0.3481,
    0.3600, 0.3721, 0.3844, 0.3969, 0.4096, 0.4225, 0.4356, 0.4489, 0.4624, 0.4761,
    0.4900, 0.5041, 0.5184, 0.5329, 0.5476, 0.5625, 0.5776, 0.5929, 0.6084, 0.6241,
    0.6400, 0.6561, 0.6724, 0.6889, 0.7056, 0.7225, 0.7396, 0.7569, 0.7744, 0.7921,
    0.8100, 0.8281, 0.8464, 0.8649, 0.8836, 0.9025, 0.9216, 0.9409, 0.9604, 0.9801,
    1.0000,
};


PwmOut Led(dp18);

int main()
{
    Led.period_us(10);  // PWM周期を10マイクロ秒に設定

    for(;;) {
        for (int i = 0; i < sizeof (LedMap) / sizeof (LedMap[0]); i++) {
            Led = LedMap[i];
            wait_ms(100);
        }
    }
}

Lフワ動画③

まだ今一つな感じもしますが、これで点灯具合が調整できるようになりました。
ただ、光り初めのときがスムーズに明るくなっていません。ガタガタしている感じがします。

ガタガタをスムーズに

どうやら、PWM周期を短くし過ぎて、分解能が不足しているようです。
10マイクロ秒を1ミリ秒に変更してみます。

main.cppの一部
    Led.period_us(1000);  // PWM周期を1ミリ秒に設定

Lフワ動画④

消えるときもフワッと

これは説明不要ですね♪

main.cpp
#include "mbed.h"

const float LedMap[] = {
    0.0000, 0.0001, 0.0004, 0.0009, 0.0016, 0.0025, 0.0036, 0.0049, 0.0064, 0.0081,
    0.0100, 0.0121, 0.0144, 0.0169, 0.0196, 0.0225, 0.0256, 0.0289, 0.0324, 0.0361,
    0.0400, 0.0441, 0.0484, 0.0529, 0.0576, 0.0625, 0.0676, 0.0729, 0.0784, 0.0841,
    0.0900, 0.0961, 0.1024, 0.1089, 0.1156, 0.1225, 0.1296, 0.1369, 0.1444, 0.1521,
    0.1600, 0.1681, 0.1764, 0.1849, 0.1936, 0.2025, 0.2116, 0.2209, 0.2304, 0.2401,
    0.2500, 0.2601, 0.2704, 0.2809, 0.2916, 0.3025, 0.3136, 0.3249, 0.3364, 0.3481,
    0.3600, 0.3721, 0.3844, 0.3969, 0.4096, 0.4225, 0.4356, 0.4489, 0.4624, 0.4761,
    0.4900, 0.5041, 0.5184, 0.5329, 0.5476, 0.5625, 0.5776, 0.5929, 0.6084, 0.6241,
    0.6400, 0.6561, 0.6724, 0.6889, 0.7056, 0.7225, 0.7396, 0.7569, 0.7744, 0.7921,
    0.8100, 0.8281, 0.8464, 0.8649, 0.8836, 0.9025, 0.9216, 0.9409, 0.9604, 0.9801,
    1.0000,
};

#define LedMapNumber    (sizeof (LedMap) / sizeof (LedMap[0]))

PwmOut Led(dp18);

int main()
{
    Led.period_us(1000);

    for(;;) {
        for (int i = 0; i < LedMapNumber; i++) {
            Led = LedMap[i];
            wait_ms(10);
        }
        for (int i = LedMapNumber - 1; i >= 0; i--) {
            Led = LedMap[i];
            wait_ms(10);
        }
        wait_ms(1000);
    }
}

Lフワ動画⑤

まとめ

  • 綺麗に撮影できるよう、PWM周期(PwmOut.period_us())を設定しましょう。
  • 明るさとON時間の対応を調整しましょう。

おまけ

PWMの最小分解能はいくつなんだろう?
PWM周期10usec.のLフワを、ロジアナで測定して確認しました。

image.png

image.png

だいたい、0.7usec.でした。