esp-idf 환경에서 m5 Stack 소프트웨어 개발 및 시작
목적
환경 버전
(esp-idf)
$ git log -n1
commit 8bf14a9238329954c7c5062eeeda569529aedf75 (HEAD, tag: v4.3.2)
Author: Ivan Grokhotkov <[email protected]>
Date: Mon Dec 20 19:02:41 2021 +0100
versions: Update version to 4.3.2
(M5GFX)
$ git log -n1
commit a8e406af056f3b1cb331c0b66126ab828197755e (HEAD -> master, tag: 0.0.15, origin/master, origin/HEAD)
Merge: 41af34c c2370c0
Author: lovyan03 <[email protected]>
Date: Sat Nov 27 12:21:25 2021 +0900
Merge pull request #24 from m5stack/develop
0.0.15
절차.
Install
github에서clone esp-idf를 시작합니다.일반적으로 clone은 pull master를 하기 때문에 적당한 버전에서 체크아웃(본편에서는 이미 체크아웃
v4.3.2
합니다.esp-idf에submodule가 있기 때문에 체크아웃 시 잊지 마세요git submodule update
[1].pyenv와 asdf를 가져오면psyhon의 처리를 주의하십시오.python 시스템 오류가 발생했을 때 pip install를 검사할 때 어디에 설치되었는지, ep-idf에서 어떤python을 사용했는지 등을 검사합니다.
git clone https://github.com/espressif/esp-idf.git -b v4.3.2
cd esp-idf.git
./install.sh
Build hello_world
idf.py
를 사용하기 위해 export.sh
에서 환경 변수를 읽습니다.이렇게 하면 idf.py
등을 사용할 수 있다.앞으로 빌딩과 기록 사용
idf.py
.source export.sh
구축, 쓰기examples/get-started/hello_world
를 시도합니다.cd examples/get-started/hello_world
idf.py build
다음과 같은 경우 성공Project build complete. To flash, run this command:
/home/fai/.espressif/python_env/idf5.0_py3.8_env/bin/python ../../../components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/hello_world.bin
or run 'idf.py -p (PORT) flash'
m5 Stack을 PC에 연결하여 디바이스 파일을 확인합니다.ls /dev/*USB*
에서 대충 확인할 수 있습니다.$ ls /dev/*USB*
/dev/ttyUSB0
구축이 성공했을 때의 메시지에 따라 flash
하면 기록합니다.편하네요.idf.py -p /dev/ttyUSB0 flash
hello_월드가 직렬로 출력되기 때문에 monitor
에서 직렬을 확인합니다."Serial을 종료하려면 누르기ctrl + ]
"메시지가 표시되므로 Serial을 종료하려고 합니다[2].idf.py -p /dev/ttyUSB0 monitor
다음 텍스트는 직렬로 수신해야 합니다.Hello world!
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision 1, 2MB external flash
Minimum free heap size: 294012 bytes
참고로 샘플은 printf
을 사용하지만 로그를 직렬로 출력하려면 printf
대신 "esp_log.h"
#include
ESP_LOGI("TAG", "message v=%d", 5);
등을 사용하는 것이 좋다.또 지령을 나란히 쓸 수 있기 때문에 개발할 때 다음 명령을 자주 두드린다.
idf.py -p /dev/ttyUSB0 build flash monitor
기타 명령이 풍부하다.특히 사용이 가능한 것은 fullclean
menuconfig
등이다.Import M5GFX
https://github.com/m5stack/M5GFX.
이동만 한다면 아래처럼components에 깊이 들어가면 됩니다.
cd components
git clone https://github.com/m5stack/M5GFX
Run M5GFX samples
esp-idf의 맨 윗부분 디렉터리로 돌아가서work 디렉터리를 만듭니다.이번에는 아래에서 프로젝트를 만들어 작업하기로 했다.hello_월드 복제, 혹시 모르니까 구축 가능.
cp -ar examples/get-started/hello_world work/
cd work/hello_world
idf.py fullclean
idf.py -p /dev/ttyUSB0 build flash monitor
M5GFX는 C++입니다.hello_world_main.c
를 hello_world_main.cpp
로 바꾸다.다시 쓰다
work/hello_world/main/CMakeLists.txt
.파일 이름 바꾸기 외에 M5GFX
를 추가하여 PRIV_REQUIRES "M5GFX"
에 의존하도록 했다.idf_component_register(SRCS "hello_world_main.cpp"
PRIV_REQUIRES "M5GFX"
INCLUDE_DIRS "")
M5GFX의 샘플을 복사해 이동하고 싶었지만, 아두노 IDE를 겨냥한 샘플에만 들어갔기 때문에 자기 앞에서 호출setup
과loop
로 실행했다.esp-idf는 임무 개념을 가지고 여러 코드를 병렬로 이동할 수 있다.
app_main
함수로도 잡도 무한순환을 할 수 있지만 얻기 어려워xTaskCreatePinnedToCore
를 사용한다.ref: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html
// hello_world_main.cpp
// ============================================================================
// BEGIN BarGraph.ino
// https://github.com/m5stack/M5GFX
// //examples/Basic/BarGraph/BarGraph.ino
// FIXME: 下記URLのコードをここに貼り付ける
// https://github.com/m5stack/M5GFX/blob/a8e406af056f3b1cb331c0b66126ab828197755e/examples/Basic/BarGraph/BarGraph.ino
// END BarGraph.ino
// ============================================================================
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
TaskHandle_t g_handle = nullptr;
void runMainLoop(void *args) {
setup();
for (;;) {
loop();
// avoid `The following tasks did not reset the watchdog in time`
vTaskDelay(1);
}
vTaskDelete(g_handle);
}
void initializeTask() {
xTaskCreatePinnedToCore(&runMainLoop, "task1-main", 8192, nullptr, 1,
&g_handle, 1);
configASSERT(g_handle);
}
extern "C" {
void app_main(void) {
//
initializeTask();
}
}
idf.py -p /dev/ttyUSB0 build flash monitor
에 기록을 구축하고 BarGraph의 시위 행진이 시작되면 ok.Implement M5GFX App
또 시료에서 알아채기 어려운 M5GFX와 관련된 문제 등을 들었다.
GPIO25 및 GND는 점프 라인을 통해 연결한 후 해제됩니다.아래의 보도는 매우 상세한 것 같다.
M5GFX
의 드로잉 명령이 버퍼링되지 않습니다.M5Canvas
를 사용하여 사이다를 써넣고 사이다를 붙여서 완충하는 것은 일반적인 상황인 것 같습니다.M5GFX g_display;
M5Canvas g_canvas(&g_display);
int g_time = 0;
void setupDisplay() {
g_display.init();
g_display.startWrite();
g_canvas.createSprite(g_display.width(), g_display.height());
}
void renderDisplay() {
int kW = g_display.width();
int kH = g_display.height();
int kL = std::min(kW, kH) * 4 / 10;
g_display.waitDisplay();
g_canvas.fillRect(0, 0, kW, kH, TFT_BLACK);
float a1 = 0.01 * g_time;
float a2 = a1 + PI * 2 / 3;
float a3 = a1 - PI * 2 / 3;
g_canvas.fillTriangle(std::cos(a1) * kL + kW / 2, std::sin(a1) * kL + kH / 2,
std::cos(a2) * kL + kW / 2, std::sin(a2) * kL + kH / 2,
std::cos(a3) * kL + kW / 2, std::sin(a3) * kL + kH / 2,
TFT_WHITE);
g_canvas.pushSprite(0, 0);
g_display.display();
g_time += 3;
}
위에 설명된 구현 방법 중에서도 유선이 들어오는 깜박임이 발생할 수 있습니다.그리는 과정에서 인터럽트가 삽입되어 있어서 그런지 적당히 라인을 양보하면 해제[3]됩니다.수중의 환경에서vTaskDelay(15 / portTICK_PERIOD_MS);
현상이 발생하여vTaskDelay(40 / portTICK_PERIOD_MS);
에 억제되었다.Control GPIO (buttons, speaker)
버튼과 스피커가 GPIO에 연결되어 있어 아두노와 랩베리피의 작업감각과 같다.새치기도 가능합니다.
buttons
gpio_config
에서 설정하고 gpio_get_level
에서 값을 읽습니다.중단된 구현 사례는
examples/peripherals/gpio/
에 포함됩니다.void initialize() {
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.pin_bit_mask =
(1ull << GPIO_NUM_39) | (1ull << GPIO_NUM_38) | (1ull << GPIO_NUM_37);
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
}
std::array<bool, 3> update() {
bool a = gpio_get_level(GPIO_NUM_39);
bool b = gpio_get_level(GPIO_NUM_38);
bool c = gpio_get_level(GPIO_NUM_37);
return std::array<bool, 3>{a, b, c};
}
speaker
driver/ledc.h
를 사용하여 PWM 제어를 수행합니다.duty
와 hpoint
에 대한 상세한 설명http://blueeyes.sakura.ne.jp/2021/01/31/3672/.공식 문서에는 ESP32 Technical Reference Manual LED PWM Controller 14개에 적혀 있습니다.void initialize() {
gpio_config_t config;
config.intr_type = GPIO_INTR_DISABLE;
config.pin_bit_mask = (1ull << GPIO_NUM_25);
config.mode = GPIO_MODE_OUTPUT;
config.pull_up_en = GPIO_PULLUP_DISABLE;
config.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config(&config);
}
void setSound(uint32_t freq, bool enable) {
ledc_timer_config_t timer_config = {};
timer_config.speed_mode = LEDC_HIGH_SPEED_MODE;
timer_config.duty_resolution = LEDC_TIMER_8_BIT;
timer_config.timer_num = LEDC_TIMER_3;
timer_config.freq_hz = freq;
timer_config.clk_cfg = LEDC_AUTO_CLK;
ledc_timer_config(&timer_config);
ledc_channel_config_t channel_config = {};
channel_config.gpio_num = GPIO_NUM_25;
channel_config.speed_mode = LEDC_HIGH_SPEED_MODE;
channel_config.channel = LEDC_CHANNEL_1;
channel_config.intr_type = LEDC_INTR_DISABLE;
channel_config.timer_sel = timer_config.timer_num;
channel_config.duty = enable ? 0x7F : 0x00;
channel_config.hpoint = 0x0;
ledc_channel_config(&channel_config);
}
void runSpeakerLoop(void *args) {
vTaskDelay(3000 / portTICK_PERIOD_MS);
g_my_io.setSound(262, true);
vTaskDelay(500 / portTICK_PERIOD_MS);
g_my_io.setSound(294, true);
vTaskDelay(500 / portTICK_PERIOD_MS);
g_my_io.setSound(330, true);
vTaskDelay(500 / portTICK_PERIOD_MS);
g_my_io.setSound(330, false);
vTaskDelete(nullptr);
}
그나저나 channel_config.channel = LEDC_CHANNEL_7
라면 duty=0
모니터가 길이 되어 사라지거나 timer_config.clk_cfg = LEDC_AUTO_CLK
이외에 다른 동작이 없어 디테일을 파악하지 못하거나...만약 무슨 착오가 있으면 나중에 수정할 것이다.sample code
동작을 확인할 때 사용하는 전체 이미지 코드
각주
까먹고 반했어.↩︎
환경에 따라 다를 수 있음↩︎
한마디로 집행
M5Canvas#pushSprite
과정에서 새치기당하지 말아야 한다.M5Canvas#fillRect
등 사이에 새치기가 발생해도 문제가 없었다.나는 더 좋은 방법이 있다고 생각한다. 어쨌든 지금은 이렇다.↩︎ Reference
이 문제에 관하여(esp-idf 환경에서 m5 Stack 소프트웨어 개발 및 시작), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/mai/articles/72519e289973c6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)