※スイッチの基板は、FETを3つ使って、ヒステリシスを作ったチャタリング対策回路になっています。
学習中なので、この方法で不具合があった場合、変更する可能性があります。
ESP-IDFで開発学習を始めました。GPIOの入出力を制御することから始めました。
開発環境:vsCode+platformIO
board:esp32dev
platform:ESP-IDF
スイッチ割込みでLEDを点滅させるようにしました。そこまでは、順調でした。ビルドの結果を見たら、PSRAMが有効になっていません。ROMも1MBまでしか使えません。PSRAMを有効にして、ROMのサイズも大きくしようとしたら、見事にハマりました。
ROMサイズの変更で、相当手こずりながら作業したので、これでいいのか、まだよくわかっていません。
FlashROMサイズは、boardの設定がリミッターになっている感じです。
・platformioのnewPojectで、新しくプロジェクトを立ち上げます。その際に選択したboardが、Espressif ESP32 Dev Moudule。このボードの初期設定は、ROMが4MB。RAMが300kB強。 そのままでは、WROVER-EのROM 8MB、RAM 8MBをフルに使用できません。 ボード設定(esp32dev.json)を変更したファイルを用意する必要がありました。
・menuConfigとパーティションテーブルを使用してビルドします。ROMの使用量が4MBを超えるとエラーになります。 boardの設定4MBの範囲内ならOKです。
・最終的に、esp32dev.jsonファイルを書き換えることで、ビルドエラーを回避できるようになりました。詳細は、以下で説明していきます。
・PSRAMの有効化は、platformio.iniまたは、menuConfigで設定。
・オリジナルのboardファイルを書き換えたくないので、それを参考にしながら、ESP32-WROVER-E用のmyboard.jsonを自作して、プロジェクト作成時に指定する方法をとっています。
・platformIOの掲示板でも、同様の質問がされていました。
ESP32-WROVER-E用に自作したboard.jsonファイル。
{
"build": {
"arduino":{
"ldscript": "esp32_out.ld"
},
"core": "esp32",
"extra_flags": "-DARDUINO_ESP32_DEV",
"f_cpu": "240000000L",
"f_flash": "40000000L",
"flash_mode": "dio",
"mcu": "esp32",
"variant": "esp32"
},
"connectivity": [
"wifi",
"bluetooth",
"ethernet",
"can"
],
"debug": {
"openocd_board": "esp-wroom-32.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "my ESP32 dev", <=====ここを書き換えた。
"upload": {
"flash_size": "8MB", <=====ここを書き換えた。
"maximum_ram_size": 327680,
"maximum_size": 8000000, <=====ここを書き換えた。
"require_upload_port": true,
"speed": 460800
},
"url": "https://en.wikipedia.org/wiki/ESP32",
"vendor": "Espressif"
}
<参考>GPIOの操作関連 Application exampleにあるgitレポジトリが、分かりやすいです。
<参考>パーティションテーブル
設定に必要なファイル
ESP-IDFで、プロジェクトをビルドしていきます。その際、必要になるファイルが4つあります。
1.kconfig.projbuild
2.sdkconfig.esp32dev
3.partition table.csv
4.platformio.ini
上記4つのファイルを必要に応じて、変更していきます。
1.kconfigファイル
srcフォルダにkconfig.projbuid
ファイルを置きます。このファイルで、GPIOのピン設定を行っています。
menu "Example Configuration"
config GPIO_OUTPUT_0
int "GPIO output pin 0"
range 0 39
default 32
help
GPIO pin number to be used as GPIO_OUTPUT_IO_0.
config GPIO_OUTPUT_1
int "GPIO output pin 1"
range 0 39
default 33
help
GPIO pin number to be used as GPIO_OUTPUT_IO_1.
config GPIO_INPUT_0
int "GPIO input pin 0"
range 0 39
default 34
help
GPIO pin number to be used as GPIO_INPUT_IO_0.
config GPIO_INPUT_1
int "GPIO input pin 1"
range 0 39
default 35
help
GPIO pin number to be used as GPIO_INPUT_IO_1.
endmenu
2.sdkcofigファイルとmenuConfig
platformIOでRun Menuconfig
をクリックすると、esp-idfの開発設定画面が、ターミナルに表示されます。
下の画面が、platformIO のターミナルに表示されます。
ここで、各種設定を行います。kconfigファイルをsrcに置くと、
kconfigファイルの先頭に書いてあるExample Configration
が選択肢に追加されています。
kconfigファイルを編集せずに、menuConfigで再設定ができます。
各種の設定をここで行うと、変更内容が、sdkcofigファイルに反映されます。Serial flasher configでROMサイズをWROVER用に8MBに変更しました。ROMサイズを広げるには、パーティションテーブル作成が必要になります。
3.パーティションテーブルを作成
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x700000,
spiffs, data, spiffs, 0x710000,0xE0000,
coredump, data, coredump,0x7F0000,0x10000,
WROVER-EのROMサイズを変更し、拡大させるため、パーティションテーブルをCSV形式で作成します。このファイルを、Pojectフォルダのルートの置きました。otaは"On the air"の略で、無線経由でROMを書き換えることを意味しています。SPIFFS は "SPI Flash File System "の略で、ROMにフォントなどを保存できる領域です。
4.platformIO iniファイル
※boardがesp32devだと、WROVER-EのROM,RAM領域が制限されます。
ESP32-WROVER-Eは、ROMが8MB、RAMは8MB あります。それにあわせて、boardファイルのjsonフォーマットをみながら、iniファイルに設定を追加していきます。
boardは、esp32devになっています。このボード設定では、WROVER-Eのスペックをフルに使用することはできません。ワーニングとエラーがでます。project作成時に、オリジナルboard.jsonを読み込ませる方法が、現状のベストです。
PSRAMの有効化は、menuConfigまたは、platformio.iniで設定します。最初は双方で設定していました。
<改変した自作ボードファイル>
my_esp32dev(これで、ROM,RAMの容量を拡張できるようになりました。)
menuConfigでsdkConfigの内容を変更、iniファイルと、パーティションテーブルを作成したので、ビルドします。
RAM: [ ] 0.2% (used 10932 bytes from 4536000 bytes)
Flash: [ ] 3.2% (used 234041 bytes from 7340032 bytes)
PSRAMが反映されて、4.5MBに、ROMは、7.3MBに拡がりました。
Board:esp32dev.jsonを書き換えてたboarファイルを使用。 最初に書いた通り、menuConfigとplatformio.iniの設定だけでは、ROMサイズの拡大ができませんでした。BoardはJSONフォーマットで書かれており、そこでのサイズは、4MBが最大と設定されています。menuConfigでWROVER用に、Flashサイズを8MBに変更するとビルド時にwarningが表示されます。パーティションテーブルを作成し、それが4MBを超えるとエラーになります。エラーを回避するため、boradJSONを変更しました。オリジナルを変更するよりは、新規にmyboard.jsonをかいて、project作成時にそれを選択する方法をとっています。
GPIO割込みのコード
//**********************************//
//GPIO割込み
//**********************************//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
//自分で追加したヘッダー
//gpioレジスタの直打ち用。
#include "soc/gpio_reg.h"
//gpio_isr_func_tのサイズを求めるため。
#include "hal/gpio_types.h"
//OUTPUTピン Kconfig.projbuildに詳細設定
#define GPIO_OUTPUT_IO_0 CONFIG_GPIO_OUTPUT_0
#define GPIO_OUTPUT_IO_1 CONFIG_GPIO_OUTPUT_1
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
//INPUTピン Kconfig.projbuildに詳細設定
#define GPIO_INPUT_IO_0 CONFIG_GPIO_INPUT_0
#define GPIO_INPUT_IO_1 CONFIG_GPIO_INPUT_1
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
//GPIO_IN1_REGレジスタの値
#define GPIO_IN1_REG_VALUE (*(volatile uint32_t*)GPIO_IN1_REG)
//GPIO割込み RAMの指定値
#define ESP_INTR_FLAG_DEFAULT 0
#define HIGH 1
#define LOW 0
//gpio.cにあるgpio_isr_func_tのサイズを求める。
//hal/gpio_types.hを読み込む。
//gpio_isr_func_tはCファイル内の記述。
typedef struct {
gpio_isr_t fn; /*!< isr function */
void *args; /*!< isr function args */
} m_gpio_isr_func_t;
//GPIO個別処理割込み関数
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
static bool val1=true,val2=true;
uint32_t gpio_num = (uint32_t)arg;
if(gpio_num==GPIO_INPUT_IO_0)
{
gpio_set_level(GPIO_OUTPUT_IO_0,val1);
val1 = !val1;
}
if(gpio_num==GPIO_INPUT_IO_1)
{
gpio_set_level(GPIO_OUTPUT_IO_1,val2);
val2= !val2;
}
}
void app_main()
{
//Output mode pin----------------------------
//zero-initialize the config structure.
gpio_config_t io_conf = {};
//disable interrupt
io_conf.intr_type = GPIO_INTR_DISABLE;
//set as output mode
io_conf.mode = GPIO_MODE_OUTPUT;
//bit mask of the pins that you want to set,e.g.GPIO32/33
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
//disable pull-down mode
io_conf.pull_down_en = 0;
//disable pull-up mode
io_conf.pull_up_en = 0;
//configure GPIO with the given settings
gpio_config(&io_conf);
//Input mode pin------------------------------
io_conf.intr_type = GPIO_INTR_POSEDGE; //GPIO割込みエッジ指定
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = 1;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
//gpio_isr_func_tについて
//GPIO0..39用 割込み関数ポインタ と デフォルト引数を格納する。
uint32_t size = sizeof(m_gpio_isr_func_t);
printf("gpio_isr_func_t size:%"PRIu32"bytes\n",size);
printf("install size:%"PRIu32"bytes\n",size*GPIO_NUM_MAX);
//GPIO割込みを設定。
uint32_t size0= esp_get_minimum_free_heap_size();
printf("Minimum free heap size: %"PRIu32" bytes\n", size0);
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
uint32_t size1 = esp_get_minimum_free_heap_size();
printf("Minimum free heap size: %"PRIu32" bytes\n", size1);
printf("Minumum free heap consumption size:%"PRIu32"bytes\n", size0-size1);
int cnt = 0;
//portTICK_PERIOD_MS デフォルトは100なので、menuConfigで1000で再設定。
printf("portTICK_PERIOD_MS:%"PRIu32"\n",portTICK_PERIOD_MS);
while(1)
{
printf("cnt: %d\n",cnt++);
vTaskDelay(1000/ portTICK_PERIOD_MS);
}
}
学習中なので、この方法で不具合があった場合、変更する可能性があります。