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

少し上質なLフワ（LEDフワフワ）をやってみよう！、という記事です。
~~あるはずのmbed LPC1768が見当たらないので~~[mbed LPC1114FN28](https://www.switch-science.com/catalog/1714/)を使います。

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

無用なトラブルを避けるために、mbed LPC1114FN28を使う前にインターフェースのファームウェアをアップデートしておきましょう。
ファームウェアと手順は[こちら](https://developer.mbed.org/teams/Switch-Science/wiki/Firmware-LPC1114FN28)です。
> 2016年8月に新しいファームウェアが出ています。
> 継続的に更新されていて、ありがたい。

#Lフワ

LEDと(電流制限)抵抗を接続します。
[PWM](http://toshiba.semicon-storage.com/jp/design-support/e-learning/brushless_motor/chap3/1274512.html)で明るさを変化させるので、"PwmOut"のピンに接続しなければいけません。今回は、dp18に接続します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/77cd0359-2a54-7685-2fbf-98be5f722a75.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|
|...|...|

```cpp: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](https://qiita-image-store.s3.amazonaws.com/0/109634/f6d17327-8b81-b17c-53ca-166ac87052e8.png)


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

さらに、デジカメで撮影すると、
[Lフワ動画①](https://drive.google.com/open?id=0Bw7FgCy5HgpFeTRiSjlWeER5MUE)
LEDが**点滅して見えて**しまいます。orz
これでは、せっかくのLフワもtwitter/Facebookで自慢が出来ないではありませんか！

問題点は以下の2つ。

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

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

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

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

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

```cpp: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フワ動画②](https://drive.google.com/open?id=0Bw7FgCy5HgpFRDYzYmVFaXdDdms)

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

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

つぎは「ドカンッ」です。
明るさとON時間の関係を数式で表現するのは[難しそう](http://www.marutsu.co.jp/pc/static/large_order/led_terms)なので、調整できるようにすることで対処します。

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/bbc85955-3bf0-7317-800c-44501cc2d6c2.png)

```cpp: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フワ動画③](https://drive.google.com/open?id=0Bw7FgCy5HgpFNk5ob3IwYURDQzg)

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

#ガタガタをスムーズに

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

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

[Lフワ動画④](https://drive.google.com/open?id=0Bw7FgCy5HgpFQ2Nya0twaDhDYjA)

#消えるときもフワッと

これは説明不要ですね♪

```cpp: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フワ動画⑤](https://drive.google.com/open?id=0Bw7FgCy5HgpFdTJVMTRqdl9RTkE)

#まとめ

* 綺麗に撮影できるよう、PWM周期([PwmOut.period_us()](https://developer.mbed.org/users/mbed_official/code/mbed/docs/faff56e089b2/group__drivers.html#ga2561e8891d8585134d870680c133dbb0))を設定しましょう。
* 明るさとON時間の対応を調整しましょう。

#おまけ

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/a0161676-5540-ee49-8cd2-88adf62cafa6.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/9a9eabef-10d2-32f5-9ad8-2a3ae05c3ddd.png)

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