こんにちは、shotaです。
社員研修として、ESP32を搭載したオリジナルマウスを製作しました。
前回の記事ではHello World!のサンプルプログラムを実行しました。
今回はHello World!の編集方法を書きます。その後GPIOのサンプルを編集し、マウスのLEDを点灯させます。
Hello World!サンプルの編集
前回はESP-IDFのサンプルからhello_worldを選択し、ビルド、書き込み、実行しました。
サンプルコードはGitHubのページからも確認できます。
このサンプルのディレクトリを見ると、CMakeLists.txtやMakefileなどがあり、その中にmainディレクトリがあります。
mainの中にはCMakeLists.txtとcomponent.mkとhello_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
変更後の文字列が表示されました。
LEDを点灯しよう
サンプルコードの編集方法が分かったので、次は別のサンプルコードを編集します。
編集するのはgpioのサンプルコードです。
このサンプルからは、GPIOのインプット、アウトプットの設定と、割り込み処理の設定方法が学べますが、今回はアウトプットの設定のみを使用します。
まず、hello_worldと同様にサンプルディレクトリをコピーします。
$ cd ~/esp $ cp -r esp-idf/examples/peripherals/gpio/ .
次に、gpio/main/gpio_example_main.cを編集します。
ファイル上部にGPIO_OUTPUT_IO_0とGPIO_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)を使ってバッテリの電圧を読み取ります。


