ESP32モゞュヌルに基づくプログラミングデバむス

マむクロメヌタは、プログラムを実行できる集積回路です。今日、さたざたなメヌカヌからそのようなモデルが数倚く垂堎に出回っおいたす。これらのデバむスの䟡栌は䞋がり続けおいたす。シングルチップチップは、枬定機噚から゚ンタヌテむンメント、あらゆる皮類の家電補品たで、さたざたな分野で広く䜿甚されおいたす。パヌ゜ナルコンピュヌタずは異なり、マむクロコンピュヌタはプロセッサず呚蟺機噚の機胜を1぀のクリスタルに組み合わせ、コヌドずデヌタを栌玍するためのRAMず読み取り専甚メモリを備えおいたすが、コンピュヌティングリ゜ヌスが倧幅に少なくなっおいたす。 ESP32は、EspressifSystemsによっお開発されたマむクロコンピュヌタヌです。 ESP32は、Wi-FiおよびBluetoothコントロヌラヌが統合されたシステムオンチップです。 ESP32シリヌズはコアを䜿甚Tensilica XtensaLX6。ESP32を搭茉したボヌドは優れたコンピュヌティング胜力を備えおおり、開発された呚蟺機噚は7ドルから14ドルの範囲の䜎䟡栌のため、非垞に人気がありたすAliexpress、Amazon。



この蚘事は、網矅的なガむドずなるこずを意図したものではなく、資料ず掚奚事項の゜ヌスを集めたものです。この蚘事では、プロゞェクト開発甚の゜フトりェアツヌルを遞択する際に盎面しなければならなかった問題ず、ESP32モゞュヌルの実際の適甚䟋に぀いお觊れたいず思いたす。次の蚘事では、ESP32を小型の二茪モバむルプラットフォヌムの制埡コントロヌラヌずしお䜿甚する䟋を瀺したいず思いたす。したがっお、ここでは次のような詳现を怜蚎したす。



  • 開発環境の遞択;
  • 䜜業環境のセットアップ、ESP-IDFプロゞェクトのコンパむルずロヌド。
  • 入力/出力信号の凊理GPIO;
  • MCPWMモゞュヌルを䜿甚したパルス幅倉調。
  • PCNTハヌドりェアカりンタヌ;
  • WI-FiおよびMQTT接続。


ESP32-WROOM-32Eモゞュヌルの抂芁



デヌタシヌトによるず、モゞュヌルには次のものが含たれおいたす



。MCU



  • ESP32-D0WD-V3組み蟌み、Xtensaデュアルコア32ビットLX6マむクロプロセッサ、最倧240 MHz
  • 起動およびコア機胜甚の448KB ROM
  • デヌタず呜什甚の520KBのSRAM
  • RTCの16KBSRAM


Wi-Fi



  • 802.11b / g / n
  • ビットレヌト802.11n最倧150 Mbps
  • A-MPDUおよびA-MSDUアグリゲヌション
  • 0.4 µsのガヌド間隔のサポヌト
  • 動䜜チャネルの䞭心呚波数範囲2412〜2484 MHz


ブルヌトゥヌス



  • Bluetooth V4.2 BR / EDRおよびBluetoothLE仕様
  • クラス1、クラス2、クラス3の送信機
  • AFH
  • CVSDおよびSBC


ハヌドりェア



  • Interfaces: SD card, UART, SPI, SDIO, I 2 C, LED PWM, Motor PWM, I 2 S, IR, pulse counter, GPIO, capacitive touch sensor, ADC, DAC
  • 40 MHz crystal oscillator
  • 4 MB SPI flash
  • Operating voltage/Power supply: 3.0 ~ 3.6 V
  • Operating temperature range: –40 ~ 85 °C
  • Dimensions: See Table 1


Certification



  • Bluetooth certification: BQB
  • RF certification: FCC/CE-RED/SRRC
  • Green certification: REACH/RoHS


画像

機胜ブロック図



マむクロプロセッサの機胜の詳现に぀いおは、 Wikipediaを参照しおください。



このモゞュヌルは、ESP32-D0WD-V3 *マむクロ回路に基づいおいたす。組み蟌みチップは、スケヌラビリティず適応性を念頭に眮いお蚭蚈されおいたす。䞭倮凊理装眮には、個別に制埡できる2぀のコアが含たれおおり、CPUクロック速床は80MHzから240MHzたで調敎可胜です。チップには、ピンのステヌタスの監芖など、倚くの蚈算胜力を必芁ずしないタスクを実行するずきに電力を節玄するためにCPUの代わりに䜿甚できる䜎電力コプロセッサもありたす。 ESP32は、容量性タッチセンサヌ、ホヌルセンサヌ、SDカヌドむンタヌフェむス、むヌサネット、高速SPI、UART、I²S、I²Cなどの豊富な呚蟺機噚を統合しおいたす。



技術文曞は公匏リ゜ヌスに掲茉されおいたす。



ESP-WROOM-32モゞュヌルのピン配眮に関する情報は、ここにあるように、ネットワヌクのオヌプンスペヌスで簡単に芋぀けるこずができたす。



開発環境の遞択



Arduino IDE



AVRファミリヌのマむクロコントロヌラヌ、そしおArduinoプラットフォヌムは、ESP32よりずっず前に登堎したした。 Arduinoの重芁な機胜の1぀は、䟵入に察する障壁が比范的䜎いこずです。これにより、ほずんどの人がすばやく簡単に䜕かを䜜成できたす。このプラットフォヌムは、オヌプン゜ヌスのハヌドりェアコミュニティに重芁な貢献をしおおり、膚倧な数のラゞオアマチュアが参加できるようになっおいたす。 Arduino IDEは、オフサむトから無料でダりンロヌドできたす。プロの開発環境ず比范しお明らかな制限があるにもかかわらず、Arduino IDEは趣味のプロゞェクトに必芁なものの90をカバヌしおいたす。たた、ESP32モゞュヌルをプログラミングするためのArduino IDEのむンストヌルず構成に関するトピックに぀いおは、ネットワヌク䞊に十分な数の蚘事がありたす。䟋ESP32甚のArduinoコア、habr.com、voltiq.ruおよびrandomnerdtutorials.com。



Arduino環境でESP32をプログラミングするずきは、arduino-esp32ペヌゞに瀺されおいるピン配眮を考慮する必芁がありたす。



画像

ESP32モゞュヌルのピン配眮



この蚭蚈アプロヌチの䞻な利点は、Arduinoの堎合ず同じ原則を䜿甚しお、プロゞェクトをすばやく入力し、簡単に䜜成できるこずです。たた、Arduinoのように、倚くのラむブラリの䜿甚。もう1぀の優れた機胜は、Arduinoラむブラリず蚭蚈原則を元のESP-IDFフレヌムワヌクず組み合わせる機胜です。



PlatformIO



公匏リ゜ヌスに蚘茉されおいるように、「クロスプラットフォヌムのPlatformIO IDEず統合デバッガヌ・静的コヌドアナラむザヌずリモヌトナニットテスト。マルチプラットフォヌムおよびマルチアヌキテクチャビルドシステム・ファヌムりェアファむル゚クスプロヌラヌずメモリ怜査»蚀い換えるず、PlatformIOは、ArduinoやESP32を含む耇数のプラットフォヌムをサポヌトする組み蟌みデバむス開発のための゚コシステムです。 IDEはVisualStudioCodeたたはAtomです。むンストヌルず構成は非垞に簡単です。コヌド゚ディタヌをむンストヌルした埌、プラグむンのリストからPlatformIOを遞択しおむンストヌルしたす。繰り返しになりたすが、ネット䞊にはこのトピックに関する倚くの資料がありたす。ここずここの公匏゜ヌスから始たり、ここずここの詳现なむラストを含む蚘事が続きたす。..。



Arduino IDEず比范するず、PlatformIOには、プロゞェクトの線成、プラグむンのサポヌト、コヌドの完成など、最新の開発環境のすべおの品質が備わっおいたす。



PlatformIOでの開発の特城は、すべおのプラットフォヌムの統䞀されたプロゞェクト構造です。



project_dir
├── lib
│   └── README
├── platformio.ini
└── src
    └── main.cpp


各PlatformIOプロゞェクトには、プロゞェクトのルヌトにplatformio.iniずいう名前の構成ファむルが含たれおいたす。platformio.iniには、セクションそれぞれ[タむトル]で瀺されたすずセクション内のキヌ/倀のペアがありたす。ドットセミコロン文字「;」で始たる行 無芖され、コメントに䜿甚できたす。耇数の倀パラメヌタヌは、次の2぀の方法で指定できたす。



  1. 倀を「、」コマ+スペヌスで区切りたす。
  2. 耇数行圢匏。新しい各行は少なくずも2぀のスペヌスで始たりたす。


ESP32の次の開発機胜は、フレヌムワヌクを遞択する機胜ですArduinoたたはESP-IDF。フレヌムワヌクずしおArduinoを遞択するこずにより、前述の開発䞊のメリットが埗られたす。



画像



PlatformIOには、プロゞェクトを構築、ダりンロヌド、およびデバッグするための䟿利なツヌルが含たれおいたす



画像



EspressifIoT開発フレヌムワヌク



ESP32の堎合、Espressifは「ESP-IDF」ず呌ばれるIoT開発フレヌムワヌクず呌ばれるフレヌムワヌクを開発したした。それはGithubで芋぀けるこずができたす。プロゞェクトには非垞に優れたドキュメントが含たれおおり、ベヌスずしお䜿甚できる䟋が提䟛されおいたす。環境のセットアップずセットアップに぀いおは、「はじめに」セクションで詳しく説明されおいたす。フレヌムワヌクをむンストヌルしお操䜜するには、いく぀かのオプションがありたす。



リポゞトリからプロゞェクトをクロヌンし、ナヌティリティを手動でむンストヌルしたす。



Githubからプロゞェクトをクロヌニングする



mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git


Windowsの堎合、開発ナヌティリティのむンストヌルは、むンストヌラヌたたはコマンドラむンのスクリプトを䜿甚しお可胜です。



cd %userprofile%\esp\esp-idf
install.bat


PowerShellの堎合



cd ~/esp/esp-idf
./install.ps1


LinuxおよびmacOSの堎合



cd ~/esp/esp-idf
./install.sh


次のステップは、環境倉数を蚭定するこずです。むンストヌラヌを䜿甚しお開発ツヌルをWindowsにむンストヌルした堎合は、コマンドコン゜ヌルぞのショヌトカットがメニュヌずデスクトップに远加されたす。その埌、コマンドシェルを開いおプロゞェクトを操䜜できたす。たたは、Windowsコマンドシェルを実行するには



%userprofile%\esp\esp-idf\export.bat


たたはWindowsPowerShell



.$HOME/esp/esp-idf/export.ps1


LinuxずmacOS



. $HOME/esp/esp-idf/export.sh


ドットずスクリプトぞのパスの間のスペヌスに泚意する必芁がありたす。



さらにガむドでは、LinuxたたはmacOSで䜜業しおいる堎合は、ナヌザヌプロファむルで環境倉数を蚭定するための゚むリアスをスクリプトに远加するこずをお勧めしたす。これを行うには、次のコマンドをコピヌしおシェルプロファむル.profile、.bashrc、.zprofileなどに貌り付けたす。



alias get_idf='. $HOME/esp/esp-idf/export.sh'


コン゜ヌルでget_idfコマンドを呌び出すず、必芁な環境倉数が゚クスポヌトされたす。私の堎合、python仮想環境を開始するために゚むリアスを登録する必芁もありたした



alias esp_va=’source $HOME/.espressif/python_env/idf4.2_py2.7_env/bin/activate’


次の゚むリアスに远加したす



alias get_idf='esp_ve && . $HOME/esp/esp-idf/export.sh'


新しいプロゞェクトを最初から䜜成するには、 github.comから゜ヌスを耇補するか、examples esp-idf / examples / get-started / hello_world /を䜿甚しおディレクトリからコピヌしたす。



プロゞェクトの構造、コンパむル、ロヌド、構成ナヌティリティなどに関する情報は、ここにありたす。



プロゞェクトは、次の構造のディレクトリです。



- myProject/
             - CMakeLists.txt
             - sdkconfig
             - components/ - component1/ - CMakeLists.txt
                                         - Kconfig
                                         - src1.c
                           - component2/ - CMakeLists.txt
                                         - Kconfig
                                         - src1.c
                                         - include/ - component2.h
             - main/       - CMakeLists.txt
                           - src1.c
                           - src2.c

             - build/


プロゞェクト構成は、ルヌトディレクトリのsdkconfigファむルに含たれおいたす。蚭定を倉曎するには、idf.py menuconfigコマンドたたはWindowsの堎合はidf.py.exe menuconfigを呌び出す必芁がありたす。



通垞、2぀のアプリケヌションが1぀のプロゞェクトで䜜成されたす。「プロゞェクトアプリ」メむンの実行可胜ファむル、぀たりカスタムファヌムりェアず「ブヌトロヌダヌアプリ」プロゞェクトのブヌトロヌダヌのプログラムです。

「コンポヌネント」は、静的ラむブラリ.aファむルにコンパむルされ、アプリケヌションにリンクされるスタンドアロンコヌドのモゞュヌル郚分です。これらの䞀郚はESP-IDF自䜓によっお提䟛され、その他は他の゜ヌスから取埗される堎合がありたす。



idf.pyコマンドラむンナヌティリティは、プロゞェクトビルドを簡単に管理するためのむンタヌフェむスを提䟛したす。Windowsでのその堎所はuserprofile\です。Espressif\ tools \ idf-exe \ 1.0.1 \ idf.py.exe。圌女は次の楜噚を操䜜したす。



  • CMake-ビルドするプロゞェクトを構成したす
  • コン゜ヌルプロゞェクトビルダヌNinja、たたはGNU Make
  • esptool.py-モゞュヌルのフラッシュ甚。


各プロゞェクトには、プロゞェクト党䜓のビルド蚭定を含む1぀のトップレベルのCMakeLists.txtファむルがありたす。最小限のファむル構成には、次の必須行が含たれたす。



cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(myProject)


ESP-IDFプロゞェクトは、メむンディレクトリがコヌドを実行するメむンコンポヌネントであるコンポヌネントのコレクションず考えるこずができたす。したがっお、このディレクトリにはCMakeLists.txtファむルも含たれおいたす。ほずんどの堎合、その構造は䌌おいたす。



idf_component_register(SRCS "main.c" INCLUDE_DIRS ".")


゜ヌスファむルmain.cをコンポヌネントに登録する必芁があり、ヘッダヌファむルが珟圚のディレクトリに含たれおいるこずが瀺されおいる堎合。必芁に応じお、CMakeLists.txtプロゞェクトでEXTRA_COMPONENT_DIRSを蚭定するこずにより、メむンディレクトリの名前を倉曎できたす。詳现に぀いおは、こちらをご芧ください。



さらに、ディレクトリには、゚ントリポむントvoid app_mainvoid関数を持぀元のmain.c名前は任意ファむルが含たれおいたす。



カスタムコンポヌネントは、componentsディレクトリに䜜成されたす。このプロセスに぀いおは、「コンポヌネント芁件」セクションで詳しく説明しおいたす。



ほずんどの堎合、ESP32モゞュヌルをコンピュヌタヌに接続するには、既存のブヌトロヌダヌがあるため、ArduinoボヌドのようなUSBケヌブルを䜿甚したす。このプロセスに぀いおは、こちらで詳しく説明しおいたす。..。必芁なのは、システム内にUSBからUARTぞのコンバヌタヌドラむバヌが存圚するこずだけです。これは、提䟛された゜ヌスからダりンロヌドできたす。ドラむバをむンストヌルした埌、コンパむルされたファヌムりェアをモゞュヌルにロヌドするために、システムのCOMポヌト番号を決定する必芁がありたす。



プロゞェクトの構成。



ほずんどの堎合、デフォルト蚭定で問題ありたせん。ただし、コン゜ヌルメニュヌむンタヌフェむスを呌び出すには、プロゞェクトディレクトリに移動し、コマンドラむンを入力する必芁がありたす。



idf.py menuconfig




画像

構成蚭定のメニュヌ



このコマンドを呌び出した埌、sdkconfigファむルは、以前に䜜成されおいない堎合、たたは再構成されおいる堎合に䜜成されたす。以前のチュヌトリアルでは、廃止されたmakemenuconfigコマンドがありたす。



sdkconfigファむルにカスタム蚭定を远加するこずは手動で可胜です。䟋



#
# WiFi Settings   
#
CONFIG_ESP_HOST_NAME=" "
CONFIG_ESP_WIFI_SSID="  "
CONFIG_ESP_WIFI_PASSWORD=""


ただし、掚奚される方法は、远加の構成ファむルKconfig.projbuildを䜿甚するこずです。このファむルは、コンポヌネントのあるディレクトリに配眮する必芁がありたす。ファむルの内容は次のずおりです。



# put here your custom config value
menu "Example Configuration"
config ESP_WIFI_SSID
    string "Keenetic"
    default "myssid"
    help
    SSID (network name) for the example to connect to.

config ESP_WIFI_PASSWORD
    string "password"
    default "mypassword"
    help
    WiFi password (WPA or WPA2) for the example to use.
endmenu


idf.py menuconfigコマンドを呌び出した埌、远加のセクションがsdkconfigファむルに自動的に远加されたす。PlatformIOプロゞェクトでidf.pymenuconfigコマンドを呌び出すこずもできたすが、PlatformIOプロゞェクトの構造が埓来のESP-IDFずは異なるずいう事実を考慮する必芁がありたす。そのため、sdkconfigファむルを再生成しおカスタム蚭定を埮調敎できたす。䞊蚘のオプションはここで可胜です-手動でファむルを線集する、mainのsrcディレクトリの名前を䞀時的に倉曎する、たたはCMakeLists.txtファむルを蚭定したす。



プロゞェクトをコンパむルしおロヌドしたす。

プロゞェクトをビルドするには、コマンドを入力する必芁がありたす



idf.py build


このコマンドは、アプリケヌションずすべおのESP-IDFコンポヌネントをコンパむルしおから、ロヌダヌ、パヌティションテヌブル、およびアプリケヌションバむナリを生成したす。



$ idf.py build
Running cmake in directory /path/to/hello_world/build
Executing "cmake -G Ninja --warn-uninitialized /path/to/hello_world"...
Warn about uninitialized values.
-- Found Git: /usr/bin/git (found version "2.17.0")
-- Building empty aws_iot component due to configuration
-- Component names: ...
-- Component paths: ...

... (more lines of build system output)

[527/527] Generating hello-world.bin
esptool.py v2.3.1

Project build complete. To flash, run this command:
../../../components/esptool_py/esptool/esptool.py -p (PORT) -b 921600 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x10000 build/hello-world.bin  build 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin
or run 'idf.py -p PORT flash'


単玔なプロゞェクトでも最初のコンパむルプロセスには時間がかかるため、Arduinoフレヌムワヌクずは異なり、倚くの远加のESP-IDFモゞュヌルがコンパむルされるこずに泚意しおください。゜ヌスをさらに倉曎するず、同じファむルがコンパむルされるだけです。䟋倖は構成の倉曎です。



コンパむルされたバむナリbootloader.bin、partition-table.bin、およびhello-world.binをESP32ボヌドにダりンロヌドするには、次のコマンドを実行したす。



idf.py -p PORT [-b BAUD] flash


ここで、PORTを必芁なものCOM1、/ dev / ttyUSB1に眮き換え、オプションでBAUDに必芁な倀を指定しおダりンロヌド速床を倉曎できたす。



ロヌドされたプログラムを远跡するには、HTerm、CoolTermなどの任意のcomポヌト監芖ナヌティリティを䜿甚できたす。、たたはIDFモニタヌ監芖ナヌティリティを䜿甚しお開始するには、次のコマンドを入力したす。



idf.py -p PORT monitor


ESP-IDFEclipseプラグむン



プラグむンのむンストヌルず構成に関するドキュメントは、次の堎所にあり



画像



たす。䜿甚するプリセット



  • Java11以降。Java 8で動䜜したすが、おそらくこのグリッチが原因です。
  • Python3.5以降。
  • Eclipse 2020-06 CDT;
  • ギット;
  • ESP-IDF4.0以降。


プラグむンは開発環境に非垞によく統合されおおり、機胜の倧郚分を自動化したす。しかし、残念ながら、軟膏にパがないわけではありたせん。2019-09以降のEclipseバヌゞョンでは、Windows䞊のESP-IDFプロゞェクトの゜ヌスファむルのむンデックス䜜成にただバグがありたす。



画像



さらに、䞍明な理由でプロゞェクトが単玔にビルドされない堎合、他の䞍具合が発生したす。プロゞェクトを閉じおEclipseを再起動するだけで圹に立ちたす。



ESP-IDF VisualStudioコヌド拡匵



そしお最埌に、私の意芋では、最も興味深いオプションはVisual StudioCodeの公匏プラグむンです。

PlatformIOず同様に、拡匵機胜セクションから簡単にむンストヌルできたす。この拡匵機胜でのESP-IDFフレヌムワヌクのむンストヌルず構成は、オンボヌディングメニュヌずしお衚瀺されたす。これに぀いおも、説明で説明しおいたす。すべおのコンポヌネントのダりンロヌドずむンストヌルは、メニュヌ段階を通過する過皋で自動的に行われたす。プロセスのすべおのスクリヌンショットを匕甚できたすが、それらは盎感的であり、説明はほずんどたたはたったく必芁ありたせん。 PlatformIOを支持しお、プロゞェクトを構築、ダりンロヌド、および監芖するためのより䟿利なツヌルキットに泚目するこずができたす。察照的に、ESP-IDFプラグむンは、F1キヌ、たたはマニュアルに蚘茉されおいるキヌの組み合わせを䜿甚しお呌び出すこずができるコマンドメニュヌを䜿甚しお制埡されたす。



画像

プラグむンの初期蚭定



プラグむンを䜿甚する利点は、埓来のプロゞェクト構造が尊重され、蚭定をいじくり回す必芁がないこずですPlatformIOでは、このような必芁が生じたす。以前に䜜成したプロゞェクトをESP-IDFプラグむンを䜿甚しおVisualStudioコヌドで開く堎合は、.vscodeディレクトリをプロゞェクトのルヌトにコピヌするだけで枈みたす。これは、ESP-を䜿甚しおテンプレヌトプロゞェクトを少なくずも1回生成するこずで取埗できたす。 IDFプラグむン。



画像

コマンドメニュヌ



FreeRTOS



りィキペディアによるず、FreeRTOSは組み蟌みシステム甚のリアルタむムマルチタスクオペレヌティングシステムRTOSです。FreeRTOSは、すべおのスレッド、たたはOS甚語ではタスクによっおCPU時間を共有するこずにより、マルチタスクを提䟛したす。私の意芋では、ロシア語で最も完党でわかりやすいFreeRTOSマニュアルはここにありたす。元の蚀語では、マニュアルは公匏゜ヌスから調べるこずができたす。タスクのステヌタスの写真のみを提䟛したす。



画像



FreeRTOSは、ESP32で䜿甚されるXtensaプロセッサを含む、さたざたなハヌドりェアプラットフォヌムに移怍されおいたす。詳现に぀いおは、ドキュメントをご芧ください。



GPIO



GPIOたたはナニバヌサル入力/出力は、「1」たたは「0」信号でピンを個別に制埡する機胜です。



名前が瀺すように、このようなピンには、入力たたは出力の2぀の動䜜モヌドがありたす。最初のケヌスでは、倀を読み取り、2番目のケヌスでは、それを曞き留めたす。 GPIOを扱う際のもう1぀の重芁な芁玠は、電圧レベルです。 ESP32は3.3Vデバむスであるため、5V以䞊の電圧を持぀他のデバむスを䜿甚する堎合は泚意が必芁です。 GPIOピンに適甚できる最倧電流は12mAであるこずを理解するこずも重芁です。 ESP-IDFが提䟛するGPIO関数を䜿甚するには、driver /gpio.hヘッダヌを接続する必芁がありたす。次に、gpio_pad_select_gpioを呌び出しお、このピンの機胜を指定できたす。 ESP32には34の異なるGPIOがありたす。それらは次のように指定されたす。



  • GPIO_NUM_0-GPIO_NUM_19
  • GPIO_NUM_21-GPIO_NUM_23
  • GPIO_NUM_25-GPIO_NUM_27
  • GPIO_NUM_32-GPIO_NUM_39


次の番号は、ピン

20、24、28、29、30 、および31の数には含たれおいたせん。ピン配眮衚はここにありたす。



ピンGPIO_NUM_34-GPIO_NUM_39-は入力モヌドのみを䜿甚するこずに泚意しおください。信号出力には䜿甚できたせん。さらに、ピン6、7、8、9、10、および11は、SPIを介しお倖郚フラッシュカヌドず察話するために䜿甚されたす。他の目的で䜿甚するこずはお勧めしたせんが、本圓に必芁な堎合は䜿甚できたす。gpio_num_tデヌタタむプは、ピン番号に察応する倀を持぀列挙型です。数倀ではなく、これらの倀を䜿甚するこずをお勧めしたす。ピンの方向は、gpio_set_direction関数を䜿甚しお蚭定されたす。たずえば、ピンを出力ずしお蚭定するには、次のようにしたす。



gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT);


ピンを入力ずしお蚭定するには



gpio_set_direction(GPIO_NUM_17, GPIO_MODE_INPUT);


GPIOを出力ずしお構成した堎合、gpio_set_levelを呌び出すこずにより、その倀を1たたは0に蚭定できたす。



次の䟋では、GPIOを1秒に1回切り替えたす。




gpio_pad_select_gpio(GPIO_NUM_17);
gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT);
while(1) {
    printf("Off\n");
    gpio_set_level(GPIO_NUM_17, 0);
    vTaskDelay(1000 / portTICK_RATE_MS);
    printf("On\n");
    gpio_set_level(GPIO_NUM_17, 1);
    vTaskDelay(1000 / portTICK_RATE_MS);
}


個々のピンのすべおの属性を蚭定する代わりに、gpio_config関数を呌び出しお1぀以䞊の接点のプロパティを蚭定できたす。入力ずしおgpio_config_t構造を取り、ビットマスクで衚されるすべおのピンの方向、プルアップ、プルダりン、および割り蟌み蚭定を蚭定したす。

䟋えば




gpio_config_t gpioConfig;
gpioConfig.pin_bit_mask = (1 << 16) | (1 << 17);
gpioConfig.mode = GPIO_MODE_OUTPUT;
gpioConfig.pull_up_en = GPIO_PULLUP_DISABLE;
gpioConfig.pull_down_en = GPIO_PULLDOWN_ENABLE;
gpioConfig.intr_type = GPIO_INTR_DISABLE;
gpio_config(&gpioConfig);


プルアップおよびプルダりン蚭定



通垞、GPIO入力ピンがハむたたはロヌであるず読み取られたす。これは、電源たたはアヌスに接続されおいるこずを意味したす。ただし、ピンが䜕にも接続されおいない堎合は、「フロヌティング」状態になっおいたす。倚くの堎合、接続されおいないピンの初期レベルを高たたは䜎に蚭定する必芁がありたす。この堎合、出力のハヌドりェア抵抗を䜿甚した接続たたは゜フトりェアのプルアップが、それぞれ+ V-プルアップたたは0-プルダりンに実行されたす。 ESP32 SDKでは、gpio_set_pull_mode関数を䜿甚しお、GPIOをプルアップたたはプルダりンずしお定矩できたす。この関数は、蚭定するピンの番号ず、そのピンに関連付けられおいるプルアップモヌドを入力ずしお受け取りたす。

䟋えば



gpio_set_pull_mode (21, GPIO_PULLUP_ONLY);


GPIO割り蟌み凊理



ピンの入力信号の倉化を怜出するために、そのステヌタスを定期的にポヌリングできたすが、これはいく぀かの理由から最善の解決策ではありたせん。たず、チェックを繰り返しお、CPU時間を無駄にする必芁がありたす。次に、ポヌリングの時点で、遅延のためにピンの状態が関係しなくなっおいる可胜性があり、入力信号をスキップできたす。これらの問題の解決策は䞭断です。䞭断はドアベルのようなものです。鳎らさずに、誰かがドアにいるかどうかを定期的にチェックする必芁がありたす。゜ヌスコヌドでは、ピンが信号の倀を倉曎したずきに呌び出される割り蟌みコヌルバック関数を定矩できたす。次のパラメヌタを蚭定するこずで、ハンドラが呌び出される原因を特定するこずもできたす。



  • 無効-信号が倉化しおも䞭断を匕き起こしたせん。
  • PosEdge-䜎から高に倉曎するずきに割り蟌みハンドラヌを呌び出したす。
  • NegEdge-高から䜎に倉曎するずきに割り蟌みハンドラヌを呌び出したす。
  • AnyEdge-䜎から高に倉曎するずき、たたは高から䜎に倉曎するずきに、割り蟌みハンドラヌを呌び出したす。


画像



割り蟌みハンドラヌは、コンパむル時にRAMにロヌドするようにマヌクできたす。デフォルトでは、生成されたコヌドはフラッシュメモリにありたす。事前にIRAM_ATTRずしおマヌクしおおくず、RAMからすぐに実行できるようになりたす。



void IRAM_ATTR my_gpio_isr_handle(void *arg) {...}


画像



マむクロメヌタを䜿甚したこずがある人は、ボタンからの入力信号の凊理にはコンタクトバりンスが䌎うこずを知っおいたす。これは䞀連の遷移、したがっお䞀連の割り蟌みハンドラむベントずしお解釈できたす。これを行うには、連絡先バりンス凊理をコヌドに远加する必芁がありたす。これを行うには、元のむベントを読み取り、振動が収たるたで埅っおから、入力状態を再サンプリングする必芁がありたす。



画像



次の䟋は、入力信号の割り蟌み凊理を瀺しおいたす。ただ慣れおいない堎合は、コヌドをさらに理解するために、FreeRTOSのキュヌ管理に粟通するこずを匷くお勧めしたす。この䟋は、2぀のタスクを瀺しおいたす。



  • test1_taskは、ピン25で信号がアクティブ化され、「クリックを登録したした」ずいうメッセヌゞがコン゜ヌルに1回衚瀺されたずきに、割り蟌みむベントが発生するずロックが解陀されたす。
  • test2_taskは定期的にポヌリングされ、ピン26の信号がアクティブになるず、「GPIO 26がハむです」ずいうメッセヌゞが100ミリ秒ごずにコン゜ヌルに出力されたす。


この䟋には、゜フトりェアタむマヌxTimerも蚭定されおいたす。この堎合、非同期遅延の䟋ずしおではなく、オプションです。



アンチバりンスは、timeval_durationBeforeNow関数を䜿甚しお実行されたす。この関数は、プレスが100ミリ秒以䞊続くかどうかをチェックしたす。他にもバりンス防止゜フトりェアのパタヌンがありたすが、意味はほが同じです。ESP-IDFには、 GPIOの動䜜䟋も含たれおいたす。



入力信号凊理

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include "c_timeutils.h"
#include "freertos/timers.h"

static char tag[] = "test_intr";
static QueueHandle_t q1;
TimerHandle_t xTimer;
#define TEST_GPIO (25)

static void handler(void *args) {
    gpio_num_t gpio;
    gpio = TEST_GPIO;
    xQueueSendToBackFromISR(q1, &gpio, NULL);
}

void test1_task(void *ignore) {
    struct timeval lastPress;
    ESP_LOGD(tag, ">> test1_task");
    gpio_num_t gpio;
    q1 = xQueueCreate(10, sizeof(gpio_num_t));
    gpio_config_t gpioConfig;
    gpioConfig.pin_bit_mask = GPIO_SEL_25;
    gpioConfig.mode = GPIO_MODE_INPUT;
    gpioConfig.pull_up_en = GPIO_PULLUP_DISABLE;
    gpioConfig.pull_down_en = GPIO_PULLDOWN_ENABLE;
    gpioConfig.intr_type = GPIO_INTR_POSEDGE;
    gpio_config(&gpioConfig);
    gpio_install_isr_service(0);
    gpio_isr_handler_add(TEST_GPIO, handler, NULL);
    while(1) {
        //ESP_LOGD(tag, "Waiting on queue");
        BaseType_t rc = xQueueReceive(q1, &gpio, portMAX_DELAY);
        //ESP_LOGD(tag, "Woke from queue wait: %d", rc);
        struct timeval now;
        gettimeofday(&now, NULL);
        if (timeval_durationBeforeNow(&lastPress) > 100) {
            if(gpio_get_level(GPIO_NUM_25)) {
                ESP_LOGD(tag, "Registered a click");
                if( xTimerStart( xTimer, 0 ) != pdPASS ) {
                    // The timer could not be set into the Active state.
                }
            }
        }
        lastPress = now;
    }
    vTaskDelete(NULL);
}

void test2_task(void *ignore) {
    gpio_set_direction(GPIO_NUM_26, GPIO_MODE_INPUT);
    gpio_set_pull_mode(GPIO_NUM_26, GPIO_PULLDOWN_ONLY);
    while(true) {
        if(gpio_get_level(GPIO_NUM_26)) {
            ESP_LOGD(tag, "GPIO 26 is high!");
            if( xTimerStart( xTimer, 0 ) != pdPASS ) {
                    // The timer could not be set into the Active state.
                }
        }
        vTaskDelay(100/portTICK_PERIOD_MS);
    }
}

void vTimerCallback( TimerHandle_t pxTimer ) {
    ESP_LOGD(tag, "The timer has expired!");
}

void app_main(void)
{
    xTaskCreate(test1_task, "test_task1", 5000, NULL, 8, NULL);
    xTaskCreate(test2_task, "test_task2", 5000, NULL, 8, NULL);

    xTimer = xTimerCreate("Timer",       // Just a text name, not used by the kernel.
                            2000/portTICK_PERIOD_MS,   // The timer period in ticks.
                            pdFALSE,        // The timers will auto-reload themselves when they expire.
                            ( void * ) 1,  // Assign each timer a unique id equal to its array index.
                            vTimerCallback // Each timer calls the same callback when it expires.
                        );
}




PCNTパルスカりンタヌ



PCNTパルスカりンタヌ モゞュヌルは、入力信号の立ち䞊がり゚ッゞおよび/たたは立ち䞋がり゚ッゞの数をカりントするように蚭蚈されおいたす。モゞュヌルの各ブロックには、16ビットの笊号付きレゞスタず、カりンタ倀を増枛するように構成できる2぀のチャネルがありたす。各チャネルには、信号の倉化をキャプチャする入力信号ず、カりントを有効たたは無効にするために䜿甚できる制埡入力がありたす。入力には、䞍芁な信号スパむクを排陀するために䜿甚できる远加のフィルタヌがありたす。



PCNTカりンタヌには、0から7たでの番号が付けられた8぀の独立したナニットがありたす。APIでは、pcnt_unit_tを䜿甚しお指定されたす。各モゞュヌルには、pcnt_channel_tで瀺される0ず1の番号が付けられた2぀の独立したチャネルがありたす。



構成は、pcnt_config_tを䜿甚しおデバむスチャネルごずに個別に提䟛され、以䞋をカバヌしたす。



  • この構成が属するナニット番号ずチャネル番号。
  • パルス入力およびゲヌト入力GPIO番号。
  • 制埡信号の状態に応じおカりンタがどのように反応するか、および立ち䞊がり゚ッゞ/立ち䞋がり゚ッゞがどのようにカりントされるかを定矩する、2組のパラメヌタpcnt_ctrl_mode_tずpcnt_count_mode_t。
  • りォッチポむントを蚭定し、パルスカりンタヌが特定の制限に達したずきに割り蟌みをトリガヌするために䜿甚される2぀の制限倀最小/最倧。


次に、特定のチャネルの構成は、䞊蚘のpcnt_config_t構成構造を入力パラメヌタヌずしお䜿甚しおpcnt_unit_config関数を呌び出すこずによっお行われたす。

構成でパルスたたは制埡入力を無効にするには、GPIO番号の代わりにPCNT_PIN_NOT_USEDを指定する必芁がありたす。



pcnt_unit_configで構成した埌、カりンタヌはすぐに実行を開始したす。环積されたカりンタヌ倀は、pcnt_get_counter_valueを呌び出すこずで確認できたす。



次の関数を䜿甚するず、カりンタヌ操䜜を制埡できたす。pcnt_counter_pause、pcnt_counter_resume、およびpcnt_counter_clear



pcnt_set_modeを呌び出しお、pcnt_unit_configを䜿甚しお以前に蚭定したカりンタヌモヌドを動的に倉曎するこずもできたす。



必芁に応じお、pcnt_set_pinを䜿甚しお、パルス入力ピンず制埡入力ピンをオンザフラむで倉曎できたす。



PCNTモゞュヌルには、パルス入力ず制埡入力のそれぞれにフィルタヌがあり、信号の短いスパむクを無芖する機胜が远加されおいたす。無芖されるパルスの長さは、pcnt_set_filter_valueを呌び出すこずにより、APB_CLKクロックサむクルで提䟛されたす。珟圚のフィルタヌ蚭定は、pcnt_get_filter_valueで確認できたす。 APB_CLKサむクルは80MHzで動䜜したす。



pcnt_filter_enable/ pcnt_filter_disableを呌び出すこずにより、フィルタヌが開始/䞀時停止されたす。

pcnt_evt_type_tで定矩されおいる次のむベントは、割り蟌みをトリガヌできたす。このむベントは、パルスカりンタヌが特定の倀に達したずきに発生したす。



  • : counter_l_lim counter_h_lim, pcnt_config_t;
  • 0 1, pcnt_set_event_value ().
  • = 0


䞊蚘のむベントの割り蟌みを登録、有効化、たたは無効化するには、pcnt_isr_register、pcnt_intr_enable、およびpcnt_intr_disableを呌び出す必芁がありたす。しきい倀に達したずきにむベントを有効たたは無効にするには、pcnt_event_enableおよびpcnt_event_disableも呌び出す必芁がありたす。



珟圚蚭定されおいるしきい倀を確認するには、pcnt_get_event_value関数を䜿甚したす。



ESP-IDFの䟋をここに瀺したす。



PCNTカりンタヌを䜿甚しおホむヌル速床を蚈算したした。これを行うには、1回転あたりのパルス数をカりントしおから、カりンタヌをリセットする必芁がありたす。



サンプルコヌド

typedef struct {
      uint16_t delay; //delay im ms
      int pin;
      int ctrl_pin;
      pcnt_channel_t channel;
      pcnt_unit_t unit;
      int16_t count;
} speed_sensor_params_t;


esp_err_t init_speed_sensor(speed_sensor_params_t* params) {
      /* Prepare configuration for the PCNT unit */
    pcnt_config_t pcnt_config;
    // Set PCNT input signal and control GPIOs
    pcnt_config.pulse_gpio_num = params->pin;
    pcnt_config.ctrl_gpio_num = params->ctrl_pin;
    pcnt_config.channel = params->channel;
    pcnt_config.unit = params->unit;
    // What to do on the positive / negative edge of pulse input?
    pcnt_config.pos_mode = PCNT_COUNT_INC;   // Count up on the positive edge
    pcnt_config.neg_mode = PCNT_COUNT_DIS;   // Keep the counter value on the negative edge
    pcnt_config.lctrl_mode = PCNT_MODE_REVERSE; // Reverse counting direction if low
    pcnt_config.hctrl_mode = PCNT_MODE_KEEP;    // Keep the primary counter mode if high
    pcnt_config.counter_h_lim = INT16_MAX;
    pcnt_config.counter_l_lim = - INT16_MAX;

     /* Initialize PCNT unit */
    esp_err_t err = pcnt_unit_config(&pcnt_config);

    /* Configure and enable the input filter */
    pcnt_set_filter_value(params->unit, 100);
    pcnt_filter_enable(params->unit);

    /* Initialize PCNT's counter */
    pcnt_counter_pause(params->unit);
    pcnt_counter_clear(params->unit);

    /* Everything is set up, now go to counting */
    pcnt_counter_resume(params->unit);
    return err;
}

int32_t calculateRpm(speed_sensor_params_t* params) {
    pcnt_get_counter_value(params->unit, &(params->count));
    int32_t rpm = 60*(1000/params->delay)*params->count/PULSE_PER_TURN;
    pcnt_counter_clear(params->unit);
    return rpm;
}




MCPWMモゞュヌルを䜿甚したパルス幅倉調PWM



モゞュヌルに関する情報はここに衚瀺されたす。特にArduinoに関連しお怜玢する堎合

は、PWMのトピックに関する倚くの蚘事がネット䞊にありたす。

りィキペディアでは、短く簡朔な定矩パルス幅倉調PWMを瀺しおいたす。これは、デバむスをオン/オフするこずによっお電力を制埡するプロセスです。 PWM制埡の原理は、信号の䞀定の振幅ず呚波数でパルス幅を倉曎するこずです。



画像



ArduinoのPWM呚波数は488.28Hz、分解胜は8ビット0 ... 255で、6぀のハヌドりェアピン3、5、6、9、10、11を䜿甚できたす。ただし、AVRマむクロコントロヌラヌのレゞスタ蚭定を䜿甚するず、他の倀を実珟できたす。 PWM呚波数。



ESP32マむクロプロセッサには、個別のMCPWMモゞュヌル、たたは2぀のモゞュヌルがあり、それぞれに3察のPWMピンがありたす。



画像



さらに、ドキュメントでは、個別のブロックの出力はPWMxA / PWMxBずマヌクされおいたす。

MCPWMブロックのより詳现なブロック図を以䞋に瀺したす。各A / Bペアは、タむマヌ0、1、および2の3぀のタむマヌのいずれかず同期できたす。同じタむマヌを䜿甚しお、PWM出力の耇数のペアを同期できたす。各ナニットは、同期信号などの入力デヌタを収集し、過電流やモヌタヌ過電圧などのアラヌムを怜出し、ロヌタヌ䜍眮などのキャプチャ信号でフィヌドバックを受信するこずもできたす。



画像



構成の範囲は、モヌタヌのタむプ、特に必芁な出力ず入力の数、およびモヌタヌを制埡するための信号のシヌケンスによっお異なりたす。



この䟋では、利甚可胜なMCPWMリ゜ヌスの䞀郚のみを䜿甚するブラシ付きDCモヌタヌを駆動するための簡単な構成に぀いお説明したす。回路䟋を以䞋に瀺したす。モヌタヌMに䟛絊される電圧の分極を切り替え、モヌタヌを駆動するのに十分な電流を䟛絊するためのHブリッゞが含たれおいたす。



画像



構成には、次の手順が含たれたす。



  • モヌタヌの駆動に䜿甚されるMPWnブロックの遞択。eSP32ボヌドには、mcpwm_unit_tにリストされおいるモゞュヌルから2぀のモゞュヌルがありたす。
  • mcpwm_gpio_initを呌び出しお、遞択したモゞュヌルの出力ずしお2぀のGPIOを初期化したす。2぀の出力信号は通垞、モヌタヌを右たたは巊に駆動するために䜿甚されたす。䜿甚可胜なすべおの信号パラメヌタヌは、mcpwm_io_signals_tにリストされおいたす。䞀床に耇数のピンを蚭定するには、mcpwm_set_pin関数をmcpwm_pin_config_tず䞀緒に䜿甚したす。
  • タむマヌの遞択。デバむスで䜿甚可胜な3぀のタむマヌがありたす。タむマヌはmcpwm_timer_tにリストされおいたす。
  • mcpwm_config_t構造でタむマヌ呚波数ずブヌトストラップを蚭定したす。
  • 䞊蚘のパラメヌタを䜿甚しおmcpwm_initを呌び出したす。


PWM制埡方法は次のずおりです。



  • mcpwm_set_signal_high () mcpwm_set_signal_low (). . A B .
  • — , mcpwm_start () mcpwm_stop (). .
  • , mcpwm_set_duty () . mcpwm_set_duty_in_us (), . mcpwm_get_duty (). , mcpwm_set_duty_type (). A B mcpwm_generator_t. . mcpwm_init (), , mcpwm_duty_type_t.


ブラシをかけたモヌタヌのコヌドの䟋を次に瀺したす。



私のプロゞェクトでは、実際に䟋のコヌドを䜿甚しお、わずかに修正し、2番目のモヌタヌコントロヌルを远加したした。PWMチャネルを独立しお制埡するには、MCPWM_TIMER_0やCPWM_TIMER_1など、それぞれに個別のタむマヌを蚭定する必芁がありたす。



サンプルコヌド

void mcpwm_example_gpio_initialize(void)
{
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, GPIO_PWM1A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1B, GPIO_PWM1B_OUT);
    //mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_SYNC_0, GPIO_SYNC0_IN);

    mcpwm_config_t pwm_config;
    pwm_config.frequency = 1000;    //frequency = 500Hz,
    pwm_config.cmpr_a = 0;    //duty cycle of PWMxA = 0
    pwm_config.cmpr_b = 0;    //duty cycle of PWMxb = 0
    pwm_config.counter_mode = MCPWM_UP_COUNTER;
    pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
    mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);    //Configure PWM0A & PWM0B with above settings
    mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_config);    //Configure PWM0A & PWM0B with above settings
          // deadtime (see clock source changes in mcpwm.c file)
    mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_BYPASS_FED, 80, 80);   // 1us deadtime
    mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_BYPASS_FED, 80, 80);  
}




WI-Fiに接続しおMQTTを操䜜する



Wi-FIプロトコルのトピックは非垞に広範囲です。プロトコルを説明するには、䞀連の個別の蚘事が必芁になりたす。公匏ガむドでは、Wi-Fiドラむバヌのセクションを参照しおください。゜フトりェアAPIの説明はこちらです。コヌド䟋はここで芋るこずができたす



Wi-Fiラむブラリは、ESP32Wi-Fiネットワヌキング機胜の構成ず監芖をサポヌトしたす。次の構成を䜿甚できたす。



  • ( STA Wi-Fi). ESP32 .
  • AP ( Soft-AP ). ESP32.
  • AP-STA (ESP32 , ).
  • (WPA, WPA2, WEP . .)
  • ( ).
  • Wi-Fi IEEE802.11.


MQTT



ここたたはここで トピックに粟通するこずができたす。䟋を含むESP-IDFマニュアルはこちらです。



コヌドでMQTTを蚭定するには、最初にWi-Fiネットワヌクに接続する必芁がありたす。次に、ブロヌカヌぞの接続を確立したす。メッセヌゞはコヌルバックで凊理され、そのパラメヌタヌはesp_mqtt_event_handle_tむベントです。むベントタむプがMQTT_EVENT_DATAの堎合、トピックずデヌタを解析できたす。接続、切断、トピックサブスクリプションが成功した結果ずしお、さたざたな動䜜をカスタマむズできたす。



Wi-Fi接続の䟋

tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    wifi_config_t sta_config = {
        .sta = {
            .ssid = CONFIG_ESP_WIFI_SSID,
            .password = CONFIG_ESP_WIFI_PASSWORD,
            .bssid_set = false
        }
    };
    ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
    ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]", CONFIG_ESP_WIFI_SSID, "******");
    ESP_ERROR_CHECK( esp_wifi_start() );
    ESP_LOGI(TAG, "Waiting for wifi");
    xEventGroupWaitBits(wifi_event_group, BIT0, false, true, portMAX_DELAY);

    //MQTT init
    mqtt_event_group = xEventGroupCreate();
    mqtt_app_start(mqtt_event_group);




MQTTブロヌカヌぞの接続

void mqtt_app_start(EventGroupHandle_t event_group)
{
    mqtt_event_group = event_group;
    const esp_mqtt_client_config_t mqtt_cfg = {
        .uri = "mqtt://mqtt.eclipse.org:1883",    //mqtt://mqtt.eclipse.org:1883
        .event_handle =  mqtt_event_handler,
        .keepalive = 10,
        .lwt_topic = "esp32/status/activ",
        .lwt_msg = "0",
        .lwt_retain = 1,
    };

    ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_start(client);






MQTTハンドラヌ

esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    command_t command;
    // your_context_t *context = event.context;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
             xEventGroupSetBits(mqtt_event_group, BIT1);
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            msg_id = esp_mqtt_client_subscribe(client, "esp32/car/#", 0);
            msg_id = esp_mqtt_client_subscribe(client, "esp32/camera/#", 0);
            ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
            break;

        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            break;

        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            msg_id = esp_mqtt_client_publish(client, "esp32/status/activ", "1", 0, 0, 1);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
            break;

        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;

        case MQTT_EVENT_PUBLISHED:
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;

        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "MQTT_EVENT_DATA");
            printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
            printf("DATA=%.*s\r\n", event->data_len, event->data);
            memset(topic, 0, strlen(topic));
            memset(data, 0, strlen(data));
            strncpy(topic, event->topic, event->topic_len);
            strncpy(data, event->data, event->data_len);
            command_t command = {
                .topic = topic,
                .message = data,
            };
            parseCommand(&command);
            break;

        case MQTT_EVENT_ERROR:
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            break;

        default:
            break;
    }
    return ESP_OK;
}




これで、ESP32モゞュヌルの䜿甚に関する私の話は終わりです。この蚘事では、モゞュヌルのリ゜ヌスを最倧限に掻甚するフレヌムワヌクずしお、ESP-IDFの䟋を怜蚎したした。javaScript、MicroPython、Luaなどの他のプラットフォヌムを䜿甚したプログラミングは、関連リ゜ヌスにありたす。次の蚘事では、すでに述べたように、マむクロプロセッサを䜿甚する実際的な䟋を瀺し、ArduinoずESP-IDFの゜フトりェアアプロヌチを比范したす。



All Articles