diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 86c8a8e2c..f23dfdab2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,13 +8,13 @@ repos: - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files - - repo: local - hooks: - - id: lychee - name: lychee link checker - entry: lycheeverse/lychee - language: docker_image - types: [markdown] - args: - - "--no-progress" - - "--include-fragments" +# - repo: local +# hooks: +# - id: lychee +# name: lychee link checker +# entry: lycheeverse/lychee +# language: docker_image +# types: [markdown] +# args: +# - "--no-progress" +# - "--include-fragments" diff --git a/content/workshops/esp-idf-basic/README.old b/content/workshops/esp-idf-basic/README.old new file mode 100644 index 000000000..9cc6431b0 --- /dev/null +++ b/content/workshops/esp-idf-basic/README.old @@ -0,0 +1,5 @@ +## TODO + +- [X] Restructure Lecture 1 +- [ ] Redraw Lecture 2 images +- [ ] Finish prerequisite table diff --git a/content/workshops/esp-idf-basic/_index.md b/content/workshops/esp-idf-basic/_index.md new file mode 100644 index 000000000..2d0328f0d --- /dev/null +++ b/content/workshops/esp-idf-basic/_index.md @@ -0,0 +1,135 @@ +--- +title: "ESP-IDF Basics: Your First Project with ESP32-C3 and Components" +date: "2025-08-05" +summary: "This workshop explores the basics of the ESP-IDF. You will build and flash basic programs, create your own components and build a REST API HTTP server." +--- + +Welcome to Espressif's ESP-IDF Basics Workshop! + +## Introduction + +In this hands-on workshop, you'll develop a solid understanding of the ESP-IDF framework, along with how to effectively use Visual Studio Code (VSCode) and Espressif’s official VSCode Extension. You'll also gain practical experience working with ESP-IDF components. + +In the first part, we’ll begin by verifying that your development environment is correctly set up, using the classic `hello world` example as our starting point. From there, we'll walk through the structure of an ESP-IDF project, explore the build system, and set up a basic access point (__SoftAP__). + +As we move to the second part, we’ll take a closer look at the network stack protocol and guide you through building a simple __HTTP server__. + +The third part focuses on working with two commonly used peripherals, namely __GPIO__ and __I2C__. We will explore the component system and the component registry, for using common libraries without worrying about managing dependencies or build system settings. After that, we’ll bring everything together to build a basic sensor gateway, combining networking and peripheral control into one cohesive project. + +By the end of this session, you’ll have the foundational skills and confidence to start developing your own Espressif-based applications using ESP-IDF. + + +{{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}} +Estimated time: 3 hours. +{{< /alert >}} + + +## Agenda + +The workshop is divided into three parts, each lasting approximately one hour. Here's the outline: + +- Part 1: __Welcome and getting started__ + - __Lecture 1__ -- ESP-IDF & VSCode Extension introduction + - __Assignment 1.1__ -- Test ESP-IDF and VSCode installation by compiling and flashing the `hello_world` example. Change the text of the example and check on the terminal. + - __Assignment 1.2__ -- Start a new project from the `blink` example and check that the LED on the board is flashing. + +- Part 2: __HTTP connectivity__ + - __Lecture 2__ -- Connectivity layers, HTTP and MQTT, HTML, REST API + - __Assignment 2.1__ -- Create an HTTP server which processes the request `GET /index.html/` and returns `

Hello LED Control

`. + - __Assignment 2.2__ -- Add to the HTTP server the routes + - `GET /led/on` → turns the LED on and returns JSON {"led": "on"} + - `GET /led/off`→ turns the LED off and returns JSON {"led": "off"} + - `POST /led/blink` → accepts JSON `{ "times": int, "interval_ms": int }` to blink the LED the specified number of times at the given interval, and returns JSON `{"blink": "done"}` + - __Assignment 2.3__ -- (Optional) Add to the HTTP server the route + - `POST /led/flash` → accepts JSON `{"periods": [int], "duty_cycles": [int]}` and for each element, calculates the on-time and off-time and drives the LED accordingly. + +- Part 3: __Peripherals and putting it all together__ + - __Lecture 3__ -- GPIO, I2C and use of component registry. Reading the sensor. + - __Assignment 3.1__ -- Create a new component to toggle the LED. + - __Assignment 3.2__ -- Refactor previous code to use the component. + - __Assignment 3.3__ -- Add component for reading the environment sensor onboard. + - __Assignment 3.4__ -- (Optional) Add route: + - `GET /environment/` → returns a sensor reading. Choose the best json format for this task. + + +## Prerequisites + +To follow this workshop, make sure you meet the prerequisites given below. + +### Basic knowledge + +* Basic electronics + * Resistors, capacitors, dc/dc supply + * Reading a schematic +* Basic embedded programming + * Flash memory + * Compile vs flash + * Basic knowledge of standard MCU peripherals, at least GPIO, and I2C. +* C programming language basics + * header files + * compiler / linker + * `define`s + * `struct`s and `typedef`s +* [JSON](https://en.wikipedia.org/wiki/JSON) and [YAML](https://en.wikipedia.org/wiki/YAML) format +* HTML and its main tags (``, ``, `

`, `

`, `

`) +* Basic knowledge of HTTP request methods (`GET`, `POST`) and the concept of URI and routes +* Reference materials (distributed prior to workshop) + +### Required software + +* VSCode installed on your machine +* [ESP-IDF extension](https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/installation.html) added to your VSCode. +* ESP-IDF installed on your machine
+ _You can install it via VSCode or using [ESP-IDF installer manager](https://docs.espressif.com/projects/idf-im-cli/en/latest/index.html)_ + +### Required hardware + +* The ESP-C3-DevKit-RUST-2 (it will be provided at the workshop).
+ _You could also use an ESP32-C3-Devkit board, but you would need to adjust gpio pin accordingly_ + +{{< alert iconColor="#df8e1d" cardColor="#edcea3">}} +We strongly recommend installing VSCode and the ESP-IDF plugin __before__ the workshop begins. If you run into any issues, there will be some time during the first assignment to complete the installation. +{{< /alert >}} + + +#### Reference table + +| Prerequisite | Description | Reference | +|---|---|---| +|MCU memory types|Difference between Flash, RAM and EEPROM|[L. Harvie (Medium)](https://medium.com/@lanceharvieruntime/embedded-systems-memory-types-flash-vs-sram-vs-eeprom-93d0eed09086)| +|MCU serial peripherals|Difference between SPI, I2C, UART|[nextpcb.com](https://www.nextpcb.com/blog/spi-i2c-uart)| +|Header files and linker|What are headers file for and what's the linker's job|[CBootCamp](https://gribblelab.org/teaching/CBootCamp/12_Compiling_linking_Makefile_header_files.html), [themewaves](https://themewaves.com/understanding-linkers-in-c-programming/)| +|JSON|Language-independent data format derived from JavaScript. Backbone of REST APIs|[Wikipedia](https://en.wikipedia.org/wiki/JSON)| +|YAML|Human readable data serialization format used for dependency management through `idf_component.yml`|[Wikipedia](https://en.wikipedia.org/wiki/YAML), [datacamp.com](https://www.datacamp.com/blog/what-is-yaml)| +|HTML tags|Basic HTML tags introduction|[Freecodecamp](https://www.freecodecamp.org/news/introduction-to-html-basics/)| +|HTTP Request method|HTTP request (GET, POST, etc.) introduction and differences|[Restfulapi.net](https://restfulapi.net/http-methods/)| +|ESP-IDF VSCode Plugin|Espressif official VSCode Extension|[vscode-esp-idf-extension installation](https://github.com/espressif/vscode-esp-idf-extension?tab=readme-ov-file#how-to-use)| + + +## Workshop + +Without further ado, let's start! You can find a link to each workshop part below. Your next step is __[Lecture 1](lecture-1/)__. + +* __Part 1__ + * [Lecture 1](lecture-1/) + * [Assignment 1.1](assignment-1-1/) + * [Assignment 1.2](assignment-1-2/) +* __Part 2__ + * [Lecture 2](lecture-2/) + * [Assignment 2.1](assignment-2-1/) + * [Assignment 2.2](assignment-2-2/) + * [Assignment 2.3](assignment-2-3/) (Optional) +* __Part 3__ + * [Lecture 3](lecture-3/) + * [Assignment 3.1](assignment-3-1/) + * [Assignment 3.2](assignment-3-2/) + * [Assignment 3.3](assignment-3-3/) + + +## Conclusion + +You just arrived at the end of this workshop, congratulation! We hope it was a fruitful experience and the start of a longer journey. Thank you for participating in Espressif's workshop! + +You are now able to create, build and flash new projects, use external libraries and components, create your own components, and control everything via an HTTP interface. You have now the basic foundation for an IoT application. + +We hope this workshop has provided you with the foundational knowledge and confidence to start building your own Espressif-based applications. Keep experimenting, keep learning—and don't forget to explore the rich ecosystem of tools and resources that Espressif offers. diff --git a/content/workshops/esp-idf-basic/assets/ass1_1_compilation_result.webp b/content/workshops/esp-idf-basic/assets/ass1_1_compilation_result.webp new file mode 100644 index 000000000..2b5fe51a2 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass1_1_compilation_result.webp differ diff --git a/content/workshops/esp-idf-basic/assets/ass1_1_hello_world_files.webp b/content/workshops/esp-idf-basic/assets/ass1_1_hello_world_files.webp new file mode 100644 index 000000000..5809ed7f4 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass1_1_hello_world_files.webp differ diff --git a/content/workshops/esp-idf-basic/assets/ass1_1_monitor.webp b/content/workshops/esp-idf-basic/assets/ass1_1_monitor.webp new file mode 100644 index 000000000..2ee4b79b1 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass1_1_monitor.webp differ diff --git a/content/workshops/esp-idf-basic/assets/ass1_1_new_project.webp b/content/workshops/esp-idf-basic/assets/ass1_1_new_project.webp new file mode 100644 index 000000000..016816e88 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass1_1_new_project.webp differ diff --git a/content/workshops/esp-idf-basic/assets/ass3_1_new_component.webp b/content/workshops/esp-idf-basic/assets/ass3_1_new_component.webp new file mode 100644 index 000000000..2e26df220 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass3_1_new_component.webp differ diff --git a/content/workshops/esp-idf-basic/assets/ass_2_1_ap_list.webp b/content/workshops/esp-idf-basic/assets/ass_2_1_ap_list.webp new file mode 100644 index 000000000..1036cebef Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass_2_1_ap_list.webp differ diff --git a/content/workshops/esp-idf-basic/assets/ass_2_1_disable_nvs.webp b/content/workshops/esp-idf-basic/assets/ass_2_1_disable_nvs.webp new file mode 100644 index 000000000..ac3f3535c Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass_2_1_disable_nvs.webp differ diff --git a/content/workshops/esp-idf-basic/assets/ass_2_1_result.webp b/content/workshops/esp-idf-basic/assets/ass_2_1_result.webp new file mode 100644 index 000000000..2fdcdc164 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/ass_2_1_result.webp differ diff --git a/content/workshops/esp-idf-basic/assets/esp-board-pins.webp b/content/workshops/esp-idf-basic/assets/esp-board-pins.webp new file mode 100644 index 000000000..1fccfb88d Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/esp-board-pins.webp differ diff --git a/content/workshops/esp-idf-basic/assets/esp-board-top.webp b/content/workshops/esp-idf-basic/assets/esp-board-top.webp new file mode 100644 index 000000000..859c051dd Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/esp-board-top.webp differ diff --git a/content/workshops/esp-idf-basic/assets/esp-board-top_old.webp b/content/workshops/esp-idf-basic/assets/esp-board-top_old.webp new file mode 100644 index 000000000..2b9ad6128 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/esp-board-top_old.webp differ diff --git a/content/workshops/esp-idf-basic/assets/esp-idf-highlevel.webp b/content/workshops/esp-idf-basic/assets/esp-idf-highlevel.webp new file mode 100644 index 000000000..165c06ff6 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/esp-idf-highlevel.webp differ diff --git a/content/workshops/esp-idf-basic/assets/esp32-c3-overview.webp b/content/workshops/esp-idf-basic/assets/esp32-c3-overview.webp new file mode 100644 index 000000000..d075d347c Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/esp32-c3-overview.webp differ diff --git a/content/workshops/esp-idf-basic/assets/lec_1_module.webp b/content/workshops/esp-idf-basic/assets/lec_1_module.webp new file mode 100644 index 000000000..56b8c4623 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/lec_1_module.webp differ diff --git a/content/workshops/esp-idf-basic/assets/lec_2_encapsulation.webp b/content/workshops/esp-idf-basic/assets/lec_2_encapsulation.webp new file mode 100644 index 000000000..de4b2ce04 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/lec_2_encapsulation.webp differ diff --git a/content/workshops/esp-idf-basic/assets/lec_2_http_request.webp b/content/workshops/esp-idf-basic/assets/lec_2_http_request.webp new file mode 100644 index 000000000..c2b180369 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/lec_2_http_request.webp differ diff --git a/content/workshops/esp-idf-basic/assets/lec_2_isoosi.webp b/content/workshops/esp-idf-basic/assets/lec_2_isoosi.webp new file mode 100644 index 000000000..62a71404f Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/lec_2_isoosi.webp differ diff --git a/content/workshops/esp-idf-basic/assets/lec_2_sta_ap.webp b/content/workshops/esp-idf-basic/assets/lec_2_sta_ap.webp new file mode 100644 index 000000000..a70a6e4f6 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/lec_2_sta_ap.webp differ diff --git a/content/workshops/esp-idf-basic/assets/lec_3_led_gpio.webp b/content/workshops/esp-idf-basic/assets/lec_3_led_gpio.webp new file mode 100644 index 000000000..952dff9dc Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/lec_3_led_gpio.webp differ diff --git a/content/workshops/esp-idf-basic/assets/lec_3_registry.webp b/content/workshops/esp-idf-basic/assets/lec_3_registry.webp new file mode 100644 index 000000000..de398b345 Binary files /dev/null and b/content/workshops/esp-idf-basic/assets/lec_3_registry.webp differ diff --git a/content/workshops/esp-idf-basic/assignment-1-1/hello_world.cast b/content/workshops/esp-idf-basic/assignment-1-1/hello_world.cast new file mode 100644 index 000000000..6a9959b10 --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-1-1/hello_world.cast @@ -0,0 +1,1132 @@ +{"version": 2, "width": 88, "height": 33, "timestamp": 1751442666, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}} +[0.104219, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[0.104638, "o", "\u001b]2;francesco@Francescos-MacBook-Pro:~/Downloads/temp_hello_world/hello_world\u0007\u001b]1;..d/hello_world\u0007"] +[0.106017, "o", "\u001b]7;file://Francescos-MacBook-Pro.local/Users/francesco/Downloads/temp_hello_world/hello_world\u001b\\"] +[0.106418, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[01;32m➜ \u001b[36mhello_world\u001b[00m \u001b[K"] +[0.106478, "o", "\u001b[?1h\u001b=\u001b[?2004h"] +[1.172941, "o", "i"] +[1.291589, "o", "\bid"] +[1.372254, "o", "f"] +[1.490067, "o", "."] +[1.852956, "o", "p"] +[2.163938, "o", "y"] +[2.259738, "o", " "] +[2.876891, "o", "m"] +[2.979279, "o", "o"] +[3.139846, "o", "n"] +[3.266308, "o", "i"] +[3.378391, "o", "t"] +[3.467048, "o", "o"] +[3.587532, "o", "r"] +[3.915528, "o", "\u001b[?1l\u001b>"] +[3.915584, "o", "\u001b[?2004l\r\r\n"] +[3.916871, "o", "\u001b]2;idf.py monitor\u0007\u001b]1;idf.py\u0007"] +[4.374027, "o", "Executing action: monitor\r\n"] +[4.375302, "o", "Serial port /dev/cu.usbmodem1131101\r\n"] +[4.377136, "o", "Connecting..."] +[4.693589, "o", "\r\n"] +[4.696965, "o", "Detecting chip type... ESP32-C3\r\n"] +[4.703017, "o", "Running idf_monitor in directory /Users/francesco/Downloads/temp_hello_world/hello_world\r\nExecuting \"/Users/francesco/.espressif/python_env/idf5.4_py3.13_env/bin/python /Users/francesco/esp/v5.4.1/esp-idf/tools/idf_monitor.py -p /dev/cu.usbmodem1131101 -b 115200 --toolchain-prefix riscv32-esp-elf- --target esp32c3 --revision 3 --decode-panic backtrace /Users/francesco/Downloads/temp_hello_world/hello_world/build/hello_world.elf -m '/Users/francesco/.espressif/python_env/idf5.4_py3.13_env/bin/python' '/Users/francesco/esp/v5.4.1/esp-idf/tools/idf.py'\"...\r\n"] +[4.797108, "o", "\u001b[0;"] +[4.797202, "o", "33m--- esp-idf-monitor 1.6.0 on /dev/cu.usb"] +[4.79721, "o", "modem113"] +[4.797297, "o", "1101 115200\u001b[0m\r\n"] +[4.801014, "o", "\u001b[0;"] +[4.801042, "o", "33m--- Quit: Ctr"] +[4.801057, "o", "l+] | Menu: Ct"] +[4.80108, "o", "rl+T | Help: Ctr"] +[4.801099, "o", "l+T "] +[4.801103, "o", "followed "] +[4.801106, "o", "by"] +[4.801139, "o", " Ctrl+H\u001b[0m\r\n"] +[4.808515, "o", "ESP-"] +[4.808523, "o", "ROM:esp"] +[4.808526, "o", "32"] +[4.808529, "o", "c3"] +[4.808532, "o", "-a"] +[4.808534, "o", "pi"] +[4.808606, "o", "1-"] +[4.808611, "o", "20210207\r\r\n"] +[4.808668, "o", "Build:Fe"] +[4.808675, "o", "b 7 2"] +[4.808744, "o", "021\r\r\nrst:0x15 ("] +[4.808749, "o", "USB_UAR"] +[4.808788, "o", "T_C"] +[4.808794, "o", "HIP_RESET),boot:0xc (SPI_FA"] +[4.808796, "o", "ST"] +[4.808809, "o", "_FLASH_B"] +[4.808811, "o", "O"] +[4.808847, "o", "O"] +[4.808871, "o", "T)\r\r\n"] +[4.808939, "o", "Saved PC:0x4004c724\r\r\n"] +[4.81617, "o", "\u001b[0"] +[4.816277, "o", ";33m--- 0x4004c724: rec"] +[4.816374, "o", "v_packet in ROM\r\n\u001b[0m\r\n"] +[4.816496, "o", "SP"] +[4.816594, "o", "IWP:0xee\r\r\nmode:DIO, clock di"] +[4.816671, "o", "v:1\r\r\nload:0x3fcd5820,len:0x1"] +[4.816679, "o", "574\r\r\n"] +[4.816774, "o", "loa"] +[4.816792, "o", "d:0x403"] +[4.816908, "o", "cc710,len:0xc30\r\r\n"] +[4.816949, "o", "load:0x403ce710,len:0x2f64"] +[4.816955, "o", "\r\r\n"] +[4.82051, "o", "ent"] +[4.820521, "o", "ry 0x403"] +[4.820548, "o", "cc7"] +[4.820564, "o", "1a\r\r\n"] +[4.82708, "o", "\u001b["] +[4.827091, "o", "0;32mI "] +[4.827094, "o", "(24)"] +[4.8271, "o", " bo"] +[4.827103, "o", "ot: "] +[4.827106, "o", "E"] +[4.827109, "o", "SP"] +[4.827114, "o", "-I"] +[4.827118, "o", "DF v"] +[4.827123, "o", "5."] +[4.827126, "o", "4.1-"] +[4.827129, "o", "di"] +[4.827131, "o", "r"] +[4.827141, "o", "t"] +[4.827151, "o", "y 2nd stage "] +[4.827352, "o", "bootloader\u001b[0m\r\r\n"] +[4.827393, "o", "\u001b[0;32mI (24) b"] +[4.827402, "o", "oot: co"] +[4.827449, "o", "mpi"] +[4.827455, "o", "le time Jul 2 2025 09:47:11\u001b[0m\r"] +[4.827459, "o", "\r\n"] +[4.827565, "o", "\u001b[0;3"] +[4.827579, "o", "2mI "] +[4.827593, "o", "(25) boot"] +[4.827596, "o", ": c"] +[4.827599, "o", "hi"] +[4.827604, "o", "p "] +[4.827664, "o", "rev"] +[4.827669, "o", "ision: v0.3\u001b[0m\r\r\n"] +[4.831126, "o", "\u001b[0;3"] +[4.831144, "o", "2mI (25) boot:"] +[4.83115, "o", " efus"] +[4.831153, "o", "e "] +[4.831156, "o", "bl"] +[4.831159, "o", "oc"] +[4.831161, "o", "k"] +[4.831164, "o", " r"] +[4.831167, "o", "ev"] +[4.83117, "o", "is"] +[4.831232, "o", "ion: v1.1\u001b[0m\r\r\n"] +[4.835076, "o", "\u001b[0;"] +[4.835083, "o", "32mI ("] +[4.835094, "o", "29) bo"] +[4.835136, "o", "ot"] +[4.835146, "o", ".esp32c3: SPI Speed : 80MHz"] +[4.835149, "o", "\u001b["] +[4.835152, "o", "0m"] +[4.835155, "o", "\r\r\n"] +[4.838766, "o", "\u001b[0;"] +[4.838772, "o", "32mI "] +[4.838775, "o", "(3"] +[4.838778, "o", "2)"] +[4.83885, "o", " b"] +[4.838856, "o", "oot.esp32c3: SPI Mode : DIO\u001b[0m\r\r\n"] +[4.842516, "o", "\u001b[0"] +[4.842522, "o", ";32mI"] +[4.842525, "o", " ("] +[4.842527, "o", "36"] +[4.842556, "o", ") "] +[4.842564, "o", "boot.esp32c3: SPI Flas"] +[4.842575, "o", "h Size :"] +[4.842603, "o", " 2MB\u001b[0m\r\r\n"] +[4.84701, "o", "\u001b[0;3"] +[4.847018, "o", "2mI (4"] +[4.847105, "o", "0) boot: Enabling"] +[4.847137, "o", " RNG early entropy source...\u001b[0m\r\r\n"] +[4.849671, "o", "\u001b[0;"] +[4.849693, "o", "32mI (44) boot:"] +[4.849698, "o", " Part"] +[4.849701, "o", "it"] +[4.849704, "o", "i"] +[4.849706, "o", "on"] +[4.849709, "o", " T"] +[4.849763, "o", "able:\u001b[0m\r\r\n"] +[4.855831, "o", "\u001b[0;3"] +[4.855838, "o", "2mI (4"] +[4.855841, "o", "7)"] +[4.855876, "o", " boot: ## Label "] +[4.855884, "o", " Us"] +[4.855886, "o", "ag"] +[4.855889, "o", "e "] +[4.855892, "o", " "] +[4.855895, "o", " "] +[4.855897, "o", " "] +[4.855949, "o", " "] +[4.85596, "o", " Type ST Offset Length\u001b[0m\r\r\n"] +[4.862379, "o", "\u001b[0"] +[4.862386, "o", ";32"] +[4.862487, "o", "mI (53) boot: 0 nvs "] +[4.862508, "o", " WiFi data "] +[4.862516, "o", " 0"] +[4.862523, "o", "1 02"] +[4.862529, "o", " 00"] +[4.862544, "o", "009000 000"] +[4.86255, "o", "06000"] +[4.862653, "o", "\u001b[0"] +[4.86266, "o", "m\r\r\n"] +[4.869024, "o", "\u001b[0;3"] +[4.86904, "o", "2mI (60) boot"] +[4.869072, "o", ": "] +[4.869079, "o", "1 phy_init RF d"] +[4.869082, "o", "at"] +[4.869085, "o", "a "] +[4.869104, "o", " 01 0"] +[4.869107, "o", "1 "] +[4.86911, "o", "00"] +[4.86913, "o", "00f000 00"] +[4.869184, "o", "001000\u001b[0m\r\r\n"] +[4.87543, "o", "\u001b[0;"] +[4.875436, "o", "32mI "] +[4.875485, "o", "(66) boot: 2 factory f"] +[4.875582, "o", "actory app 00 00 00010000 00100"] +[4.875588, "o", "000\u001b["] +[4.875592, "o", "0m"] +[4.875595, "o", "\r\r\n"] +[4.878624, "o", "\u001b[0"] +[4.878663, "o", ";32mI"] +[4.878719, "o", " (73) boot: End of partition table"] +[4.878741, "o", "\u001b"] +[4.878783, "o", "[0m\r\r\n"] +[4.886076, "o", "\u001b[0;3"] +[4.886086, "o", "2mI (76) "] +[4.886122, "o", "esp"] +[4.886143, "o", "_image: segment 0: paddr=00010020 v"] +[4.886147, "o", "add"] +[4.88615, "o", "r="] +[4.886153, "o", "3c"] +[4.886156, "o", "02"] +[4.886159, "o", "00"] +[4.886161, "o", "2"] +[4.886164, "o", "0 "] +[4.886167, "o", "si"] +[4.886215, "o", "ze"] +[4.886226, "o", "=08c0ch ( 35852) map\u001b[0m\r\r\n"] +[4.893546, "o", "\u001b[0;"] +[4.893552, "o", "32mI "] +[4.893581, "o", "(89) e"] +[4.893597, "o", "sp_image: segment 1: p"] +[4.893604, "o", "addr="] +[4.893608, "o", "00"] +[4.893636, "o", "01"] +[4.893642, "o", "8c34 vaddr=3fc8ba00"] +[4.893646, "o", " si"] +[4.893649, "o", "ze"] +[4.893663, "o", "=0128ch ("] +[4.893705, "o", " "] +[4.89371, "o", "4748) load\u001b[0m\r\r\n"] +[4.900916, "o", "\u001b[0;3"] +[4.900952, "o", "2mI (92"] +[4.900957, "o", ") e"] +[4.900961, "o", "sp_"] +[4.900966, "o", "i"] +[4.90101, "o", "mage: segment 2: paddr=00019"] +[4.901017, "o", "ec8 v"] +[4.90102, "o", "ad"] +[4.901028, "o", "dr"] +[4.901037, "o", "=4038000"] +[4.901073, "o", "0 s"] +[4.901079, "o", "ize=06150h ( 24912) load"] +[4.901106, "o", "\u001b[0m\r\r\n"] +[4.908464, "o", "\u001b[0"] +[4.90847, "o", ";32mI"] +[4.90852, "o", " (103) esp_image: segment 3: "] +[4.908527, "o", "paddr"] +[4.90854, "o", "=0"] +[4.908546, "o", "00200"] +[4.908559, "o", "20 v"] +[4.908596, "o", "addr=42"] +[4.908636, "o", "000020 size=16770h ( 92"] +[4.908654, "o", "016) map\u001b[0m\r\r\n"] +[4.923542, "o", "\u001b[0;3"] +[4.923555, "o", "2mI (121) es"] +[4.923559, "o", "p_i"] +[4.923562, "o", "ma"] +[4.923655, "o", "ge: segment 4: paddr=00036798 vaddr=40386150 size=056ech ("] +[4.923664, "o", " 22252)"] +[4.923751, "o", " load\u001b[0m\r\r\n"] +[4.927866, "o", "\u001b[0;"] +[4.927877, "o", "32mI (125"] +[4.92788, "o", ") "] +[4.927917, "o", "esp_image: segment 5: pa"] +[4.92792, "o", "ddr"] +[4.927923, "o", "=0"] +[4.927926, "o", "00"] +[4.928028, "o", "3b"] +[4.928033, "o", "e8c vaddr=50000200 size=0001ch ( 28) load\u001b[0m\r\r\n"] +[4.932129, "o", "\u001b[0;32"] +[4.932141, "o", "mI (129) bo"] +[4.932179, "o", "o"] +[4.932224, "o", "t"] +[4.932232, "o", ": Loa"] +[4.932312, "o", "ded app from partition at o"] +[4.932317, "o", "ffset 0x10000\u001b[0m\r\r\n"] +[4.936672, "o", "\u001b[0;32mI (129)"] +[4.936679, "o", " boot: "] +[4.936682, "o", "Di"] +[4.936779, "o", "sabling RNG early e"] +[4.936853, "o", "ntropy source...\u001b[0m\r\r\n"] +[4.948474, "o", "\u001b[0;32"] +[4.948491, "o", "mI (145) cp"] +[4.948495, "o", "u_sta"] +[4.948502, "o", "rt:"] +[4.948505, "o", " Uni"] +[4.948577, "o", "core app\u001b[0m\r\r\n"] +[4.956706, "o", "\u001b[0"] +[4.956713, "o", ";32mI "] +[4.956716, "o", "(1"] +[4.956719, "o", "54"] +[4.956739, "o", ") "] +[4.956746, "o", "cpu_start: Pro c"] +[4.956758, "o", "pu start"] +[4.95676, "o", " u"] +[4.956764, "o", "se"] +[4.956805, "o", "r"] +[4.95687, "o", " code\u001b[0m\r\r\n"] +[4.956973, "o", "\u001b[0"] +[4.956979, "o", ";32"] +[4.956982, "o", "mI"] +[4.957038, "o", " (154) cpu_start: cpu freq: 160000000 "] +[4.957044, "o", "Hz\u001b[0"] +[4.957047, "o", "m\r"] +[4.95711, "o", "\r\n"] +[4.957134, "o", "\u001b[0;"] +[4.957145, "o", "32mI (1"] +[4.957149, "o", "54)"] +[4.957152, "o", " a"] +[4.957154, "o", "pp"] +[4.957157, "o", "_"] +[4.95716, "o", "in"] +[4.957215, "o", "it"] +[4.957221, "o", ": Application information:\u001b[0m\r\r\n"] +[4.960936, "o", "\u001b[0"] +[4.960945, "o", ";32mI ("] +[4.960948, "o", "15"] +[4.960961, "o", "4"] +[4.960967, "o", ") app_init:"] +[4.96097, "o", " P"] +[4.960973, "o", "r"] +[4.96101, "o", "oject name: hell"] +[4.961092, "o", "o_world\u001b[0m\r\r\n"] +[4.965517, "o", "\u001b["] +[4.965798, "o", "0;32mI (158) app_init: App version: 1"] +[4.965809, "o", "\u001b[0m"] +[4.965814, "o", "\r\r\n"] +[4.970251, "o", "\u001b[0;32mI (162) app_init: Compile time: Jul 2 2025 09:47:07\u001b[0m\r\r\n"] +[4.974384, "o", "\u001b[0;32mI (167) app_init: "] +[4.974466, "o", "ELF f"] +[4.974569, "o", "ile SHA256: 5c3063487...\u001b[0m\r\r\n"] +[4.98034, "o", "\u001b[0;32m"] +[4.980368, "o", "I (171) app_"] +[4.980375, "o", "in"] +[4.980381, "o", "it"] +[4.980387, "o", ":"] +[4.980392, "o", " E"] +[4.980397, "o", "S"] +[4.980402, "o", "P-"] +[4.980407, "o", "I"] +[4.980412, "o", "DF"] +[4.980418, "o", ": "] +[4.980423, "o", " "] +[4.980428, "o", " "] +[4.980434, "o", " "] +[4.980439, "o", " "] +[4.980444, "o", " "] +[4.980449, "o", " "] +[4.980455, "o", "v5"] +[4.98046, "o", "."] +[4.980465, "o", "4."] +[4.98047, "o", "1"] +[4.980475, "o", "-d"] +[4.98048, "o", "i"] +[4.980485, "o", "rt"] +[4.98049, "o", "y"] +[4.980495, "o", "\u001b["] +[4.9805, "o", "0"] +[4.980506, "o", "m\r"] +[4.980511, "o", "\r\n"] +[4.982297, "o", "\u001b[0;32mI (175) efuse_ini"] +[4.982317, "o", "t: Min c"] +[4.982323, "o", "hi"] +[4.982328, "o", "p "] +[4.982334, "o", "re"] +[4.982357, "o", "v"] +[4.982365, "o", ": v0"] +[4.982385, "o", ".3\u001b[0"] +[4.982399, "o", "m\r\r\n"] +[4.985945, "o", "\u001b[0;3"] +[4.985966, "o", "2mI (179) e"] +[4.986019, "o", "fu"] +[4.986028, "o", "se_init: Max chip rev: v1.99 "] +[4.986032, "o", "\u001b[0"] +[4.986035, "o", "m\r"] +[4.986038, "o", "\r\n"] +[4.989748, "o", "\u001b[0;"] +[4.989759, "o", "32mI (183"] +[4.989829, "o", ") efuse_init: Chip rev: v0.3"] +[4.98984, "o", "\u001b[0m\r\r\n"] +[4.995832, "o", "\u001b[0;"] +[4.995842, "o", "32mI (18"] +[4.995845, "o", "7)"] +[4.995848, "o", " h"] +[4.99585, "o", "ea"] +[4.995853, "o", "p"] +[4.995887, "o", "_i"] +[4.995925, "o", "nit: Initializing. RAM av"] +[4.99593, "o", "ailable for dynamic allocat"] +[4.99594, "o", "ion:\u001b"] +[4.995948, "o", "[0m\r\r\n"] +[5.001169, "o", "\u001b[0;"] +[5.001177, "o", "32mI ("] +[5.001194, "o", "1"] +[5.001201, "o", "93) h"] +[5.001237, "o", "eap_init: At 3"] +[5.00131, "o", "FC8D"] +[5.001316, "o", "B40 l"] +[5.001404, "o", "en 000324C0 (2"] +[5.001423, "o", "01 KiB): RAM\u001b[0m\r\r\n"] +[5.007063, "o", "\u001b[0;"] +[5.007072, "o", "32mI "] +[5.007099, "o", "(19"] +[5.007106, "o", "9) heap_init: At 3FC"] +[5.007109, "o", "C0"] +[5.007123, "o", "000 len 00"] +[5.007133, "o", "01C710"] +[5.007138, "o", " (11"] +[5.00717, "o", "3 "] +[5.007177, "o", "KiB): Retention RAM\u001b[0m\r"] +[5.007189, "o", "\r\n"] +[5.013037, "o", "\u001b[0;"] +[5.013046, "o", "32mI ("] +[5.013073, "o", "20"] +[5.013077, "o", "5) heap_init: At 3F"] +[5.01308, "o", "CD"] +[5.013083, "o", "C7"] +[5.013085, "o", "10"] +[5.013163, "o", " "] +[5.013169, "o", "len 00002950 (10 KiB): Retention RAM\u001b[0m\r\r\n"] +[5.018538, "o", "\u001b[0;"] +[5.018548, "o", "32mI (21"] +[5.018553, "o", "1) "] +[5.018638, "o", "hea"] +[5.018648, "o", "p_init:"] +[5.018693, "o", " At 500"] +[5.018714, "o", "00"] +[5.018719, "o", "21C len 00001D"] +[5.018722, "o", "CC"] +[5.018725, "o", " ("] +[5.018728, "o", "7"] +[5.01873, "o", " K"] +[5.018733, "o", "iB"] +[5.018736, "o", "):"] +[5.018738, "o", " "] +[5.018741, "o", "RT"] +[5.018743, "o", "CR"] +[5.018746, "o", "A"] +[5.018749, "o", "M\u001b"] +[5.018751, "o", "[0"] +[5.018754, "o", "m"] +[5.01883, "o", "\r\r\n"] +[5.022266, "o", "\u001b[0;"] +[5.022272, "o", "32mI "] +[5.022292, "o", "(2"] +[5.022298, "o", "17) spi_flash: d"] +[5.022302, "o", "et"] +[5.022304, "o", "ec"] +[5.022307, "o", "te"] +[5.02231, "o", "d "] +[5.022312, "o", "c"] +[5.022315, "o", "hi"] +[5.022356, "o", "p:"] +[5.022363, "o", " generic\u001b[0m\r\r\n"] +[5.025165, "o", "\u001b["] +[5.025171, "o", "0;32"] +[5.025174, "o", "mI"] +[5.02522, "o", " (220) spi_flash: flash io: di"] +[5.025225, "o", "o\u001b[0"] +[5.025273, "o", "m\r\r\n"] +[5.037261, "o", "\u001b[0;3"] +[5.03727, "o", "3mW (223"] +[5.037305, "o", ") spi_"] +[5.037312, "o", "flash: Detected siz"] +[5.037315, "o", "e(4"] +[5.037318, "o", "09"] +[5.037321, "o", "6k"] +[5.037324, "o", ")"] +[5.037327, "o", " l"] +[5.03733, "o", "ar"] +[5.037378, "o", "ge"] +[5.037384, "o", "r than the size in the binary ima"] +[5.037394, "o", "ge hea"] +[5.037399, "o", "der("] +[5.037402, "o", "20"] +[5.037405, "o", "48"] +[5.037408, "o", "k)"] +[5.037411, "o", "."] +[5.03747, "o", " U"] +[5.037486, "o", "sing the size in the binary image header"] +[5.037502, "o", ".\u001b[0m\r\r\n"] +[5.043363, "o", "\u001b[0;"] +[5.043414, "o", "32mI"] +[5.043422, "o", " (235) sleep_gpio: Configure to is"] +[5.043425, "o", "ol"] +[5.043428, "o", "at"] +[5.043468, "o", "e all GPIO pins in sleep"] +[5.043474, "o", " stat"] +[5.043477, "o", "e\u001b"] +[5.043528, "o", "[0m\r\r\n"] +[5.050122, "o", "\u001b[0"] +[5.05016, "o", ";32mI (241) sleep_gpio: En"] +[5.050167, "o", "able "] +[5.05017, "o", "au"] +[5.050173, "o", "to"] +[5.050193, "o", "matic switch"] +[5.050209, "o", "ing of GPIO"] +[5.050213, "o", " sl"] +[5.050223, "o", "eep co"] +[5.050228, "o", "nfi"] +[5.050231, "o", "gu"] +[5.050329, "o", "ra"] +[5.050334, "o", "tion\u001b[0m\r\r\n"] +[5.053349, "o", "\u001b[0"] +[5.053375, "o", ";32mI ("] +[5.053383, "o", "248) main_task:"] +[5.053404, "o", " S"] +[5.05341, "o", "tarted on CPU0\u001b"] +[5.053414, "o", "[0"] +[5.053417, "o", "m\r"] +[5.05342, "o", "\r\n"] +[5.056725, "o", "\u001b[0"] +[5.056731, "o", ";32mI"] +[5.056742, "o", " (248"] +[5.056748, "o", ") main"] +[5.056781, "o", "_t"] +[5.056788, "o", "ask: Calling app_main("] +[5.056797, "o", ")\u001b"] +[5.056802, "o", "[0m\r\r\n"] +[5.057966, "o", "He"] +[5.057974, "o", "llo w"] +[5.057982, "o", "orld!"] +[5.057993, "o", "\r\r\n"] +[5.066276, "o", "This"] +[5.066285, "o", " is es"] +[5.06629, "o", "p3"] +[5.066293, "o", "2c"] +[5.066296, "o", "3 "] +[5.066299, "o", "c"] +[5.06632, "o", "hip with 1 CP"] +[5.066323, "o", "U "] +[5.066343, "o", "co"] +[5.066347, "o", "re(s), WiFi/B"] +[5.06635, "o", "LE"] +[5.06639, "o", ","] +[5.066399, "o", " silicon revision v0.3, 2MB "] +[5.066404, "o", "ext"] +[5.066416, "o", "ernal f"] +[5.066421, "o", "las"] +[5.066497, "o", "h\r"] +[5.066502, "o", "\r\n"] +[5.069471, "o", "Mini"] +[5.069476, "o", "mum"] +[5.069497, "o", " f"] +[5.069525, "o", "ree heap size:"] +[5.069531, "o", " 329588 bytes\r\r\n"] +[5.071964, "o", "Rest"] +[5.071977, "o", "arti"] +[5.071981, "o", "ng in"] +[5.072007, "o", " 10"] +[5.072013, "o", " seconds...\r\r\n"] +[6.071471, "o", "Rest"] +[6.0717, "o", "arting in 9"] +[6.071746, "o", " seconds...\r\r\n"] +[7.071584, "o", "Rest"] +[7.071677, "o", "arting i"] +[7.071897, "o", "n 8"] +[7.071932, "o", " seconds...\r\r\n"] +[8.07162, "o", "Rest"] +[8.07185, "o", "arting in 7 seconds...\r\r\n"] +[9.071445, "o", "Rest"] +[9.071534, "o", "arting in 6 se"] +[9.071557, "o", "con"] +[9.071575, "o", "ds"] +[9.071595, "o", ".."] +[9.071866, "o", ".\r"] +[9.071979, "o", "\r\n"] +[10.071586, "o", "Rest"] +[10.071837, "o", "arting in 5 seconds...\r\r\n"] +[11.070981, "o", "Resta"] +[11.0711, "o", "rting in 4 seconds...\r\r\n"] +[12.071537, "o", "Res"] +[12.071775, "o", "tarting in 3 s"] +[12.07189, "o", "econds...\r\r\n"] +[13.071601, "o", "Rest"] +[13.071691, "o", "arting in 2 s"] +[13.071713, "o", "eco"] +[13.071732, "o", "nd"] +[13.071985, "o", "s.."] +[13.072112, "o", ".\r\r\n"] +[14.071558, "o", "Rest"] +[14.07169, "o", "arting in 1 sec"] +[14.071732, "o", "onds..."] +[14.072012, "o", "\r\r\n"] +[15.071569, "o", "Restar"] +[15.071624, "o", "ting in 0 "] +[15.071637, "o", "sec"] +[15.071648, "o", "on"] +[15.071657, "o", "d"] +[15.071666, "o", "s."] +[15.071675, "o", ".."] +[15.071683, "o", "\r"] +[15.07169, "o", "\r\n"] +[16.071324, "o", "Res"] +[16.071516, "o", "tarting now.\r\r\n"] +[16.073351, "o", "ES"] +[16.073499, "o", "P-ROM:esp32c3-ap"] +[16.073596, "o", "i1-"] +[16.073646, "o", "20210"] +[16.073669, "o", "207"] +[16.073897, "o", "\r\r\n"] +[16.07416, "o", "Bu"] +[16.074263, "o", "ild"] +[16.074291, "o", ":Feb 7 202"] +[16.074417, "o", "1\r"] +[16.074548, "o", "\r\n"] +[16.074744, "o", "rs"] +[16.074851, "o", "t:0"] +[16.074907, "o", "xc (RTC_SW_C"] +[16.075012, "o", "PU_RST"] +[16.075082, "o", "),boot:0xc ("] +[16.075163, "o", "SPI_FAS"] +[16.075211, "o", "T_FLASH_BOOT)\r\r\n"] +[16.075352, "o", "Sav"] +[16.075417, "o", "ed "] +[16.075462, "o", "PC:0x40380834"] +[16.075502, "o", "\r\r\n"] +[16.092118, "o", "\u001b[0;33"] +[16.092274, "o", "m--- 0x40380834: esp_restart_noos at /Users/fran"] +[16.092436, "o", "cesco"] +[16.092536, "o", "/esp/v5.4.1/esp-idf/components/esp_system/port/soc/"] +[16.092612, "o", "esp32c3/system_internal.c:112\r\n"] +[16.092819, "o", "\u001b[0m\r\n"] +[16.093135, "o", "SP"] +[16.093244, "o", "IWP:0xee\r\r\n"] +[16.093558, "o", "mode:DIO"] +[16.093703, "o", ", clock di"] +[16.093787, "o", "v:1\r\r\n"] +[16.0941, "o", "l"] +[16.09416, "o", "oad:0x3fcd5"] +[16.094217, "o", "820,le"] +[16.094236, "o", "n:0x157"] +[16.09427, "o", "4\r"] +[16.094295, "o", "\r\n"] +[16.094563, "o", "load:0x403cc710,"] +[16.09462, "o", "len:0x"] +[16.094736, "o", "c30\r\r\n"] +[16.094922, "o", "lo"] +[16.094936, "o", "ad:0x"] +[16.094944, "o", "40"] +[16.09495, "o", "3"] +[16.095093, "o", "ce710,len:0"] +[16.095105, "o", "x"] +[16.095111, "o", "2f"] +[16.095117, "o", "6"] +[16.095198, "o", "4\r\r\n"] +[16.095366, "o", "ent"] +[16.095378, "o", "ry 0x"] +[16.095414, "o", "40"] +[16.095427, "o", "3cc71a\r\r\n"] +[16.096588, "o", "\u001b[0"] +[16.096608, "o", ";32mI (2"] +[16.096616, "o", "4)"] +[16.096622, "o", " b"] +[16.096628, "o", "oo"] +[16.096635, "o", "t:"] +[16.096641, "o", " E"] +[16.096646, "o", "SP"] +[16.096652, "o", "-"] +[16.096658, "o", "ID"] +[16.096687, "o", "F v5.4.1"] +[16.0967, "o", "-dirt"] +[16.096735, "o", "y "] +[16.096742, "o", "2nd stage b"] +[16.096825, "o", "ootloader"] +[16.096878, "o", "\u001b[0m\r\r\n"] +[16.097164, "o", "\u001b[0"] +[16.097181, "o", ";32mI (2"] +[16.09719, "o", "4) "] +[16.097199, "o", "bo"] +[16.097207, "o", "ot"] +[16.097214, "o", ": "] +[16.097333, "o", "com"] +[16.097347, "o", "pile time Jul 2 2025 09:47:11\u001b[0m\r\r\n"] +[16.097552, "o", "\u001b"] +[16.097626, "o", "["] +[16.097648, "o", "0;32mI (24) boo"] +[16.097655, "o", "t: "] +[16.09766, "o", "ch"] +[16.097666, "o", "i"] +[16.097689, "o", "p revi"] +[16.097728, "o", "sion"] +[16.097755, "o", ": v0."] +[16.097765, "o", "3\u001b["] +[16.097772, "o", "0m"] +[16.097819, "o", "\r\r\n"] +[16.100637, "o", "\u001b[0;"] +[16.100651, "o", "32mI "] +[16.100657, "o", "(2"] +[16.100677, "o", "4)"] +[16.100789, "o", " boot: e"] +[16.100883, "o", "fuse block revision: v1.1\u001b[0m\r\r\n"] +[16.104582, "o", "\u001b[0"] +[16.104597, "o", ";32mI ("] +[16.104604, "o", "28)"] +[16.104609, "o", " "] +[16.104615, "o", "bo"] +[16.104619, "o", "ot"] +[16.104624, "o", ".e"] +[16.104631, "o", "sp"] +[16.104635, "o", "32"] +[16.10464, "o", "c"] +[16.104645, "o", "3:"] +[16.104843, "o", " S"] +[16.104898, "o", "PI Speed : 80MHz\u001b[0m\r\r\n"] +[16.108215, "o", "\u001b[0"] +[16.108318, "o", ";32mI (32) boot.esp32"] +[16.108362, "o", "c3: SPI"] +[16.108418, "o", " Mo"] +[16.108432, "o", "de : DIO"] +[16.108438, "o", "\u001b["] +[16.108488, "o", "0m"] +[16.108511, "o", "\r\r\n"] +[16.11194, "o", "\u001b[0;"] +[16.111989, "o", "32mI (36) boot.esp32"] +[16.111997, "o", "c3: "] +[16.112036, "o", "SP"] +[16.11205, "o", "I Flash Size : 2MB\u001b"] +[16.112055, "o", "[0m"] +[16.112061, "o", "\r\r\n"] +[16.116369, "o", "\u001b[0"] +[16.116379, "o", ";32mI "] +[16.116386, "o", "(3"] +[16.116391, "o", "9)"] +[16.116395, "o", " b"] +[16.116399, "o", "oo"] +[16.116493, "o", "t: Enabling RNG early entropy source.."] +[16.116501, "o", ".\u001b["] +[16.116506, "o", "0m"] +[16.116525, "o", "\r\r\n"] +[16.119093, "o", "\u001b[0"] +[16.119105, "o", ";32mI"] +[16.119178, "o", " ("] +[16.119211, "o", "44) boot: Partition Table:\u001b["] +[16.11922, "o", "0m\r\r\n"] +[16.125315, "o", "\u001b[0"] +[16.125329, "o", ";32mI ("] +[16.125382, "o", "46)"] +[16.125438, "o", " boot: ## Label Usage "] +[16.125449, "o", " Type "] +[16.125455, "o", "ST "] +[16.125515, "o", "Of"] +[16.12556, "o", "fset Length\u001b[0m\r\r\n"] +[16.131912, "o", "\u001b["] +[16.131957, "o", "0;32"] +[16.131973, "o", "mI (53) boot: 0 n"] +[16.131979, "o", "vs"] +[16.132061, "o", " WiFi data "] +[16.132072, "o", " 01 "] +[16.132077, "o", "02"] +[16.132082, "o", " 0"] +[16.132166, "o", "0"] +[16.132175, "o", "009000 00006000\u001b[0m\r\r\n"] +[16.138309, "o", "\u001b[0;32mI (59) "] +[16.138319, "o", "boot: "] +[16.138325, "o", " 1"] +[16.13833, "o", " "] +[16.138362, "o", "ph"] +[16.138394, "o", "y_init "] +[16.138557, "o", " RF data 01 01 0000"] +[16.138589, "o", "f000 000010"] +[16.138715, "o", "00\u001b[0m\r\r\n"] +[16.144969, "o", "\u001b[0"] +[16.144984, "o", ";32mI ("] +[16.144992, "o", "66"] +[16.14506, "o", ") b"] +[16.145072, "o", "oot: 2 factory f"] +[16.145107, "o", "act"] +[16.145113, "o", "ory app "] +[16.14518, "o", " "] +[16.145273, "o", " 00 00"] +[16.145311, "o", " 00010000 00100000\u001b[0m\r\r\n"] +[16.148162, "o", "\u001b[0"] +[16.148173, "o", ";32mI"] +[16.14818, "o", " ("] +[16.148185, "o", "72"] +[16.14819, "o", ") "] +[16.148195, "o", "b"] +[16.1482, "o", "oo"] +[16.148205, "o", "t:"] +[16.14821, "o", " E"] +[16.148215, "o", "n"] +[16.14822, "o", "d "] +[16.148245, "o", "of"] +[16.148251, "o", " partitio"] +[16.148256, "o", "n "] +[16.148359, "o", "ta"] +[16.14838, "o", "ble\u001b[0m\r\r\n"] +[16.155427, "o", "\u001b[0"] +[16.155439, "o", ";32mI "] +[16.155445, "o", "(7"] +[16.15545, "o", "6)"] +[16.155455, "o", " "] +[16.15546, "o", "es"] +[16.155465, "o", "p_"] +[16.155471, "o", "im"] +[16.155476, "o", "ag"] +[16.155507, "o", "e: segment "] +[16.155533, "o", "0:"] +[16.155546, "o", " paddr=00010"] +[16.155552, "o", "02"] +[16.155693, "o", "0 "] +[16.155701, "o", "vaddr=3c020020 size=08c0ch ( 35852) map\u001b[0m\r\r\n"] +[16.162924, "o", "\u001b[0"] +[16.162936, "o", ";32mI "] +[16.162949, "o", "(89"] +[16.162954, "o", ") es"] +[16.16296, "o", "p_i"] +[16.163015, "o", "ma"] +[16.163039, "o", "ge: segment 1: paddr=00018c34"] +[16.163047, "o", " vadd"] +[16.163053, "o", "r="] +[16.163057, "o", "3f"] +[16.163062, "o", "c8"] +[16.163154, "o", "b"] +[16.163165, "o", "a00 size=0128ch ( 4748) load\u001b[0m\r\r\n"] +[16.170424, "o", "\u001b[0;"] +[16.170437, "o", "32mI ("] +[16.170443, "o", "9"] +[16.17057, "o", "1) esp_image: segment 2: paddr=00019"] +[16.17063, "o", "ec8 v"] +[16.170642, "o", "addr=40380000 size=06"] +[16.170647, "o", "150"] +[16.170652, "o", "h "] +[16.170669, "o", "( 249"] +[16.17081, "o", "12) loa"] +[16.170853, "o", "d\u001b[0m\r\r\n"] +[16.177868, "o", "\u001b[0"] +[16.177913, "o", ";32mI "] +[16.177969, "o", "(102) esp_image:"] +[16.178001, "o", " segment 3: paddr=00020020"] +[16.178056, "o", " vaddr=42000020 size="] +[16.178066, "o", "16770"] +[16.178116, "o", "h ( 92016) map\u001b[0m"] +[16.178127, "o", "\r\r\n"] +[16.193112, "o", "\u001b[0"] +[16.193132, "o", ";32mI ("] +[16.193212, "o", "120"] +[16.193263, "o", ") esp_image: segment 4: pad"] +[16.193279, "o", "dr=00036798 vadd"] +[16.193286, "o", "r="] +[16.193292, "o", "40"] +[16.193298, "o", "38"] +[16.193314, "o", "61"] +[16.193408, "o", "50 si"] +[16.193423, "o", "ze=056ech ( 22252) load\u001b[0m\r\r\n"] +[16.197516, "o", "\u001b[0"] +[16.197528, "o", ";32mI"] +[16.197535, "o", " ("] +[16.197541, "o", "12"] +[16.197547, "o", "4"] +[16.197552, "o", ") "] +[16.19757, "o", "esp"] +[16.197814, "o", "_image:"] +[16.197828, "o", " segment 5: paddr=0003be8c vaddr=50000200 size=0001ch "] +[16.197835, "o", "( "] +[16.197841, "o", " "] +[16.197848, "o", " 2"] +[16.197854, "o", "8"] +[16.197981, "o", ") "] +[16.198021, "o", "load\u001b[0m\r\r\n"] +[16.20157, "o", "\u001b[0;"] +[16.201582, "o", "32mI "] +[16.201589, "o", "(1"] +[16.201666, "o", "28) boo"] +[16.201679, "o", "t: Loaded app from pa"] +[16.201689, "o", "rti"] +[16.201696, "o", "ti"] +[16.201702, "o", "on"] +[16.201771, "o", " a"] +[16.201809, "o", "t offset 0x10000\u001b[0m\r\r\n"] +[16.206207, "o", "\u001b[0;"] +[16.20625, "o", "32mI (1"] +[16.206263, "o", "29) boot: Di"] +[16.206307, "o", "sa"] +[16.206329, "o", "bling RNG early"] +[16.206341, "o", " entropy"] +[16.206424, "o", " source."] +[16.206435, "o", "..\u001b[0m\r\r\n"] +[16.217852, "o", "\u001b["] +[16.217865, "o", "0;32"] +[16.217872, "o", "mI"] +[16.217879, "o", " "] +[16.217916, "o", "(145) cpu"] +[16.217933, "o", "_star"] +[16.21794, "o", "t:"] +[16.218016, "o", " U"] +[16.218112, "o", "nicore app\u001b[0m\r\r\n"] +[16.226305, "o", "\u001b[0;32mI "] +[16.226322, "o", "(153)"] +[16.22633, "o", " c"] +[16.226343, "o", "pu"] +[16.226355, "o", "_star"] +[16.226477, "o", "t: Pro cpu start user code\u001b[0"] +[16.226567, "o", "m\r\r\n"] +[16.226822, "o", "\u001b[0;32mI ("] +[16.22701, "o", "153) cpu_start: cpu fre"] +[16.227078, "o", "q: 160000000 Hz\u001b[0m\r\r\n"] +[16.227189, "o", "\u001b[0;32m"] +[16.227205, "o", "I (15"] +[16.227216, "o", "4) "] +[16.227226, "o", "app"] +[16.22733, "o", "_"] +[16.227421, "o", "init: Application information:\u001b[0m"] +[16.227436, "o", "\r\r\n"] +[16.230417, "o", "\u001b["] +[16.230429, "o", "0;32"] +[16.230435, "o", "mI"] +[16.230463, "o", " (154) a"] +[16.230571, "o", "pp"] +[16.230723, "o", "_init: Project name: hello_world\u001b[0m\r\r\n"] +[16.233762, "o", "\u001b["] +[16.23378, "o", "0;32mI "] +[16.233839, "o", "(15"] +[16.233862, "o", "8) app_init: App v"] +[16.233889, "o", "ersion: "] +[16.233995, "o", " 1\u001b[0m"] +[16.234005, "o", "\r\r\n"] +[16.238871, "o", "\u001b[0;32mI"] +[16.238891, "o", " (161)"] +[16.239019, "o", " app_init: Compile time: Jul "] +[16.239033, "o", " 2"] +[16.239186, "o", " 2025 09:47:07\u001b[0m\r\r\n"] +[16.24321, "o", "\u001b[0"] +[16.243224, "o", ";32mI "] +[16.243231, "o", "(1"] +[16.243237, "o", "66"] +[16.243244, "o", ") "] +[16.24325, "o", "ap"] +[16.243256, "o", "p_"] +[16.243263, "o", "i"] +[16.243297, "o", "nit: ELF f"] +[16.243329, "o", "ile SHA256:"] +[16.243337, "o", " "] +[16.243343, "o", "5c"] +[16.243349, "o", "30"] +[16.243359, "o", "63"] +[16.243543, "o", "487...\u001b[0m\r\r\n"] +[16.247545, "o", "\u001b[0;"] +[16.247575, "o", "32mI (1"] +[16.247592, "o", "71) ap"] +[16.247599, "o", "p_ini"] +[16.247667, "o", "t: "] +[16.24768, "o", "ESP-IDF: v5.4."] +[16.247687, "o", "1-"] +[16.247693, "o", "di"] +[16.247699, "o", "rt"] +[16.247705, "o", "y\u001b"] +[16.247711, "o", "[0"] +[16.247729, "o", "m\r\r\n"] +[16.251359, "o", "\u001b[0"] +[16.251391, "o", ";32m"] +[16.251404, "o", "I (175) efu"] +[16.251471, "o", "se"] +[16.251483, "o", "_init: Min chip rev: "] +[16.251517, "o", " "] +[16.251528, "o", "v0.3\u001b[0m\r\r\n"] +[16.255355, "o", "\u001b["] +[16.255369, "o", "0;32m"] +[16.255375, "o", "I "] +[16.255381, "o", "(1"] +[16.255387, "o", "7"] +[16.25546, "o", "9)"] +[16.255473, "o", " efuse_init: Max chip rev"] +[16.255479, "o", ": "] +[16.255485, "o", " "] +[16.255649, "o", " v1.99 \u001b[0m\r\r\n"] +[16.259266, "o", "\u001b[0;3"] +[16.259347, "o", "2mI (183) efuse"] +[16.25936, "o", "_init: Chip rev: "] +[16.259367, "o", " "] +[16.259372, "o", "v0"] +[16.259378, "o", ".3"] +[16.259383, "o", "\u001b["] +[16.259388, "o", "0m"] +[16.259393, "o", "\r"] +[16.259398, "o", "\r\n"] +[16.265322, "o", "\u001b[0"] +[16.265333, "o", ";32mI"] +[16.26534, "o", " "] +[16.265346, "o", "(1"] +[16.265352, "o", "87"] +[16.26543, "o", ")"] +[16.265496, "o", " heap_init: Initializing. RAM"] +[16.265531, "o", " available for dyna"] +[16.265547, "o", "mic allocati"] +[16.265573, "o", "on:\u001b[0m\r"] +[16.265613, "o", "\r\n"] +[16.270636, "o", "\u001b[0"] +[16.270647, "o", ";32"] +[16.270804, "o", "mI"] +[16.270868, "o", " (193) heap_init: At 3FC8"] +[16.270973, "o", "DB40 len "] +[16.271028, "o", "000324C0 (201 KiB): RAM\u001b[0m\r\r\n"] +[16.276602, "o", "\u001b[0"] +[16.276658, "o", ";32mI "] +[16.276671, "o", "(198) heap_init:"] +[16.27677, "o", " At 3FCC00"] +[16.27681, "o", "00 le"] +[16.276896, "o", "n 0001C"] +[16.27691, "o", "710 (113 KiB)"] +[16.276965, "o", ": Retention RAM\u001b"] +[16.277016, "o", "[0m\r"] +[16.277028, "o", "\r\n"] +[16.28256, "o", "\u001b[0"] +[16.282571, "o", ";32"] +[16.282601, "o", "mI (204) "] +[16.282702, "o", "heap"] +[16.282726, "o", "_init: At 3FCD"] +[16.282869, "o", "C710 len 00002950 (10 KiB): Retenti"] +[16.28288, "o", "on RA"] +[16.282886, "o", "M\u001b"] +[16.28295, "o", "["] +[16.282985, "o", "0m\r\r\n"] +[16.287944, "o", "\u001b[0;"] +[16.287957, "o", "32mI "] +[16.287964, "o", "(2"] +[16.28797, "o", "1"] +[16.288113, "o", "0)"] +[16.288128, "o", " heap_init: At 500002"] +[16.288187, "o", "1C len 00"] +[16.288341, "o", "001DCC (7 KiB): RTCRAM\u001b[0m\r\r\n"] +[16.291697, "o", "\u001b[0"] +[16.29176, "o", ";32mI (216) spi_fl"] +[16.291803, "o", "ash: de"] +[16.291814, "o", "tected chip: "] +[16.291821, "o", "ge"] +[16.291846, "o", "neric\u001b["] +[16.291853, "o", "0m"] +[16.291935, "o", "\r\r\n"] +[16.294666, "o", "\u001b[0"] +[16.294706, "o", ";32mI (219) "] +[16.294734, "o", "spi_"] +[16.294781, "o", "flash: flash io: dio"] +[16.294792, "o", "\u001b[0m"] +[16.294856, "o", "\r\r\n"] +[16.306759, "o", "\u001b[0"] +[16.306775, "o", ";33mW"] +[16.306786, "o", " (2"] +[16.306802, "o", "22) "] +[16.306925, "o", "spi_flash: Detect"] +[16.306946, "o", "ed size(4096k) large"] +[16.306955, "o", "r t"] +[16.306962, "o", "ha"] +[16.306984, "o", "n the "] +[16.30708, "o", "size in the binary image "] +[16.307167, "o", "header(2048k). Usi"] +[16.307226, "o", "ng the si"] +[16.30724, "o", "ze in the binar"] +[16.307313, "o", "y image header.\u001b[0"] +[16.307336, "o", "m\r\r\n"] +[16.312907, "o", "\u001b["] +[16.312923, "o", "0;32m"] +[16.313054, "o", "I (234) sleep_gp"] +[16.31316, "o", "io: Configure to iso"] +[16.313174, "o", "late "] +[16.313227, "o", "al"] +[16.313262, "o", "l GPIO pins in sleep "] +[16.31327, "o", "st"] +[16.313341, "o", "at"] +[16.313377, "o", "e\u001b[0m\r\r\n"] +[16.319495, "o", "\u001b["] +[16.31951, "o", "0;32m"] +[16.319518, "o", "I "] +[16.319526, "o", "(2"] +[16.319533, "o", "40"] +[16.31954, "o", ")"] +[16.319547, "o", " s"] +[16.319568, "o", "leep_g"] +[16.319682, "o", "pio"] +[16.319714, "o", ": Enable automatic switching of GPI"] +[16.319727, "o", "O sl"] +[16.319887, "o", "eep configuration\u001b[0m\r\r\n"] +[16.323021, "o", "\u001b[0"] +[16.323036, "o", ";32mI"] +[16.323056, "o", " (2"] +[16.323072, "o", "47) "] +[16.32311, "o", "main_"] +[16.323119, "o", "task: Star"] +[16.323233, "o", "ted on CPU0\u001b[0m\r\r\n"] +[16.3266, "o", "\u001b[0;"] +[16.326711, "o", "32mI (247) main_"] +[16.326755, "o", "task: Calling app_main()\u001b["] +[16.326788, "o", "0m\r\r\n"] +[16.327544, "o", "He"] +[16.327562, "o", "llo wo"] +[16.327571, "o", "rld"] +[16.327628, "o", "!\r"] +[16.327664, "o", "\r\n"] +[16.336085, "o", "This"] +[16.33618, "o", " is esp32c3 chip with 1 CP"] +[16.336223, "o", "U co"] +[16.336254, "o", "re(s), WiFi"] +[16.33629, "o", "/BLE, si"] +[16.336338, "o", "licon revi"] +[16.336352, "o", "sion v0.3, 2"] +[16.336395, "o", "MB "] +[16.336423, "o", "external fl"] +[16.336443, "o", "ash\r\r\n"] +[16.33915, "o", "Min"] +[16.339184, "o", "imum fre"] +[16.339196, "o", "e heap"] +[16.339206, "o", " s"] +[16.339307, "o", "ize"] +[16.339349, "o", ": 329588 bytes\r\r\n"] +[16.341636, "o", "Res"] +[16.341726, "o", "tarting in"] +[16.341738, "o", " 10 seconds...\r\r\n"] +[17.341139, "o", "Res"] +[17.341362, "o", "tarting in 9 seconds...\r\r\n"] +[18.340914, "o", "Rest"] +[18.341129, "o", "arting in 8 seconds...\r\r\n"] +[19.34087, "o", "Restart"] +[19.341016, "o", "ing in 7 seconds...\r\r\n"] +[20.340962, "o", "Res"] +[20.341199, "o", "tarting in 6"] +[20.34126, "o", " seconds...\r\r\n"] +[21.340354, "o", "Resta"] +[21.340408, "o", "rting in 5 seconds...\r\r\n"] +[22.340835, "o", "Res"] +[22.34106, "o", "tarting in 4 "] +[22.341187, "o", "seconds...\r\r\n"] +[23.340558, "o", "Resta"] +[23.340703, "o", "rting in 3 seconds...\r\r\n"] +[24.340323, "o", "Resta"] +[24.340348, "o", "rting in 2 second"] +[24.34042, "o", "s..."] +[24.340468, "o", "\r\r\n"] +[25.340836, "o", "Res"] +[25.340918, "o", "tarting in 1"] +[25.340941, "o", " se"] +[25.340961, "o", "co"] +[25.341115, "o", "nd"] +[25.341152, "o", "s...\r\r\n"] +[26.341023, "o", "Res"] +[26.341246, "o", "tarting in 0 seconds...\r\r\n"] +[27.340904, "o", "Rest"] +[27.34111, "o", "arting now.\r\r\n"] diff --git a/content/workshops/esp-idf-basic/assignment-1-1/index.md b/content/workshops/esp-idf-basic/assignment-1-1/index.md new file mode 100644 index 000000000..41ef313fb --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-1-1/index.md @@ -0,0 +1,132 @@ +--- +title: "ESP-IDF Basics - Assign. 1.1" +date: "2025-08-05" +series: ["WS00A"] +series_order: 2 +showAuthor: false +--- + + +## Step 0: Install ESP-IDF Extension for VSCode + +In this workshop, we'll be using VSCode extension. If you didn't install it yet, please follow [these instructions](https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/). + +To install ESP-IDF itself, there are two ways: + +1. Through the extension configuration +2. Using the [ESP-IDF installation manager](https://docs.espressif.com/projects/idf-im-ui/en/latest/) + +The second will soon become the standard way to manage ESP-IDF. + +## Step 1: Create and test a project from an example + +In this section, we will: + +1. Create a new project from an example +2. Build the project +3. Flash and monitor + +Please note that most commands in VSCode are executed through the __Command Palette__, which you can open by pressing `Ctrl`+`Shift`+`P` (or `Cmd`+`Shift`+`P`) + +{{< alert iconColor="#df8e1d" cardColor="#edcea3">}} + In this guide, commands to enter in the __Command Palette__ are marked with the __symbol `>`__. Usually it is sufficient to type a few character of the command, then a dropdown menu will help you find the right one. +{{< /alert >}} + + +### Create a new project from an example + +1. Open VSCode +2. `> ESP-IDF: Show Example Project` +3. (If asked) Choose the ESP-IDF version +4. Click on `get_started` → `hello_world` +5. Click on the button `Select Location for Creating `hello_world` Example` in the new tab. + + +{{< figure +default=true +src="../assets/ass1_1_new_project.webp" +height=500 +caption="Fig.1 - Create new project tab" + >}} + +A new window will open with the following file structure: + + +{{< figure +default=true +src="../assets/ass1_1_hello_world_files.webp" +height=500 +caption="Fig.2 - `hello_world` example files" + >}} + +For now, you can ignore `.vscode`, `.devcontainer`, and `build` folder. You will work on the `hello_world_main.c` file. + +### Build the project + +To compile (_build_) your project, you first need to tell the compiler which core (called _target_) you are using. You can do it through the IDE as follows: + +* `> ESP-IDF: Set Espressif Device Target` +* In the dropdown menu, choose `esp32c3` → `ESP32-C3 chip (via builtin USB-JTAG)` + +Now you're ready to compile your project: +* `> ESP-IDF: Build Your Project` + _You can also click on the small 🔧 icon located in the bottom bar_ + +A terminal tab will open at the bottom of your IDE and show the successful compilation and size of the compiled binary. + + +{{< figure +default=true +src="../assets/ass1_1_compilation_result.webp" +height=500 +caption="Fig.3 - Compilation result" + >}} + +{{< alert icon="lightbulb" iconColor="#179299" cardColor="#9cccce">}} +If you have problems that are hard to debug, it is useful to do a full clean of your project by using the command `> ESP-IDF: Full clean project`. +{{< /alert >}} + +### Flash and monitor + +To see the firmware running, you need to store it on the device (_flash_) and then you need to read the output it emits on the serial port (_monitor_). + +* Connect the board to your workstation +* Check that the device is recognized +* Note the name assigned to the Espressif device + * On Windows, it starts with `COM` + * On Linux/macOS, it starts with `tty` or `ttyUSB` + +If you're having trouble, check the [Establish Serial Connection with ESP32 Guide](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/establish-serial-connection.html#establish-serial-connection-with-esp32). + +Now you can flash and monitor your device. + +* `> ESP-IDF: Build, Flash and Start a Monitor on Your Device` + +In the terminal, you should now see the `Hello World!` string and the countdown before the reset. + + + + +{{< asciinema + key="hello_world" + idleTimeLimit="2" + speed="1.5" + poster="npt:0:09" +>}} + + +## Step 2: Change the output text + +Identify the output string and change it to `Hello LED`. + +## Conclusion + +You can now create a new project and flash it on the board. In the next assignment, we'll consolidate this process. + +### Next step +> Next assignment → [Assignment 1.2](assignment-1-2/) diff --git a/content/workshops/esp-idf-basic/assignment-1-2/index.md b/content/workshops/esp-idf-basic/assignment-1-2/index.md new file mode 100644 index 000000000..1322d22cb --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-1-2/index.md @@ -0,0 +1,41 @@ +--- +title: "ESP-IDF Basics - Assign. 1.2" +date: "2025-08-05" +series: ["WS00A"] +series_order: 3 +showAuthor: false +--- + +## Main task + +For this assignment, you will create a new project from the other `get_started` example: `blink`. +In the `blink` example, you need to specify the GPIO on which the LED is connected. The default value is `GPIO8` but it's different on your board. You will need to change the configuration value through `menuconfig`. + +* Create the project from example as done in the previous assignment. +* Change the example GPIO number in `menuconfig`: + * Find the GPIO on which the LED is connected on your board + * `> ESP-IDF: SDK Configuration Editor (menuconfig)` → `Example Configuration` → `Blink GPIO number` +* Build, flash, and monitor the example. +* Check that the LED is flashing. Is the output port correct? See the board schematic. + + +{{< figure +default=true +src="../assets/esp-board-top.webp" +height=500 +caption="Fig.1 - Board Top View" + >}} + +## Bonus task + +* (Bonus) Change the main filename to `hello_led_main.c` and the project folder to `hello_led`. Did you encounter errors? + * Where is the problem? + +## Conclusion + +You have now a solid understanding of the project creation, building, and flashing. +In the next lesson, we will focus on what usually is the main topic for an Espressif application -- *connectivity*. + +### Next step + +> Next lecture → __[Lecture 2](lecture-2/)__ diff --git a/content/workshops/esp-idf-basic/assignment-2-1/index.md b/content/workshops/esp-idf-basic/assignment-2-1/index.md new file mode 100644 index 000000000..ae7bde6a5 --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-2-1/index.md @@ -0,0 +1,457 @@ +--- +title: "ESP-IDF Basics - Assign. 2.1" +date: "2025-08-05" +series: ["WS00A"] +series_order: 5 +showAuthor: false +--- + + + +In this assignment, we will build up on the code from the last assignment. We will start a soft-AP and an HTTP server. + + +## Starting a soft-AP + +To keep things as simple as possible, this tutorial will hard-code the access point (AP) credentials. As a result, we won't use Non-Volatile Storage (NVS), which is typically used in Wi-Fi applications to store credentials and calibration data. + +NVS is enabled by default. To avoid warnings and errors, we have to disable it through `menuconfig`. + +### Disable NVS + +To disable NVS, we need to access the `menuconfig` and look for `NVS` + +* `> ESP-IDF: SDK Configuration Editor (menuconfig)` → `NVS` + +{{< figure +default=true +src="../assets/ass_2_1_disable_nvs.webp" +height=500 +caption="NVS options to be disabled" + >}} + +### Define soft-AP parameters + +The soft-AP parameters we need are +```c +#define ESP_WIFI_SSID "" +#define ESP_WIFI_PASS "test_esp" +#define ESP_WIFI_CHANNEL 1 +#define MAX_STA_CONN 2 +``` + +{{< alert iconColor="#df8e1d" cardColor="#edcea3">}} + This is __not__ the recommended way to store credentials. Please store them securely in NVS or manage them through configuration settings using menuconfig. For this workshop, use a unique SSID value! +{{< /alert >}} + +### Initialize IP stack and Event Loop + +Espressif's Wi-Fi component relies on an [event loop](https://en.wikipedia.org/wiki/Event_loop) to handle asynchronous events. To start the soft-AP, we need to: + +1. Include `esp_wifi.h` and `string.h` +1. Initialize the IP stack (via `esp_netif_init` and `esp_netif_create_default_wifi_ap`) +1. Start the [default event loop](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_event.html#default-event-loop) +1. Create and register an event handler function to process Wi-Fi events. + +To keep things clean, we'll encapsulate this code in the function `wifi_init_softap` + +```c +#include "esp_wifi.h" +#include "string.h" + +// ... + +void wifi_init_softap() +{ + esp_netif_init(); + esp_event_loop_create_default(); + esp_netif_create_default_wifi_ap(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // always start with this + + esp_wifi_init(&cfg); + + esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &wifi_event_handler, + NULL, + NULL); + + wifi_config_t wifi_config = { + .ap = { + .ssid = ESP_WIFI_SSID, + .ssid_len = strlen(ESP_WIFI_SSID), + .channel = ESP_WIFI_CHANNEL, + .password = ESP_WIFI_PASS, + .max_connection = MAX_STA_CONN, + .authmode = WIFI_AUTH_WPA2_PSK, + .pmf_cfg = { + .required = true, + }, + }, + }; + + + esp_wifi_set_mode(WIFI_MODE_AP); + esp_wifi_set_config(WIFI_IF_AP, &wifi_config); + esp_wifi_start(); + + ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", + ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); +} +``` +### Register handlers for soft-AP + +The function handling Wi-Fi events is as follows: + +```c +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data){ + printf("Event nr: %ld!\n", event_id); +} +``` + +Now compile, flash, start a monitor and run the project. We should start seeing several event numbers appearing on the terminal. + +### Connect to the soft-AP with a Smartphone + +Take your smartphone, open the Wi-Fi list, and select the SSID `esp_tutorial`. + +{{< figure + default=true + src="../assets/ass_2_1_ap_list.webp" + height=500 + caption="List of APs" + >}} + +In the terminal, you should now see `Event nr: 14!` which corresponds to `WIFI_EVENT_AP_STACONNECTED` (you can check the enum value on [GitHub](https://github.com/espressif/esp-idf/blob/c5865270b50529cd32353f588d8a917d89f3dba4/components/esp_wifi/include/esp_wifi_types_generic.h#L964) - remember that enumeration of values start from 0!) + +This indicates that a station (i.e. your smartphone) has connected to the soft-AP (i.e. the Espressif module). + +### Assignment Code: First part + +Your code should resemble [this one](https://gist.github.com/FBEZ/3a81918239081bcaf48ba3684ceac412). + +## Starting HTTP server + +The HTTP server library provided by ESP-IDF is called `esp_http_server`. To use it, you’ll need to include the library and configure and start the server. + +### Include the library + +To use `esp_http_server` in your project, you’ll need to ensure that CMake recognizes it as a required component. + +1. Include the HTTP server header: + + ```c + #include "esp_http_server.h" + ``` + +2. Add `esp_http_server` to your `CMakeLists.txt` under the `PRIV_REQUIRES` list. This tells the build system to include the necessary components. + +Your `CMakeLists.txt` should look like this: + +```cmake +idf_component_register(SRCS "blink_example_main.c" + PRIV_REQUIRES esp_wifi esp_http_server esp_driver_gpio + INCLUDE_DIRS ".") +``` + +### Configure the HTTP Server + +We'll encapsulate the server setup in a dedicated function: + +```c +httpd_handle_t start_webserver() { + httpd_handle_t server = NULL; + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + + if (httpd_start(&server, &config) == ESP_OK) { + ESP_LOGI(TAG, "Server started successfully, registering URI handlers..."); + return server; + } + + ESP_LOGE(TAG, "Failed to start server"); + return NULL; +} +``` + +After calling `httpd_start()`, the `server` handle is initialized and can be used to manage the HTTP server. + +In your `app_main` function, you can now start the server calling: + +```c +httpd_handle_t server = start_webserver(); +``` + +### HTTP URI management + +We'll return an HTML page when the user visits the `/` route. +To register a route, we call the function `httpd_register_uri_handler` after the `start_webserver` in `app_main`. + +```c +httpd_register_uri_handler(server,&hello_world_uri); +``` + +The `httpd_uri_t` structure defines the properties of the URI being registered. +```c + +static const httpd_uri_t hello_world_uri= { + .uri = "/", // the address at which the resource can be found + .method = HTTP_GET, // The HTTP method (HTTP_GET, HTTP_POST, ...) + .handler = hello_get_handler, // The function which process the request + .user_ctx = NULL // Additional user data for context +}; +``` + +The last piece we need is the request handler function + +```c +static esp_err_t hello_get_handler(httpd_req_t *req) +{ + const char* resp_str = "

Hello World

"; + httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); + return ESP_OK; + +} +``` +Note the HTML embedded in the response string. + +#### Connect to the server + +For Espressif devices, the default IP address of the Soft-AP is usually `192.168.4.1`. + +You can verify this in the terminal output. Look for a log line like this: +```bash +I (766) esp_netif_lwip: DHCP server started on interface WIFI_AP_DEF with IP: 192.168.4.1 +``` + +Open the web browser again on your connected device and enter the IP address in the address bar. As shown in Fig.3, you should now get the HTML page that we sent in the `hello_get_handler` function. + +{{< figure +default=true +src="../assets/ass_2_1_result.webp" +height=100 +caption="Fig. 3 – HTML page displayed" + >}} + + ## Assignment Code + +
+Show assignment code + +```c +/* Blink Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include "led_strip.h" +#include "sdkconfig.h" +#include "esp_wifi.h" +#include "string.h" +#include "esp_http_server.h" + +static const char *TAG = "example"; + + +#define ESP_WIFI_SSID "esp_tutorial" +#define ESP_WIFI_PASS "test_esp" +#define ESP_WIFI_CHANNEL 1 +#define MAX_STA_CONN 2 + + +/* Use project configuration menu (idf.py menuconfig) to choose the GPIO to blink, + or you can edit the following line and set a number here. +*/ +#define BLINK_GPIO CONFIG_BLINK_GPIO + +static uint8_t s_led_state = 0; + +#ifdef CONFIG_BLINK_LED_STRIP + +static led_strip_handle_t led_strip; + +static void blink_led(void) +{ + /* If the addressable LED is enabled */ + if (s_led_state) { + /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */ + led_strip_set_pixel(led_strip, 0, 16, 16, 16); + /* Refresh the strip to send data */ + led_strip_refresh(led_strip); + } else { + /* Set all LED off to clear all pixels */ + led_strip_clear(led_strip); + } +} + +static void configure_led(void) +{ + ESP_LOGI(TAG, "Example configured to blink addressable LED!"); + /* LED strip initialization with the GPIO and pixels number*/ + led_strip_config_t strip_config = { + .strip_gpio_num = BLINK_GPIO, + .max_leds = 1, // at least one LED on board + }; +#if CONFIG_BLINK_LED_STRIP_BACKEND_RMT + led_strip_rmt_config_t rmt_config = { + .resolution_hz = 10 * 1000 * 1000, // 10MHz + .flags.with_dma = false, + }; + ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); +#elif CONFIG_BLINK_LED_STRIP_BACKEND_SPI + led_strip_spi_config_t spi_config = { + .spi_bus = SPI2_HOST, + .flags.with_dma = true, + }; + ESP_ERROR_CHECK(led_strip_new_spi_device(&strip_config, &spi_config, &led_strip)); +#else +#error "unsupported LED strip backend" +#endif + /* Set all LED off to clear all pixels */ + led_strip_clear(led_strip); +} + +#elif CONFIG_BLINK_LED_GPIO + +static void blink_led(void) +{ + /* Set the GPIO level according to the state (LOW or HIGH)*/ + gpio_set_level(BLINK_GPIO, s_led_state); +} + +static void configure_led(void) +{ + ESP_LOGI(TAG, "Example configured to blink GPIO LED!"); + gpio_reset_pin(BLINK_GPIO); + /* Set the GPIO as a push/pull output */ + gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); +} + +#else +#error "unsupported LED type" +#endif + +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data){ + printf("Event nr: %ld!\n", event_id); +} + + + +void wifi_init_softap() +{ + esp_netif_init(); + esp_event_loop_create_default(); + esp_netif_create_default_wifi_ap(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // always start with this + + esp_wifi_init(&cfg); + + esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &wifi_event_handler, + NULL, + NULL); + + wifi_config_t wifi_config = { + .ap = { + .ssid = ESP_WIFI_SSID, + .ssid_len = strlen(ESP_WIFI_SSID), + .channel = ESP_WIFI_CHANNEL, + .password = ESP_WIFI_PASS, + .max_connection = MAX_STA_CONN, + .authmode = WIFI_AUTH_WPA2_PSK, + .pmf_cfg = { + .required = true, + }, + }, + }; + + + esp_wifi_set_mode(WIFI_MODE_AP); + esp_wifi_set_config(WIFI_IF_AP, &wifi_config); + esp_wifi_start(); + + ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", + ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); +} + +static esp_err_t hello_get_handler(httpd_req_t *req) +{ + const char* resp_str = "

Hello World

"; + httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); + return ESP_OK; + +} + +static const httpd_uri_t hello_world_uri= { + .uri = "/", // the address at which the resource can be found + .method = HTTP_GET, // The HTTP method (HTTP_GET, HTTP_POST, ...) + .handler = hello_get_handler, // The function which process the request + .user_ctx = NULL // Additional user data for context +}; + + + +httpd_handle_t start_webserver() { + httpd_handle_t server = NULL; + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + + if (httpd_start(&server, &config) == ESP_OK) { + ESP_LOGI(TAG, "Server started successfully, registering URI handlers..."); + return server; + } + + ESP_LOGE(TAG, "Failed to start server"); + return NULL; +} + + +void app_main(void) +{ + + /* Configure the peripheral according to the LED type */ + configure_led(); + wifi_init_softap(); + httpd_handle_t server = start_webserver(); + httpd_register_uri_handler(server,&hello_world_uri); + + while (1) { + ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF"); + blink_led(); + /* Toggle the LED state */ + s_led_state = !s_led_state; + vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS); + } +} + +``` + +
+ + + + +## Conclusion + +Now you can put the Espressif device into Soft-AP or STA mode and create an HTTP server which can return both HTML based content of a JSON based response for a REST API. + +### Next step + +> Next assignment: [Assignment 2.2](assignment-2-2/) diff --git a/content/workshops/esp-idf-basic/assignment-2-2/index.md b/content/workshops/esp-idf-basic/assignment-2-2/index.md new file mode 100644 index 000000000..979c3c57d --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-2-2/index.md @@ -0,0 +1,235 @@ +--- +title: "ESP-IDF Basics - Assign. 2.2" +date: "2025-08-05" +series: ["WS00A"] +series_order: 6 +showAuthor: false +--- + +The second assignment is to add the following routes to the HTTP server that we created in the previous assignment: + + +- `GET /led/on` → turns the LED on and returns JSON {"led": "on"} +- `GET /led/off`→ turns the LED off and returns JSON {"led": "off"} +- `POST /led/blink` → accepts JSON `{ "times": int, "interval_ms": int }` to blink the LED the specified number of times at the given interval, and returns JSON `{"blink": "done"}` + + +## Assignment Code + +
+Show assignment code + +```c +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include "led_strip.h" +#include "sdkconfig.h" + +#include "esp_wifi.h" +#include "string.h" +#include "esp_http_server.h" + +// Define an unique SSID +#define ESP_WIFI_SSID "esp_tutorial" +// Define a password for the WiFi network +#define ESP_WIFI_PASS "test_esp" +#define ESP_WIFI_CHANNEL 1 +#define MAX_STA_CONN 2 + +#define BLINK_GPIO GPIO_NUM_7 // GPIO pin for the LED + +static const char *TAG = "assingment"; + + +static uint8_t s_led_state = 0; + +static void led_control(uint8_t s_led_state) +{ + /* Set the GPIO level according to the state (LOW or HIGH)*/ + gpio_set_level(BLINK_GPIO, s_led_state); +} + +static void configure_led(void) +{ + ESP_LOGI(TAG, "Example configured to blink GPIO LED!"); + gpio_reset_pin(BLINK_GPIO); + /* Set the GPIO as a push/pull output */ + gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); +} + +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data){ + printf("Event nr: %ld!\n", event_id); +} + +void wifi_init_softap() +{ + esp_netif_init(); + esp_event_loop_create_default(); + esp_netif_create_default_wifi_ap(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // always start with this + + esp_wifi_init(&cfg); + + esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &wifi_event_handler, + NULL, + NULL); + + wifi_config_t wifi_config = { + .ap = { + .ssid = ESP_WIFI_SSID, + .ssid_len = strlen(ESP_WIFI_SSID), + .channel = ESP_WIFI_CHANNEL, + .password = ESP_WIFI_PASS, + .max_connection = MAX_STA_CONN, + .authmode = WIFI_AUTH_WPA2_PSK, + .pmf_cfg = { + .required = true, + }, + }, + }; + + esp_wifi_set_mode(WIFI_MODE_AP); + esp_wifi_set_config(WIFI_IF_AP, &wifi_config); + esp_wifi_start(); + + ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", + ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); +} + +static esp_err_t hello_get_handler(httpd_req_t *req) +{ + const char* resp_str = "

Hello World

"; + httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); + return ESP_OK; + +} + +static const httpd_uri_t hello_world_uri= { + .uri = "/", // the address at which the resource can be found + .method = HTTP_GET, // The HTTP method (HTTP_GET, HTTP_POST, ...) + .handler = hello_get_handler, // The function which process the request + .user_ctx = NULL // Additional user data for context +}; + +static esp_err_t led_on_handler(httpd_req_t *req) +{ + led_control(1); + + const char* resp_str = "{\"led\": \"on\"}"; + httpd_resp_set_type(req, "application/json"); + httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); + return ESP_OK; +} + +static esp_err_t led_off_handler(httpd_req_t *req) +{ + led_control(0); + + const char* resp_str = "{\"led\": \"off\"}"; + httpd_resp_set_type(req, "application/json"); + httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); + return ESP_OK; +} + +static esp_err_t led_blink_handler(httpd_req_t *req) +{ + char buf[100]; + int ret = httpd_req_recv(req, buf, sizeof(buf)); + if (ret <= 0) { + httpd_resp_send_500(req); + return ESP_FAIL; + } + + buf[ret] = '\0'; + + int times = 0, interval = 0; + sscanf(buf, "{\"times\": %d, \"interval_ms\": %d}", ×, &interval); + + // add logging for debugging + ESP_LOGI(TAG, "Blinking LED %d times with interval %d ms", times, interval); + + for (int i = 0; i < times; i++) { + s_led_state = 1; + led_control(s_led_state); + vTaskDelay(interval / portTICK_PERIOD_MS); + s_led_state = 0; + led_control(s_led_state); + vTaskDelay(interval / portTICK_PERIOD_MS); + } + + const char* resp_str = "{\"blink\": \"done\"}"; + httpd_resp_set_type(req, "application/json"); + httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN); + return ESP_OK; +} + +static const httpd_uri_t led_on_uri = { + .uri = "/led/on", + .method = HTTP_GET, + .handler = led_on_handler, + .user_ctx = NULL +}; + +static const httpd_uri_t led_off_uri = { + .uri = "/led/off", + .method = HTTP_GET, + .handler = led_off_handler, + .user_ctx = NULL +}; + +static const httpd_uri_t led_blink_uri = { + .uri = "/led/blink", + .method = HTTP_POST, + .handler = led_blink_handler, + .user_ctx = NULL +}; + +httpd_handle_t start_webserver() { + httpd_handle_t server = NULL; + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + + if (httpd_start(&server, &config) == ESP_OK) { + ESP_LOGI(TAG, "Server started successfully, registering URI handlers..."); + return server; + } + + ESP_LOGE(TAG, "Failed to start server"); + return NULL; +} + +void app_main(void) +{ + + /* Configure the peripheral according to the LED type */ + configure_led(); + wifi_init_softap(); + httpd_handle_t server = start_webserver(); + httpd_register_uri_handler(server, &hello_world_uri); + httpd_register_uri_handler(server, &led_on_uri); + httpd_register_uri_handler(server, &led_off_uri); + httpd_register_uri_handler(server, &led_blink_uri); + +} +``` +
+### Conclusion + +Now we have a clear picture of how to connect REST API requests to physical device control. You will work on a more complex application in the last assignment 3.3. + +### Next step + +If you still have time, you can try this optional assignment. + +> Next (optional) assignment → [Assignment 2.3](assignment-2-3/) + +Otherwise, you can move to the third lecture. + +> Next lecture → [Lecture 3](lecture-3/) diff --git a/content/workshops/esp-idf-basic/assignment-2-3/index.md b/content/workshops/esp-idf-basic/assignment-2-3/index.md new file mode 100644 index 000000000..83908f6cf --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-2-3/index.md @@ -0,0 +1,37 @@ +--- +title: "ESP-IDF Basics - Assign. 2.3 (Optional)" +date: "2025-08-05" +series: ["WS00A"] +series_order: 7 +showAuthor: false +--- + +This assignment is optional and it should be done if there's some time left before the break. + +Add another route to the HTTP server from the previous assignments: + +- `POST /led/flash` → accepts JSON `{"periods": [int], "duty_cycles": [int]}` and for each element, calculates the on-time and off-time and drives the LED accordingly. + +You need to first check that both periods and duty_cycles have the same length and contain positive number only. `duty_cycles` should contain numbers between 0 and 100. + +Then, you can traverse the two arrays and calculate for each element at index `i` the LED `on_time` and `off_time` as follows: +```c +on_time[i] = duty_cycle[i]/100 * periods[i] +off_time[i] = periods[i]-on_time[i] +```` + +Now you can drive the LED according to the sequence: +```c +ON: on_time[1] +OFF: off_time[1] +ON: on_time[2] +OFF: off_time[2] +... +``` + +## Conclusion + +If you managed to reach this point, it means you have good understanding of a basic REST API implementation. You can now move to the third lecture, detailing the management of external libraries and the use of the components found on the component registry. + +### Next step +> Next lecture → [Lecture 3](lecture-3/) diff --git a/content/workshops/esp-idf-basic/assignment-3-1/index.md b/content/workshops/esp-idf-basic/assignment-3-1/index.md new file mode 100644 index 000000000..371e9df7b --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-3-1/index.md @@ -0,0 +1,115 @@ +--- +title: "ESP-IDF Basics - Assign. 3.1" +date: "2025-08-05" +series: ["WS00A"] +series_order: 9 +showAuthor: false +--- + +This assignment has two tasks: + + +1. Create a `led-toggle` component +2. Refactor the `hello_led` example using the created component + +## `led-toggle` component + +The first task is to create a `led-toggle` component. + +### Create a new component + +1. Open your project `hello_led` in VSCode +2. Create a new component: `> ESP-IDF: Create New ESP-IDF Component` +3. Type `led_toggle` in the text field appearing on top (see Fig.1) + +{{< figure +default=true +src="../assets/ass3_1_new_component.webp" +caption="Fig.1 - Create new component" + >}} + +The project will now contain the folder `components` and all the required files: +```bash +. +└── hello_led/ + ├── components/ + │ └── led_toggle/ + │ ├── include/ + │ │ └── led_toggle.h + │ ├── CMakeList.txt + │ └── led_toggle.c + ├── main + └── build +``` + +### Create the toggle function + +Inside the `led_toggle.h`, add: + +```c +#include "driver/gpio.h" + +typedef struct { + int gpio_nr; + bool status; +}led_gpio_t; + + + +esp_err_t config_led(led_gpio_t * led_gpio); +esp_err_t drive_led(led_gpio_t * led_gpio); +esp_err_t toggle_led(led_gpio_t * led_gpio); +``` + +{{< alert icon="lightbulb" iconColor="#179299" cardColor="#9cccce">}} +`esp_err` is an enum (hence an int) used to return error codes. You can check its values [in the documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/error-codes.html). +This enum is used also with logging and macros like `ESP_ERR_CHECK`, which you will find almost all esp-idf examples. +{{< /alert >}} + +In the `led_toggle.c`, we have to implement the toggling logic: + + +```c +esp_err_t config_led(led_gpio_t * led_gpio){ + + gpio_config_t io_conf = {}; + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = (1ULL<gpio_nr); + io_conf.pull_down_en = 0; + io_conf.pull_up_en = 0; + return gpio_config(&io_conf); +} + +esp_err_t drive_led(led_gpio_t * led_gpio){ + return gpio_set_level(led_gpio->gpio_nr, led_gpio->status); // turns led on +} + +esp_err_t toggle_led(led_gpio_t * led_gpio){ + //TBD + return 0; +} +``` + +As we've seen in the previous lecture, you first need to configure the peripheral. This is done with the function `config_led`, where you can see the configuration structure we discussed in the lecture. +To test that you chose the correct GPIO and that the LED is working properly, you can also write a `drive_led` which simply drives the GPIO up or down. + +Now you have to: + +1. Include the appropriate header file in your main file. +2. Call the `drive_led` function and check the led is turning on and off + + +## Refactor the `hello_led` code + +Now you are ready to: + +1. Implement the `toggle_led` function +2. Refactor the `hello_led` code to use the newly created component. + +## Conclusion + +You can now create your own components, which makes your code easier to maintain and to share. In the next assignment, you will face a typical development problem and use the skills you just learned. + +### Next step +> Next assignment → [Assignment 3.2](assignment-3-2/) diff --git a/content/workshops/esp-idf-basic/assignment-3-2/index.md b/content/workshops/esp-idf-basic/assignment-3-2/index.md new file mode 100644 index 000000000..1c0f7c0ab --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-3-2/index.md @@ -0,0 +1,26 @@ +--- +title: "ESP-IDF Basics - Assign. 3.2" +date: "2025-08-05" +series: ["WS00A"] +series_order: 10 +showAuthor: false +--- + +In this assignment, you will read the humidity and temperature values from the on-board sensor. + +For this assignment, you have to +1. Find the part number of the sensor on your board +2. Find the code for driving the sensor +3. Read temperature and humidity from the sensor and output it on the serial port with `printf`. + +{{< alert icon="lightbulb" iconColor="#179299" cardColor="#9cccce">}} +It is not asked to develop the driver, focus on the fastest way to solve the problem and what the previous lecture was about. +{{< /alert >}} + +## Conclusion + +Now that you can read the on board sensor, you're ready to move to the last assignment of the workshop to put everything together. + +### Next step + +> Next assignment → [Assignment 3.3](assignment-3-3/) diff --git a/content/workshops/esp-idf-basic/assignment-3-3/index.md b/content/workshops/esp-idf-basic/assignment-3-3/index.md new file mode 100644 index 000000000..585c3c92b --- /dev/null +++ b/content/workshops/esp-idf-basic/assignment-3-3/index.md @@ -0,0 +1,39 @@ +--- +title: "ESP-IDF Basics - Assign. 3.3" +date: "2025-08-05" +series: ["WS00A"] +series_order: 11 +showAuthor: false +--- + +## Putting it all together + + +In this assignment, you will put combine all you have done together by adding the two routes below to your HTTP server. + +For this assignment, you have to + +1. Add the route `GET /enviroment/` which returns the `json` object + +```json +{ + 'temperature': float, + 'humidity': float +} +``` + +### Optional task + +2. (Optional) add route `POST /startblink/` which flashes the led according to the temperature reading + * Flashes the number of tens digit (e.g. 29 degrees → 2) with 400ms on and 200ms off + * Pauses 1 sec + * Flashes the number of units digit (e.g. 29 degrees → 2) with 400ms on and 200ms off + + +## Conclusion + +You have create a basic IoT application, putting together sensor reading and HTTP connectivity, letting external services to interact with your application. + +### Next step + +> Next step → [Conclusion](#conclusion) diff --git a/content/workshops/esp-idf-basic/featured.webp b/content/workshops/esp-idf-basic/featured.webp new file mode 100644 index 000000000..08bba0dfe Binary files /dev/null and b/content/workshops/esp-idf-basic/featured.webp differ diff --git a/content/workshops/brazil-2025/featured.webp b/content/workshops/esp-idf-basic/featured_old.webp similarity index 100% rename from content/workshops/brazil-2025/featured.webp rename to content/workshops/esp-idf-basic/featured_old.webp diff --git a/content/workshops/esp-idf-basic/lecture-1/index.md b/content/workshops/esp-idf-basic/lecture-1/index.md new file mode 100644 index 000000000..c85d6d35d --- /dev/null +++ b/content/workshops/esp-idf-basic/lecture-1/index.md @@ -0,0 +1,267 @@ +--- +title: "ESP-IDF Basics - Lecture 1" +date: "2025-08-05" +series: ["WS00A"] +series_order: 1 +showAuthor: false +--- + +## ESP-IDF Introduction + +The ESP-IDF (Espressif IoT Development Framework) is the official operating system and development framework for the Espressif Systems SoCs. It provides a comprehensive environment for building IoT applications with robust networking, security, and reliability features. + +The ESP-IDF framework includes FreeRTOS, enabling developers to build real-time, multitasking applications. It provides a comprehensive set of libraries, tools, and documentation, serving as the foundation for development on Espressif devices. + +ESP-IDF includes more than 400 examples, covering a wide range of use cases and helping developers quickly get started on their projects. + +### Architecture + +The ESP-IDF platform architecture is mainly divided into 3 layers: + +- **ESP-IDF platform** + - Contains the core components required and the operating system. Includes the FreeRTOS, drivers, build system, protocols, etc. +- **Middleware** + - Adds new features to ESP-IDF, for example the audio framework and HMI. In this workshop, we won't use them. +- **AIoT Application** + - Your application. + + + +{{< figure +default=true +src="../assets/esp-idf-highlevel.webp" +height=500 +caption="Fig.1 - ESP-IDF High level Overview" + >}} + +All the necessary building blocks for your application will be included in the ESP-IDF platform. +ESP-IDF is constantly developing, growing, and improving; acquiring new features and supporting more Espressif cores. +Visit the ESP-IDF project on GitHub to get the updated list of supported versions and the maintenance period. + +{{< github repo="espressif/esp-idf" >}} + +### Main ESP-IDF blocks + +As mentioned, ESP-IDF is built on FreeRTOS and contains several libraries. The main libraries you will include in your projects are: + +1. FreeRTOS (`freertos`): lightweight, real-time operating system kernel designed for embedded devices, providing multitasking capabilities through preemptive scheduling, task management, and inter-task communication. +2. Drivers (`esp_driver_xxx`): libraries for driving peripherals. +3. Protocols (`esp_http`, `esp-tls` etc.): libraries implementing protocols. + +During the assignments, you will learn how to include both internal libraries provided by ESP-IDF and external libraries. ESP-IDF also offers a convenient system for managing external dependencies, known as components. + +### Components + +Components are packages that include libraries along with additional files for dependency management, metadata, and configuration. + +They are used to add new features such as sensor drivers, communication protocols, board support packages, and other functionalities not included in ESP-IDF by default. Some components are already integrated into example projects, and ESP-IDF itself adopts the external component model to promote modularity. + +Using components enhances maintainability and accelerates development by enabling code reuse and sharing across multiple projects. + +If you want to create and publish your own component, we recommend that you watch the talk [DevCon23 - Developing, Publishing, and Maintaining Components for ESP-IDF](https://www.youtube.com/watch?v=D86gQ4knUnc) or read the [How to create an ESP-IDF component](https://developer.espressif.com/blog/2024/12/how-to-create-an-esp-idf-component/) article. + +{{< youtube D86gQ4knUnc >}} + +You can also find components by browsing our [ESP Registry](https://components.espressif.com) platform. + +In [assignment 3.2](assignment-3-2/), you will have a chance to create your own component and use it in your project. + + +### Frameworks + +Also, ESP-IDF serves as the basis for several other frameworks, including: + +- **Arduino for Espressif** +- **ESP-ADF** (Audio Development Framework): Designed for audio applications. +- **ESP-WHO** (AI Development Framework): Focused on face detection and recognition. +- **ESP-RainMaker**: Simplifies building connected devices with cloud capabilities. +- **ESP-Matter SDK**: Espressif's SDK for Matter is the official Matter development framework for ESP32 series SoCs. + +To see all the supported frameworks, please visit our [GitHub organization page](https://github.com/espressif). + + +## ESP-IDF Development + +In addition to libraries, ESP-IDF includes the necessary tools to compile, flash, and monitor your device. + +You can develop applications for Espressif devices using any plain text editor, such as [Gedit](https://gedit-text-editor.org/) or [Notepad++](https://notepad-plus-plus.org/), by following the [manual installation guide](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html#manual-installation) provided in Espressif's documentation. + +However, for this workshop, we will use an IDE (Integrated Development Environment) to streamline both development and setup. Espressif supports several IDEs, but we will focus on Visual Studio Code (VSCode). Espressif provides an official VSCode extension called [`ESP-IDF`](https://marketplace.visualstudio.com/items?itemName=espressif.esp-idf-extension), which enables you to develop, compile, flash, and debug your projects directly within the editor. + +To give you an idea, the ESP-IDF VSCode Extension manages the toolchain and gives you some useful commands which we will use later, such as: + +* `> ESP-IDF: Build Your Project` +* `> ESP-IDF: Set Espressif Device Target` +* `> ESP-IDF: Full clean project` + + +The character `>` indicates VSCode Command Palette, which can be opened by pressing `F1` or `Ctrl`+`Shift`+`P` (or `Cmd`+`Shift`+`P`). + +All these commands are wrappers around the main `ESP-IDF` front-end tool which is [`idf.py`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-py.html). + +## Hardware used in this workshop + +In this workshop we will use an [ESP32-C3 SoC](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) based module, called [ESP32-C3-Mini-1-N4](https://www.espressif.com/sites/default/files/documentation/esp32-c3-mini-1_datasheet_en.pdf). You can spot the ESP32-C3-Mini-1-N4 on your workshop board (see Fig. 2). The ESP32-C3 SoC is under the ESP32-C3-Mini-1-N4 shield. + +{{< figure +default=true +src="../assets/lec_1_module.webp" +height=500 +caption="Fig.2 - ESP32-C3 SoC, module, and workshop board" + >}} + +### ESP32-C3 SoC + +ESP32-C3 is a highly-integrated SoC equipped with a 32-bit RISC-V processor, supporting 2.4 GHz Wi-Fi and Bluetooth LE connectivity. The functional block diagram for ESP32-C3 is shown in Figure 3. + + +{{< figure +default=true +src="../assets/esp32-c3-overview.webp" +height=500 +caption="Fig.3 - ESP32-C3 Block Diagram" + >}} + +ESP32-C3 has the following features: + +- A 32-bit RISC-V single-core processor @ 160 MHz. + +- A __Wi-Fi subsystem__
+ _Supports Station mode, SoftAP mode, SoftAP + Station mode, and promiscuous mode._ + +- A __Bluetooth LE subsystem__
+ _Supports Bluetooth 5 and Bluetooth mesh._ + +- __Integrated memory__
+ _400 KB SRAM and 384 KB ROM on the chip, external flash connection capability_ + +- __Security mechanisms__
+ _Cryptographic hardware accelerators, encrypted flash, secure bootloader_ + +- A __rich set of peripheral interfaces__
+ _The 22 programmable GPIOs can be configured flexibly to support LED PWM, UART, I2C, SPI, I2S, ADC, TWAI, RMT, and USB Serial/JTAG applications._ + +The ESP32-C3 series of chips has several variants, including the version with in-package SPI flash. You can find them on the [ESP32-C3 Series Comparison](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf#page=12) section of the datasheet. ESP8685 is a small package version of ESP32-C3. + + + + +### ESP32-C3-Mini-1-N4 Module + +In addition to SoCs, Espressif offers modules, which integrate an SoC, additional flash, (optionally) PSRAM memory, and a PCB antenna or an antenna connector. The main advantage of modules is not only their ease of use but also a simplified certification process. + +The module we will use is the ESP32-C3-MINI-1-N4. As the name suggests, it includes 4MB of flash. If you're curious about how to interpret the module part number, you can check the article [Espressif part numbers explained: A complete guide - Modules](https://developer.espressif.com/blog/2025/03/espressif-part-numbers-explained/) on the Espressif Developer Portal . + +### ESP32-C3 Workshop board + + +{{< figure +default=true +src="../assets/esp-board-top.webp" +height=500 +caption="Fig.2 - Workshop board" + >}} + +#### Board peripheral overview + +__I2C peripheral__ + +This board includes the following peripherals over the I2C bus: + +| Peripheral | Part number | Reference | Crate | Address | +| ------------------------ | ----------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------- | +| IMU | ICM-42670-P | [Datasheet](https://invensense.tdk.com/download-pdf/icm-42670-p-datasheet/) | [Link](https://crates.io/crates/icm42670) | 0x68 | +| Temperature and Humidity | SHTC3 | [Datasheet](https://www.mouser.com/datasheet/2/682/Sensirion_04202018_HT_DS_SHTC3_Preliminiary_D2-1323493.pdf) | [Link](https://crates.io/crates/shtcx) | 0x70 | + +_I2C Bus Connection_ + +| Signal | GPIO | +| ------ | ------ | +| SDA | GPIO7 | +| SCL | GPIO8 | + +__GPIO__ + +The following devices are connected through GPIO: + +| I/O Devices | GPIO | +| ----------- | ----- | +| WS2812 LED | GPIO2 | +| LED | GPIO10 | +| Button/Boot | GPIO9 | + +__Power supply__ + +* USB type-C (*no PD compatibility*). +* Li-Ion battery charger - MCP73831T-2ACI/OT, it charges up to 4.2V. + * Recommendation: MCP73831T-2ACI/OT does not provide battery protection for over-current or over-discharge. For the battery (Li-Ion or Li-Po), it's recommended to use the ones with embedded protection. + * Limitation: reading the battery voltage is not supported. + +__Pin Layout__ + + +_Left Side_ + +| Pin Number | Description | SoC | +| ---------- | ------------ | ---------- | +| 1 | Reset | EN/CHIP_PU | +| 2 | 3V3 | | +| 3 | N/C | | +| 4 | GND | | +| 5 | IO0/ADC1-0 | GPIO0 | +| 6 | IO1/ADC1-1 | GPIO1 | +| 7 | IO2/ADC1-2 | GPIO2 | +| 8 | IO3/ADC1-3 | GPIO3 | +| 9 | IO4/ADC2-0 | GPIO4 | +| 10 | IO5/ADC2-1 | GPIO5 | +| 11 | IO6/MTCK | GPIO6 | +| 12 | IO7/MTDO/LED | GPIO7 | +| 13 | IO8/LOG | GPIO8 | +| 14 | IO21/U0RXD | GPIO21 | +| 15 | IO20/U0TXD | GPIO20 | +| 16 | IO9/BOOT | GPIO9 | + +_Right Side_ + +| Pin Number | Description | SoC | +| ---------- | ----------- | ------ | +| 1 | VBAT | | +| 2 | EN [1] | | +| 3 | VBUS [2] | | +| 4 | NC | | +| 5 | NC | | +| 6 | NC | | +| 7 | NC | | +| 8 | NC | | +| 9 | IO18/USB_D- | GPIO18 | +| 10 | IO19/USB_D+ | GPIO19 | +| 11 | IO8/SCL | GPIO8 | +| 12 | IO10/SDA | GPIO10 | + + * [1] Connected to LDO enable pin* + * [2] Connected to USB 5V* + +#### Schematics +You can find the board schematic on the [KiCad Libraries GitHub Repository](https://github.com/espressif/kicad-libraries). + + +## Conclusion + +Now that we have a high-level overview of both hardware and firmware, we're ready to start the first assignment. + +### Next Step +> Next Assignment → __[assignment 1.1](assignment-1-1)__ diff --git a/content/workshops/esp-idf-basic/lecture-2/index.md b/content/workshops/esp-idf-basic/lecture-2/index.md new file mode 100644 index 000000000..244a4db7f --- /dev/null +++ b/content/workshops/esp-idf-basic/lecture-2/index.md @@ -0,0 +1,229 @@ +--- +title: "ESP-IDF Basics - Lecture 2" +date: "2025-08-05" +series: ["WS00A"] +series_order: 4 +showAuthor: false +--- + +## Internet connectivity + +Applications communicate over the internet using different protocols, many of which are build on top of other protocols forming a layered structure. + +The __ISO/OSI model__ is a _conceptual_ framework that breaks down how data (like messages, videos, or web pages) travels across networks — including Wi-Fi and Ethernet — into __seven steps (layers)__. Each layer has its own job and uses specific __protocols__ (rules or languages for communication). + +The **ISO/OSI model** is a *conceptual* framework that explains how data such as messages, videos, or web pages travels across networks like Wi-Fi or Ethernet. It organizes this process into seven *layers*, each with a specific role and associated *protocols* --- the rules that govern communication at that layer. + +It is typically visualized like on Fig.1. + +{{< figure +default=true +src="../assets/lec_2_isoosi.webp" +height=500 +caption="Fig.1 - ISO OSI Stack" + >}} +Starting from the bottom, the layers are: +1. __Physical__ - This is the actual hardware: radio signals, antennas, and frequencies.
+ 🔧 *Example: Wi-Fi, Ethernet* + +2. __Data Link__ - Controls the direct connection between devices (like your laptop and router) and handles things like access to the wireless channel.
+ 🔧 *Example: MAC (Media Access Control)* + +3. __Network__ - Figures out how data gets from one network to another.
+ 🔧 *Example: IP (Internet Protocol)* + +4. __Transport__ - Makes sure data is delivered correctly and in the right order.
+ 🔧 *Examples: TCP (Transmission Control Protocol), UDP (User Datagram Protocol)* + +5. __Session__ - Manages and maintains connections between devices or applications.
+ 🔧 *No single protocol in Wi-Fi, but session handling happens in apps using things like NetBIOS, SMB, or TLS* + +6. __Presentation__ - Translates data so it's readable on both ends (like turning an encrypted message back into text).
+ 🔧 *Examples: SSL/TLS (used for encryption), JPEG, MP3, ASCII* + +7. __Application__ - What the user sees: websites, video calls, email, etc.
+ 🔧 *Examples: HTTP (web), HTTPS (secure web), SMTP (email), FTP (file transfer), DNS (domain names)* + + +Some of the layers of this conceptual framework can me managed by a single protocol. For instance the Ethernet protocol takes care of both the physical and the data link layers. + +Each layer passes its work to the next. +You can combine these layers as it usually happens. For instance the __MQTT__ protocol sits at the same level as HTTP. Both of them make use of the TCP/IP stack. + +### Encapsulation + +The combination of the layers is done through encapsulation. + +Encapsulation is the process by which data is wrapped with protocol information at each layer of the network stack to facilitate proper transmission and delivery. In the context of a Wi-Fi network, application data is first encapsulated within a __TCP segment__, which provides reliable transport services. This TCP segment is then encapsulated within an __IP packet__, adding logical addressing and routing information necessary for delivery across networks. Finally, the IP packet is enclosed within a __Wi-Fi (IEEE 802.11) frame__ or an __Ethernet frame__, which handles the physical and data link layer functions for wireless communication. Each layer adds its own header (and sometimes trailer) to the data unit, enabling modular and efficient network communication. + +A picture is worth more than a thousand words: + +{{< figure +default=true +src="../assets/lec_2_encapsulation.webp" +height=500 +caption="Fig.2 - Encapsulation" + >}} + +Simply put, the whole content of the higher level is inside the _payload_ or _data_ field of the lower layer protocol. + +## Connectivity in Espressif + +Now that we have an understanding of the connectivity layers, let's explore which ones are supported by Espressif. + +### Physical Layers + +Espressif modules support three main physical layers, depending on the SoC: + +1. **Wi-Fi**: Supported by all devices, it is used for connection to a router and then to the internet. It will be the focus of this workshop. +2. **BLE**: In IoT, it is mainly used for direct communication with a smartphone and for provisioning (i.e. setting up credentials). +3. **Thread/Zigbee**: IoT protocols that are used for __local__ machine-to-machine (M2M) communication based on mesh topology (many to many connection). To connect to the internet, a Thread-to-Wi-Fi bridge is required. + +{{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}} +The Matter protocol utilizes all of these connectivity layers: BLE is used for provisioning, Thread enables low-power communication, and Wi-Fi is used for high-bandwidth data transfer. +{{< /alert >}} + +In this workshop, we will focus on Wi-Fi only. Let's briefly review its topology. + +#### Wi-Fi topology + +In a Wi-Fi network, there are two main roles: __Access Point (AP)__ (usually called softAP in Espressif) and __Station (STA)__. + +* The __Access Point (AP)__ is the central device (like a Wi-Fi router) that broadcasts the wireless network and connects stations to each other _and_ to external networks like the internet. +* A __Station (STA)__ is any device that connects to the AP. It can be a smartphone, laptop, or smart home device. + +The AP manages the wireless medium, while STAs communicate __through__ the AP, not directly with each other (unless in ad hoc mode). +This setup forms a __basic infrastructure mode__ network, which is the most common type of Wi-Fi setup. + + +{{< figure +default=true +src="../assets/lec_2_sta_ap.webp" +height=500 +caption="Fig.3 - STA vs AP" + >}} + +Espressif's modules can function in both modes. +To connect to an AP, a station need the __SSID__ (router network name) and the password. + +In the first part of the assignment, we will put the Espressif device in AP mode and use our smartphone to connect to it. + +### Application layer protocols + +In the Internet of Things (IoT), various communication protocols are used, with __MQTT__ and __HTTP__ being among the most common. +__MQTT__ is specifically designed for __machine-to-machine (M2M) communication__ and is widely used to manage networks of sensors and actuators, particularly in home automation systems due to its lightweight and efficient messaging model. + +__HTTP__, on the other hand, is best known as the protocol behind the web, used to deliver HTML-based content. However, another major application of HTTP in IoT is for implementing __REST APIs__. These APIs are not intended for direct user interaction, but rather to be accessed by external applications or services. + +For example, imagine a smart home web application that displays the status of various sensors in your house. Instead of connecting to each device individually, the application queries the __REST API__ exposed by a __sensor gateway__, which acts as a bridge between the devices and the user interface. + +In this webinar, we will use HTTP to serve a simple HTML page and implement a REST API, so let's focus on these concepts. + +## HTTP, HTML, and JSON: Serving Web Pages and Building REST APIs + +HTTP can be used to serve HTML pages (like those viewed in web browsers) and structured data such as JSON, which is commonly used to implement REST APIs—mainly for communication between applications. + +### HTTP Basics + +__HTTP (Hypertext Transfer Protocol)__ is the foundation of communication on the web, based on a simple __client-server model__. In this model, the client (such as a web browser or application) sends a request to a server, which processes it and returns a response. + +#### HTTP Requests + +HTTP defines several request methods, each serving a specific purpose: + +* __GET__ - Retrieve data from the server +* __POST__ - Send or create new data on the server +* __PUT__ - Update existing data +* __DELETE__ - Remove data + +#### HTTP Responses + +After receiving a request, the server sends an HTTP response, which includes a __status code__ to indicate the outcome. Common status codes include: + +* __200 OK__ - The request was successful +* __201 Created__ - A new resource was successfully created (usually after a POST) +* __400 Bad Request__ - The server couldn't understand the request due to invalid syntax +* __401 Unauthorized__ - Authentication is required or has failed +* __404 Not Found__ - The requested resource does not exist +* __500 Internal Server Error__ - A general error occurred on the server + +Modern applications and IoT systems often use __JSON (JavaScript Object Notation)__ to format and exchange data. This structured format is at the core of __REST APIs__, which allow clients to interact with server-side resources using standard HTTP methods. + +{{< figure +default=true +src="../assets/lec_2_http_request.webp" +height=500 +caption="Fig.4 - Client-server interaction" +>}} + +### HTML: Web Pages + +__HTML (HyperText Markup Language)__ is the standard language for creating web pages. With ESP-IDF, you can serve HTML pages directly from your embedded device using HTTP. + +These HTML pages can be used to: + +* Display real-time sensor readings +* Provide control interfaces (e.g., buttons or sliders to interact with GPIOs) +* Allow user configuration of network settings or parameters + +A simple HTML page served by an ESP device might look like this: + +```html + + + + ESP Sensor Dashboard + + +

Living Room Sensor

+

Temperature: 22.5°C

+

Humidity: 60%

+ + +``` + +Serving HTML content from your ESP device allows users to interact with it through any web browser, with no additional software required. + +### JSON: REST API + +__JSON__ is a lightweight, human-readable format used to represent structured data. It's ideal for web and IoT applications to exchange information between clients and servers. + +A JSON object is made up of key-value pairs. Here's a simple example: + +```json +{ + "temperature": 22.5, + "humidity": 60, + "sensor": "living_room" +} +``` + +In this case, the object represents a reading from a sensor in the living room. + +#### REST API + +A __REST API__ (Representational State Transfer Application Programming Interface) allows applications to interact with a server using standard __HTTP__ methods. It follows the client-server model, with the server usually responding with JSON-formatted data and an appropriate HTTP status code. + +REST APIs organize access to resources through __routes__, or __URL paths__, which are typically human-readable and logically structured. + +__Example REST API routes__: + +* `GET /sensors` - Retrieve a list of all sensors +* `GET /sensors/42` - Retrieve data for sensor with ID 42 +* `POST /sensors` - Create a new sensor +* `PUT /sensors/42` - Update sensor 42's settings +* `DELETE /sensors/42` - Delete sensor 42 + +This approach allows easy access and manipulation of data, making REST APIs ideal for modern web and IoT applications. + +In the second part of this workshop, you will implement both a simple HTML page and a REST API using HTTP. These examples will help you understand how to serve web content and expose device data to external applications. + +## Conclusion + +This article introduced the layered structure of internet communication, focusing on the ISO/OSI model and its practical use in Wi-Fi networks. We explored how protocols like HTTP and MQTT operate within this framework, how encapsulation allows data to flow through the layers, and how REST APIs enable structured, JSON-based communication between devices and applications. These concepts form the foundation for building modern, connected IoT systems. + +Now you have all the technical background to start the assignments. + +### Next step + +> Next assignment → __[Assignment 2.1](assignment-2-1/)__ diff --git a/content/workshops/esp-idf-basic/lecture-3/index.md b/content/workshops/esp-idf-basic/lecture-3/index.md new file mode 100644 index 000000000..088412721 --- /dev/null +++ b/content/workshops/esp-idf-basic/lecture-3/index.md @@ -0,0 +1,257 @@ +--- +title: "ESP-IDF Basics - Lecture 3" +date: "2025-08-05" +series: ["WS00A"] +series_order: 8 +showAuthor: false +--- + +## Introduction + +As we saw earlier, ESP-IDF contains several libraries, from FreeRTOS --- the operating system which manages all tasks --- to the peripheral drivers and protocol libraries. +Including the libraries for every possible protocol, algorithm, or driver inside ESP-IDF is not possible: It's size would increase dramatically. +If you need a specific protocol, you can probably find it's C implementation somewhere on Github. In this case, the challenge will be to port it to ESP-IDF, taking care of finding all dependencies and informing the build system about which files should be compiled and linked. + +To solve these problem, Espressif developed a component system similar to a package system in GNU/Linux distributions. The components take care of the dependencies and the build system and you can simply include the header file and you're ready to go! +Like in the case of Linux packages, there is also a component manager and a component registry, where you can find all the official packages by Espressif. Once, components are included, the `idf.py` tool will download the component and set the stage for its use. + + +For additional information, we recommend that you watch the talk [DevCon23 - Developing, Publishing, and Maintaining Components for ESP-IDF](https://www.youtube.com/watch?v=D86gQ4knUnc). + +{{< youtube D86gQ4knUnc >}} + +We will explore the differences in the use of the integrated libraries and the ones provided by the component registry. We will also see how to create a component, in order to make reusable code. + +We will explore how to: + +1. Include and use the `gpio` and the `i2c` libraries (included) +2. See how and use the `button` component (registry) +3. Create a new component + +During the assignments, the goal will be to control the LED and the I2C sensor (SHTC3) on the board (see Fig. 1). + +{{< figure +default=true +src="../assets/lec_3_led_gpio.webp" +caption="Fig.1 - GPIO connected to the LED" + >}} + +## Included Libraries + +Let’s take a look at how to use the included libraries. This usually involves three main steps: + +1. Let the build system know about the library + _(include the header file and update `CMakeLists.txt`)_ +2. Configure the library settings +3. Use the library by calling its functions + + +### GPIO + +A GPIO (General-Purpose Input/Output) peripheral is a digital interface on a microcontroller or processor that allows it to read input signals (like button presses) or control output devices (like LEDs) through programmable pins. These pins can be configured individually as either input or output and are commonly used for basic device interfacing and control. + +On our board, we have an LED connected to the GPIO10 (see Fig. 1) and we will use this pin for the example. + +#### Including the library + +To include the `gpio` library, we first need to include the header file and tell the build system where to find it. + +We need first to include +```c +#include "driver/gpio.h" +``` + +and then add to `CMakeList.txt` + +```c +REQUIRES esp_driver_gpio +``` + +Note that the header file and the required path are different: When including a library, make sure you check the [programming guide](https://docs.espressif.com/projects/esp-idf/en/v5.4.1/esp32c3/index.html) first. +You need to: + +* In the upper left corner, choose the core (ESP32-C3) +* Find the page for the peripheral (GPIO) +* Find the section [API Reference](https://docs.espressif.com/projects/esp-idf/en/v5.4.1/esp32c3/api-reference/peripherals/gpio.html#api-reference-normal-gpio) + +#### Configuration + +Peripherals have many settings (input/output, frequency, etc). You need to confiure them before using the peripherals. + +In case of GPIO, a basic configuration is +```c + //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.GPIO18/19 + 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); +``` + +In this workshop, we will use GPIO for output. Due to this, we won't talk about: + +* Interrupts (trigger a function when the input changes) +* Pull-up and pull-down (set a default input value) + + +The only field that needs some explanation is the `pin_bit_mask`. +The configuration refers to the whole GPIO peripheral. In order to apply the configuration only to certain pins (via `gpio_config`), we need to specify the pins via a [bit mask](https://en.wikipedia.org/wiki/Mask_(computing)). +The `pin_bit_mask` is set equal to GPIO_OUTPUT_PIN_SEL which is + +```c +#define GPIO_OUTPUT_LED 10 +#define GPIO_OUTPUT_PIN_SEL (1ULL< ESP-IDF: Open ESP-IDF Terminal` and paste the instruction + +{{< figure +default=true +src="../assets/lec_3_registry.webp" +caption="Fig.2 - espressif/button component" + >}} + +You should get a message +```bash +Executing action: add-dependency +NOTICE: Successfully added dependency "espressif/button": "^4.1.3" to component "main" +NOTICE: If you want to make additional changes to the manifest file at path /blink/main/idf_component.yml manually, please refer to the documentation: https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/manifest_file.html +``` + +A new file `idf_component.yml` has been created in your project with the following content: + +```yaml +dependencies: + espressif/led_strip: ^2.4.1 + espressif/button: ^4.1.3 +``` + +You can add dependencies directly in this file, but it's recommended to use `idf.py add-dependency` utility. + +To use the component, you have to include the appropriate header file and call the functions given in the component documentation and folder. + + + + +### Create a component + +For detailed instructions on how to create a component using the CLI, you can refer to the article [How to create an ESP-IDF component](https://developer.espressif.com/blog/2024/12/how-to-create-an-esp-idf-component/) on the Espressif Developer Portal. + + +In VSCode, you can follow a similar flow: + +1. Create a new project +2. Create a new component by calling `> ESP-IDF: Create New ESP-IDF Component` +3. Give the component a name (e.g. `led_toggle`) + +The project will now contain a components folder and all the required files +```bash +. +└── project_folder/ + ├── components/ + │ └── led_toggle/ + │ ├── include/ + │ │ └── led_toggle.h + │ ├── CMakeList.txt + │ └── led_toggle.c + ├── main + └── build +``` + +{{< alert iconColor="#df8e1d" cardColor="#edcea3">}} +Each time you create or download a component, you need to perform a project __full cleal__ by calling: + +`> ESP-IDF: Full Clean Project` +{{< /alert >}} + +You can then include your component in the main file as `led_toggle.h`. + +## Conclusion + +In this short lecture, we explored two main ways to include external libraries: directly through the CMakeLists.txt file and via the component registry. We covered how to include and use libraries with both methods and explained how to create a custom component from scratch using VSCode. Now it's time to put these concepts into practice in the upcoming assignments. + +### Next step + +> Next assignment → [Assignment 3.1](assignment-3-1/)