HX711 の準備完了時間、mbed OS5 での thread

HX711 では、データ出力準備が整ったら、DOUTが HIGH -> LOW になる。この出力時間の待ち受け時間を計ったところ、約77msかかる。メインループで待ち受けすると77msは割と支配的でUIのレスポンスに悪化に繋がる。

AVR の Arduino なら Timer のハードウェア割り込みを使って、メインループとは別のところで処理しつつ、適当な volatile 変数に値を入れるような実装を書くと思う。

mbed OS 5 の場合

mbed は指定時間ごとに関数を呼び出せる Ticker クラスが用意されているが、割り込みハンドラは全部合わせて1つなので、Ticker に重い処理を登録すると遅延が発生する。

mbed OS5 では rtos になったので、この辺の優先度付けが出来るのかと思ったら現状特に出来ないので、Thread を使ってメインループ以外で実行し続けることで解決してみた。

例えばこんな感じ。

#include <mbed.h>
#include "HX711.hpp"

class ScaleGauge {
    HX711 *_p_scale;
    Thread _thread;
    volatile float _gram;

    void threadLoop() {
        while(1) {
            _gram = _p_scale->readGram(1);
        }
    }
public:
    ScaleGauge(HX711 *hx711) :
        _p_scale(hx711), _thread(osPriorityLow) {
    }

    void start() {
        _thread.start(callback(this, &ScaleGauge::threadLoop));
    }

    float getGram() {
        return _gram;
    }
};

あとは main で

int main() {
    ScaleGauge sg(&hx711);
    sg.start();

    while(1) { wait_ms(100) };
}

とすれば、ずっと裏側で値をとり続ける。

最初

int main() {
    ScaleGauge sg(&hx711);
    sg.start();

    while(1);
}

としててうまく動かない (threadLoop がよばれない) けど、理由は Thread の優先度をosPriorityLow にしていたからで、その場合 while(1) が延々と呼び出されてしまう。osPriorityNormal の標準プライオリティにするか、わざと割り込みできるように wait_ms() 等を入れるか、yield で処理を戻すか等々をする必要がある。

あわせてよみたい:

追記:

 Thread::wait(osWaitForever);

で待ち受ければ良いぽい。