Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/img/authors/daniel-paul.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions content/authors/daniel-paul/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
title: Daniel Paul
---
Copy link
Collaborator

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.

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

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.
Copy link
Collaborator

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The 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).
Loading