esp-open-rtosを使ってみる

1wire通信(DS18B20)

exampleディレクトリーには、センサーやTFT/LCDを扱うための沢山のサンプルコードが含まれています。
今回は、その中からds18b20_onewireのサンプルを紹介します。
このサンプルは、1wireのDS18B20から温度とセンサーIDを取り出すサンプルです。
DS18B20と1wireで通信する部分は、extras/onewireの関数群として提供されています。
こちらも、提供されているのは関数群だけなので、ドライバータスクは自分で作る必要が有ります。
アプリケーションのタスク構成はものすごくシンプルで、1つのタスクしかありません。

DS18B20のData Input/OutputはGPIO13に接続します。
#define SENSOR_GPIO 13

サンプルコードをビルドして実行すると、以下の様に表示されます。(一部、無関係な表示は消しています)
温度とセンサーIDを表示します。
ESP-Open-SDK ver: 0.0.1 compiled @ Jan 26 2019 16:49:37
1 sensors detected:
  Sensor c004170118e8ff28 reports 17.687500 deg C (63.837502 deg F)

  Sensor c004170118e8ff28 reports 17.750000 deg C (63.950001 deg F)

  Sensor c004170118e8ff28 reports 17.750000 deg C (63.950001 deg F)

  Sensor c004170118e8ff28 reports 17.750000 deg C (63.950001 deg F)

  Sensor c004170118e8ff28 reports 17.750000 deg C (63.950001 deg F)

  Sensor c004170118e8ff28 reports 17.750000 deg C (63.950001 deg F)

  Sensor c004170118e8ff28 reports 17.750000 deg C (63.950001 deg F)

  Sensor c004170118e8ff28 reports 17.750000 deg C (63.950001 deg F)

実際の1wire通信は以下の様にGPIOをゴニョゴニョ操作しています。
static bool _onewire_write_bit(int pin, bool v) {
    if (!_onewire_wait_for_bus(pin, 10)) return false;
    if (v) {
        taskENTER_CRITICAL();
        gpio_write(pin, 0);  // drive output low
        sdk_os_delay_us(10);
        gpio_write(pin, 1);  // allow output high
        taskEXIT_CRITICAL();
        sdk_os_delay_us(55);
    } else {
        taskENTER_CRITICAL();
        gpio_write(pin, 0);  // drive output low
        sdk_os_delay_us(65);
        gpio_write(pin, 1); // allow output high
        taskEXIT_CRITICAL();
    }
    sdk_os_delay_us(1);

    return true;
}

static int _onewire_read_bit(int pin) {
    int r;

    if (!_onewire_wait_for_bus(pin, 10)) return -1;
    taskENTER_CRITICAL();
    gpio_write(pin, 0);
    sdk_os_delay_us(2);
    gpio_write(pin, 1);  // let pin float, pull up will raise
    sdk_os_delay_us(11);
    r = gpio_read(pin);  // Must sample within 15us of start
    taskEXIT_CRITICAL();
    sdk_os_delay_us(48);

    return r;
}

1wireは詳しくないのですが、GPIO経由でこれらのコマンドを投げています。
#define ONEWIRE_SELECT_ROM 0x55
#define ONEWIRE_SKIP_ROM   0xcc
#define ONEWIRE_SEARCH     0xf0



しばらく動かし続けたらstack overflowになってしまいました。
Task stack overflow (high water mark=0 name="print_temperatu")
Task stack overflow (high water mark=0 name="print_temperatu")
Task stack overflow (high water mark=0 name="print_temperatu")
  Sensor c004170118e8ff28 reports 16.812500 deg C (62.262501 deg F)

Task stack overflow (high water mark=0 name="print_temperatu")
Task stack overflow (high water mark=0 name="print_temperatu")
Task stack overflow (high water mark=0 name="print_temperatu")
  Sensor c004170118e8ff28 reports 16.812500 deg C (62.262501 deg F)

サンプルソース(ds18b20_onewire.c)の以下の部分(StackSize)を変更したら出なくなりました。
    //xTaskCreate(&print_temperature, "print_temperature", 256, NULL, 2, NULL);
    xTaskCreate(&print_temperature, "print_temperature", 512, NULL, 2, NULL);



DS18B20についてはもう一つ面白いサンプルが提供されています。
examples/ds18b20_broadcasterでは、DS18B20で測定した温度をUDPを使ってBroadcastしています。
ネットワークの処理では、lwIPのSequential-style API(Netconn API)が使われています。
examples/ds18b20_broadcaster/README.mdに書かれているPythonスクリプトをLinuxマシンで実行 してみました。
BroadCastなので、ネットワーク内のどのマシンでも受け取ることができます。


また、このサンプルでは面白いSDKのAPIが使われています。
sdk_wifi_status_led_install()
WiFi接続が確立するまでGPIO2が高速でLチカします。

こちらのサンプルも しばらく動かし続けたらstack overflowになってしまいました。
xTaskCreate()のStackSizeを256→512に変更したら出なくなりました。

続く....