読者です 読者をやめる 読者になる 読者になる

わしろのめも

たいした話はしません

Arduinoを用いてLEDの指数関数的な輝度の変化を観察してみる

はじめに

視覚・聴覚などの人間の感覚は線形ではなく対数的にはたらいていると言われています.例えば聴覚の場合,小さい音とすごく小さい音の音量の違いはわかりやすいのに対し,大きい音とすごく大きい音の違いはわかりにくいといった具合です.
そこで今回はそういった人間の特性を踏まえ,Arduino UNOを用いてLEDの輝度を線形的に変化させたときと指数関数的に変化させたときを比較してみます.
ここで輝度を指数関数的に変化させる理由としては,単純に人間の感覚が対数的なので,その逆関数である指数関数的な変化を与えれば見え方としては線形っぽくなるはずだよねという話です.

やってみる

書いたArduinoのコードを載せます.家に転がってた12Ωの抵抗を電流制限抵抗として適当につなぎました.出力には3番ピンを用いています.

線形変化させてみる

int ledPin = 3;
int signFlag = 0; // 0: positive, 1: negative

void setup() {
}

void loop() {
    if (signFlag == 0) {
        positiveWrite();
    } else { 
        negativeWrite();
    }   
}

void positiveWrite() {
    for (int i = 0; i < 256; i++) {
        analogWrite(ledPin, i); 
        delay(4);
    }   

    signFlag = 1;
}

void negativeWrite() {
    for (int i = 255; i >= 0; i--) {
        analogWrite(ledPin, i); 
        delay(4);
    }   

    signFlag = 0;
}

signFlagはLEDを明るくしていくか暗くしていくかを判定するためのフラグで,値に応じてpositiveWrite(), negativeWrite()が呼び出されます.あとはもうそのままです.

指数関数的に変化させてみる

#include <math.h>

#define k (255 / (exp(10) - 1))

int ledPin = 3;
int signFlag = 0; // 0: positive, 1: negative

void setup() {
}

void loop() {
    if (signFlag == 0) {
        positiveWrite();
    } else { 
        negativeWrite();
    }   
}

void positiveWrite() {
    for (float i = 0; i < 10; i = i + 0.1) {
        analogWrite(ledPin, k * (exp(i) - 1));
        delay(10);
    }

    signFlag = 1;
}

void negativeWrite() {
    for (float i = 10 ; i >= 0; i = i - 0.1) {
        analogWrite(ledPin, k * (exp(i) - 1));
        delay(10);
    }   

    signFlag = 0;
}

主なところで先ほどから変わったのはpositiveWrite(), negativeWrite()関数内のanalogWrite()による出力値です.要するに,

k(e^i-1)

という数式に対して,iを0から10まで0.1ずつ変化させています.1を引いているのはiがゼロのときに出力をゼロにするためで,kは出力の最大値を255とするための定数です.

見てみる

肝心の光り具合の観察です.まずは線形変化させたときがこちらになります.

www.youtube.com

次に指数関数的に変化させたときがこちらになります.

www.youtube.com

おわりに

感覚的なものなので主観的なところはありますが,指数関数的に変化させた時のほうが綺麗に明るさが変わったように見えたのではないのでしょうか.このように明るさがスムーズに変化するLEDが組み込まれた製品を目にしたら,「おっこだわってんな」なんて思ってもいいかもしれません.