-
Notifications
You must be signed in to change notification settings - Fork 43
feat: add micropython in the browser workshop #580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| --- | ||
| title: Daniel Paul | ||
| --- |
f-hollow marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| --- | ||
| title: "MicroPython Jupyter Notebooks in the Browser with ESP32-C3-DevKit-RUST-2" | ||
| date: 2025-10-17 | ||
| showAuthor: false | ||
| series: ["WS00M"] | ||
| series_order: 1 | ||
| tags: ["Workshop", "MicroPython", "Jupyter", "Browser"] | ||
| authors: | ||
| - "daniel-paul" | ||
| showTableOfContents: false | ||
| showAuthor: false | ||
| summary: "In this workshop, you will learn how to program Espressif SoCs directly in your browser using MicroPython and Jupyter notebooks. We will primarily be using ESP32-C3-DevKit-RUST-2 development board. In the process, we will cover LED control, wireless communication, sensors, and MQTT." | ||
| --- | ||
|
|
||
| Welcome to the workshop on MicroPython Jupyter Notebooks in the browser! In this session, you will see how modern web technologies enable direct hardware programming without the need to install local development tools. You'll learn how to flash firmware, execute code interactively, and build IoT applications using only a browser and a USB connection. | ||
|
|
||
| ## About the workshop | ||
|
|
||
| This workshop covers both basic and advanced MicroPython programming for ESP32-C3-DevKit-RUST-2 development board through hands-on assignments: | ||
|
|
||
| <!-- no toc --> | ||
|
|
||
| - **Setup** - Flash MicroPython firmware and understand the development environment | ||
| - **Assignment 1: Blink** -- Control addressable LED | ||
| - **Assignment 2: Button Input** -- Read button presses and create interactive responses | ||
| - **Assignment 3: ESP-NOW Communication** -- Implement wireless Morse code communication between two ESP32-C3-DevKit-RUST-2 development boards | ||
| - **Assignment 4: IMU Sensor and MQTT Communication** -- Read orientation data from an IMU and publish it to MQTT broker | ||
|
|
||
|
|
||
| ## Prerequisites | ||
|
|
||
| ### Hardware | ||
|
|
||
| - A computer running Windows, macOS or Linux | ||
| - ESP32-C3-DevKit-RUST-2 board (Provided by us) | ||
| - USB-C cable (data + power) compatible with the board | ||
|
|
||
| ### Software | ||
|
|
||
| - Chromium-based browser (Google Chrome, Microsoft Edge, Opera, Brave, Vivaldi) | ||
| - [Mosquitto](https://mosquitto.org/download/) client (Optional) | ||
|
|
||
| ### Effort | ||
|
|
||
| {{< alert icon="mug-hot">}} | ||
| **Estimated time: 120 min** | ||
| {{< /alert >}} | ||
|
|
||
| ## Workshop | ||
|
|
||
| Without further ado, let's dive into the exciting world of ESP microcontrollers and MicroPython! Please follow along as we explore the capabilities of this powerful platform. | ||
|
|
||
| * [Introduction and Setup](introduction-and-setup/) | ||
| * [Assignment 1 - Blink](assignment-1/) | ||
| * [Assignment 2 - Button Input](assignment-2/) | ||
| * [Assignment 3 - ESP-NOW Communication](assignment-3/) | ||
| * [Assignment 4 - IMU Sensor and MQTT Communication](assignment-4/) | ||
|
|
||
| ## Conclusion | ||
|
|
||
| You've learned to program ESP32-C3-DevKit-RUST-2 development board using browser-based Jupyter notebooks, covering: | ||
|
|
||
| - MicroPython firmware flashing and interactive development | ||
| - GPIO control for LEDs and button input | ||
| - ESP-NOW wireless communication protocol | ||
| - IMU sensor data acquisition and processing | ||
| - MQTT protocol for IoT messaging | ||
|
|
||
| These skills form the foundation for building sophisticated IoT applications. The browser-based approach eliminates toolchain complexity while maintaining full access to MicroPython's capabilities. | ||
|
|
||
| ## FAQ | ||
| - I have been prompted to select a kernel in Jupyter Notebook. Which one should I use? | ||
| - Select `Embedded Kernel`. | ||
| - How do I connect my device to the Jupyter notebook? | ||
| - Click on the ESP Control Panel, click `Connect` and select your device. | ||
| - Which of the devices is my ESP board? | ||
| - The ESP board usually appears as `USB JTAG`. | ||
| - I cannot connect to a different Jupyter notebook. | ||
| - Disconnect from the previous notebook and connect the new one. | ||
| - The notebook isn’t running my code, what should I do | ||
| - In the ESP Control Panel, click `Disconnect device`, then reopen the notebook and connect again. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| --- | ||
| title: "Assignment 1: Blink - Control the addressable LED" | ||
| date: 2025-10-17T00:00:00+01:00 | ||
| showTableOfContents: true | ||
| series: ["WS00M"] | ||
| series_order : 2 | ||
| showAuthor: false | ||
XDanielPaul marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| --- | ||
|
|
||
| In this assignment you will initialize and control the onboard addressable LED in three different ways. | ||
|
|
||
| ## Understanding addressable LEDs | ||
|
|
||
| WS2812 are individually addressable RGB LEDs. Each LED can display any color by mixing red, green, and blue values (0-255 each). The ESP32-C3-DevKit-RUST-2 board has one addressable LED on GPIO 2. | ||
|
|
||
| Work through the following tasks in your Assignment 1 Jupyter notebook: | ||
|
|
||
| ## Task 1: Initialize the addressable LED | ||
| In this task, you’ll set up the addressable LED so your code can communicate with it. The `neopixel.NeoPixel(machine.Pin(2), 1)` line tells the chip which pin the LED is connected to (GPIO 2) and how many LEDs are being controlled (1 in this case). | ||
|
|
||
| ```python | ||
| neopixel_led = neopixel.NeoPixel(machine.Pin(2), 1) | ||
| ``` | ||
|
|
||
| ## Task 2: Set the Solid Colors | ||
|
|
||
| Here, you’ll write helper functions to change the LED’s color. | ||
| The `set_color()` function lets you set any RGB color by adjusting red, green, and blue brightness values from 0–255. | ||
| The `clear_led()` function turns the LED off. | ||
| You’ll then test the LED by cycling through a few example colors. | ||
|
|
||
|
|
||
| ```python | ||
| def set_color(r, g, b): | ||
| """Set the addressable LED to a specific RGB color""" | ||
| neopixel_led[0] = (r, g, b) | ||
| neopixel_led.write() | ||
|
|
||
| def clear_led(): | ||
| """Turn off the LED""" | ||
| set_color(0, 0, 0) | ||
|
|
||
|
|
||
| # Try different colors | ||
| set_color(255, 0, 0) # Red | ||
| time.sleep(1) | ||
| set_color(0, 255, 0) # Green | ||
| time.sleep(1) | ||
| set_color(0, 0, 255) # Blue | ||
| time.sleep(1) | ||
| set_color(255, 255, 0) # Yellow | ||
| time.sleep(1) | ||
| clear_led() | ||
| ``` | ||
|
|
||
| ## Task 3: Rainbow cycle effect | ||
|
|
||
| This task adds a simple animation. | ||
| You’ll create a rainbow_cycle() function that loops through a list of predefined colors — red, orange, yellow, green, blue, indigo, and violet — so the LED smoothly transitions through the rainbow spectrum. | ||
|
|
||
| ```python | ||
| def rainbow_cycle(): | ||
| """Cycle through rainbow colors""" | ||
| colors = [ | ||
| (255, 0, 0), # Red | ||
| (255, 127, 0), # Orange | ||
| (255, 255, 0), # Yellow | ||
| (0, 255, 0), # Green | ||
| (0, 0, 255), # Blue | ||
| (75, 0, 130), # Indigo | ||
| (148, 0, 211) # Violet | ||
| ] | ||
|
|
||
| for color in colors: | ||
| set_color(*color) | ||
| time.sleep(0.3) | ||
| clear_led() | ||
|
|
||
| rainbow_cycle() | ||
| ``` | ||
|
|
||
| ## Task 4: Breathing Effect | ||
|
|
||
| Now you’ll create a more dynamic lighting effect. | ||
| The breathing_effect() function gradually fades the LED in and out using brightness scaling, giving a “breathing” glow. | ||
| You can adjust the color, duration, and smoothness by changing the parameters. | ||
|
|
||
| ```python | ||
| def breathing_effect(r, g, b, duration=2, steps=50): | ||
| """ | ||
| Create a breathing effect with the specified color | ||
| """ | ||
| step_delay = duration / (steps * 2) | ||
|
|
||
| # Fade in | ||
| for i in range(steps): | ||
| brightness = i / steps | ||
| set_color(int(r * brightness), int(g * brightness), int(b * brightness)) | ||
| time.sleep(step_delay) | ||
|
|
||
| # Fade out | ||
| for i in range(steps, 0, -1): | ||
| brightness = i / steps | ||
| set_color(int(r * brightness), int(g * brightness), int(b * brightness)) | ||
| time.sleep(step_delay) | ||
|
|
||
| clear_led() | ||
|
|
||
| breathing_effect(0, 100, 255) | ||
| ``` | ||
|
|
||
| #### Next step | ||
|
|
||
| {{< alert iconColor="#df8e1d" cardColor="#edcea3">}} | ||
| Click on the ESP Control Panel and `Disconnect device` the device from the Jupyter notebook. | ||
| {{< /alert >}} | ||
|
|
||
|
|
||
| > Next step: [Assignment 2](../assignment-2/). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| --- | ||
| title: "Assignment 2: Button Input" | ||
| date: 2025-10-17T00:00:00+01:00 | ||
| showTableOfContents: true | ||
| series: ["WS00M"] | ||
| series_order : 3 | ||
| showAuthor: false | ||
| --- | ||
|
|
||
| Navigate to `workshops/2025-10-17` directory and open Assignment 2 in the MicroPython Jupyter Notebook browser interface. | ||
|
|
||
| If prompted with selecting kernel, select `Embedded Kernel`, click on the ESP Control Panel and connect your device. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems some part is missing. After the end of assignment 1, we're left with our browser open and device disconnected. Why and when could this prompt appear?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing this out, I added text to guide a user forward |
||
|
|
||
| In this assignment, you will learn to read button inputs and generate interactive responses with LEDs. | ||
|
|
||
| {{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}} | ||
| You will be configuring a `boot` button located on Pin 9. | ||
| {{< /alert >}} | ||
|
|
||
| ## Understanding Pull-up Resistors | ||
|
|
||
| On the ESP32-C3-DevKit-RUST-2 board, pressing the **boot** button connects pin 9 to ground. When the button is not pressed, the pin is left floating, which leads to an undefined logic level. Pull-up resistors ensure that the pin maintains a defined logic high level when the button is released. | ||
|
|
||
| In summary: | ||
| * Button not pressed: GPIO reads HIGH (1) thanks to pull-up resistor. | ||
| * Button pressed: GPIO reads LOW (0) because the pin is connected to ground. | ||
|
|
||
| The ESP32-C3-DevKit-RUST-2 has internal pull-up resistors that can be enabled in software. | ||
|
|
||
| ## Task 1: Configure button | ||
|
|
||
| In this task, you’ll initialize the onboard button so your program can read its state. | ||
| The pin is configured as an input (`machine.Pin.IN`) with an internal pull-up resistor (`machine.Pin.PULL_UP`). | ||
|
|
||
|
|
||
| ```python | ||
| button = machine.Pin(9, machine.Pin.IN, machine.Pin.PULL_UP) | ||
| ``` | ||
|
|
||
| ## Task 2: Simple Button Press Detection | ||
|
|
||
| Here you’ll write a function that waits until the button is pressed. | ||
| The loop continuously checks the pin’s value — when it changes from HIGH to LOW, the program detects a press and prints a message. | ||
|
|
||
| ```python | ||
| def wait_for_button_press(): | ||
| """Wait until button is pressed""" | ||
| while button.value() == 1: | ||
| time.sleep(0.05) | ||
| print("Button pressed!") | ||
| ``` | ||
|
|
||
| Now you’ll make the LED respond to button input. | ||
| Each time the button is pressed, the LED toggles between ON and OFF. | ||
| A small delay is added to handle “debouncing” — preventing multiple rapid triggers from one press. | ||
|
|
||
| {{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}} | ||
| “Bouncing” happens when you press a button and instead of sending a single clean signal, it wiggles a little and makes the system think you pressed it many times really fast. Debouncing is just a way to make the system listen to only one press, no matter how wobbly the button is.” | ||
| {{< /alert >}} | ||
|
|
||
|
|
||
| ## Task 3: Toggle LED on Button Press | ||
|
|
||
| ```python | ||
| led_state = False | ||
|
|
||
| while True: | ||
| if button.value() == 0: # Button pressed | ||
| led_state = not led_state | ||
| if led_state: | ||
| set_color(255, 0, 0) | ||
| else: | ||
| clear_led() | ||
|
|
||
| # Wait for button release (debounce) | ||
| while button.value() == 0: | ||
| time.sleep(0.05) | ||
| time.sleep(0.1) # Additional debounce delay | ||
| ``` | ||
|
|
||
| ## Task 4: Measure Press duration | ||
|
|
||
| In this task, you’ll measure how long the button is held down. | ||
| The program records the start time when pressed and calculates the total duration once released. | ||
|
|
||
| ```python | ||
| def measure_press_duration(): | ||
| """Measure how long the button is held down""" | ||
| start = time.ticks_ms() | ||
| while button.value() == 0: | ||
| time.sleep(0.05) | ||
| duration = time.ticks_diff(time.ticks_ms(), start) / 1000.0 | ||
| return duration | ||
|
|
||
| wait_for_button_press() | ||
| duration = measure_press_duration() | ||
| print(f"Button held for {duration:.2f} seconds") | ||
| ``` | ||
|
|
||
| ## Bonus Challenge | ||
|
|
||
| Create a visual feedback based on duration. | ||
|
|
||
| Change LED color based on how long the button is pressed: | ||
| - Short press (< 1s): Blue | ||
| - Medium press (1-3s): Yellow | ||
| - Long press (> 3s): Red | ||
|
|
||
|
|
||
| #### Next step | ||
|
|
||
| {{< alert iconColor="#df8e1d" cardColor="#edcea3">}} | ||
| Click on the ESP Control Panel and `Disconnect device` the device from the Jupyter notebook. | ||
| {{< /alert >}} | ||
|
|
||
| > Next step: [Assignment 3](../assignment-3). | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file must be named
_index.md, so that it can work as a main page. Otherwise, it won't work like a multi-page article.I know that if you add an underscore, the information about the author and summary disappear. It is a default behavior that we ourselves don't like and will fix it soon. Sorry for that!
If you add yourself as an author in child pages, the author entries will be visible. Feel free to do it.