ESP32マウス(shota)マウス自作研修

shotaのマイクロマウス研修29 ESP32マウスでLチカ

ESP32マウス(shota)

こんにちは、shotaです。
社員研修として、ESP32を搭載したオリジナルマウスを製作しました。

初めてのオリジナルマウス Especial

前回の記事ではHello World!のサンプルプログラムを実行しました。

今回はHello World!の編集方法を書きます。その後GPIOのサンプルを編集し、マウスのLEDを点灯させます。

Hello World!サンプルの編集

前回はESP-IDFのサンプルからhello_worldを選択し、ビルド、書き込み、実行しました。
サンプルコードはGitHubのページからも確認できます。

esp-idf/examples/get-started/hello_world at master · espressif/esp-idf
Espressif IoT Development Framework. Official development framework for Espressif SoCs. - espressif/esp-idf

このサンプルのディレクトリを見ると、CMakeLists.txtMakefileなどがあり、その中にmainディレクトリがあります。
mainの中にはCMakeLists.txtcomponent.mkhello_world_main.cがあります。

今回編集するのはhello_world_main.cです。これがHello Worldのソースファイルです。

hello_world_main.cの中身を見ると、

void app_main(void)
{
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU cores, WiFi%s%s, ",
            CHIP_NAME,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("silicon revision %d, ", chip_info.revision);

    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    for (int i = 10; i >= 0; i--) {
        printf("Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    printf("Restarting now.\n");
    fflush(stdout);
    esp_restart();
}

となっています。Hello world!を表示するだけなのに中身多くない!?と思うかもしれませんが、そのとおりです。
このサンプルコードはHello world!以外の情報も表示しています。

CPUの情報やフラッシュメモリのサイズ等を表示していますが、マウスの機能としては不要です。
こういう機能があるんだ〜、程度に覚えておきましょう。

そこで、下記のように編集してみます。
Hello world!の文字列を変更して、それ以外のコードはコメントアウトしました。

void app_main(void)
{
    printf("ESP32マウスをはじめよう!\n");

    /* Print chip information */
    // esp_chip_info_t chip_info;
    // esp_chip_info(&chip_info);
    // printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
    //         chip_info.cores,
    //         (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
    //         (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
    //
    // printf("silicon revision %d, ", chip_info.revision);
    //
    // printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
    //         (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
    //
    // for (int i = 10; i >= 0; i--) {
    //     printf("Restarting in %d seconds...\n", i);
    //     vTaskDelay(1000 / portTICK_PERIOD_MS);
    // }
    // printf("Restarting now.\n");
    // fflush(stdout);
    // esp_restart();
}

これを書き込んで実行します。

# buildは省略していますが、ファイルが変更されていると自動でbuildしてくれます。
$ idf.py -p /dev/ttyUSB0 flash monitor

ESP32マウスをはじめよう!

変更後の文字列が表示されました。

LEDを点灯しよう

サンプルコードの編集方法が分かったので、次は別のサンプルコードを編集します。
編集するのはgpioのサンプルコードです。

esp-idf/examples/peripherals/gpio at master · espressif/esp-idf
Espressif IoT Development Framework. Official development framework for Espressif SoCs. - espressif/esp-idf

このサンプルからは、GPIOのインプット、アウトプットの設定と、割り込み処理の設定方法が学べますが、今回はアウトプットの設定のみを使用します。

まず、hello_worldと同様にサンプルディレクトリをコピーします。

$ cd ~/esp
$ cp -r esp-idf/examples/peripherals/gpio/ .

次に、gpio/main/gpio_example_main.cを編集します。

ファイル上部にGPIO_OUTPUT_IO_0GPIO_OUTPUT_IO_1が設定されているので、これをEspecialのLEDポートに変更します。

Especialのピン番号と機能については下記に記載しています。

shotaのマイクロマウス研修18 ESP32周辺回路とピンの機能選択

#define GPIO_OUTPUT_IO_0    22 //18
#define GPIO_OUTPUT_IO_1    23 //19

変更したらマウスに書き込みます。

$ idf.py -p /dev/ttyUSB0 flash

LEDが点滅(Lチカ)しました。

サンプルコードを詳しく読む

Lチカを実現するにはGPIOのアウトプットの設定が必要です。それ以外は不要です。

そこで、サンプルコードからLチカに不要な部分を取り除きました。

コメントも追加したので、各行で何を実行しているのか理解しやすいと思います。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

#define GPIO_OUTPUT_IO_0    22 //18
#define GPIO_OUTPUT_IO_1    23 //19

void app_main(void)
{
    gpio_config_t io_conf;
    // 割り込みをしない
    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
    // 出力モード
    io_conf.mode = GPIO_MODE_OUTPUT;
    // 設定したいピンのビットマスク
    // 1ULLはunsigned long long(64bit)で1を表現する
    // 22ピンと23ピンを設定するので、ビットマスクは下記のようになる
    // 上位32ビット:MSB|0000 0000|0000 0000|0000 0000|0000 0000|
    // 下位32ビット:    0000 0000|1100 0000|0000 0000|0000 0000|LSB
    io_conf.pin_bit_mask = ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1));
    // 内部プルダウンしない
    io_conf.pull_down_en = 0;
    // 内部プルアップしない
    io_conf.pull_up_en = 0;
    // 設定をセットする
    gpio_config(&io_conf);


    int cnt = 0;
    while(1) {
        // カウンタcntをインクリメント
        printf("cnt: %d\n", cnt++);
        // 1秒停止
        vTaskDelay(1000 / portTICK_RATE_MS);
        // gpioの出力をセットする
        // 0: Lo, 1: Hi
        // cntが奇数のとき、cnt % 2が1になるので、出力はHi
        // cntが偶数のとき、cnt % 2が0になるので、出力はHi
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
        gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
    }
}

ここで重要なのは、driver/gpio.hをインクルードすることと、gpio_config()でピンを設定することです。

GPIOの詳細については、下記ドキュメントを参照してください。
https://docs.espressif.com/projects/esp-idf/en/stable/api-reference/peripherals/gpio.html

次回の記事

次回はADC(Analog to Digital Converter)を使ってバッテリの電圧を読み取ります。

タイトルとURLをコピーしました