Skip to content

Commit f0262da

Browse files
committed
feat: add micropython in the browser workshop
1 parent 14b33c5 commit f0262da

File tree

12 files changed

+782
-0
lines changed

12 files changed

+782
-0
lines changed
54.6 KB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
title: Daniel Paul
3+
---
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
title: "MicroPython Jupyter Notebooks in the Browser with ESP32-C3-DevKit-RUST-2"
3+
date: 2025-10-17
4+
showAuthor: false
5+
series: ["WS00M"]
6+
series_order: 1
7+
tags: ["Workshop", "MicroPython", "Jupyter", "Browser"]
8+
authors:
9+
- "daniel-paul"
10+
showTableOfContents: false
11+
showAuthor: false
12+
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."
13+
---
14+
15+
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.
16+
17+
## About the workshop
18+
19+
This workshop covers both fundamental and advanced MicroPython programming for ESP32-C3-DevKit-RUST-2 development board through hands-on assignments:
20+
21+
<!-- no toc -->
22+
23+
- **Setup** - Flash MicroPython firmware and understand the development environment
24+
- **Assignment 1: Blink** -- Control NeoPixel LED
25+
- **Assignment 2: Button Input** -- Read button presses and create interactive responses
26+
- **Assignment 3: ESP-NOW Communication** -- Implement wireless Morse code communication between two ESP32-C3-DevKit-RUST-2 development boards
27+
- **Assignment 4: IMU Sensor and MQTT Communication** -- Read orientation data from an IMU and publish it to MQTT broker
28+
29+
30+
## Prerequisites
31+
32+
### Hardware
33+
34+
- Computer running Windows, macOS or Linux
35+
- Chromium-based browser (Google Chrome, Microsoft Edge, Opera, Brave, Vivaldi)
36+
- ESP32-C3-DevKit-RUST-2 development board (Provided by us)
37+
- USB-C cable (data + power) compatible with the board
38+
39+
### Software
40+
41+
- Modern Chromium-based browser with WebSerial API support
42+
- [Mosquitto](https://mosquitto.org/download/) message broker
43+
44+
### Effort
45+
46+
{{< alert icon="mug-hot">}}
47+
**Estimated time: 120 min**
48+
{{< /alert >}}
49+
50+
## Introduction
51+
52+
As it has already been announced, this workshop will be using MicroPython and Jupyter Notebooks. Let's quickly introduce them.
53+
54+
### MicroPython
55+
56+
MicroPython is a lean implementation of Python 3 optimized for microcontrollers. It provides an interactive REPL (Read-Eval-Print Loop) and supports most Python standard library features, making embedded development accessible to Python programmers.
57+
58+
### Jupyter Notebook
59+
60+
Jupyter Notebook is a web-based interactive computing environment that allows you to create documents that contain live code, and narrative text. It is composed from a kernel, which is a program that executes the code, and a frontend, which is a user interface that allows you to interact with the kernel.
61+
62+
The code is composed of cells, which can be executed independently or sequentially, either by clicking on the cell and pressing the run button or using a keyboard shortcut `Shift + Enter`. If the code executes a `while True` loop, it can be interrupted by clicking on the stop button in the toolbar.
63+
64+
### Why MicroPython Jupyter Notebooks in the Browser?
65+
Traditional embedded development requires installing toolchains, IDEs, and drivers. Browser-based Jupyter notebooks eliminate this setup by leveraging the WebSerial API, which allows web applications to communicate directly with serial devices. This approach offers several advantages:
66+
67+
- **Zero installation**: No local toolchain required
68+
- **Interactive development**: Execute code cells individually and see immediate results
69+
- **Educational value**: Clear separation of concepts into notebook cells
70+
- **Cross-platform**: Works identically on Windows, macOS, and Linux
71+
- **Version control friendly**: Notebooks can be easily shared and versioned
72+
73+
### How It Works
74+
The browser connects to your ESP32-C3-DevKit-RUST-2 development board via USB using the WebSerial API. Jupyter notebooks send Python code to the MicroPython REPL running on the device. The device executes the code and returns output, which displays in the notebook interface.
75+
76+
### Related documentation
77+
78+
- [MicroPython Documentation](https://docs.micropython.org/en/latest/)
79+
- [ESP32 MicroPython Guide](https://docs.micropython.org/en/latest/esp32/quickref.html)
80+
- [ESP-NOW Protocol](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html)
81+
- [ESP-NOW in MicroPython](https://docs.micropython.org/en/latest/library/espnow.html)
82+
83+
## Workshop
84+
85+
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.
86+
87+
* [Setup](setup/)
88+
* [Assignment 1 - Blink](assignment-1/)
89+
* [Assignment 2 - Button Input](assignment-2/)
90+
* [Assignment 3 - ESP-NOW Communication](assignment-3/)
91+
* [Assignment 4 - IMU Sensor and MQTT Communication](assignment-4/)
92+
93+
## Conclusion
94+
95+
You've learned to program ESP32-C3-DevKit-RUST-2 development board using browser-based Jupyter notebooks, covering:
96+
97+
- MicroPython firmware flashing and interactive development
98+
- GPIO control for LEDs and button input
99+
- ESP-NOW wireless communication protocol
100+
- IMU sensor data acquisition and processing
101+
- MQTT protocol for IoT messaging
102+
103+
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.
104+
105+
## FAQ
106+
- I have been prompted to select a kernel in Jupyter Notebook. Which kernel should I use?
107+
- Select `Embedded Kernel`.
108+
- How do I connect my device to the Jupyter notebook?
109+
- Click on the ESP Control Panel, click `Connect` and select your device.
110+
- Which of the devices is my ESP board?
111+
- The ESP board usually appears as `USB JTAG`.
112+
- I cannot connect to a different Jupyter notebook.
113+
- Disconnect from the previous notebook and connect the new one.
114+
- The notebook isn’t running my code, what should I do
115+
- In the ESP Control Panel, click `Disconnect device`, then reopen the notebook and connect again.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
title: "Assignment 1: Blink - Control the NeoPixel LED"
3+
date: 2025-10-17T00:00:00+01:00
4+
showTableOfContents: true
5+
series: ["WS00M"]
6+
series_order : 2
7+
showAuthor: false
8+
---
9+
10+
## Assignment 1: Blink
11+
12+
Let's continue by controlling the onboard NeoPixel LED.
13+
14+
### Understanding NeoPixel LEDs
15+
16+
NeoPixel (WS2812) LEDs 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 NeoPixel on GPIO 2.
17+
18+
Work through the following tasks in your Assignment 1 Jupyter notebook:
19+
20+
### Task 1: Initialize the NeoPixel
21+
In this task, you’ll set up the NeoPixel 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).
22+
23+
```python
24+
neopixel_led = neopixel.NeoPixel(machine.Pin(2), 1)
25+
```
26+
27+
### Task 2: Set the Solid Colors
28+
29+
Here, you’ll write helper functions to change the LED’s color.
30+
The `set_color()` function lets you set any RGB color by adjusting red, green, and blue brightness values from 0–255.
31+
The `clear_led()` function turns the LED off.
32+
You’ll then test the LED by cycling through a few example colors.
33+
34+
35+
```python
36+
def set_color(r, g, b):
37+
"""Set the NeoPixel to a specific RGB color"""
38+
neopixel_led[0] = (r, g, b)
39+
neopixel_led.write()
40+
41+
def clear_led():
42+
"""Turn off the LED"""
43+
set_color(0, 0, 0)
44+
45+
46+
# Try different colors
47+
set_color(255, 0, 0) # Red
48+
time.sleep(1)
49+
set_color(0, 255, 0) # Green
50+
time.sleep(1)
51+
set_color(0, 0, 255) # Blue
52+
time.sleep(1)
53+
set_color(255, 255, 0) # Yellow
54+
time.sleep(1)
55+
clear_led()
56+
```
57+
58+
### Task 3: Rainbow cycle effect
59+
60+
This task adds a simple animation.
61+
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.
62+
63+
```python
64+
def rainbow_cycle():
65+
"""Cycle through rainbow colors"""
66+
colors = [
67+
(255, 0, 0), # Red
68+
(255, 127, 0), # Orange
69+
(255, 255, 0), # Yellow
70+
(0, 255, 0), # Green
71+
(0, 0, 255), # Blue
72+
(75, 0, 130), # Indigo
73+
(148, 0, 211) # Violet
74+
]
75+
76+
for color in colors:
77+
set_color(*color)
78+
time.sleep(0.3)
79+
clear_led()
80+
81+
rainbow_cycle()
82+
```
83+
84+
### Task 4: Breathing Effect
85+
86+
Now you’ll create a more dynamic lighting effect.
87+
The breathing_effect() function gradually fades the LED in and out using brightness scaling, giving a “breathing” glow.
88+
You can adjust the color, duration, and smoothness by changing the parameters.
89+
90+
```python
91+
def breathing_effect(r, g, b, duration=2, steps=50):
92+
"""
93+
Create a breathing effect with the specified color
94+
"""
95+
step_delay = duration / (steps * 2)
96+
97+
# Fade in
98+
for i in range(steps):
99+
brightness = i / steps
100+
set_color(int(r * brightness), int(g * brightness), int(b * brightness))
101+
time.sleep(step_delay)
102+
103+
# Fade out
104+
for i in range(steps, 0, -1):
105+
brightness = i / steps
106+
set_color(int(r * brightness), int(g * brightness), int(b * brightness))
107+
time.sleep(step_delay)
108+
109+
clear_led()
110+
111+
breathing_effect(0, 100, 255)
112+
```
113+
114+
Click on the ESP Control Panel and `Disconnect device` the device from the Jupyter notebook before proceeding with the next [assignment](../assignment-2/).
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
---
2+
title: "Assignment 2: Button Input"
3+
date: 2025-10-17T00:00:00+01:00
4+
showTableOfContents: true
5+
series: ["WS00M"]
6+
series_order : 2
7+
showAuthor: false
8+
---
9+
10+
## Assignment 2: Button Input
11+
12+
Learn to read button input and create interactive LED responses.
13+
14+
If prompted with selecting kernel, select `Embedded Kernel`, click on the ESP Control Panel and connect your device.
15+
16+
{{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}}
17+
In this assignment you will be configuring a `boot` button located on Pin 9.
18+
{{< /alert >}}
19+
20+
### Understanding Pull-up Resistors
21+
22+
Buttons create a connection when pressed. Pull-up resistors ensure a defined logic level when the button is not pressed:
23+
24+
Button not pressed: GPIO reads HIGH (1) due to pull-up resistor.
25+
26+
Button pressed: GPIO reads LOW (0) as it connects to ground.
27+
28+
The ESP32-C3-DevKit-RUST-2 has internal pull-up resistors that can be enabled in software.
29+
30+
### Task 1: Configure button
31+
32+
In this task, you’ll initialize the onboard button so your program can read its state.
33+
The pin is configured as an input (`machine.Pin.IN`) with an internal pull-up resistor (`machine.Pin.PULL_UP`).
34+
35+
36+
```python
37+
button = machine.Pin(9, machine.Pin.IN, machine.Pin.PULL_UP)
38+
```
39+
40+
### Task 2: Simple Button Press Detection
41+
42+
Here you’ll write a function that waits until the button is pressed.
43+
The loop continuously checks the pin’s value — when it changes from HIGH to LOW, the program detects a press and prints a message.
44+
45+
```python
46+
def wait_for_button_press():
47+
"""Wait until button is pressed"""
48+
while button.value() == 1:
49+
time.sleep(0.01)
50+
print("Button pressed!")
51+
```
52+
53+
Now you’ll make the LED respond to button input.
54+
Each time the button is pressed, the LED toggles between ON and OFF.
55+
A small delay is added to handle “debouncing” — preventing multiple rapid triggers from one press.
56+
57+
### Task 3: Toggle LED on Button Press
58+
59+
```python
60+
led_state = False
61+
62+
while True:
63+
if button.value() == 0: # Button pressed
64+
led_state = not led_state
65+
if led_state:
66+
set_color(255, 0, 0)
67+
else:
68+
clear_led()
69+
70+
# Wait for button release (debounce)
71+
while button.value() == 0:
72+
time.sleep(0.01)
73+
time.sleep(0.1) # Additional debounce delay
74+
```
75+
76+
### Task 4: Measure Press duration
77+
78+
In this task, you’ll measure how long the button is held down.
79+
The program records the start time when pressed and calculates the total duration once released.
80+
81+
```python
82+
def measure_press_duration():
83+
"""Measure how long the button is held down"""
84+
start = time.ticks_ms()
85+
while button.value() == 0:
86+
time.sleep(0.01)
87+
duration = time.ticks_diff(time.ticks_ms(), start) / 1000.0
88+
return duration
89+
90+
wait_for_button_press()
91+
duration = measure_press_duration()
92+
print(f"Button held for {duration:.2f} seconds")
93+
```
94+
95+
### Bonus Challenge
96+
97+
Create a visual feedback based on duration.
98+
99+
Change LED color based on how long the button is pressed:
100+
- Short press (< 1s): Blue
101+
- Medium press (1-3s): Yellow
102+
- Long press (> 3s): Red
103+
104+
Click on the ESP Control Panel and `Disconnect device` the device from the Jupyter notebook before proceeding with the next [assignment](../assignment-3).

0 commit comments

Comments
 (0)