Things used in this project
Software apps and online services
| https://wokwi.com |
Story
👩🔬✨ Introduction
This project is a playful yet comprehensive journey through electronics and microcontrollers — from A to Z — using the Wokwi online simulator. Each letter represents a hands-on experiment, from blinking LEDs to advanced sensor integration, designed to teach core concepts interactively.
I created this project to make electronics education more accessible, especially for students and educators who may not have physical components. Wokwi allows anyone to simulate real-world circuits and microcontroller behavior directly in the browser, making it perfect for remote learning and prototyping.
The experiments are structured to grow in complexity, st…
Things used in this project
Software apps and online services
| https://wokwi.com |
Story
👩🔬✨ Introduction
This project is a playful yet comprehensive journey through electronics and microcontrollers — from A to Z — using the Wokwi online simulator. Each letter represents a hands-on experiment, from blinking LEDs to advanced sensor integration, designed to teach core concepts interactively.
I created this project to make electronics education more accessible, especially for students and educators who may not have physical components. Wokwi allows anyone to simulate real-world circuits and microcontroller behavior directly in the browser, making it perfect for remote learning and prototyping.
The experiments are structured to grow in complexity, starting with basic GPIO and moving toward communication protocols, task scheduling, and sensor fusion. Whether you’re using Raspberry Pi Pico or any MCU, each module is designed to be modular, visual, and beginner-friendly 😊✨
What Every Experiment Includes:
✅ A Live Wokwi Simulation – A clickable link to an interactive circuit you can run and modify immediately.
✅ Core Concept Explanation – A clear, concise breakdown of the theory behind the experiment.
✅ Commented & Robust Code – Sample firmware (in MicroPython/C) featuring safe-exit practices and basic error handling.
✅ Visual Walkthrough – Screenshots or diagrams highlighting key parts of the circuit and code logic.
✅ Challenge & Next Steps – Ideas to modify, break, and expand the experiment on your own.
🔤 Experiment A: Analog Sensor — Reading Voltage with Raspberry Pi Pico
We start with a fundamental skill: how a Microcontroller Unit (MCU) reads the analog world around it. In this experiment, we’ll use a Voltage Divider circuit with a potentiometer to simulate an analog sensor (like a light-dependent resistor or a simple temperature sensor). We will read its value using the Analog-to-Digital Converter (ADC) built into the Raspberry Pi Pico and display the digital result on the Serial Monitor.
The Wokwi CircuitCreate a new Wokwi project for Raspberry Pi Pico and build the following circuit:
Wokwi Circuit
MCU**:** Raspberry Pi Pico.
- One 10 kΩ potentiometer (POT1). Connect its three pins:
Pin 1 (or 3) → 3V3Pin 2 (the wiper/middle) → GP26 (this is ADC0 on the Pico)Pin 3 (or 1) → GND
- (Optional) One LED between GP15 and GND with a 330Ω current-limiting resistor.
🔗 Final Circuit Reference Link: ****https://wokwi.com/projects/450135957833432065
The Code (MicroPython)
# Experiment A: Analog Sensor Reading# Reads a voltage from a potentiometer (simulating an analog sensor)# and prints the value to the Serial Monitor.import machineimport utime# 1. Initialize the ADC pin (GP26 is ADC0 on Pico)adc = machine.ADC(26)# 2. (Optional) Initialize an LED pin for visual feedbackled = machine.PWM(machine.Pin(15))led.freq(1000) # Set PWM frequency to 1kHzprint("🔌 Experiment A: Analog Sensor Started!")print("📊 Turn the potentiometer knob in Wokwi and watch the values change.")print("------------------------------------------------")try: while True: # 3. Read the raw ADC value (0-65535 for Pico's 16-bit ADC) adc_value = adc.read_u16() # 4. Convert the raw value to a voltage (0.0 - 3.3V) voltage = (adc_value / 65535) * 3.3 # 5. (Optional) Use the value to control LED brightness led.duty_u16(adc_value) # Direct mapping # 6. Print the values to the Serial Monitor print(f"ADC: {adc_value:5d} | Voltage: {voltage:.2f}V") # 7. Short delay for readable output utime.sleep_ms(200)except KeyboardInterrupt: # 8. Safe exit: turn off LED and print message if code is stopped led.duty_u16(0) print("\n✅ Experiment safely stopped.")
Code Walkthrough
- Setup (machine.ADC(26)): Configures pin GP26 to function as an Analog-to-Digital Converter (ADC) input.
- Reading (adc.read_u16()): This function returns the digital number corresponding to the pin’s voltage. On the Pico, it ranges from 0 (0V) to 65535 (3.3V).
Voltage Conversion
- Voltage Conversion: We convert the raw digital number to a human-understandable voltage using a simple proportionality rule.
Voltage = (adc_value / 2^resolution) * Vref
Example: (32768 / 65535) * 3.3 ≈ 1.65V
⚠️ Important Note on adc.read_u16() in MicroPython: When using the function adc.read_u16(), the returned value ranges from 0 to 65535 (16‑bit). This does not mean that the Raspberry Pi Pico’s ADC is 16‑bit. In reality, the Pico’s ADC has a 12‑bit resolution (values from 0 to 4095). MicroPython simply scales the 12‑bit result up to 16‑bit to provide a consistent interface across different microcontrollers.
If you want the true 12‑bit value, you can shift the result:
adc12 = adc.read_u16() >> 4 # gives 0–4095
- Visual Feedback (Optional): We use the same value to control an LED’s brightness via Pulse Width Modulation (PWM), creating an immediate visual interaction.
Pulse Width Modulation (PWM)
- Serial Print: We display the values for you to monitor. Open Wokwi’s Serial Monitor (the chart icon) to see the output.
- Safe Handling (try/except): This structure prevents errors if the simulation is stopped abruptly and ensures components are closed neatly.
👀 What You’ll See & Do
- Click the "Run Simulation" button in Wokwi.
- Change the potentiometer value in the simulator by clicking and dragging its knob.
Run Simulation
Change the potentiometer value in the simulator
You will observe:
- The numbers in the Serial Monitor changing in real-time.
- (If you added the LED) The LED’s brightness changing proportionally to the potentiometer’s value.
🚀 Challenge
- Challenge 1: Change the delay period (utime.sleep_ms(200)) to 50 or 500. What happens? Why is timing important for sensor reads?
- Challenge 2: Modify the code to turn the LED on only when the voltage exceeds a certain threshold (e.g., 2.0V), turning it into a simple voltage alarm.
- Challenge 3: Replace the 3-pin potentiometer in your simulation with components that mimic an LDR’s behavior. Build this voltage divider: Connect 3V3 → Fixed Resistor (e.g., 10kΩ) → GP26. Connect GP26 → Variable Resistor (simulating the LDR) → GND. Would you now trigger the LED in bright light or darkness? How does this relate to building a nightlight?
🔤 Experiment B: Button Debouncing — Reading Digital Input Reliably
We now tackle a fundamental input device: the push button. However, a simple button press isn’t always "clean" to a microcontroller. Due to the mechanical nature of buttons, when pressed or released, the electrical signal can rapidly bounce between HIGH and LOW for a few milliseconds before stabilizing. This phenomenon is called switch bouncing. If not handled, a single press can be read as multiple presses. Debouncing is the essential software (or hardware) technique to ensure one press = one action.
one press = one action
In this experiment, we’ll learn to read a button reliably using a simple yet effective software debouncing algorithm with the Raspberry Pi Pico.
The Wokwi Circuit
Wokwi Circuit
Create a new Wokwi project for Raspberry Pi Pico and build the following circuit:
- MCU: Raspberry Pi Pico.
- Push Button:
Connect one side of the button to the GND pin.
Connect the other side of the button to GP5 (our digital input pin).
- LED (for visual feedback):
Connect the anode (long leg) to GP16 through a 330Ω resistor.
Connect the cathode (short leg) directly to GND.
🔗 Final Circuit Reference Link: ****https://wokwi.com/projects/450149913905965057
The Code (MicroPython)
# Experiment B: Button Debouncing import machineimport utimebutton = machine.Pin(5, machine.Pin.IN, machine.Pin.PULL_UP) # pressed = LOWled = machine.Pin(16, machine.Pin.OUT)debounce_delay = 20 # mslast_stable_state = button.value()last_raw_state = last_stable_statelast_change_time = utime.ticks_ms()press_count = 0print("🔘 Debouncing started (PULL_UP). Pressed = LOW.")try:while True:raw = button.value()if raw != last_raw_state:last_raw_state = rawlast_change_time = utime.ticks_ms()if utime.ticks_diff(utime.ticks_ms(), last_change_time) > debounce_delay:if raw != last_stable_state:last_stable_state = rawif last_stable_state == 0: # falling to LOW = pressled.value(1)press_count += 1print(f"✅ PRESSED! Count: {press_count}")else: # rising to HIGH = releaseled.value(0)print("🔘 RELEASED.")utime.sleep_ms(5)except KeyboardInterrupt:led.value(0)print(f"\n🛑 Stopped. Total reliable presses: {press_count}")
Code Walkthrough
Hardware Initialization:
- button = machine.Pin(5, machine.Pin.IN, machine.Pin.PULL_UP): Configures GP5 with internal pull-up resistor. When button is not pressed, pin reads 1 (HIGH).
- led = machine.Pin(16, machine.Pin.OUT): Simple output for LED.
Internal Pull-Up Resistor
Debouncing Variables (Improved):
- last_stable_state: The last confirmed bounce-free state.
- last_raw_state: Tracks the immediately previous raw reading for change detection.
- last_change_time: Timestamp when a raw change was detected.
- Using utime.ticks_diff() is more robust for time comparison.
Core Debouncing Algorithm:
- Change Detection: If raw reading differs from last_raw_state, reset the timer.
- Stability Check: Wait debounce_delay ms of consistent reading.
- Edge Detection: If stable state differs from last_stable_state, register as valid press/release.
- Action: Press (LOW) turns LED ON, release (HIGH) turns LED OFF.
- Clean Exit: KeyboardInterrupt handling ensures safe termination.
👀 What You’ll See & Do
- Run Simulation: Click "Run" in Wokwi.
- Initial State: LED is OFF (button not pressed = HIGH).
- Press Button: LED turns ON immediately, Serial Monitor shows: "✅ PRESSED! Count: 1"
- Release Button: LED turns OFF, shows: "🔘 RELEASED."
- Stress Test: Try rapid clicking. The counter should increment exactly once per intended press, proving debouncing success.
Wokwi Circuit Test
🚀 Challenge
- Challenge 1 (Timing Analysis): Change debounce_delay to 5ms. Do you see false presses? Change to 100ms. How does button feel? Find optimal value.
- Challenge 2 (Toggle Mode): Modify code so button toggles LED state with each press. (Hint: Track led_state variable that flips on button press only.)
- Challenge 3 (Hardware Debouncing): Add a 0.1µF capacitor between GP5 and GND. Does this allow shorter debounce_delay?
🔤 Experiment C: Clock on Character LCD
In this experiment, we build a complete real-time clock (RTC) system using the Raspberry Pi Pico, a DS1307 RTC module, and a 16×2 I²C character LCD. The project demonstrates how to:
- Read and format time from an external RTC chip.
- Display multiple modes on an LCD (24‑hour, 12‑hour, date, and stopwatch).
- Switch modes interactively using a push button.
- Create simple custom characters for progress indicators.
This experiment combines timekeeping, display control, and user interaction — a practical example of circuit communication.
The Wokwi Circuit
- MCU: Raspberry Pi Pico
- RTC: DS1307 module (with backup battery)
- LCD: 16×2 I²C character LCD (address 0x27)
- Button: Push button for mode switching
Wiring:
Pico GPIO0 (SDA) → LCD SDA + RTC SDAPico GPIO1 (SCL) → LCD SCL + RTC SCLPico 3.3V → LCD VCC + RTC VCCPico GND → LCD GND + RTC GNDPico GPIO5 → Button → GND
🔗 Final Circuit Reference Link: ****https://wokwi.com/projects/450161091277526017
Wokwi Circuit
Code Walkthrough
1. Hardware Initialization
- I²C Configuration: Sets up the I²C bus at 400kHz frequency using GPIO0 (SDA) and GPIO1 (SCL)
- LCD Initialization: Creates an instance of the 16x2 LCD with address 0x27
- RTC Initialization: Initializes the DS1307 module using the custom driver
- Button Setup: Configures GPIO5 as input with internal pull-up resistor
2. Time Formatting Logic
- 24-Hour Format: Directly displays hours (00-23) with consistent two-digit formatting
- 12-Hour Conversion: Converts 24-hour time to 12-hour format with correct AM/PM designation
- Date Formatting: Displays dates in DD/MM/YYYY format with month abbreviations
3. Display Mode Management
- Mode Cycling: Pressing the button cycles through four display modes in sequence
- Debounce Handling: 300ms delay prevents multiple mode changes from a single press
- Visual Feedback: Each mode has distinct display formatting for clear differentiation
4. Progress Indicator Implementation
- The date mode includes a visual progress bar showing how much of the current day has passed:
progress = int((hour * 60 + minute) / (24 * 60) * 16)
This calculates the percentage of the day completed and displays it as a bar of "=" characters.
5. Error Handling and Clean Exit
- Graceful Shutdown: Catches KeyboardInterrupt (Ctrl+C) to display "Clock Stopped"
- Exception Handling: Catches and displays any runtime errors
- Resource Cleanup: Ensures the LCD is cleared before exit
👀 What You’ll See & Do
24-Hour Format
12-Hour Conversion
Displays dates in DD/MM/YYYY format with month abbreviations
Catches KeyboardInterrupt (Ctrl+C) to display "Clock Stopped"
🚀 Challenge
- Challenge 1: Implement the stopwatch mode fully, with start/stop functionality.
- Challenge 2: Add alarm functionality that triggers at a set time.
- Additional Enhancement Ideas:
Temperature Display: Integrate I²C temperature sensor
Timezone Support: Switch between multiple time zones
Automatic DST: Calculate daylight saving time adjustments
Battery Monitoring: Check RTC backup battery voltage
Serial Configuration: Set time via USB serial commands
Light Sensor: Auto-adjust LCD backlight based on ambient light
🔤 Experiment D : Digital Duplex — Mastering I²C & SPI Communication
This experiment teaches two essential synchronous serial protocols: I²C (Inter-Integrated Circuit) and SPI (Serial Peripheral Interface). You will build a circuit where a Raspberry Pi Pico reads temperature from an MPU-6050 inertial sensor (via I²C) and simultaneously controls 8 LEDs through a 74HC595 shift register (via SPI) to create a dynamic visual feedback loop.
Core Concept: Contrasting I²C (2-wire, address-based, multi-master) with SPI (4-wire, select-based, full-duplex) in a single, interactive system.
The Wokwi Circuit
Components:
- MCU: Raspberry Pi Pico.
- I²C Device: MPU-6050 (Inertial Measurement Unit with a built-in temperature sensor).
- SPI Device: 74HC595 (8-bit Serial-In, Parallel-Out Shift Register).
- Output: 8 LEDs.
Wiring Guide:
Wokwi Circuit
🔗 Final Circuit Reference Link:
https://wokwi.com/projects/450177243795993601
Code Walkthrough
- I²C Initialization: Sets up the I²C bus at 400kHz on GP0 (SDA) and GP1 (SCL), then wakes up the MPU-6050 by writing to its power management register.
- SPI Initialization: Configures hardware SPI0 with correct pins (SCK=GP2, MOSI=GP7, MISO=GP4) and sets up GP3 as the Chip Select/Latch pin for the 74HC595.
- Temperature Reading: The read_mpu6050_temp() function reads two bytes from the MPU-6050’s temperature registers and converts them to Celsius using the formula from the sensor’s datasheet.
- Decision Logic: The temperature controls two aspects of the LED animation:
- Speed (delay): Changes from 100ms (hot) to 500ms (cold).
- Number of Active LEDs (max_pattern): Ranges from 1 LED (cold) to 8 LEDs (hot).
- SPI Data Transmission: The current animation pattern is masked with max_pattern and sent as a single byte to the 74HC595, which then lights up the corresponding LEDs.
- Safe Exit: A KeyboardInterrupt handler ensures all LEDs are turned off when the simulation stops.
👀 What You’ll See & Do
- Run the Simulation: Click "Run Simulation". The Serial Monitor will show the MPU-6050 initialization message and start streaming temperature data.
Wokwi Circuit Test 1
- Observe the Output: You’ll see lines like:
🌡️ Temp: 45.7°C | LEDs: 00001111
Wokwi Circuit Test1
Wokwi Circuit Test 2
- This shows the temperature reading, the binary state of all 8 LEDs, and the current animation speed.
Interact with the Simulation:
MPU-6050 Simulation
-
Watch the LEDs: The pattern of lit LEDs will "move" (animate), and both the speed of animation and the maximum number of LEDs lit will change in real-time based on the temperature you set.
-
Advanced Analysis: Click the "Logic Analyzer" icon in Wokwi. You’ll see the actual I²C waveform (on SDA/SCL) when temperature is read, and the SPI clock/data signals (on SCK/MOSI) when LED patterns are updated—allowing for direct comparison of the two protocols.
🚀 Challenges:
- Protocol Analyzer Challenge: Use Wokwi’s Virtual Logic Analyzer to capture and compare the I²C and SPI waveforms. Can you identify the start/stop conditions in I²C versus the continuous clock in SPI?
- Multi-Device Expansion: The 74HC595 has a Q7S (pin 9) output. Use it to daisy-chain a second 74HC595 and control 16 LEDs. Update the code to send 2 bytes and modify the patterns accordingly.
- Sensor Fusion Challenge: The MPU-6050 also has a gyroscope and accelerometer. Modify the code to read the gyro_x value and use it to control the direction of the LED animation (e.g., left vs right shift).
- Energy Efficiency Mod: Change the logic so that LEDs only update when the temperature changes by more than 0.5°C, simulating a power-conscious system.
🔤 Experiment E: Environmental Echo — IoT Sensor Node with WiFi
This experiment introduces the Internet of Things (IoT) by building a complete sensor node that transmits environmental data to the cloud. Using the Raspberry Pi Pico W’s built-in WiFi, you will read temperature, humidity, and light levels, then send this data to a live cloud dashboard for real-time visualization—all within the Wokwi simulator.
**Core Concept: **You will understand the complete flow of an IoT system: from physical sensor input, through microcontroller processing, to cloud-based data visualization and remote monitoring.
Wokwi Circuit
Create a new Wokwi project for Raspberry Pi Pico W and build the following circuit:
- MCU: Raspberry Pi Pico W
- Sensors:
- DHT22 Temperature & Humidity Sensor
- Photoresistor (LDR) with a 10kΩ resistor forming a voltage divider.
- Optional Visual Feedback: An LED connected to GP14 with a 330Ω resistor (for high-temperature alerts).
🔗 **Final Circuit Reference Link: **https://wokwi.com/projects/450223599413456897
Wokwi Circuit
Wokwi Circuit Test
Code Walkthrough
- Hardware Initialization: Configures the DHT22 sensor on a digital pin and the photoresistor on an ADC-capable pin to read analog voltage.
- Network Connection: The connect_to_wifi() function handles the connection to Wokwi’s simulated WiFi, with clear status feedback.
- Sensor Reading Logic: read_environmental_data() safely reads from both sensors, implementing error handling for the DHT22 and linear conversion for the light sensor.
- Cloud Transmission Gateway: The send_to_cloud() function is a dispatcher. Based on CLOUD_SERVICE, it formats the correct HTTP request (GET for ThingSpeak/IFTTT) and sends the data. A DEMO mode provides a clear learning path.
- Main Loop: Orchestrates the sequence: read, display, transmit, and wait in a continuous, interruptible loop.
👀 What You’ll See & Do
- Run the Simulation: Click "Start Simulation". In the Serial Monitor, you will see a clear startup sequence: hardware initialization, network connection (Connecting to ‘Wokwi-GUEST’.....), and the start of the transmission loop.
- Observe Live Data: The console will print a new reading every 15 seconds, formatted for clarity:
READING #012Temperature: 24.5 °CHumidity: 55.0 %Light Level: 72.3 %[CLOUD] DEMO: T=24.5°C, H=55.0%, L=72.3%
- Interact with the Virtual Environment:
Wokwi Circuit Test 2
- Make it Real (Cloud Challenge):
New Channel
Save Channel
API key
Channel Status
Channel Status
🚀 Challenge
- Implement a Local Alert: Add code to turn on the optional LED on GP14 when the temperature exceeds a configurable threshold (e.g., 28°C), creating a visual hardware alert independent of the cloud.
- Add a Second Cloud Service: Modify send_to_cloud() to transmit the same sensor reading to both ThingSpeak and IFTTT simultaneously, practicing data fan-out.
- Simulate Power Savings: Implement a "deep sleep" pattern using machine.deepsleep() (simulated in Wokwi) where the Pico W wakes up only once per minute to take a reading, mimicking a battery-powered IoT node.
🔤 Experiment F : Flip -Flop Fundamentals — Building Digital Memory with D Flip-Flop
This experiment introduces sequential logic and digital memory at its most fundamental level. You will build and test a D Flip-Flop circuit, the essential building block of computer memory (used in registers and RAM). You will see how it can "remember" a single binary bit (0 or 1) using pure logic, independent of continuous microcontroller input.
The Wokwi Circuit
- MCU: Raspberry Pi Pico (to provide power and optional control/monitoring)
- Logic Chip: D Flip-Flop (A standalone 4-pin logic component in Wokwi)
- Inputs: Push Buttons (for `Data`)
- Outputs: 2x LEDs (for `Q` and `Q̅` - the output and its complement)
- Resistors: 3 Resistors (for button and LEDs)
- Optional Clock Source
🔗 Final Circuit Reference Link:
https://wokwi.com/projects/450238900173187073
Wokwi Circuit
Wokwi Circuit Test1
Wokwi Circuit Test2
Working Principle: The input value (`D`) is copied to the output (`Q`) only at the rising edge (transition from LOW to HIGH) of the clock signal (`CLK`). Afterward, the circuit remembers this value until the next clock pulse, regardless of any subsequent change to `D`.
👀 What You’ll See & Do
- Run the Simulation: Click "Start Simulation". The flip-flop powers on, and one LED will light up (initial random state). The Serial Monitor will show the clock count and the current stored bit.
- Store a ‘0’ (LOW):
Connect the flip-flop’s D input pin directly to GND in the simulator.
Wait for the next clock pulse (watch the counter increment in the Serial Monitor).
Observe: The Green LED (Q) turns OFF, and the Red LED (Q̅) turns ON. The bit 0 is now stored.
- Store a ‘1’ (HIGH):
Disconnect D from GND and connect it to 3.3V.
Wait for the next clock pulse.
Observe: The LEDs swap! Green ON, Red OFF. The circuit now remembers 1.
- Verify Memory:
After storing a bit, try changing the D input again. You will see that the output LEDs do not change until the next clock pulse, proving the circuit "remembers" the old value.
🚀 Challenge
- Build a Toggle Circuit (1-bit Counter): Connect the flip-flop’s own Q̅ output back to its D input. Now, every automatic clock pulse will toggle (flip) the stored bit. Watch your LED blink on and off every second! This transforms your memory cell into a simple binary counter.
- Create a 2-bit Shift Register: Add a second D Flip-Flop to your simulation. Connect the Q output of the first to the D input of the second. Connect both of their CLK inputs to Pico GP18. You now have a circuit that can store a 2-bit number (00, 01, 10, 11), demonstrating how basic memory cells combine to form registers.
- Adjust the Clock: In the code, change CLOCK_FREQ = 1 to 5 or 10. Re-run the simulation and observe how the speed of updates changes, demonstrating the role of clock speed in digital systems.
See You in Part 2! 🔮
**Read more