(4)Blinkサンプル

別の例題サンプルに ”Blink” というものが有りました。今回はこのサンプルを見て行きます。

blink サンプル

先ずはサンプルを ~/esp フォルダーにコピーします。ターミナルで以下を実行


G500:~$ cd esp
G500:~/esp$ cp -r $IDF_PATH/examples/get-started/blink .
@G500:~/esp$ 

コピーされた ”blink” フォルダーを見ると以下の構成になっていました。


~/esp/
    --blink/
       --CMakeLists.txt
       --README.md
       --example_test.py
       --sdkconfig.ci
       --sdkconfig.defaults
       --main/
             --blink_example_main.c
             --CMakeLists.txt
             --Kconfig.projbuild

各ファイルの中身

  • blink フォルダー直下
    • CMakeLists.txt
      • # The following five lines of boilerplate have to be in your project's
        # CMakeLists in this exact order for cmake to work correctly
        cmake_minimum_required(VERSION 3.5)
        
        set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/led_strip)
        
        include($ENV{IDF_PATH}/tools/cmake/project.cmake)
        project(blink)
      • 前回の、”Hello_World”の時と比べ5行目に、”set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/led_strip)”が追加されています。
      • この指定でコンパイル時にこのフォルダーが追加参照されます。
    • READ.md
      • このサンプルの説明
    • example_test.py
      • 何かプログラムが書いて有りましたが、どこで使用されるか分かりません。
    • sdkconfig.ci
      • 空のファイル
    • sdkconfig.defaults
      • “#”が一個
    • main フォルダーの直下
      • blink_example_main.c
        • 今回のメインプログラム。後で内容確認します。
      • CMakeLists.txt
        •  idf_component_register(SRCS "blink_example_main.c"
                              INCLUDE_DIRS ".")
        • 内容的には、”Hello_world” と同じ
      • Kconfig.projbuild
        • menu "Example Configuration"
          
              choice BLINK_LED
                  prompt "Blink LED type"
                  default BLINK_LED_GPIO if IDF_TARGET_ESP32
                  default BLINK_LED_RMT
                  help
                      Defines the default peripheral for blink example
          
                  config BLINK_LED_GPIO
                      bool "GPIO"
                  config BLINK_LED_RMT
                      bool "RMT - Addressable LED"
              endchoice
          
              config BLINK_LED_RMT_CHANNEL
                  depends on BLINK_LED_RMT
                  int "RMT Channel"
                  range 0 7
                  default 0
                  help
                      Set the RMT peripheral channel.
                      ESP32 RMT channel from 0 to 7
                      ESP32-S2 RMT channel from 0 to 3
                      ESP32-S3 RMT channel from 0 to 3
                      ESP32-C3 RMT channel from 0 to 1
          
              config BLINK_GPIO
                  int "Blink GPIO number"
                  range 0 48
                  default 8 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32H2
                  default 18 if IDF_TARGET_ESP32S2
                  default 48 if IDF_TARGET_ESP32S3
                  default 5
                  help
                      GPIO number (IOxx) to blink on and off or the RMT signal for the addressable LED.
                      Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
          
              config BLINK_PERIOD
                  int "Blink period in ms"
                  range 10 3600000
                  default 1000
                  help
                      Define the blinking period in milliseconds.
          
          endmenu
        • このファイル初登場です。menuconfigで表示される設定項目をこのファイルで追加出来る様です。色んな定数を設定していますが詳細は分かりません。とりあえず進みます。

下記は”blink_example_main.c”。

blink_example_main.c

/* Blink Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "led_strip.h"
#include "sdkconfig.h"

static const char *TAG = "example";

/* Use project configuration menu (idf.py menuconfig) to choose the GPIO to blink,
   or you can edit the following line and set a number here.
*/
#define BLINK_GPIO CONFIG_BLINK_GPIO

static uint8_t s_led_state = 0;

#ifdef CONFIG_BLINK_LED_RMT
static led_strip_t *pStrip_a;

static void blink_led(void)
{
    /* If the addressable LED is enabled */
    if (s_led_state) {
        /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
        pStrip_a->set_pixel(pStrip_a, 0, 16, 16, 16);
        /* Refresh the strip to send data */
        pStrip_a->refresh(pStrip_a, 100);
    } else {
        /* Set all LED off to clear all pixels */
        pStrip_a->clear(pStrip_a, 50);
    }
}

static void configure_led(void)
{
    ESP_LOGI(TAG, "Example configured to blink addressable LED!");
    /* LED strip initialization with the GPIO and pixels number*/
    pStrip_a = led_strip_init(CONFIG_BLINK_LED_RMT_CHANNEL, BLINK_GPIO, 1);
    /* Set all LED off to clear all pixels */
    pStrip_a->clear(pStrip_a, 50);
}

#elif CONFIG_BLINK_LED_GPIO

static void blink_led(void)
{
    /* Set the GPIO level according to the state (LOW or HIGH)*/
    gpio_set_level(BLINK_GPIO, s_led_state);
}

static void configure_led(void)
{
    ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
    gpio_reset_pin(BLINK_GPIO);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
}

#endif

void app_main(void)
{

    /* Configure the peripheral according to the LED type */
    configure_led();

    while (1) {
        ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF");
        blink_led();
        /* Toggle the LED state */
        s_led_state = !s_led_state;
        vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
    }
}
  • 22行:define BLINK_GPIO CONFIG_BLINK_GPIO
    • CONFIG_BLINK_GPIOが見つからない
  • 26行と52行のIF文でCONFIG_BLINK_LED_RMT、CONFIG_BLINK_LED_GPIOが見つからない
  • 使われている関数の詳細が分からない。
    • 使われている関数に付いて、ESP-IDF Programming Guide にマニュアルが有ることが分かりました。
    • こんな感じで検索します。
  • 81行:vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
    • 引数に使われている、CONFIG_BLINK_PERIOD と portTICK_PERIOD_MS の値が分からない。
  • 要所要所に出てくる、ESP_LOGI(TAG,〜); の使い方。

が分からない。プログラム自体は LED_RMT か LED_GPIO を一定時間間隔で点滅させるものの様です。

次は、idf.py menuconfig

次にidf.py menuconfigを行います。ちなみにidf.py set-targetでCPUを指定しないでidf.py menuconfigを行うとDefualtで CPUがESP32となるようです。

idf.py menuconfigを実行した時に表示される画面を前回のHello_worldと比較して見ます。

左側が今回、右側がHello_Worldの画面です。今回の画面には、”Example Configuration” と言う項目が追加されているのが分かります。このフレーズは、 “Kconfig.projbuild” ファイルの先頭に有った文と同じです。

表示されているメニュー画面では、”Example Configuration”ー>”Blink LED type”と進む事が出来ます。この様子と “Kconfig.projbuild” を比べると下記の様になりました。

Blink GPIO / Blink period in ms メニューを選ぶとそれぞれ上図赤枠で囲んだ項目が表示されました。

”Blink LED type”の項目で、GPIOを選ぶと、”BLINK_LED_GPIO”が bool として定義される様に見えます。今回はdefualtでGPIOが選ばれていたので変更無しにmenuconfigを抜けました。menucofig によって作成された sdkconfig ファイルを開くと定義している箇所が有りました。

sdkconfig(一部)

#
# Example Configuration
#
CONFIG_BLINK_LED_GPIO=y
# CONFIG_BLINK_LED_RMT is not set
CONFIG_BLINK_GPIO=5
CONFIG_BLINK_PERIOD=1000
# end of Example Configuration

#

Kconfig.projbuildファイルでは、BLINK_LED_GPIO, BLINK_GPIO, BLINK_PERIOD という宣言でしたが、sdkconfig ではそれらの頭に ”CONFIG_” が追加した形式に変わっていました。そしてそれらは ソースファイルで定義の位置が分からなかった変数となります。

ちなみに、vTaskDelay(CONFIG_BLINK_PERIOD , portTICK_PERIOD_MS);関数で使われていた、”portTICK_PERIOD_MS”ですが、ESP-IDF Programming Guideで検索を変えると、ms単位のdelay を実行する時に使う定数の様でした。

ここまでをまとめると以下のなります。

  • 対象CPUは、ESP32
  • GPIO 5 を使ってLEDを点滅させるプログラム
  • 点滅の間隔は1000ms つまり 1秒。

動作確認の為ハードの製作

今回は36ピンのESP32を使って下記の回路を作りました。

プログラムを書き込んで実行

USBケーブルをESP32につないで、idf.py flash を実行。LEDが1秒間隔で点滅しました。

今回分かった事

  • ”set(EXTRA_COMPONENT_DIRS  〜)”
    • 特別に参照する箇所が有る場合このコマンドを、プロジェクト直下の ”CMakeLists.txt”に追加する。
  • 分からない関数や用語は
  • “Kconfig.projbuild” ファイルを作成すれば menuconfig で表示されるメニューに設定項目を追加出来る。
    • いまいち使い方とメリットが分かりません。
    • Include fileで定義する場合に比べメリットは何なのでしょうか。
  • idf.py set-target コマンドを行わずに idf.py menuconfig を行うと CPUはESP32になる。
  • いきなり idf.py build を行うとCPUはCPUはESP32になる。

次回

今回はCMakeLists.txt が良く分からないのに Kconfig.projbuild なんて新しいファイルが出てきました。別のサンプルを見つけてもう少し理解を深めたいと思います。