Perangkat pemrograman berdasarkan modul ESP32

Mikrokontroler adalah sirkuit terintegrasi yang mampu menjalankan program. Ada banyak model seperti itu di pasaran saat ini dari berbagai produsen. Harga perangkat ini terus turun. Chip chip tunggal banyak digunakan di berbagai bidang: dari alat ukur hingga hiburan dan semua jenis peralatan rumah tangga. Tidak seperti komputer pribadi, mikrokontroler menggabungkan fungsi prosesor dan perangkat periferal dalam satu kristal, berisi RAM dan memori hanya-baca untuk menyimpan kode dan data, tetapi memiliki sumber daya komputasi yang jauh lebih sedikit. ESP32 adalah mikrokontroler yang dikembangkan oleh Espressif Systems. ESP32 adalah sistem-on-chip dengan pengontrol Wi-Fi dan Bluetooth terintegrasi. Seri ESP32 menggunakan intiTensilica Xtensa LX6 . Papan dengan ESP32 memiliki daya komputasi yang baik, periferal yang dikembangkan sangat populer karena harganya yang rendah di kisaran $ 7 - $ 14: Aliexpress , Amazon .



Artikel ini tidak dimaksudkan sebagai panduan lengkap, melainkan kumpulan sumber bahan dan rekomendasi. Dalam artikel ini, saya ingin menyentuh masalah yang harus saya hadapi ketika memilih alat perangkat lunak untuk pengembangan proyek, serta beberapa kasus penerapan praktis modul ESP32. Pada artikel berikutnya, saya ingin menunjukkan contoh ilustrasi penggunaan ESP32 sebagai pengontrol kontrol untuk platform seluler roda dua kecil. Oleh karena itu, di sini kami akan mempertimbangkan detail seperti:



  • Memilih lingkungan pengembangan;
  • Menyiapkan lingkungan kerja, menyusun dan memuat proyek ESP-IDF;
  • Pemrosesan sinyal input / output GPIO;
  • Modulasi lebar pulsa menggunakan modul MCPWM;
  • Penghitung perangkat keras PCNT;
  • Koneksi WI-Fi dan MQTT.


Ringkasan modul ESP32-WROOM-32E



Menurut datasheet modul tersebut berisi:



MCU



  • ESP32-D0WD-V3 tertanam, mikroprosesor Xtensa dual-core 32-bit LX6, hingga 240 MHz
  • ROM 448 KB untuk booting dan fungsi inti
  • 520 KB SRAM untuk data dan instruksi
  • 16 KB SRAM di RTC


Wifi



  • 802.11b / g / n
  • Kecepatan bit: 802.11n hingga 150 Mbps
  • Agregasi A-MPDU dan A-MSDU
  • Dukungan interval penjaga 0,4 Β΅s
  • Rentang frekuensi pusat saluran operasi: 2412 ~ 2484 MHz


Bluetooth



  • Spesifikasi Bluetooth V4.2 BR / EDR dan Bluetooth LE
  • Pemancar kelas-1, kelas-2 dan kelas-3
  • AFH
  • CVSD dan SBC


Perangkat keras



  • 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


gambar

Diagram blok fungsional



Lebih detail tentang fitur mikrokontroler dapat ditemukan di Wikipedia .



Modul ini didasarkan pada sirkuit mikro ESP32-D0WD-V3 *. Chip yang disematkan dirancang dengan mempertimbangkan skalabilitas dan kemampuan beradaptasi. Unit pemrosesan pusat berisi dua inti yang dapat dikontrol secara individual, dan kecepatan clock CPU dapat disesuaikan dari 80 MHz hingga 240 MHz. Chip tersebut juga memiliki koprosesor berdaya rendah yang dapat digunakan sebagai pengganti CPU untuk menghemat daya saat melakukan tugas yang tidak membutuhkan banyak daya komputasi, seperti memantau status pin. ESP32 mengintegrasikan beragam perangkat periferal mulai dari sensor sentuh kapasitif, sensor Hall, antarmuka kartu SD, Ethernet, SPI kecepatan tinggi, UART, IΒ²S, dan IΒ²C.



Dokumentasi teknis disajikan di sumber resmi .



Informasi tentang pinout modul ESP-WROOM-32 dapat dengan mudah ditemukan di ruang terbuka jaringan, seperti di sini



Memilih lingkungan pengembangan



IDE Arduino



Mikrokontroler dari keluarga AVR, dan kemudian platform Arduino, muncul jauh sebelum ESP32. Salah satu fitur utama Arduino adalah penghalang masuknya yang relatif rendah, memungkinkan hampir semua orang membuat sesuatu dengan cepat dan mudah. Platform ini telah memberikan kontribusi penting bagi komunitas perangkat keras open source dan memungkinkan sejumlah besar amatir radio untuk bergabung. Arduino IDE dapat diunduh gratis dari luar situs . Terlepas dari batasan yang jelas dibandingkan dengan lingkungan pengembangan profesional, Arduino IDE mencakup 90% dari apa yang diperlukan untuk proyek hobi. Ada juga cukup banyak artikel di jaringan tentang topik menginstal dan mengkonfigurasi Arduino IDE untuk pemrograman modul ESP32, misalnya: Arduino core untuk ESP32 , habr.com, Voltiq.ru dan randomnerdtutorials.com .



Saat memprogram ESP32 di lingkungan Arduino, Anda perlu memperhitungkan pinout seperti yang ditunjukkan pada halaman arduino-esp32 .



gambar

Pinout modul ESP32



Keuntungan utama dari pendekatan desain ini adalah entri cepat dan kemudahan pembuatan proyek, menggunakan prinsip yang sama seperti untuk Arduino. Dan juga penggunaan banyak pustaka, adapun Arduino. Fitur bagus lainnya adalah kemampuan untuk menggabungkan pustaka Arduino dan prinsip desain dengan kerangka ESP-IDF asli.



PlatformIO



Seperti yang dinyatakan pada sumber resmi : β€œCross-platform PlatformIO IDE dan Unified Debugger Β· Static Code Analyzer dan Remote Unit Testing. Sistem Bangun Multi-platform dan Multi-arsitektur Β· Penjelajah File Firmware dan Pemeriksaan Memori Β»Dengan kata lain, PlatformIO adalah ekosistem untuk pengembangan perangkat tertanam yang mendukung berbagai platform termasuk Arduino dan ESP32. IDE adalah Visual Studio Code atau Atom. Instalasi dan konfigurasi cukup sederhana - setelah menginstal editor kode, pilih PlatformIO dari daftar plugin dan instal. Sekali lagi, ada banyak materi tentang topik ini di internet, mulai dari sumber resminya di sini dan di sini , dan dilanjutkan dengan artikel dengan ilustrasi terperinci di sini dan di sini....



Dibandingkan dengan Arduino IDE, PlatformIO memiliki semua kualitas lingkungan pengembangan modern: organisasi proyek, dukungan plug-in, penyelesaian kode, dan banyak lagi.



Fitur pengembangan di PlatformIO adalah struktur proyek terpadu untuk semua platform



project_dir
β”œβ”€β”€ lib
β”‚   └── README
β”œβ”€β”€ platformio.ini
└── src
    └── main.cpp


Setiap proyek PlatformIO berisi file konfigurasi bernama platformio.ini di root proyek. platformio.ini memiliki bagian (masing-masing dilambangkan dengan [judul]) dan pasangan kunci / nilai di dalam bagian. Garis yang dimulai dengan titik-titik koma ";" diabaikan dan dapat digunakan untuk komentar. Beberapa parameter nilai dapat ditentukan dengan dua cara:



  1. memisahkan nilai dengan "," (koma + spasi);
  2. format multi-baris, di mana setiap baris baru dimulai dengan setidaknya dua spasi.


Fitur pengembangan selanjutnya untuk ESP32 adalah kemampuan untuk memilih kerangka kerja: Arduino atau ESP-IDF. Dengan memilih Arduino sebagai kerangka kerja, kami mendapatkan manfaat pengembangan yang dijelaskan sebelumnya.



gambar



PlatformIO menyertakan alat yang mudah digunakan untuk membangun, mengunduh, dan men-debug proyek



gambar



Framework Pengembangan IoT Espressif



Untuk ESP32, Espressif telah mengembangkan kerangka kerja yang disebut Kerangka Pengembangan IoT yang dikenal sebagai "ESP-IDF". Itu dapat ditemukan di Github . Proyek ini berisi dokumentasi yang sangat bagus dan dilengkapi dengan contoh-contoh yang dapat Anda ambil sebagai dasar. Menyiapkan dan menyiapkan lingkungan didokumentasikan dengan baik di bagian Memulai . Ada beberapa opsi untuk menginstal dan bekerja dengan framework.



Menggandakan proyek dari repositori dan menginstal utilitas secara manual.



Menggandakan proyek dari Github



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


Untuk Windows, penginstalan utilitas pengembangan dapat dilakukan menggunakan penginstal atau menggunakan skrip untuk baris perintah:



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


Untuk PowerShell



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


Untuk Linux dan macOS



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


Langkah selanjutnya adalah menyiapkan variabel lingkungan . Jika alat pengembangan diinstal pada Windows menggunakan penginstal, maka pintasan ke konsol perintah ditambahkan ke menu dan ke desktop, setelah itu Anda dapat membuka shell perintah dan bekerja dengan proyek. Alternatifnya, untuk menjalankan shell perintah Windows:



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


atau Windows PowerShell:



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


Linux dan macOS:



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


Anda harus memperhatikan ruang antara titik dan jalur ke skrip.



Lebih lanjut dalam panduan ini, disarankan untuk menambahkan alias ke skrip untuk mengatur variabel lingkungan di profil pengguna jika Anda bekerja di Linux atau macOS. Untuk melakukan ini, salin dan tempel perintah berikut ke profil shell Anda (.profile, .bashrc, .zprofile, dll.):



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


Dengan memanggil perintah get_idf di konsol, variabel lingkungan yang diperlukan akan diekspor. Dalam kasus saya, itu juga perlu mendaftarkan alias untuk memulai lingkungan virtual python



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


dan menambahkannya ke alias berikutnya



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


Untuk membuat proyek baru dari awal, Anda dapat mengkloning sumber dari github.com atau menyalin dari direktori dengan contoh esp-idf / contoh / get-mulai / hello_world /.



Informasi tentang struktur proyek, kompilasi, pemuatan, utilitas konfigurasi, dll ada di sini .



Proyek adalah direktori dengan struktur berikut:



- 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/


Konfigurasi proyek terdapat dalam file sdkconfig di direktori root. Untuk mengubah pengaturan, Anda perlu memanggil perintah idf.py menuconfig (atau mungkin idf.py.exe menuconfig di Windows).



Biasanya dua aplikasi dibuat dalam satu proyek - "aplikasi proyek" (file utama yang dapat dijalankan, yaitu firmware khusus Anda) dan "aplikasi bootloader" (program bootloader proyek).

"Komponen" adalah bagian modular dari kode yang berdiri sendiri yang dikompilasi ke dalam pustaka statis (file .a) dan ditautkan ke aplikasi. Beberapa di antaranya disediakan oleh ESP-IDF sendiri, yang lainnya dapat diperoleh dari sumber lain.



Utilitas baris perintah idf.py menyediakan antarmuka untuk mengelola pembangunan proyek dengan mudah. Lokasinya di Windows adalah% userprofile% \. Espressif \ tools \ idf-exe \ 1.0.1 \ idf.py.exe. Dia mengontrol instrumen berikut:



  • CMake - mengonfigurasi proyek yang akan dibangun
  • Pembuat proyek konsol: Ninja, atau GNU Make)
  • esptool.py - untuk mem-flash modul.


Setiap proyek memiliki satu file CMakeLists.txt tingkat atas yang berisi pengaturan build untuk keseluruhan proyek. Konfigurasi file minimal mencakup baris yang diperlukan berikut ini:



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


Proyek ESP-IDF dapat dianggap sebagai kumpulan komponen di mana direktori utama adalah komponen utama yang menjalankan kode. Oleh karena itu, direktori ini juga berisi file CMakeLists.txt. Paling sering, strukturnya mirip:



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


Di mana diindikasikan bahwa file sumber main.c harus didaftarkan untuk komponen, dan file header terdapat dalam direktori saat ini. Jika perlu, Anda dapat mengganti nama direktori utama dengan menyetel EXTRA_COMPONENT_DIRS di proyek CMakeLists.txt. Detail selengkapnya dapat ditemukan di sini .



Selain itu, direktori ini berisi file main.c asli (namanya bisa apa saja) dengan titik masuk - fungsi void app_main (void).



Komponen kustom akan dibuat di direktori komponen. Prosesnya dijelaskan lebih detail di bagian Persyaratan Komponen.



Menghubungkan modul ESP32 ke komputer dalam banyak kasus dilakukan menggunakan kabel USB seperti papan Arduino karena bootloader yang ada. Prosesnya dijelaskan lebih detail di sini... Satu-satunya hal yang diperlukan adalah kehadiran driver konverter USB ke UART di sistem, yang dapat diunduh dari sumber yang diberikan. Setelah menginstal driver, Anda perlu menentukan nomor port COM di sistem untuk memuat firmware yang telah dikompilasi ke dalam modul.



Mengonfigurasi proyek.



Pengaturan default baik-baik saja dalam banyak kasus. Tetapi untuk memanggil antarmuka menu konsol, Anda harus pergi ke direktori proyek dan mengetik di baris perintah:



idf.py menuconfig




gambar

Menu dengan pengaturan konfigurasi



Setelah memanggil perintah ini, file sdkconfig akan dibuat jika sebelumnya tidak atau jika telah dikonfigurasi ulang. Dalam tutorial sebelumnya, Anda akan melihat perintah make menuconfig yang sudah usang.



Menambahkan pengaturan kustom ke file sdkconfig dapat dilakukan secara manual, misalnya:



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


Tetapi metode yang lebih disukai adalah menggunakan file konfigurasi tambahan Kconfig.projbuild, yang harus ditempatkan di direktori dengan komponen tersebut. Isi file dapat berupa sebagai berikut:



# 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


Setelah memanggil perintah idf.py menuconfig, bagian tambahan secara otomatis ditambahkan di file sdkconfig. Memanggil perintah idf.py menuconfig juga dapat dilakukan dalam proyek PlatformIO, namun, Anda perlu mempertimbangkan fakta bahwa struktur proyek PlatformIO berbeda dari ESP-IDF klasik, karena itu file sdkconfig dapat dibuat ulang dan mengubah pengaturan kustom. Di sini, opsi di atas dimungkinkan - mengedit file dengan tangan, mengganti nama sementara direktori src di main, atau menyiapkan file CMakeLists.txt



Mengompilasi dan memuat proyek.

Untuk membangun sebuah proyek, Anda perlu mengetikkan perintahnya



idf.py build


Perintah ini akan mengkompilasi aplikasi dan semua komponen ESP-IDF dan kemudian menghasilkan loader, tabel partisi, dan binari aplikasi.



$ 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'


Perlu diingat bahwa proses kompilasi awal bahkan untuk proyek sederhana membutuhkan waktu, jadi, tidak seperti kerangka Arduino, banyak modul ESP-IDF tambahan dikompilasi. Perubahan lebih lanjut pada sumber hanya mengarah pada kompilasi file yang sama. Pengecualiannya adalah perubahan konfigurasi.



Untuk mengunduh biner yang dikompilasi (bootloader.bin, partition-table.bin dan hello-world.bin) ke papan ESP32, jalankan perintah:



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


di mana kami mengganti PORT dengan apa yang kami butuhkan (COM1, / dev / ttyUSB1), dan kami secara opsional dapat mengubah kecepatan unduh dengan menentukan nilai yang diperlukan untuk BAUD.



Untuk melacak program yang dimuat, Anda dapat menggunakan utilitas pemantauan port com apa pun, seperti HTerm , CoolTerm , atau gunakan utilitas pemantauan Monitor IDF , untuk memulainya, masukkan perintah:



idf.py -p PORT monitor


Plugin Eclipse ESP-IDF



Dokumentasi untuk menginstal dan mengkonfigurasi plugin ada di sini



gambar



Preset untuk digunakan:



  • Java 11 ke atas; (meskipun berfungsi di java 8, mungkin karena gangguan ini);
  • Python 3.5 dan yang lebih baru;
  • Eclipse 2020-06 CDT;
  • Git;
  • ESP-IDF 4.0 dan yang lebih baru;


Plugin ini terintegrasi dengan cukup baik ke dalam lingkungan pengembangan, mengotomatiskan sebagian besar fungsi tersebut. Tapi, sayangnya, bukan tanpa lalat di salep. Dalam versi Eclipse yang lebih baru dari 2019-09, masih ada bug dengan pengindeksan file sumber di proyek ESP-IDF di Windows.



gambar



Selain itu, ada gangguan lain ketika proyek tidak dibuat karena alasan yang tidak diketahui. Hanya menutup proyek dan memulai ulang Eclipse membantu.



Ekstensi Kode Visual Studio ESP-IDF



Dan yang terakhir menurut saya pilihan yang paling menarik adalah plugin resmi untuk Visual Studio Code.

Seperti PlatformIO, itu dapat dengan mudah dipasang dari bagian ekstensi. Menginstal dan mengonfigurasi kerangka kerja ESP-IDF di ekstensi ini disajikan sebagai menu orientasi, yang juga dijelaskan dalam deskripsi. Mengunduh dan menginstal semua komponen terjadi secara otomatis dalam proses melalui tahapan menu. Semua tangkapan layar dari proses tersebut dapat dikutip, tetapi mereka intuitif dan memerlukan sedikit atau tanpa penjelasan. Untuk mendukung PlatformIO, toolkit yang lebih nyaman untuk membangun, mengunduh, dan memantau proyek dapat dicatat. Sebaliknya, plug-in ESP-IDF dikontrol menggunakan menu perintah yang dapat dipanggil menggunakan tombol F1, atau kombinasi tombol yang dijelaskan di manual.



gambar

Penyiapan plugin awal



Keuntungan menggunakan plugin ini adalah struktur proyek klasik dihormati, tidak perlu mengotak-atik pengaturan (di PlatformIO, kebutuhan seperti itu muncul). Ada satu nuansa, jika kita ingin membuka proyek yang dibuat sebelumnya dalam kode Visual studio dengan plugin ESP-IDF, maka kita hanya perlu menyalin direktori .vscode ke root proyek, yang dapat diperoleh dengan membuat setidaknya satu proyek template menggunakan ESP- Plugin IDF.



gambar

Menu perintah



FreeRTOS



Menurut wikipedia, FreeRTOS adalah sistem operasi multitasking waktu nyata (RTOS) untuk sistem tertanam. FreeRTOS menyediakan multitasking dengan membagi waktu CPU dengan semua utas, atau dalam terminologi OS, tugas. Menurut pendapat saya, manual FreeRTOS paling lengkap dan paling jelas dalam bahasa Rusia ada di sini . Dalam bahasa aslinya, manual dapat dipelajari dari sumber resmi . Saya hanya akan memberikan gambaran tentang status tugas.



gambar



FreeRTOS telah di-porting ke berbagai platform perangkat keras termasuk prosesor Xtensa yang digunakan di ESP32. Detail lebih lanjut dapat ditemukan di dokumentasi.



GPIO



GPIO atau universal input / output adalah kemampuan untuk mengontrol pin secara terpisah dengan sinyal "1" atau "0".



Sesuai namanya, pin semacam itu memiliki dua mode operasi - input atau output. Dalam kasus pertama, kami membaca nilainya, di kasus kedua, kami menuliskannya. Faktor penting lainnya saat berhadapan dengan GPIO adalah level voltase. ESP32 adalah perangkat 3.3V. Oleh karena itu, berhati-hatilah saat bekerja dengan perangkat lain yang memiliki tegangan 5V atau lebih tinggi. Penting juga untuk dipahami bahwa arus maksimum yang dapat dialirkan ke pin GPIO adalah 12 mA. Untuk menggunakan fungsi GPIO yang disediakan oleh ESP-IDF, kita perlu menghubungkan header driver / gpio.h. Anda kemudian dapat memanggil gpio_pad_select_gpio () untuk menentukan fungsi pin ini. Ada 34 GPIO berbeda yang tersedia di ESP32. Mereka ditetapkan sebagai:



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


Penomoran berikut tidak termasuk dalam jumlah pin 20, 24, 28, 29, 30 dan 31.

Tabel pinout dapat ditemukan di sini .



Harap perhatikan bahwa pin GPIO_NUM_34 - GPIO_NUM_39 - hanya menggunakan mode masukan. Mereka tidak dapat digunakan untuk keluaran sinyal. Selain itu, pin 6, 7, 8, 9, 10 dan 11 digunakan untuk berinteraksi dengan kartu flash eksternal melalui SPI, tidak disarankan untuk menggunakannya untuk tujuan lain, tetapi jika Anda benar-benar ingin, Anda bisa. Tipe data gpio_num_t adalah enumerasi dengan nilai yang sesuai dengan nomor pin. Disarankan untuk menggunakan nilai-nilai ini daripada angka. Arah pin diatur menggunakan fungsi gpio_set_direction (). Misalnya, untuk menyetel pin sebagai keluaran:



gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT);


Untuk mengatur pin sebagai masukan:



gpio_set_direction(GPIO_NUM_17, GPIO_MODE_INPUT);


Jika kita telah mengkonfigurasi GPIO sebagai output, maka kita dapat mengatur nilainya menjadi 1 atau 0 dengan memanggil gpio_set_level ().



Contoh berikut mengganti GPIO sekali per detik:




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);
}


Sebagai alternatif untuk menyetel semua atribut pin individu, kita dapat menyetel properti dari satu atau lebih kontak dengan memanggil fungsi gpio_config (). Dibutuhkan struktur gpio_config_t sebagai input dan mengatur arah, tarik ke atas, ke bawah dan pengaturan interupsi untuk semua pin yang direpresentasikan dalam bitmask.

Misalnya:




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);


Pengaturan pull up dan pull down



Biasanya terlihat bahwa pin input GPIO tinggi atau rendah. Ini berarti terhubung ke sumber listrik atau ke ground. Namun, jika pin tidak terhubung ke apa pun, maka pin berada dalam status "mengambang". Seringkali perlu untuk mengatur level awal dari pin yang tidak terhubung ke tinggi atau rendah. Dalam hal ini, perangkat keras (koneksi menggunakan resistor) atau perangkat lunak pull-up dari output dilakukan, masing-masing, ke + V - tarik ke atas atau ke 0 - tarik ke bawah. Di ESP32 SDK, kita dapat mendefinisikan GPIO sebagai pull up atau pull down menggunakan fungsi gpio_set_pull_mode (). Fungsi ini memasukkan nomor pin yang ingin kita atur dan mode pull-up yang terkait dengan pin itu.

Misalnya:



gpio_set_pull_mode (21, GPIO_PULLUP_ONLY);


Penanganan interupsi GPIO



Untuk mendeteksi perubahan dalam sinyal input pada pin, kami dapat mengumpulkan statusnya secara berkala, tetapi ini bukan solusi terbaik karena sejumlah alasan. Pertama, kita harus melakukan siklus melalui pemeriksaan, membuang-buang waktu CPU. Kedua, pada saat polling, status pin mungkin tidak lagi relevan karena penundaan dan Anda dapat melewati sinyal input. Solusi untuk masalah ini adalah gangguan. Interupsi seperti bel pintu. Tanpa menelepon, kami harus memeriksa secara berkala untuk melihat apakah ada orang di pintu. Dalam kode sumber, kita dapat mendefinisikan fungsi panggilan balik interupsi yang akan dipanggil ketika pin mengubah nilai sinyalnya. Kami juga dapat menentukan apa yang menyebabkan penangan dipanggil dengan mengatur parameter berikut:



  • Nonaktifkan - jangan memicu interupsi saat sinyal berubah;
  • PosEdge - panggil penangan interupsi saat mengubah dari rendah ke tinggi;
  • NegEdge - panggil penangan interupsi saat mengubah dari tinggi ke rendah;
  • AnyEdge - aktifkan penangan interupsi baik saat mengubah dari rendah ke tinggi, atau saat mengubah dari tinggi ke rendah;


gambar



Penangan interupsi dapat ditandai untuk dimuat ke dalam RAM pada waktu kompilasi. Secara default, kode yang dihasilkan ada di memori flash. Jika sebelumnya Anda menandainya sebagai IRAM_ATTR, ini akan siap untuk dieksekusi langsung dari RAM.



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


gambar



Mereka yang telah bekerja dengan mikrokontroler tahu bahwa pemrosesan sinyal input dari tombol disertai dengan pantulan kontak. Yang dapat diartikan sebagai rangkaian transisi, dan oleh karena itu rangkaian peristiwa pengendali interupsi. Untuk melakukan ini, kita harus menambahkan penanganan bounce contact ke kode. Untuk melakukan ini, kita perlu membaca peristiwa asli, menunggu hingga getaran mereda, lalu sampel ulang status input.



gambar



Contoh berikut menunjukkan penanganan interupsi sinyal input. Saya sangat menyarankan agar Anda membiasakan diri dengan manajemen antrian di FreeRTOS untuk pemahaman lebih lanjut tentang kode jika Anda belum terbiasa dengannya. Contoh menunjukkan dua tugas:



  • test1_task, yang tidak terkunci ketika peristiwa interupsi terjadi ketika sinyal diaktifkan pada pin 25 dan pesan "Terdaftar klik" ditampilkan ke konsol sekali;
  • test2_task secara berkala disurvei, dan ketika sinyal pada pin 26 diaktifkan, pesan β€œGPIO 26 is high!” dikeluarkan ke konsol setiap 100 ms.


Contoh juga memiliki perangkat lunak timer xTimer set, opsional untuk kasus ini, bukan sebagai contoh penundaan asynchronous.



Anti-bounce dilakukan menggunakan fungsi timeval_durationBeforeNow , yang memeriksa apakah pers berlangsung lebih dari 100ms. Ada pola perangkat lunak anti-pantulan lainnya, tetapi artinya hampir sama. ESP-IDF juga menyertakan contoh cara kerja GPIO.



Pemrosesan sinyal input

#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 (Penghitung Pulsa)



The PCNT (Pulse Kontra) modul dirancang untuk menghitung jumlah naik dan / atau jatuh tepi sinyal input. Setiap blok modul memiliki register 16-bit yang ditandatangani dan dua saluran yang dapat dikonfigurasi untuk menambah atau mengurangi nilai penghitung. Setiap saluran memiliki sinyal input yang menangkap perubahan sinyal, serta input kontrol yang dapat digunakan untuk mengaktifkan atau menonaktifkan penghitungan. Input memiliki filter tambahan yang dapat digunakan untuk menghilangkan lonjakan sinyal yang tidak diinginkan.



Penghitung PCNT memiliki delapan unit independen, dinomori dari 0 hingga 7. Dalam API, mereka ditentukan menggunakan pcnt_unit_t. Setiap modul memiliki dua saluran independen, bernomor 0 dan 1, ditunjukkan dengan pcnt_channel_t.



Konfigurasi disediakan secara terpisah untuk setiap saluran perangkat menggunakan pcnt_config_t dan meliputi:



  • Nomor unit dan nomor saluran milik konfigurasi ini;
  • Input pulsa dan input gerbang nomor GPIO;
  • Dua pasang parameter, pcnt_ctrl_mode_t dan pcnt_count_mode_t, untuk menentukan bagaimana penghitung bereaksi tergantung pada status sinyal kontrol dan bagaimana tepi naik / turun dihitung.
  • Dua nilai batas (min / maks) yang digunakan untuk mengatur watchpoint dan memicu interupsi saat penghitung denyut nadi mencapai batas tertentu.


Konfigurasi saluran tertentu kemudian dilakukan dengan memanggil fungsi pcnt_unit_config () dengan struktur konfigurasi pcnt_config_t di atas sebagai parameter masukan.

Untuk menonaktifkan pulsa atau input kontrol dalam konfigurasi, Anda perlu menentukan PCNT_PIN_NOT_USED sebagai ganti nomor GPIO.



Setelah mengkonfigurasi dengan pcnt_unit_config (), penghitung segera mulai berjalan. Nilai penghitung yang terakumulasi dapat diperiksa dengan memanggil pcnt_get_counter_value ().



Fungsi berikut memungkinkan Anda untuk mengontrol operasi pencacah: pcnt_counter_pause (), pcnt_counter_resume () dan pcnt_counter_clear ()



Juga dimungkinkan untuk secara dinamis mengubah mode pencacah sebelumnya menggunakan pcnt_unit_config () dengan memanggil pcnt_set_mode ().



Jika diinginkan, pin input pulsa dan pin input kontrol dapat diubah dengan cepat menggunakan pcnt_set_pin ().



Modul PCNT memiliki filter pada setiap pulsa dan input kontrol, menambahkan kemampuan untuk mengabaikan lonjakan pendek sinyal. Panjang pulsa yang diabaikan disediakan dalam siklus jam APB_CLK dengan memanggil pcnt_set_filter_value (). Pengaturan filter saat ini dapat diperiksa dengan pcnt_get_filter_value (). Siklus APB_CLK beroperasi pada 80 MHz.



Filter dimulai / dihentikan sementara dengan memanggil pcnt_filter_enable () / pcnt_filter_disable ().

Peristiwa berikut, didefinisikan dalam pcnt_evt_type_t, dapat memicu interupsi. Peristiwa terjadi ketika penghitung denyut nadi mencapai nilai tertentu:



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


Untuk mendaftar, mengaktifkan atau menonaktifkan interupsi untuk kejadian di atas, Anda harus memanggil pcnt_isr_register (), pcnt_intr_enable (), dan pcnt_intr_disable (). Untuk mengaktifkan atau menonaktifkan peristiwa saat ambang batas tercapai, Anda juga perlu memanggil pcnt_event_enable () dan pcnt_event_disable ().



Untuk memeriksa ambang mana yang saat ini disetel, gunakan fungsi pcnt_get_event_value ().



Contoh dari ESP-IDF disajikan di sini .



Saya menggunakan penghitung PCNT untuk menghitung kecepatan roda. Untuk melakukan ini, perlu menghitung jumlah pulsa per revolusi, dan kemudian mengatur ulang penghitung.



Kode sampel

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;
}




Modulasi lebar pulsa (PWM) menggunakan modul MCPWM



Informasi tentang modul disajikan di sini

Ada banyak artikel di internet tentang topik PWM , terutama jika Anda mencari yang berhubungan dengan Arduino.

Wikipedia memberikan definisi yang singkat dan ringkas - Pulse-width modulation (PWM) - proses pengendalian daya dengan menghidupkan dan mematikan perangkat. Prinsip kontrol PWM adalah mengubah lebar pulsa pada amplitudo dan frekuensi sinyal yang konstan.



gambar



Frekuensi PWM Arduino adalah 488,28 Hz, resolusinya adalah 8 bit (0 ... 255), dan dimungkinkan untuk menggunakan enam pin perangkat keras 3, 5, 6, 9, 10, 11. Namun, dengan menggunakan pengaturan register mikrokontroler AVR, Anda dapat mencapai nilai lain Frekuensi PWM.



Mikrokontroler ESP32 memiliki gudang modul MCPWM terpisah, atau lebih tepatnya dua modul, yang masing-masing memiliki tiga pasang pin PWM.



gambar



Selanjutnya, dalam dokumentasi, keluaran dari blok terpisah ditandai sebagai PWMxA / PWMxB.

Diagram blok yang lebih rinci dari blok MCPWM disajikan di bawah ini. Setiap pasangan A / B dapat disinkronisasi dengan salah satu dari tiga timer: Timer 0, 1, dan 2. Timer yang sama dapat digunakan untuk mensinkronisasi lebih dari satu pasangan output PWM. Setiap unit juga dapat mengumpulkan data masukan seperti sinyal sinkronisasi, mendeteksi alarm seperti arus berlebih atau tegangan motor berlebih, dan menerima umpan balik dari sinyal penangkapan seperti posisi rotor.



gambar



Ruang lingkup konfigurasi tergantung pada jenis motor, khususnya berapa banyak keluaran dan masukan yang diperlukan dan apa urutan sinyal yang akan digunakan untuk mengendalikan motor.



Dalam kasus kami, kami akan menjelaskan konfigurasi sederhana untuk menggerakkan motor DC sikat yang hanya menggunakan sedikit dari sumber daya MCPWM yang tersedia. Contoh rangkaian ditunjukkan di bawah ini. Ini termasuk jembatan-H untuk mengalihkan polarisasi tegangan yang disuplai ke motor (M) dan menyediakan arus yang cukup untuk menggerakkannya.



gambar



Konfigurasi tersebut mencakup langkah-langkah berikut:



  • Pemilihan blok MPWn yang akan digunakan untuk menggerakkan motor. Ada dua modul yang tersedia di papan ESP32 dari yang terdaftar di mcpwm_unit_t.
  • Menginisialisasi dua GPIO sebagai output pada modul yang dipilih dengan memanggil mcpwm_gpio_init (). Kedua sinyal keluaran tersebut biasanya digunakan untuk menggerakkan motor ke kanan atau ke kiri. Semua parameter sinyal yang tersedia terdaftar di mcpwm_io_signals_t. Untuk menyetel lebih dari satu pin sekaligus, gunakan fungsi mcpwm_set_pin () bersama dengan mcpwm_pin_config_t.
  • Pemilihan pengatur waktu. Ada tiga timer yang tersedia di perangkat. Pengatur waktu dicantumkan dalam mcpwm_timer_t.
  • Mengatur frekuensi pengatur waktu dan bootstrap dalam struktur mcpwm_config_t.
  • Memanggil mcpwm_init () dengan parameter di atas.


Metode kontrol PWM adalah sebagai berikut:



  • 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.


Contoh kode untuk motor yang disikat ada di



sini.Dalam proyek saya, saya praktis menggunakan kode dari contoh, sedikit memperbaikinya dan menambahkan kontrol motor kedua. Untuk kontrol independen saluran PWM, masing-masing harus dikonfigurasi dengan timer terpisah, misalnya MCPWM_TIMER_0 dan CPWM_TIMER_1:



Kode sampel

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);  
}




Menghubungkan ke WI-Fi dan bekerja dengan MQTT



Topik protokol Wi-FI cukup luas. Serangkaian artikel terpisah diperlukan untuk menjelaskan protokol tersebut. Di panduan resmi, lihat bagian driver Wi-Fi . Penjelasan tentang software API ada di sini . Contoh kode dapat dilihat di sini



Perpustakaan Wi-Fi menyediakan dukungan untuk mengonfigurasi dan memantau fungsi jaringan Wi-Fi ESP32. Konfigurasi berikut tersedia:



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


MQTT



Anda bisa mengenal topik ini di sini atau di sini . Panduan ESP-IDF dengan contoh ada di sini .



Untuk menyiapkan MQTT dalam kode, Anda harus menyambungkan ke jaringan Wi-Fi terlebih dahulu. Kemudian buat koneksi ke broker. Pesan diproses dalam callback, parameternya adalah event esp_mqtt_event_handle_t. Jika jenis acara adalah MQTT_EVENT_DATA, maka topik dan data dapat diuraikan. Anda dapat menyesuaikan perilaku yang berbeda sebagai hasil dari koneksi yang sukses, pemutusan hubungan dan langganan topik.



Contoh koneksi 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);




Menghubungkan ke broker 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);






Penangan 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;
}




Ini menyimpulkan cerita saya tentang penggunaan modul ESP32. Artikel ini membahas contoh-contoh di ESP-IDF, sebagai kerangka kerja yang memanfaatkan sumber daya modul secara maksimal. Pemrograman menggunakan platform lain seperti javaScript, MicroPython, Lua dapat ditemukan di sumber daya terkait. Pada artikel selanjutnya, seperti yang telah disebutkan, saya akan memberikan contoh praktis penggunaan mikrokontroler, dan juga membandingkan pendekatan perangkat lunak Arduino dan ESP-IDF.



All Articles