SNSへはこちら

ESP8266でベアメタル(9) - PWM(その2)

前回の続きです。前回は PWM をやりましたが、今回は疑問点を考え、SDK で実験をしてみたという回です。

PWMを無効化する方法

どうやらPWMは一度設定したら無効化できないっぽいです。ESP8266 の SDK を見ても、pwm_disablepwm_deinit という無効化関数は見当たりませんね。PWM は前述の通り、HW タイマーを使っていますが、コールバック関数の登録を無効化するhw_timer_set_func(NULL)でもなぜか無効化出来ませんでした。。。

一応 pwm_init(0, NULL, 0, NULL) で無効化出来るっぽいのですが(普通にその後 GPIO の制御が効く)、その後に再度有効化しようとするとどうも上手く動いてくれません。恐らく SDK の内部変数と実際のマイコンの状態が合っていないんでしょう(憶測)。

ということで、PWM は一度設定したら無効化するようなことを意図していないということが判明しました。なので無効化する動作はしないほうが良いと思われます。

PWM設定関数の挙動

不明。pwm_start() もしくは pwm_set_duty は OS タイマ関数上で1回しか読んじゃいけないらしい。PWM 波形が1周期出るまでに二度目に呼ぶと無視されるようです。以下のようなコードで動かしました。

static os_timer_t os_timer;
static void os_timer_cb(void *arg) { // {{{
    {
        static uint32 count = 0;
        count += 22222 * 10 / 100; // incr by 10%
        if( count >= 22222 ) count = 0;
        pwm_set_duty(count, 0);
        pwm_start();
    }

    struct ip_info info;
    wifi_get_ip_info(STATION_IF, &info);
    if( wifi_station_get_connect_status() == STATION_GOT_IP ) {
        ...

        os_printf("GOT an IP address!\r\n");
        pwm_set_duty(22222, 0);
        pwm_start();

        ...
        os_timer_disarm(&os_timer); // Now os timer is not needed.
    }
} // }}}

OS タイマー割り込み時、上部のブロックで pwm_start を呼びますが、if 分の条件を満たすと下のブロックで再度呼ばれます。その時、pwm_set_duty に渡している値が異なりますね。この if 文の条件を満たすときに呼ぶと、上の条件が適用されます。1回目のコールではタイミング的に暗くなり、2回目のコールでは duty が 100% になるはずなんですが、実際に適用されるのは 1回目の暗い光でした。