100% found this document useful (1 vote)
37 views205 pages

ESP32 Code Guide

The document outlines a series of MicroPython projects for ESP32, categorized into five segments based on educational levels from 8th-9th grade to final year engineering. Each project includes a prompt, hardware requirements, and a sample MicroPython code for tasks such as LED control, sensor data reading, and communication protocols. The projects aim to teach concepts in electronics, programming, and data handling through practical applications.

Uploaded by

arya.patkar22
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
37 views205 pages

ESP32 Code Guide

The document outlines a series of MicroPython projects for ESP32, categorized into five segments based on educational levels from 8th-9th grade to final year engineering. Each project includes a prompt, hardware requirements, and a sample MicroPython code for tasks such as LED control, sensor data reading, and communication protocols. The projects aim to teach concepts in electronics, programming, and data handling through practical applications.

Uploaded by

arya.patkar22
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

SEGMENT 1: 8th–9th GRADE (FOUNDATION &

CURIOSITY) – 1 to 20
1.​ LED Blink (Electric circuit basics)​

2.​ Button Controlled LED (Boolean logic)​

3.​ Traffic Light Controller (Sequencing)​

4.​ LED Chaser Pattern​

5.​ Buzzer Sound Generator (Sound concept)​

6.​ RGB LED Color Mixing (Color theory)​

7.​ Timer-Based LED Blink​

8.​ Serial Monitor Data Display​

9.​ Digital Counter Program​

10.​Random Number Generator (Probability)​

11.​LDR Light Detection (Light vs resistance)​

12.​Day/Night Automatic Light​

13.​Temperature Measurement (DHT11)​

14.​Digital Thermometer (°C ↔ °F)​

15.​Simple Weather Display​

16.​Speed = Distance / Time Calculator​

17.​Area & Perimeter Calculator​

18.​Ohm’s Law Verification (V = IR)​

19.​Electrical Power Calculation (P = VI)​


20.​Basic Safety Alarm System​

SEGMENT 2: 10th–12th GRADE (SCIENCE, MATH &


REAL-WORLD) – 21 to 45
21.​PWM LED Dimming (Duty cycle)​

22.​Potentiometer Voltage Divider​

23.​Analog Voltage Measurement (ADC)​

24.​Battery Percentage Estimation​

25.​Temperature & Humidity Monitor (DHT22)​

26.​Soil Moisture Based Irrigation Alert​

27.​Water Level Monitoring System​

28.​Ultrasonic Distance Measurement​

29.​Speed of Sound Experiment​

30.​IR Obstacle Detection (Reflection)​

31.​Motion Detection (PIR sensor)​

32.​Sound Level Meter (Decibel scale)​

33.​RTC Digital Clock System​

34.​Time vs Temperature Data Logging​

35.​Linear Equation Solver (ax + b = 0)​

36.​Quadratic Equation Solver​

37.​Discriminant & Nature of Roots​


38.​Trigonometric Calculator​

39.​Projectile Motion Calculator​

40.​Statistical Calculator (mean, max, min)​

41.​Sensor Graph Plotting (value vs time)​

42.​Energy Consumption Calculator​

43.​Gas Detection & Safety Indicator​

44.​Smart Street Light System​

45.​Automatic Water Tank Controller​

SEGMENT 3: DIPLOMA / FY ENGINEERING (EMBEDDED


& IOT) – 46 to 70
46.​OLED Display Data Visualization​

47.​LCD 16×2 Interface System​

48.​UART Communication Protocol​

49.​Bluetooth Serial Communication​

50.​Bluetooth Home Automation System​

51.​WiFi Network Scanner​

52.​WiFi Signal Strength Analyzer​

53.​Web Server – Device Control​

54.​Web Dashboard – Live Sensor Data​

55.​JSON Data Encoding & Parsing​


56.​SPI Communication Demo​

57.​I2C Master–Slave Communication​

58.​SD Card File Read/Write​

59.​CSV Sensor Data Logger​

60.​OTA Firmware Update System​

61.​DC Motor Speed Control (RPM relation)​

62.​Servo Motor Angle Control​

63.​Stepper Motor Positioning System​

64.​Deep Sleep Power Management​

65.​Interrupt-Based Input Handling​

66.​Watchdog Timer Fault Recovery​

67.​Event-Driven Programming Model​

68.​Error Detection & Logging System​

69.​Circular / Ring Buffer for Data​

70.​Internet Time Sync (NTP)​

SEGMENT 4: CORE ENGINEERING (DSA, CONTROL,


SIGNALS) – 71 to 105
Data Structures & Algorithms

71.​Array Operations​

72.​String Processing Algorithms​


73.​Frequency Counter (Hashing)​

74.​Linear Search Algorithm​

75.​Binary Search Algorithm​

76.​Stack Implementation​

77.​Circular Queue​

78.​Singly Linked List​

79.​Doubly Linked List​

80.​Recursion (Factorial, Fibonacci)​

81.​Sorting Algorithms (Basic)​

82.​Sorting Algorithms (Merge, Quick)​

83.​Prefix Sum Technique​

84.​Sliding Window Algorithm​

85.​Hash Table Implementation​

86.​Binary Tree Traversals​

87.​Binary Search Tree Operations​

88.​Heap (Min & Max)​

89.​Priority Queue Scheduler​

90.​Graph Representation​

91.​BFS & DFS Traversals​

92.​Dijkstra’s Shortest Path​

93.​Dynamic Programming (Knapsack)​

Math, Control & Signal Processing


94.​Numerical Integration​

95.​Numerical Differentiation​

96.​FFT Spectrum Analyzer​

97.​FIR Digital Filter​

98.​IIR Digital Filter​

99.​PID Temperature Controller​

100.​ PID Motor Speed Controller​

101.​ Kalman Filter (Sensor Fusion)​

102.​ State Space Control System​

103.​ Time Series Analysis​

104.​ Statistical Anomaly Detection​

105.​ Mathematical Expression Parser​

SEGMENT 5: FINAL YEAR & INDUSTRIAL LEVEL – 106 to


125
Advanced Sensors & Perception

106.​ Camera Image Capture (ESP32-CAM)​

107.​ Video Frame Processing​

108.​ Motion Detection using Video​

109.​ Thermal Sensor Heat Mapping​

110.​ LiDAR Distance Mapping​


111.​ GPS Coordinate Parsing & Distance Formula​

112.​ GSM SMS & Data Communication​

Networking, RTOS & Industry

113.​ FreeRTOS Multitasking System​

114.​ FreeRTOS Queues & Semaphores​

115.​ ESP-NOW Peer Communication​

116.​ ESP-NOW Mesh Network​

117.​ MQTT Sensor Publisher​

118.​ MQTT Cloud Dashboard​

119.​ HTTP REST API Client​

120.​ Secure TLS Communication​

121.​ Ethernet Communication (W5500)​

122.​ CAN Bus Communication​

123.​ Modbus RTU / TCP System​

AI, NLP, VOICE & SYSTEM INTEGRATION

124.​ Voice Command Recognition (Sound / NLP)​

125.​ Complete Smart System​


(Sensors → Algorithms → AI → Decision → Actuation → Cloud)​
1. LED Blink (Electric circuit basics)
Prompt: Create a MicroPython program for ESP32 that blinks an LED connected to GPIO pin 2
with 1 second ON and 1 second OFF intervals continuously.

Hardware Requirements:

●​ ESP32 development board


●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ LED anode to GPIO2 through resistor, cathode to GND

MicroPython Program Code:

from machine import Pin


import time

led = Pin(2, [Link])

while True:
[Link]()
[Link](1)
[Link]()
[Link](1)

2. Button Controlled LED (Boolean logic)


Prompt: Create a MicroPython program for ESP32 where pressing a button connected to GPIO
4 turns ON an LED on GPIO 2, and releasing it turns OFF the LED.

Hardware Requirements:

●​ ESP32 development board


●​ LED
●​ Push button
●​ 220Ω resistor
●​ 10kΩ pull-down resistor
●​ Breadboard and jumper wires
●​ LED to GPIO2, Button to GPIO4
MicroPython Program Code:

from machine import Pin

led = Pin(2, [Link])


button = Pin(4, [Link], Pin.PULL_DOWN)

while True:
if [Link]() == 1:
[Link]()
else:
[Link]()

3. Traffic Light Controller (Sequencing)


Prompt: Create a MicroPython program for ESP32 that simulates a traffic light with RED (GPIO
2) for 5 seconds, YELLOW (GPIO 4) for 2 seconds, and GREEN (GPIO 5) for 5 seconds in a
continuous loop.

Hardware Requirements:

●​ ESP32 development board


●​ 3 LEDs (Red, Yellow, Green)
●​ 3x 220Ω resistors
●​ Breadboard and jumper wires
●​ Red LED to GPIO2, Yellow to GPIO4, Green to GPIO5

MicroPython Program Code:

from machine import Pin


import time

red = Pin(2, [Link])


yellow = Pin(4, [Link])
green = Pin(5, [Link])

while True:
[Link]()
[Link]()
[Link]()
[Link](5)
[Link]()
[Link]()
[Link]()
[Link](2)

[Link]()
[Link]()
[Link]()
[Link](5)

4. LED Chaser Pattern


Prompt: Create a MicroPython program for ESP32 that creates a chaser pattern with 4 LEDs
connected to GPIO pins 2, 4, 5, and 18, lighting them one by one in sequence with 0.3 second
delay.

Hardware Requirements:

●​ ESP32 development board


●​ 4 LEDs
●​ 4x 220Ω resistors
●​ Breadboard and jumper wires
●​ LEDs to GPIO2, GPIO4, GPIO5, GPIO18

MicroPython Program Code:

from machine import Pin


import time

leds = [Pin(2, [Link]), Pin(4, [Link]), Pin(5, [Link]), Pin(18, [Link])]

while True:
for led in leds:
[Link]()
[Link](0.3)
[Link]()
5. Buzzer Sound Generator (Sound
concept)
Prompt: Create a MicroPython program for ESP32 that generates a beep sound on a buzzer
connected to GPIO 15, beeping for 0.5 seconds ON and 0.5 seconds OFF continuously.

Hardware Requirements:

●​ ESP32 development board


●​ Active buzzer or Passive buzzer
●​ Breadboard and jumper wires
●​ Buzzer positive to GPIO15, negative to GND

MicroPython Program Code:

from machine import Pin


import time

buzzer = Pin(15, [Link])

while True:
[Link]()
[Link](0.5)
[Link]()
[Link](0.5)

6. RGB LED Color Mixing (Color theory)


Prompt: Create a MicroPython program for ESP32 that cycles through Red, Green, Blue,
Yellow, Cyan, Magenta, and White colors on an RGB LED connected to GPIO pins 2 (Red), 4
(Green), and 5 (Blue) with 1 second delay between colors.

Hardware Requirements:

●​ ESP32 development board


●​ Common cathode RGB LED
●​ 3x 220Ω resistors
●​ Breadboard and jumper wires
●​ R to GPIO2, G to GPIO4, B to GPIO5, common cathode to GND
MicroPython Program Code:

from machine import Pin


import time

red = Pin(2, [Link])


green = Pin(4, [Link])
blue = Pin(5, [Link])

colors = [
(1, 0, 0), # Red
(0, 1, 0), # Green
(0, 0, 1), # Blue
(1, 1, 0), # Yellow
(0, 1, 1), # Cyan
(1, 0, 1), # Magenta
(1, 1, 1), # White
]

while True:
for r, g, b in colors:
[Link](r)
[Link](g)
[Link](b)
[Link](1)

7. Timer-Based LED Blink


Prompt: Create a MicroPython program for ESP32 that uses a hardware timer to blink an LED
on GPIO 2 every 500 milliseconds without using sleep().

Hardware Requirements:

●​ ESP32 development board


●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ LED to GPIO2

MicroPython Program Code:


from machine import Pin, Timer

led = Pin(2, [Link])


timer = Timer(0)

def toggle(t):
[Link](not [Link]())

[Link](period=500, mode=[Link], callback=toggle)

8. Serial Monitor Data Display


Prompt: Create a MicroPython program for ESP32 that prints "Hello from ESP32" followed by
an incrementing counter value to the serial monitor every second.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

import time

counter = 0

while True:
print("Hello from ESP32")
print("Counter:", counter)
counter += 1
[Link](1)

9. Digital Counter Program


Prompt: Create a MicroPython program for ESP32 that increments a counter each time a
button on GPIO 4 is pressed and displays the count on the serial monitor, with debounce
handling.
Hardware Requirements:

●​ ESP32 development board


●​ Push button
●​ 10kΩ pull-down resistor
●​ Breadboard and jumper wires
●​ Button to GPIO4

MicroPython Program Code:

from machine import Pin


import time

button = Pin(4, [Link], Pin.PULL_DOWN)


counter = 0
last_state = 0

while True:
current_state = [Link]()
if current_state == 1 and last_state == 0:
counter += 1
print("Count:", counter)
[Link](0.2)
last_state = current_state

10. Random Number Generator


(Probability)
Prompt: Create a MicroPython program for ESP32 that generates and displays a random
number between 1 and 100 on the serial monitor every 2 seconds.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

import random
import time
while True:
number = [Link](1, 100)
print("Random Number:", number)
[Link](2)

11. LDR Light Detection (Light vs


resistance)
Prompt: Create a MicroPython program for ESP32 that reads an LDR sensor value connected
to GPIO 34 (ADC) and displays the light level on the serial monitor every second.

Hardware Requirements:

●​ ESP32 development board


●​ LDR (Light Dependent Resistor)
●​ 10kΩ resistor
●​ Breadboard and jumper wires
●​ LDR in voltage divider with GPIO34 (ADC1_CH6)

MicroPython Program Code:

from machine import ADC, Pin


import time

ldr = ADC(Pin(34))
[Link](ADC.ATTN_11DB)

while True:
light_value = [Link]()
print("Light Level:", light_value)
[Link](1)

12. Day/Night Automatic Light


Prompt: Create a MicroPython program for ESP32 that automatically turns ON an LED on
GPIO 2 when light level from LDR on GPIO 34 falls below 1500 (night) and turns it OFF when
above 1500 (day).
Hardware Requirements:

●​ ESP32 development board


●​ LDR (Light Dependent Resistor)
●​ 10kΩ resistor
●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ LDR to GPIO34, LED to GPIO2

MicroPython Program Code:

from machine import ADC, Pin


import time

ldr = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
led = Pin(2, [Link])

while True:
light_value = [Link]()
if light_value < 1500:
[Link]()
print("Night - LED ON")
else:
[Link]()
print("Day - LED OFF")
[Link](1)

13. Temperature Measurement (DHT11)


Prompt: Create a MicroPython program for ESP32 that reads temperature and humidity from a
DHT11 sensor connected to GPIO 4 and displays values on the serial monitor every 2 seconds.

Hardware Requirements:

●​ ESP32 development board


●​ DHT11 temperature and humidity sensor
●​ 10kΩ pull-up resistor (if not built-in)
●​ Breadboard and jumper wires
●​ DHT11 data pin to GPIO4
MicroPython Program Code:

from machine import Pin


import dht
import time

sensor = dht.DHT11(Pin(4))

while True:
[Link]()
temp = [Link]()
humidity = [Link]()
print("Temperature:", temp, "°C")
print("Humidity:", humidity, "%")
[Link](2)

14. Digital Thermometer (°C ↔ °F)


Prompt: Create a MicroPython program for ESP32 that reads temperature from DHT11 on
GPIO 4 and displays it in both Celsius and Fahrenheit on the serial monitor every 2 seconds.

Hardware Requirements:

●​ ESP32 development board


●​ DHT11 temperature sensor
●​ 10kΩ pull-up resistor (if not built-in)
●​ Breadboard and jumper wires
●​ DHT11 data pin to GPIO4

MicroPython Program Code:

from machine import Pin


import dht
import time

sensor = dht.DHT11(Pin(4))

while True:
[Link]()
temp_c = [Link]()
temp_f = (temp_c * 9/5) + 32
print("Temperature:", temp_c, "°C /", temp_f, "°F")
[Link](2)

15. Simple Weather Display


Prompt: Create a MicroPython program for ESP32 that reads temperature and humidity from
DHT11 on GPIO 4 and displays weather status (Hot/Comfortable/Cold based on temperature
and Humid/Dry based on humidity) on the serial monitor every 3 seconds.

Hardware Requirements:

●​ ESP32 development board


●​ DHT11 temperature and humidity sensor
●​ 10kΩ pull-up resistor (if not built-in)
●​ Breadboard and jumper wires
●​ DHT11 data pin to GPIO4

MicroPython Program Code:

from machine import Pin


import dht
import time

sensor = dht.DHT11(Pin(4))

while True:
[Link]()
temp = [Link]()
humidity = [Link]()

if temp > 30:


temp_status = "Hot"
elif temp > 20:
temp_status = "Comfortable"
else:
temp_status = "Cold"

if humidity > 70:


humid_status = "Humid"
else:
humid_status = "Dry"
print("Weather:", temp_status, "&", humid_status)
print("Temp:", temp, "°C, Humidity:", humidity, "%")
[Link](3)

16. Speed = Distance / Time Calculator


Prompt: Create a MicroPython program for ESP32 that calculates and displays speed when
distance is 100 meters and time is 10 seconds, printing the result to the serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

distance = 100
time_taken = 10

speed = distance / time_taken

print("Distance:", distance, "meters")


print("Time:", time_taken, "seconds")
print("Speed:", speed, "m/s")

17. Area & Perimeter Calculator


Prompt: Create a MicroPython program for ESP32 that calculates and displays the area and
perimeter of a rectangle with length 15 and width 10 on the serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:


length = 15
width = 10

area = length * width


perimeter = 2 * (length + width)

print("Length:", length)
print("Width:", width)
print("Area:", area)
print("Perimeter:", perimeter)

18. Ohm's Law Verification (V = IR)


Prompt: Create a MicroPython program for ESP32 that calculates voltage using Ohm's Law
with current 2A and resistance 10Ω, and displays the result on the serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

current = 2
resistance = 10

voltage = current * resistance

print("Current (I):", current, "A")


print("Resistance (R):", resistance, "Ω")
print("Voltage (V):", voltage, "V")
print("Ohm's Law: V = I × R")

19. Electrical Power Calculation (P = VI)


Prompt: Create a MicroPython program for ESP32 that calculates electrical power using
voltage 230V and current 5A, and displays the result on the serial monitor.
Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

voltage = 230
current = 5

power = voltage * current

print("Voltage (V):", voltage, "V")


print("Current (I):", current, "A")
print("Power (P):", power, "W")
print("Formula: P = V × I")

20. Basic Safety Alarm System


Prompt: Create a MicroPython program for ESP32 that monitors a PIR motion sensor on GPIO
13 and triggers a buzzer on GPIO 15 and LED on GPIO 2 when motion is detected, displaying
alert messages on the serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ PIR motion sensor
●​ Buzzer
●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ PIR to GPIO13, Buzzer to GPIO15, LED to GPIO2

MicroPython Program Code:

from machine import Pin


import time

pir = Pin(13, [Link])


buzzer = Pin(15, [Link])
led = Pin(2, [Link])
print("Safety Alarm System Active")

while True:
if [Link]() == 1:
[Link]()
[Link]()
print("ALERT! Motion Detected!")
[Link](2)
else:
[Link]()
[Link]()
[Link](0.1)

SEGMENT 2: 10th–12th GRADE (SCIENCE, MATH &


REAL-WORLD) – 21 to 45

1. PWM LED Dimming (Duty cycle)


Prompt: Create a MicroPython program for ESP32 that dims an LED on GPIO 2 using PWM,
gradually increasing brightness from 0% to 100% and then decreasing back to 0% continuously.

Hardware Requirements:

●​ ESP32 development board


●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ LED to GPIO2

MicroPython Program Code:

from machine import Pin, PWM


import time

led = PWM(Pin(2), freq=1000)

while True:
for duty in range(0, 1024, 10):
[Link](duty)
[Link](0.02)
for duty in range(1023, -1, -10):
[Link](duty)
[Link](0.02)

2. Potentiometer Voltage Divider


Prompt: Create a MicroPython program for ESP32 that reads analog value from a
potentiometer connected to GPIO 34 and displays the voltage on the serial monitor every 0.5
seconds.

Hardware Requirements:

●​ ESP32 development board


●​ 10kΩ Potentiometer
●​ Breadboard and jumper wires
●​ Potentiometer middle pin to GPIO34, other pins to 3.3V and GND

MicroPython Program Code:

from machine import ADC, Pin


import time

pot = ADC(Pin(34))
[Link](ADC.ATTN_11DB)

while True:
adc_value = [Link]()
voltage = (adc_value / 4095) * 3.3
print("ADC Value:", adc_value, "| Voltage:", round(voltage, 2), "V")
[Link](0.5)

3. Analog Voltage Measurement (ADC)


Prompt: Create a MicroPython program for ESP32 that measures analog voltage on GPIO 34
using ADC and displays both raw ADC value and calculated voltage on the serial monitor every
second.

Hardware Requirements:
●​ ESP32 development board
●​ Voltage divider circuit or sensor
●​ Breadboard and jumper wires
●​ Analog input to GPIO34 (max 3.3V)

MicroPython Program Code:

from machine import ADC, Pin


import time

adc = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
[Link](ADC.WIDTH_12BIT)

while True:
raw_value = [Link]()
voltage = (raw_value / 4095) * 3.3
print("Raw ADC:", raw_value)
print("Voltage:", round(voltage, 3), "V")
print("---")
[Link](1)

4. Battery Percentage Estimation


Prompt: Create a MicroPython program for ESP32 that reads battery voltage from GPIO 34 (via
voltage divider) and estimates battery percentage assuming 4.2V is 100% and 3.0V is 0%,
displaying results on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ Battery (3.7V Li-ion)
●​ Voltage divider (2x 10kΩ resistors)
●​ Breadboard and jumper wires
●​ Voltage divider output to GPIO34

MicroPython Program Code:

from machine import ADC, Pin


import time

adc = ADC(Pin(34))
[Link](ADC.ATTN_11DB)

V_MAX = 4.2
V_MIN = 3.0

while True:
adc_value = [Link]()
voltage = (adc_value / 4095) * 3.3 * 2

if voltage > V_MAX:


percentage = 100
elif voltage < V_MIN:
percentage = 0
else:
percentage = ((voltage - V_MIN) / (V_MAX - V_MIN)) * 100

print("Battery Voltage:", round(voltage, 2), "V")


print("Battery Percentage:", round(percentage, 1), "%")
[Link](2)

5. Temperature & Humidity Monitor


(DHT22)
Prompt: Create a MicroPython program for ESP32 that reads temperature and humidity from
DHT22 sensor on GPIO 4 and displays values with higher precision on the serial monitor every
3 seconds.

Hardware Requirements:

●​ ESP32 development board


●​ DHT22 temperature and humidity sensor
●​ 10kΩ pull-up resistor
●​ Breadboard and jumper wires
●​ DHT22 data pin to GPIO4

MicroPython Program Code:

from machine import Pin


import dht
import time
sensor = dht.DHT22(Pin(4))

while True:
try:
[Link]()
temp = [Link]()
humidity = [Link]()
print("Temperature:", temp, "°C")
print("Humidity:", humidity, "%")
print("---")
except OSError as e:
print("Failed to read sensor")
[Link](3)

6. Soil Moisture Based Irrigation Alert


Prompt: Create a MicroPython program for ESP32 that reads soil moisture from an analog
sensor on GPIO 34 and turns ON an LED on GPIO 2 with alert message when moisture falls
below threshold 1500.

Hardware Requirements:

●​ ESP32 development board


●​ Soil moisture sensor (analog)
●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ Sensor analog output to GPIO34, LED to GPIO2

MicroPython Program Code:

from machine import ADC, Pin


import time

moisture_sensor = ADC(Pin(34))
moisture_sensor.atten(ADC.ATTN_11DB)
led = Pin(2, [Link])

THRESHOLD = 1500
while True:
moisture_value = moisture_sensor.read()
print("Soil Moisture:", moisture_value)

if moisture_value < THRESHOLD:


[Link]()
print("ALERT: Irrigation Required!")
else:
[Link]()
print("Soil Moisture: OK")

print("---")
[Link](2)

7. Water Level Monitoring System


Prompt: Create a MicroPython program for ESP32 that monitors water level using an analog
sensor on GPIO 34 and displays level status (Empty/Low/Medium/Full) with LED indication on
GPIO 2 for low level alert.

Hardware Requirements:

●​ ESP32 development board


●​ Water level sensor (analog)
●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ Sensor to GPIO34, LED to GPIO2

MicroPython Program Code:

from machine import ADC, Pin


import time

water_sensor = ADC(Pin(34))
water_sensor.atten(ADC.ATTN_11DB)
led = Pin(2, [Link])

while True:
level = water_sensor.read()
print("Water Level Value:", level)
if level < 500:
status = "Empty"
[Link]()
elif level < 1500:
status = "Low"
[Link]()
elif level < 2500:
status = "Medium"
[Link]()
else:
status = "Full"
[Link]()

print("Status:", status)
print("---")
[Link](2)

8. Ultrasonic Distance Measurement


Prompt: Create a MicroPython program for ESP32 that measures distance using HC-SR04
ultrasonic sensor with trigger on GPIO 5 and echo on GPIO 18, displaying distance in cm on
serial monitor every second.

Hardware Requirements:

●​ ESP32 development board


●​ HC-SR04 ultrasonic sensor
●​ Breadboard and jumper wires
●​ Trigger to GPIO5, Echo to GPIO18, VCC to 5V, GND to GND

MicroPython Program Code:

from machine import Pin


import time

trigger = Pin(5, [Link])


echo = Pin(18, [Link])

def get_distance():
[Link]()
time.sleep_us(2)
[Link]()
time.sleep_us(10)
[Link]()

timeout = time.ticks_ms()
while [Link]() == 0:
pulse_start = time.ticks_us()
if time.ticks_diff(time.ticks_ms(), timeout) > 1000:
​ return -1

timeout = time.ticks_ms()
while [Link]() == 1:
pulse_end = time.ticks_us()
if time.ticks_diff(time.ticks_ms(), timeout) > 1000:
return -1

pulse_duration = time.ticks_diff(pulse_end, pulse_start)


distance = (pulse_duration * 0.0343) / 2
return distance

while True:
dist = get_distance()
print("Distance:", round(dist, 2), "cm")
[Link](1)

9. Speed of Sound Experiment


Prompt: Create a MicroPython program for ESP32 that calculates speed of sound using
ultrasonic sensor on GPIO 5 (trigger) and GPIO 18 (echo), measuring time for echo to return
from a known distance.

Hardware Requirements:

●​ ESP32 development board


●​ HC-SR04 ultrasonic sensor
●​ Breadboard and jumper wires
●​ Trigger to GPIO5, Echo to GPIO18

MicroPython Program Code:


from machine import Pin
import time

trigger = Pin(5, [Link])


echo = Pin(18, [Link])

def measure_speed_of_sound():
[Link]()
time.sleep_us(2)
[Link]()
time.sleep_us(10)
[Link]()

while [Link]() == 0:
pulse_start = time.ticks_us()

while [Link]() == 1:
pulse_end = time.ticks_us()

pulse_duration = time.ticks_diff(pulse_end, pulse_start)


distance = 100
time_seconds = pulse_duration / 1000000
speed = (2 * distance) / time_seconds
return speed, pulse_duration

while True:
speed, duration = measure_speed_of_sound()
print("Pulse Duration:", duration, "µs")
print("Calculated Speed of Sound:", round(speed, 2), "cm/s")
print("Expected: ~34300 cm/s")
print("---")
[Link](3)

10. IR Obstacle Detection (Reflection)


Prompt: Create a MicroPython program for ESP32 that detects obstacles using an IR sensor on
GPIO 13 and turns ON an LED on GPIO 2 with alert message when obstacle is detected.

Hardware Requirements:

●​ ESP32 development board


●​ IR obstacle detection sensor
●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ IR sensor OUT to GPIO13, LED to GPIO2

MicroPython Program Code:

from machine import Pin


import time

ir_sensor = Pin(13, [Link])


led = Pin(2, [Link])

while True:
if ir_sensor.value() == 0:
[Link]()
print("OBSTACLE DETECTED!")
else:
[Link]()
print("No obstacle")
[Link](0.5)

11. Motion Detection (PIR sensor)


Prompt: Create a MicroPython program for ESP32 that detects motion using PIR sensor on
GPIO 13 and displays motion status on serial monitor with LED indication on GPIO 2.

Hardware Requirements:

●​ ESP32 development board


●​ PIR motion sensor
●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ PIR OUT to GPIO13, LED to GPIO2

MicroPython Program Code:

from machine import Pin


import time
pir = Pin(13, [Link])
led = Pin(2, [Link])

print("PIR Motion Detector Ready")


[Link](2)

while True:
if [Link]() == 1:
[Link]()
print("MOTION DETECTED!")
[Link](1)
else:
[Link]()
print("No motion")
[Link](0.5)

12. Sound Level Meter (Decibel scale)


Prompt: Create a MicroPython program for ESP32 that reads sound level from an analog
sound sensor on GPIO 34 and estimates decibel level, displaying values on serial monitor every
0.5 seconds.

Hardware Requirements:

●​ ESP32 development board


●​ Sound sensor module (analog output)
●​ Breadboard and jumper wires
●​ Sound sensor analog out to GPIO34

MicroPython Program Code:

from machine import ADC, Pin


import time
import math

sound_sensor = ADC(Pin(34))
sound_sensor.atten(ADC.ATTN_11DB)

while True:
sound_value = sound_sensor.read()
voltage = (sound_value / 4095) * 3.3
if voltage > 0.01:
decibel = 20 * math.log10(voltage / 0.00631) + 94
else:
decibel = 0

print("Sound Value:", sound_value)


print("Estimated dB:", round(decibel, 1))
print("---")
[Link](0.5)

13. RTC Digital Clock System


Prompt: Create a MicroPython program for ESP32 that displays current time in HH:MM:SS
format on serial monitor using internal RTC, updating every second.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

from machine import RTC


import time

rtc = RTC()
[Link]((2025, 1, 1, 0, 10, 30, 0, 0))

while True:
current_time = [Link]()
hour = current_time[4]
minute = current_time[5]
second = current_time[6]

print("Time: {:02d}:{:02d}:{:02d}".format(hour, minute, second))


[Link](1)
14. Time vs Temperature Data Logging
Prompt: Create a MicroPython program for ESP32 that logs temperature from DHT11 on GPIO
4 along with timestamp every 5 seconds and displays on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ DHT11 temperature sensor
●​ 10kΩ pull-up resistor
●​ Breadboard and jumper wires
●​ DHT11 data pin to GPIO4

MicroPython Program Code:

from machine import Pin, RTC


import dht
import time

sensor = dht.DHT11(Pin(4))
rtc = RTC()
[Link]((2025, 1, 1, 0, 12, 0, 0, 0))

print("Time | Temperature")
print("-------------------")

while True:
try:
[Link]()
temp = [Link]()
current_time = [Link]()

time_str = "{:02d}:{:02d}:{:02d}".format(
current_time[4], current_time[5], current_time[6]
)

print(time_str, "|", temp, "°C")


except:
print("Sensor read error")

[Link](5)
15. Linear Equation Solver (ax + b = 0)
Prompt: Create a MicroPython program for ESP32 that solves linear equation ax + b = 0 for
given values of a=5 and b=15, displaying the solution on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

a=5
b = 15

print("Linear Equation: ax + b = 0")


print("Given: a =", a, ", b =", b)

if a == 0:
if b == 0:
print("Infinite solutions")
else:
print("No solution")
else:
x = -b / a
print("Solution: x =", x)

16. Quadratic Equation Solver


Prompt: Create a MicroPython program for ESP32 that solves quadratic equation ax² + bx + c =
0 for a=1, b=-5, c=6 and displays roots on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

import math
a=1
b = -5
c=6

print("Quadratic Equation: ax² + bx + c = 0")


print("a =", a, ", b =", b, ", c =", c)

discriminant = b**2 - 4*a*c

if discriminant > 0:
root1 = (-b + [Link](discriminant)) / (2*a)
root2 = (-b - [Link](discriminant)) / (2*a)
print("Two real roots:")
print("Root 1 =", root1)
print("Root 2 =", root2)
elif discriminant == 0:
root = -b / (2*a)
print("One real root:")
print("Root =", root)
else:
real_part = -b / (2*a)
imag_part = [Link](-discriminant) / (2*a)
print("Two complex roots:")
print("Root 1 =", real_part, "+", imag_part, "i")
print("Root 2 =", real_part, "-", imag_part, "i")

17. Discriminant & Nature of Roots


Prompt: Create a MicroPython program for ESP32 that calculates discriminant of quadratic
equation with a=2, b=4, c=2 and determines nature of roots, displaying results on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

import math

a=2
b=4
c=2

print("Quadratic Equation: ax² + bx + c = 0")


print("a =", a, ", b =", b, ", c =", c)

discriminant = b**2 - 4*a*c

print("Discriminant (Δ) =", discriminant)

if discriminant > 0:
print("Nature: Two distinct real roots")
elif discriminant == 0:
print("Nature: Two equal real roots")
else:
print("Nature: Two complex roots")

18. Trigonometric Calculator


Prompt: Create a MicroPython program for ESP32 that calculates sine, cosine, and tangent for
angle 45 degrees and displays results on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

import math

angle_deg = 45
angle_rad = [Link](angle_deg)

sin_value = [Link](angle_rad)
cos_value = [Link](angle_rad)
tan_value = [Link](angle_rad)

print("Angle:", angle_deg, "degrees")


print("Sine:", round(sin_value, 4))
print("Cosine:", round(cos_value, 4))
print("Tangent:", round(tan_value, 4))

19. Projectile Motion Calculator


Prompt: Create a MicroPython program for ESP32 that calculates maximum height and range
of projectile with initial velocity 20 m/s at 45 degrees angle, displaying results on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

import math

velocity = 20
angle_deg = 45
g = 9.8

angle_rad = [Link](angle_deg)

max_height = (velocity**2 * [Link](angle_rad)**2) / (2 * g)


range_distance = (velocity**2 * [Link](2 * angle_rad)) / g
time_of_flight = (2 * velocity * [Link](angle_rad)) / g

print("Initial Velocity:", velocity, "m/s")


print("Angle:", angle_deg, "degrees")
print("Max Height:", round(max_height, 2), "m")
print("Range:", round(range_distance, 2), "m")
print("Time of Flight:", round(time_of_flight, 2), "s")

20. Statistical Calculator (mean, max, min)


Prompt: Create a MicroPython program for ESP32 that calculates mean, maximum, and
minimum of a list of temperature readings [22, 25, 23, 27, 24, 26] and displays results on serial
monitor.
Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

data = [22, 25, 23, 27, 24, 26]

mean = sum(data) / len(data)


maximum = max(data)
minimum = min(data)
data_range = maximum - minimum

print("Data:", data)
print("Mean:", round(mean, 2))
print("Maximum:", maximum)
print("Minimum:", minimum)
print("Range:", data_range)

21. Sensor Graph Plotting (value vs time)


Prompt: Create a MicroPython program for ESP32 that reads temperature from DHT11 on
GPIO 4 every 2 seconds and displays values in time-series format for plotting on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ DHT11 temperature sensor
●​ 10kΩ pull-up resistor
●​ Breadboard and jumper wires
●​ DHT11 data pin to GPIO4

MicroPython Program Code:

from machine import Pin


import dht
import time

sensor = dht.DHT11(Pin(4))
reading_count = 0
print("Time(s), Temperature(°C)")

while True:
try:
[Link]()
temp = [Link]()
print(reading_count * 2, ",", temp)
reading_count += 1
except:
print("Error reading sensor")

[Link](2)

22. Energy Consumption Calculator


Prompt: Create a MicroPython program for ESP32 that calculates energy consumption in kWh
for a device with power 100W running for 5 hours and displays cost at rate 10 per kWh on serial
monitor.

Hardware Requirements:

●​ ESP32 development board


●​ USB cable for serial communication

MicroPython Program Code:

power_watts = 100
time_hours = 5
cost_per_kwh = 10

energy_kwh = (power_watts * time_hours) / 1000


total_cost = energy_kwh * cost_per_kwh

print("Power:", power_watts, "W")


print("Time:", time_hours, "hours")
print("Energy Consumed:", energy_kwh, "kWh")
print("Cost per kWh:", cost_per_kwh)
print("Total Cost:", total_cost)
23. Gas Detection & Safety Indicator
Prompt: Create a MicroPython program for ESP32 that monitors gas level using MQ-2 sensor
on GPIO 34 and triggers buzzer on GPIO 15 and LED on GPIO 2 when gas level exceeds
threshold 2000, displaying status on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ MQ-2 gas sensor (analog output)
●​ Buzzer
●​ LED
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ MQ-2 analog to GPIO34, Buzzer to GPIO15, LED to GPIO2

MicroPython Program Code:

from machine import ADC, Pin


import time

gas_sensor = ADC(Pin(34))
gas_sensor.atten(ADC.ATTN_11DB)
buzzer = Pin(15, [Link])
led = Pin(2, [Link])

THRESHOLD = 2000

print("Gas Detection System Active")

while True:
gas_level = gas_sensor.read()
print("Gas Level:", gas_level)

if gas_level > THRESHOLD:


[Link]()
[Link]()
print("DANGER! Gas Detected!")
else:
[Link]()
[Link]()
print("Safe")

print("---")
[Link](1)

24. Smart Street Light System


Prompt: Create a MicroPython program for ESP32 that automatically controls street light LED
on GPIO 2 based on LDR on GPIO 34 (turns ON when dark) and PIR sensor on GPIO 13 (turns
ON when motion detected at night), displaying status on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ LDR with 10kΩ resistor
●​ PIR motion sensor
●​ LED (street light)
●​ 220Ω resistor
●​ Breadboard and jumper wires
●​ LDR to GPIO34, PIR to GPIO13, LED to GPIO2

MicroPython Program Code:

from machine import ADC, Pin


import time

ldr = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
pir = Pin(13, [Link])
led = Pin(2, [Link])

DARK_THRESHOLD = 1500

print("Smart Street Light System")

while True:
light_level = [Link]()
motion = [Link]()

print("Light Level:", light_level, "| Motion:", motion)

if light_level < DARK_THRESHOLD:


if motion == 1:
[Link]()
print("Night + Motion: Light ON")
else:
[Link]()
print("Night + No Motion: Light OFF")
else:
[Link]()
print("Day: Light OFF")

print("---")
[Link](1)

25. Automatic Water Tank Controller


Prompt: Create a MicroPython program for ESP32 that monitors water level using sensor on
GPIO 34 and controls a pump relay on GPIO 5, turning pump ON when level is low (below
1000) and OFF when full (above 3000), displaying status on serial monitor.

Hardware Requirements:

●​ ESP32 development board


●​ Water level sensor (analog)
●​ Relay module
●​ LED (pump indicator)
●​ Breadboard and jumper wires
●​ Water sensor to GPIO34, Relay to GPIO5

MicroPython Program Code:

from machine import ADC, Pin


import time

water_sensor = ADC(Pin(34))
water_sensor.atten(ADC.ATTN_11DB)
pump_relay = Pin(5, [Link])

LOW_LEVEL = 1000
HIGH_LEVEL = 3000

pump_state = False

print("Automatic Water Tank Controller")


while True:
water_level = water_sensor.read()

if water_level < LOW_LEVEL and not pump_state:


pump_relay.on()
pump_state = True
print("Water Level LOW - Pump ON")
elif water_level > HIGH_LEVEL and pump_state:
pump_relay.off()
pump_state = False
print("Water Level FULL - Pump OFF")

print("Water Level:", water_level, "| Pump:", "ON" if pump_state else "OFF")


[Link](2)

SEGMENT 3: DIPLOMA / FY
ENGINEERING (EMBEDDED & IOT) – 46 to
70
1. OLED Display Data Visualization
Prompt: Create an ESP32 MicroPython program to display text and sensor data on an OLED
display using I2C interface with SSD1306 driver.

Hardware Requirements:

●​ ESP32 Development Board


●​ SSD1306 OLED Display (128x64, I2C)
●​ Jumper wires
●​ Connections: SDA to GPIO21, SCL to GPIO22, VCC to 3.3V, GND to GND

⚠️ IMPORTANT - Library Installation:


# Upload [Link] to ESP32

# Download from:
[Link]
# Using ampy:

ampy --port /dev/ttyUSB0 put [Link]

# Or use Thonny IDE to save it to the device

MicroPython Code:

from machine import Pin, I2C


import ssd1306
import time

i2c = I2C(0, scl=Pin(22), sda=Pin(21))


oled = ssd1306.SSD1306_I2C(128, 64, i2c)

while True:
[Link](0)
[Link]('ESP32 OLED', 0, 0)
[Link]('Temp: 25C', 0, 20)
[Link]('Humidity: 60%', 0, 30)
[Link]('Pressure:1013', 0, 40)
[Link]()
[Link](2)

2. LCD 16×2 Interface System


Prompt: Create an ESP32 MicroPython program to interface with a 16x2 LCD display and show
scrolling text messages.

Hardware Requirements:

●​ ESP32 Development Board


●​ 16x2 LCD with I2C module (PCF8574)
●​ Jumper wires
●​ Connections: SDA to GPIO21, SCL to GPIO22, VCC to 5V, GND to GND

Important Instructions:
# On your computer, install the library:​
pip install esp8266-i2c-lcd --break-system-packages

# Then upload the library files to your ESP32:

# Option 1: Using ampy​


ampy --port /dev/ttyUSB0 put esp8266_i2c_lcd.py

# Option 2: Using Thonny IDE

# File > Save As > MicroPython device > save as "esp8266_i2c_lcd.py"

MicroPython Code:

from machine import Pin, I2C


from esp8266_i2c_lcd import I2cLcd
import time

i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)


lcd = I2cLcd(i2c, 0x27, 2, 16)

while True:
[Link]()
[Link]("ESP32 System")
[Link](2)
[Link]()
[Link]("Temp: 28C\nHumid: 55%")
[Link](2)

3. UART Communication Protocol


Prompt: Create an ESP32 MicroPython program to demonstrate UART serial communication
by sending and receiving data between two UART ports.

Hardware Requirements:

●​ ESP32 Development Board


●​ USB-to-Serial adapter (optional for external device)
●​ Jumper wires
●​ Connections: TX2 (GPIO17) to RX of external device, RX2 (GPIO16) to TX of external
device
MicroPython Code:

from machine import UART, Pin


import time

uart1 = UART(1, baudrate=9600, tx=Pin(17), rx=Pin(16))


uart2 = UART(2, baudrate=9600, tx=Pin(25), rx=Pin(26))

print("UART Communication Started")

while True:
[Link]("Hello from UART1\n")
print("UART1 Sent: Hello from UART1")
[Link](1)

if [Link]():
data = [Link]()
print("UART2 Received:", [Link]())

[Link](2)

4. Bluetooth Serial Communication


Prompt: Create an ESP32 MicroPython program to establish Bluetooth serial communication
and exchange data with a smartphone app.

Hardware Requirements:

●​ ESP32 Development Board


●​ Smartphone with Bluetooth Serial Terminal app

MicroPython Code:

from machine import UART


import time

uart = UART(0, baudrate=115200)


print("Bluetooth Serial Ready")

counter = 0
while True:
if [Link]():
data = [Link]()
print("Received:", [Link]())
[Link]("Echo: " + [Link]() + "\n")

counter += 1
message = "Counter: " + str(counter) + "\n"
[Link](message)
print("Sent:", [Link]())
[Link](3)

5. Bluetooth Home Automation System


Prompt: Create an ESP32 MicroPython program to control home appliances (LEDs
representing devices) via Bluetooth commands from a smartphone.

Hardware Requirements:

●​ ESP32 Development Board


●​ 4x LEDs
●​ 4x 220Ω Resistors
●​ Smartphone with Bluetooth Serial Terminal app
●​ Connections: LEDs to GPIO23, GPIO22, GPIO21, GPIO19

⚠️ IMPORTANT - Bluetooth Setup Required:


Using Bluetooth Classic (Serial Port Profile - SPP)

This method requires pairing your phone with ESP32 first:

1.​ Enable Bluetooth on your phone


2.​ Search for "ESP32" device
3.​ Pair with it (PIN: 1234 usually)
4.​ Use Serial Bluetooth Terminal app to connect

Note: Standard MicroPython uses UART(0) which is the USB serial, not Bluetooth. For true
Bluetooth functionality, you need to use Bluetooth library or custom firmware.

MicroPython Code:

from machine import Pin, UART


import time

uart = UART(0, baudrate=115200)


led1 = Pin(23, [Link])
led2 = Pin(22, [Link])
led3 = Pin(21, [Link])
led4 = Pin(19, [Link])

print("Bluetooth Home Automation Ready")


print("Commands: 1ON, 1OFF, 2ON, 2OFF, 3ON, 3OFF, 4ON, 4OFF")

while True:
if [Link]():
cmd = [Link]().decode().strip()
print("Command:", cmd)

if cmd == "1ON":
[Link]()
[Link]("Device 1 ON\n")
elif cmd == "1OFF":
[Link]()
[Link]("Device 1 OFF\n")
elif cmd == "2ON":
[Link]()
[Link]("Device 2 ON\n")
elif cmd == "2OFF":
[Link]()
[Link]("Device 2 OFF\n")
elif cmd == "3ON":
[Link]()
[Link]("Device 3 ON\n")
elif cmd == "3OFF":
[Link]()
[Link]("Device 3 OFF\n")
elif cmd == "4ON":
[Link]()
[Link]("Device 4 ON\n")
elif cmd == "4OFF":
[Link]()
[Link]("Device 4 OFF\n")

[Link](0.1)
6. WiFi Network Scanner
Prompt: Create an ESP32 MicroPython program to scan for available WiFi networks and
display their SSID, signal strength, and security type.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import network
import time

wlan = [Link](network.STA_IF)
[Link](True)

print("WiFi Network Scanner")


print("-" * 50)

while True:
networks = [Link]()
print("\nAvailable Networks:")
print("-" * 50)

for net in networks:


ssid = net[0].decode()
bssid = ':'.join('%02x' % b for b in net[1])
channel = net[2]
rssi = net[3]
security = net[4]

print("SSID:", ssid)
print("RSSI:", rssi, "dBm")
print("Channel:", channel)
print("Security:", security)
print("-" * 50)

[Link](10)

7. WiFi Signal Strength Analyzer


Prompt: Create an ESP32 MicroPython program to connect to a WiFi network and continuously
monitor the signal strength (RSSI) with quality indicators.

Hardware Requirements:

●​ ESP32 Development Board


●​ WiFi Router

MicroPython Code:

import network
import time

SSID = "YourWiFiSSID"
PASSWORD = "YourWiFiPassword"

wlan = [Link](network.STA_IF)
[Link](True)

print("Connecting to WiFi...")
[Link](SSID, PASSWORD)

while not [Link]():


[Link](1)

print("Connected to:", SSID)


print("IP Address:", [Link]()[0])
print("-" * 50)

while True:
rssi = [Link]('rssi')

if rssi >= -50:


quality = "Excellent"
elif rssi >= -60:
quality = "Good"
elif rssi >= -70:
quality = "Fair"
else:
quality = "Poor"

print("Signal Strength:", rssi, "dBm -", quality)


[Link](2)
8. Web Server – Device Control
Prompt: Create an ESP32 MicroPython program to run a web server that allows controlling
LEDs through a web interface with ON/OFF buttons.

Hardware Requirements:

●​ ESP32 Development Board


●​ 2x LEDs
●​ 2x 220Ω Resistors
●​ WiFi Router
●​ Connections: LEDs to GPIO23 and GPIO22

MicroPython Code:

import network
import socket
from machine import Pin
import time

SSID = "YourWiFiSSID"
PASSWORD = "YourWiFiPassword"

led1 = Pin(23, [Link])


led2 = Pin(22, [Link])

wlan = [Link](network.STA_IF)
[Link](True)
[Link](SSID, PASSWORD)

while not [Link]():


[Link](1)

print("Connected! IP:", [Link]()[0])

html = """HTTP/1.1 200 OK


Content-Type: text/html

<html>
<head><title>ESP32 Control</title></head>
<body>
<h1>Device Control</h1>
<p>LED 1: <a href="?led1=on"><button>ON</button></a> <a
href="?led1=off"><button>OFF</button></a></p>
<p>LED 2: <a href="?led2=on"><button>ON</button></a> <a
href="?led2=off"><button>OFF</button></a></p>
</body>
</html>
"""

addr = [Link]('[Link]', 80)[0][-1]


s = [Link]()
[Link](addr)
[Link](1)
print("Server running on port 80")

while True:
cl, addr = [Link]()
request = [Link](1024).decode()

if "?led1=on" in request:
[Link]()
elif "?led1=off" in request:
[Link]()
elif "?led2=on" in request:
[Link]()
elif "?led2=off" in request:
[Link]()

[Link](html)
[Link]()

9. Web Dashboard – Live Sensor Data


Prompt: Create an ESP32 MicroPython program to display live sensor data on a web
dashboard with auto-refresh functionality.

Hardware Requirements:

●​ ESP32 Development Board


●​ WiFi Router

MicroPython Code:

import network
import socket
from machine import Pin
import time
import random

SSID = "YourWiFiSSID"
PASSWORD = "YourWiFiPassword"

wlan = [Link](network.STA_IF)
[Link](True)
[Link](SSID, PASSWORD)

while not [Link]():


[Link](1)

print("Connected! IP:", [Link]()[0])

def get_sensor_data():
temp = 20 + [Link](0, 15)
humidity = 40 + [Link](0, 40)
pressure = 1000 + [Link](0, 30)
return temp, humidity, pressure

addr = [Link]('[Link]', 80)[0][-1]


s = [Link]()
[Link](addr)
[Link](1)
print("Server running on port 80")

while True:
cl, addr = [Link]()
request = [Link](1024)

temp, humidity, pressure = get_sensor_data()

html = """HTTP/1.1 200 OK


Content-Type: text/html

<html>
<head>
<title>Sensor Dashboard</title>
<meta http-equiv="refresh" content="5">
</head>
<body>
<h1>Live Sensor Data</h1>
<h2>Temperature: {}C</h2>
<h2>Humidity: {}%</h2>
<h2>Pressure: {} hPa</h2>
<p>Auto-refresh every 5 seconds</p>
</body>
</html>
""".format(temp, humidity, pressure)

[Link](html)
[Link]()

10. JSON Data Encoding & Parsing


Prompt: Create an ESP32 MicroPython program to encode sensor data into JSON format and
parse received JSON data for processing.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import json
import time
import random

def create_sensor_json():
data = {
"device_id": "ESP32_001",
"timestamp": [Link](),
"sensors": {
"temperature": 22 + [Link](0, 10),
"humidity": 50 + [Link](0, 30),
"pressure": 1013 + [Link](-10, 10)
},
"status": "active"
}
return data

def parse_json(json_string):
try:
data = [Link](json_string)
print("Parsed Data:")
print("Device ID:", data["device_id"])
print("Temperature:", data["sensors"]["temperature"])
print("Humidity:", data["sensors"]["humidity"])
print("Pressure:", data["sensors"]["pressure"])
print("Status:", data["status"])
except Exception as e:
print("Parse Error:", e)

print("JSON Encoding & Parsing Demo")


print("-" * 50)

while True:
sensor_data = create_sensor_json()
json_string = [Link](sensor_data)

print("\nEncoded JSON:")
print(json_string)
print("-" * 50)

parse_json(json_string)
print("-" * 50)

[Link](5)

11. SPI Communication Demo


Prompt: Create an ESP32 MicroPython program to demonstrate SPI communication by
interfacing with an SPI device and transferring data.

Hardware Requirements:

●​ ESP32 Development Board


●​ SPI device (e.g., MCP3008 ADC or any SPI sensor)
●​ Jumper wires
●​ Connections: MOSI to GPIO23, MISO to GPIO19, SCK to GPIO18, CS to GPIO5

MicroPython Code:

from machine import Pin, SPI


import time
spi = SPI(1, baudrate=1000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
cs = Pin(5, [Link])
[Link](1)

print("SPI Communication Demo")

def spi_transfer(data):
[Link](0)
time.sleep_us(1)
result = [Link](len(data), data[0])
[Link](1)
return result

while True:
tx_data = bytearray([0x01, 0x80, 0x00])
print("Transmitting:", [hex(b) for b in tx_data])

rx_data = spi_transfer(tx_data)
print("Received:", [hex(b) for b in rx_data])

value = ((rx_data[1] & 0x03) << 8) | rx_data[2]


print("Converted Value:", value)
print("-" * 50)

[Link](2)

12. I2C Master–Slave Communication


Prompt: Create an ESP32 MicroPython program to demonstrate I2C master-slave
communication by reading data from an I2C slave device.

Hardware Requirements:

●​ ESP32 Development Board


●​ I2C Slave device (e.g., MPU6050, BMP280)
●​ Jumper wires
●​ Connections: SDA to GPIO21, SCL to GPIO22

MicroPython Code:

from machine import Pin, I2C


import time
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)

print("I2C Master-Slave Communication")


print("Scanning I2C bus...")

devices = [Link]()
if devices:
print("Found I2C devices at addresses:", [hex(addr) for addr in devices])
else:
print("No I2C devices found")

SLAVE_ADDR = 0x68

while True:
try:
data = [Link](SLAVE_ADDR, 6)
print("Read from slave:", [hex(b) for b in data])

write_data = bytearray([0x3B, 0x00])


[Link](SLAVE_ADDR, write_data)
print("Written to slave:", [hex(b) for b in write_data])

except Exception as e:
print("Communication Error:", e)

print("-" * 50)
[Link](2)

13. SD Card File Read/Write


Prompt: Create an ESP32 MicroPython program to read and write data files on an SD card
using SPI interface.

Hardware Requirements:

●​ ESP32 Development Board


●​ SD Card Module
●​ SD Card
●​ Jumper wires
●​ Connections: MISO to GPIO19, MOSI to GPIO23, SCK to GPIO18, CS to GPIO5
⚠️ IMPORTANT - SD Card Driver Required: The [Link] driver is not included in
MicroPython by default. You need to upload it to your ESP32.

Step 1: Download [Link]

# Download the official driver:

wget
[Link]

# Or get it from MicroPython libraries

Step 2: Upload to ESP32

# Using ampy:

ampy --port /dev/ttyUSB0 put [Link]

# Or use Thonny IDE: File > Save As > MicroPython device > save as "[Link]"

MicroPython Code:

from machine import Pin, SPI


import sdcard
import os
import time

spi = SPI(1, baudrate=1000000, sck=Pin(18), mosi=Pin(23), miso=Pin(19))


cs = Pin(5, [Link])

try:
sd = [Link](spi, cs)
[Link](sd, '/sd')
print("SD Card mounted successfully")

file_path = '/sd/[Link]'

with open(file_path, 'w') as f:


[Link]("ESP32 SD Card Test\n")
[Link]("Temperature: 25C\n")
[Link]("Humidity: 60%\n")
print("Data written to", file_path)

with open(file_path, 'r') as f:


content = [Link]()
print("File Contents:")
print(content)

print("File operations completed")

except Exception as e:
print("SD Card Error:", e)

14. CSV Sensor Data Logger


Prompt: Create an ESP32 MicroPython program to log sensor data to a CSV file on an SD card
with timestamp and multiple sensor readings.

Hardware Requirements:

●​ ESP32 Development Board


●​ SD Card Module
●​ SD Card
●​ Jumper wires
●​ Connections: MISO to GPIO19, MOSI to GPIO23, SCK to GPIO18, CS to GPIO5

MicroPython Code:

from machine import Pin, SPI


import sdcard
import os
import time
import random

spi = SPI(1, baudrate=1000000, sck=Pin(18), mosi=Pin(23), miso=Pin(19))


cs = Pin(5, [Link])

try:
sd = [Link](spi, cs)
[Link](sd, '/sd')
print("SD Card mounted")

csv_file = '/sd/sensor_log.csv'

with open(csv_file, 'w') as f:


[Link]("Timestamp,Temperature,Humidity,Pressure\n")
print("CSV file created")
counter = 0
while counter < 10:
timestamp = [Link]()
temp = 20 + [Link](0, 15)
humidity = 40 + [Link](0, 40)
pressure = 1000 + [Link](0, 30)

with open(csv_file, 'a') as f:


[Link]("{},{},{},{}\n".format(timestamp, temp, humidity, pressure))

print("Logged: {},{},{},{}".format(timestamp, temp, humidity, pressure))


counter += 1
[Link](2)

print("Data logging completed")

except Exception as e:
print("Error:", e)

15. OTA Firmware Update System


Prompt: Create an ESP32 MicroPython program to implement Over-The-Air (OTA) firmware
update capability via WiFi with version checking.

Hardware Requirements:

●​ ESP32 Development Board


●​ WiFi Router

MicroPython Code:

import network
import socket
import time
import os

SSID = "YourWiFiSSID"
PASSWORD = "YourWiFiPassword"

FIRMWARE_VERSION = "1.0.0"
UPDATE_SERVER = "[Link]"
UPDATE_PORT = 8080

wlan = [Link](network.STA_IF)
[Link](True)
[Link](SSID, PASSWORD)

while not [Link]():


[Link](1)

print("Connected! IP:", [Link]()[0])


print("Current Firmware Version:", FIRMWARE_VERSION)

def check_for_update():
try:
s = [Link]()
addr = [Link](UPDATE_SERVER, UPDATE_PORT)[0][-1]
[Link](addr)
[Link](b'GET /version HTTP/1.1\r\nHost: update-server\r\n\r\n')
response = [Link](1024).decode()
[Link]()

version_line = [Link]('\n')[-1]
server_version = version_line.strip()

print("Server Version:", server_version)

if server_version > FIRMWARE_VERSION:


print("New firmware available!")
return True
else:
print("Firmware is up to date")
return False
except Exception as e:
print("Update check failed:", e)
return False

def download_firmware():
print("Downloading firmware...")
print("OTA update simulated (actual implementation requires file write)")

while True:
print("\nChecking for updates...")
if check_for_update():
download_firmware()
[Link](60)

16. DC Motor Speed Control (RPM relation)


Prompt: Create an ESP32 MicroPython program to control DC motor speed using PWM and
calculate RPM based on duty cycle relationship.

Hardware Requirements:

●​ ESP32 Development Board


●​ L298N Motor Driver
●​ DC Motor
●​ 12V Power Supply
●​ Jumper wires
●​ Connections: ENA to GPIO25, IN1 to GPIO26, IN2 to GPIO27

MicroPython Code:

from machine import Pin, PWM


import time

in1 = Pin(26, [Link])


in2 = Pin(27, [Link])
ena = PWM(Pin(25), freq=1000)

def set_motor_speed(duty):
[Link]()
[Link]()
[Link](duty)
rpm = int((duty / 1023) * 200)
return rpm

print("DC Motor Speed Control")


print("-" * 50)

while True:
for duty in range(0, 1024, 100):
rpm = set_motor_speed(duty)
print("Duty Cycle: {}% | Estimated RPM: {}".format(int(duty/10.23), rpm))
[Link](2)
for duty in range(1023, -1, -100):
rpm = set_motor_speed(duty)
print("Duty Cycle: {}% | Estimated RPM: {}".format(int(duty/10.23), rpm))
[Link](2)

17. Servo Motor Angle Control


Prompt: Create an ESP32 MicroPython program to control servo motor position by setting
precise angles from 0 to 180 degrees.

Hardware Requirements:

●​ ESP32 Development Board


●​ SG90 Servo Motor
●​ Jumper wires
●​ Connections: Signal to GPIO13, VCC to 5V, GND to GND

MicroPython Code:

from machine import Pin, PWM


import time

servo = PWM(Pin(13), freq=50)

def set_angle(angle):
if angle < 0:
angle = 0
elif angle > 180:
angle = 180

duty = int(40 + (angle / 180) * 75)


[Link](duty)

print("Servo Motor Angle Control")


print("-" * 50)

angles = [0, 45, 90, 135, 180, 135, 90, 45, 0]

while True:
for angle in angles:
print("Setting angle to:", angle, "degrees")
set_angle(angle)
[Link](1)

print("-" * 50)

18. Stepper Motor Positioning System


Prompt: Create an ESP32 MicroPython program to control a stepper motor for precise
positioning with step count and direction control.

Hardware Requirements:

●​ ESP32 Development Board


●​ ULN2003 Driver Board
●​ 28BYJ-48 Stepper Motor
●​ Jumper wires
●​ Connections: IN1 to GPIO19, IN2 to GPIO18, IN3 to GPIO5, IN4 to GPIO17

MicroPython Code:

from machine import Pin


import time

IN1 = Pin(19, [Link])


IN2 = Pin(18, [Link])
IN3 = Pin(5, [Link])
IN4 = Pin(17, [Link])

step_sequence = [
[1, 0, 0, 0],
[1, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 1, 0],
[0, 0, 1, 1],
[0, 0, 0, 1],
[1, 0, 0, 1]
]

def step_motor(steps, direction=1, delay=0.002):


for _ in range(steps):
for step in step_sequence[::direction]:
[Link](step[0])
[Link](step[1])
[Link](step[2])
[Link](step[3])
[Link](delay)

print("Stepper Motor Positioning System")


print("-" * 50)

position = 0

while True:
print("Moving forward 512 steps (90 degrees)")
step_motor(512, 1)
position += 512
print("Current Position:", position, "steps")
[Link](1)

print("Moving backward 512 steps (-90 degrees)")


step_motor(512, -1)
position -= 512
print("Current Position:", position, "steps")
[Link](1)

print("-" * 50)

19. Deep Sleep Power Management


Prompt: Create an ESP32 MicroPython program to implement deep sleep mode with timer
wakeup for power-efficient operation.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

from machine import Pin, deepsleep


import esp32
import time

led = Pin(2, [Link])


wake_reason = esp32.wake_reason()

if wake_reason == esp32.WAKEUP_TIMER:
print("Woke up from deep sleep (timer)")
elif wake_reason == esp32.WAKEUP_EXT0:
print("Woke up from external signal")
else:
print("Power on or reset")

print("Active mode - performing tasks...")

for i in range(5):
[Link]()
[Link](0.5)
[Link]()
[Link](0.5)
print("Task iteration:", i+1)

print("Entering deep sleep for 10 seconds...")


[Link](1)

deepsleep(10000)

20. Interrupt-Based Input Handling


Prompt: Create an ESP32 MicroPython program to handle button inputs using hardware
interrupts with debouncing and event counting.

Hardware Requirements:

●​ ESP32 Development Board


●​ 2x Push Buttons
●​ 2x 10kΩ Pull-down Resistors
●​ LED
●​ 220Ω Resistor
●​ Connections: Button1 to GPIO12, Button2 to GPIO14, LED to GPIO2

MicroPython Code:

from machine import Pin


import time
led = Pin(2, [Link])
button1 = Pin(12, [Link], Pin.PULL_DOWN)
button2 = Pin(14, [Link], Pin.PULL_DOWN)

button1_count = 0
button2_count = 0
last_time1 = 0
last_time2 = 0

def button1_handler(pin):
global button1_count, last_time1
current_time = time.ticks_ms()
if time.ticks_diff(current_time, last_time1) > 200:
button1_count += 1
print("Button 1 pressed | Count:", button1_count)
[Link]()
[Link](0.1)
[Link]()
last_time1 = current_time

def button2_handler(pin):
global button2_count, last_time2
current_time = time.ticks_ms()
if time.ticks_diff(current_time, last_time2) > 200:
button2_count += 1
print("Button 2 pressed | Count:", button2_count)
last_time2 = current_time

[Link](trigger=Pin.IRQ_RISING, handler=button1_handler)
[Link](trigger=Pin.IRQ_RISING, handler=button2_handler)

print("Interrupt-Based Input Handling Ready")


print("Press buttons to trigger interrupts")

while True:
[Link](1)

21. Watchdog Timer Fault Recovery


Prompt: Create an ESP32 MicroPython program to implement watchdog timer for automatic
system recovery from hangs or crashes.
Hardware Requirements:

●​ ESP32 Development Board


●​ LED
●​ 220Ω Resistor
●​ Connections: LED to GPIO2

MicroPython Code:

from machine import Pin, WDT


import time

led = Pin(2, [Link])


wdt = WDT(timeout=5000)

print("Watchdog Timer Fault Recovery System")


print("Watchdog timeout set to 5 seconds")
print("-" * 50)

iteration = 0

while True:
iteration += 1
print("Iteration:", iteration)

[Link]()
[Link](0.5)
[Link]()
[Link](0.5)

[Link]()
print("Watchdog fed")
if iteration == 10
print("Simulating system hang...")
print("Watchdog will reset the system in 5 seconds")
while True:
[Link](1)
[Link](2)

22. Event-Driven Programming Model

Prompt:
Create an ESP32 MicroPython program to demonstrate event-driven programming with multiple
event sources and handlers.

Hardware Requirements:
- ESP32 Development Board
- 2x Push Buttons
- 2x LEDs
- 2x 10kΩ Resistors
- 2x 220Ω Resistors
- Connections: Button1 to GPIO12, Button2 to GPIO14, LED1 to GPIO2, LED2 to GPIO4

MicroPython Code:

from machine import Pin, Timer


import time

led1 = Pin(2, [Link])


led2 = Pin(4, [Link])
button1 = Pin(12, [Link], Pin.PULL_DOWN)
button2 = Pin(14, [Link], Pin.PULL_DOWN)

event_queue = []

def button1_event(pin):
event_queue.append(("BUTTON1", time.ticks_ms()))
print("Event: Button 1 pressed")

def button2_event(pin):
event_queue.append(("BUTTON2", time.ticks_ms()))
print("Event: Button 2 pressed")

def timer_event(timer):
event_queue.append(("TIMER", time.ticks_ms()))
print("Event: Timer tick")

def process_events():
while event_queue:
event_type, timestamp = event_queue.pop(0)
print("Processing event:", event_type, "at", timestamp)

if event_type == "BUTTON1":
[Link]()
[Link](0.5)
[Link]()
elif event_type == "BUTTON2":
[Link]()
[Link](0.5)
[Link]()
elif event_type == "TIMER":
[Link]()
[Link]()
[Link](0.2)
[Link]()
[Link]()

[Link](trigger=Pin.IRQ_RISING, handler=button1_event)
[Link](trigger=Pin.IRQ_RISING, handler=button2_event)

timer = Timer(0)
[Link](period=5000, mode=[Link], callback=timer_event)

print("Event-Driven System Ready")

while True:
process_events()
[Link](0.1)

23. Error Detection & Logging System


Prompt: Create an ESP32 MicroPython program to implement error detection, logging, and
reporting with severity levels and timestamps.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time
import random

class ErrorLogger:
def __init__(self):
self.error_count = 0
self.warning_count = 0
self.info_count = 0
self.log_file = "error_log.txt"

def log(self, level, message):


timestamp = [Link]()
log_entry = "[{}] {} - {}".format(timestamp, level, message)
print(log_entry)

if level == "ERROR":
self.error_count += 1
elif level == "WARNING":
self.warning_count += 1
elif level == "INFO":
self.info_count += 1

try:
with open(self.log_file, 'a') as f:
[Link](log_entry + "\n")
except:
print("Failed to write to log file")

def error(self, message):


[Link]("ERROR", message)

def warning(self, message):


[Link]("WARNING", message)

def info(self, message):


[Link]("INFO", message)

def report(self):
print("\n" + "-" * 50)
print("Error Report:")
print("Total Errors:", self.error_count)
print("Total Warnings:", self.warning_count)
print("Total Info:", self.info_count)
print("-" * 50)

logger = ErrorLogger()

print("Error Detection & Logging System")


[Link]("System started")

for i in range(10):
sensor_value = [Link](0, 100)
if sensor_value > 80:
[Link]("Sensor value critically high: {}".format(sensor_value))
elif sensor_value > 60:
[Link]("Sensor value elevated: {}".format(sensor_value))
else:
[Link]("Sensor value normal: {}".format(sensor_value))

[Link](2)

[Link]()

24. Circular / Ring Buffer for Data


Prompt: Create an ESP32 MicroPython program to implement a circular buffer for efficient data
storage and retrieval with overflow handling.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time
import random

class CircularBuffer:
def __init__(self, size):
[Link] = size
[Link] = [None] * size
[Link] = 0
[Link] = 0
[Link] = 0

def is_full(self):
return [Link] == [Link]

def is_empty(self):
return [Link] == 0

def write(self, data):


[Link][[Link]] = data
[Link] = ([Link] + 1) % [Link]

if self.is_full():
[Link] = ([Link] + 1) % [Link]
print("Buffer full - overwriting oldest data")
else:
[Link] += 1

def read(self):
if self.is_empty():
print("Buffer empty")
return None

data = [Link][[Link]]
[Link] = ([Link] + 1) % [Link]
[Link] -= 1
return data

def display(self):
print("Buffer contents:", [Link])
print("Head:", [Link], "| Tail:", [Link], "| Count:", [Link])

buffer = CircularBuffer(5)

print("Circular Buffer Demo (Size: 5)")


print("-" * 50)

for i in range(8):
value = [Link](10, 99)
print("\nWriting:", value)
[Link](value)
[Link]()
[Link](1)

print("\n" + "-" * 50)


print("Reading data from buffer:")

for i in range(5):
data = [Link]()
print("Read:", data)
[Link]()
[Link](1)
25. Internet Time Sync (NTP)
Prompt: Create an ESP32 MicroPython program to synchronize system time with internet NTP
servers and display local time.

Hardware Requirements:

●​ ESP32 Development Board


●​ WiFi Router

MicroPython Code:

import network
import ntptime
import time
from machine import RTC

SSID = "YourWiFiSSID"
PASSWORD = "YourWiFiPassword"

wlan = [Link](network.STA_IF)
[Link](True)
[Link](SSID, PASSWORD)

print("Connecting to WiFi...")
while not [Link]():
[Link](1)

print("Connected! IP:", [Link]()[0])

rtc = RTC()

def sync_time():
try:
print("Syncing time with NTP server...")
[Link]()
print("Time synchronized successfully")
return True
except Exception as e:
print("Time sync failed:", e)
return False

def get_local_time():
current_time = [Link]()
return "{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(
current_time[0], current_time[1], current_time[2],
current_time[3], current_time[4], current_time[5]
)

sync_time()

print("-" * 50)
print("Internet Time Sync (NTP) System")
print("-" * 50)

while True:
print("Current Time:", get_local_time())
print("Unix Timestamp:", [Link]())
[Link](5)

SEGMENT 4: CORE ENGINEERING (DSA,


CONTROL, SIGNALS) – 71 to 105
DATA STRUCTURES & ALGORITHMS

1. Array Operations
Prompt: Create an ESP32 MicroPython program to demonstrate basic array operations
including insertion, deletion, searching, and traversal.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class ArrayOps:
def __init__(self, size):
[Link] = []
[Link] = size
def insert(self, element):
if len([Link]) < [Link]:
[Link](element)
print("Inserted:", element)
else:
print("Array is full")

def delete(self, element):


if element in [Link]:
[Link](element)
print("Deleted:", element)
else:
print("Element not found")

def search(self, element):


if element in [Link]:
index = [Link](element)
print("Found", element, "at index", index)
return index
else:
print("Element not found")
return -1

def display(self):
print("Array:", [Link])

print("Array Operations Demo")


print("-" * 50)

arr = ArrayOps(10)

[Link](10)
[Link](20)
[Link](30)
[Link](40)
[Link](50)
[Link]()

[Link](30)
[Link](20)
[Link]()

[Link](60)
[Link](70)
[Link]()

print("Array length:", len([Link]))

2. String Processing Algorithms


Prompt: Create an ESP32 MicroPython program to demonstrate string processing algorithms
including reverse, palindrome check, substring search, and character frequency.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def reverse_string(s):
return s[::-1]

def is_palindrome(s):
s = [Link]().replace(" ", "")
return s == s[::-1]

def substring_search(text, pattern):


index = [Link](pattern)
return index

def char_frequency(s):
freq = {}
for char in s:
if char in freq:
freq[char] += 1
else:
freq[char] = 1
return freq

def count_vowels(s):
vowels = "aeiouAEIOU"
count = 0
for char in s:
if char in vowels:
count += 1
return count

print("String Processing Algorithms")


print("-" * 50)

text = "ESP32 MicroPython"


print("Original:", text)
print("Reversed:", reverse_string(text))
print("-" * 50)

test_str = "madam"
print("String:", test_str)
print("Is Palindrome:", is_palindrome(test_str))
print("-" * 50)

pattern = "Micro"
index = substring_search(text, pattern)
print("Pattern '{}' found at index: {}".format(pattern, index))
print("-" * 50)

freq = char_frequency(text)
print("Character Frequency:", freq)
print("-" * 50)

print("Vowel count:", count_vowels(text))

3. Frequency Counter (Hashing)


Prompt: Create an ESP32 MicroPython program to implement frequency counter using hashing
to count occurrences of elements in a collection.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class FrequencyCounter:
def __init__(self):
self.freq_map = {}

def add(self, element):


if element in self.freq_map:
self.freq_map[element] += 1
else:
self.freq_map[element] = 1

def get_frequency(self, element):


return self.freq_map.get(element, 0)

def most_frequent(self):
if not self.freq_map:
return None
max_freq = max(self.freq_map.values())
for key, value in self.freq_map.items():
if value == max_freq:
return key, max_freq

def display(self):
print("Frequency Map:")
for key, value in self.freq_map.items():
print("{}: {}".format(key, value))

print("Frequency Counter (Hashing)")


print("-" * 50)

counter = FrequencyCounter()

data = [1, 2, 3, 2, 1, 4, 5, 3, 2, 1, 6, 3, 2]
print("Input data:", data)

for item in data:


[Link](item)

[Link]()
print("-" * 50)

print("Frequency of 2:", counter.get_frequency(2))


print("Frequency of 5:", counter.get_frequency(5))
print("-" * 50)

most_freq = counter.most_frequent()
print("Most frequent element: {} (appears {} times)".format(most_freq[0], most_freq[1]))
4. Linear Search Algorithm
Prompt: Create an ESP32 MicroPython program to implement linear search algorithm with
step-by-step visualization and comparison count.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def linear_search(arr, target):


comparisons = 0
print("Searching for:", target)
print("-" * 50)

for i in range(len(arr)):
comparisons += 1
print("Step {}: Checking arr[{}] = {}".format(comparisons, i, arr[i]))

if arr[i] == target:
print("Found at index:", i)
print("Total comparisons:", comparisons)
return i

[Link](0.5)

print("Element not found")


print("Total comparisons:", comparisons)
return -1

print("Linear Search Algorithm")


print("-" * 50)

arr = [15, 23, 8, 42, 17, 31, 9, 56, 12]


print("Array:", arr)
print("-" * 50)

target = 31
result = linear_search(arr, target)
print("=" * 50)

target = 100
result = linear_search(arr, target)

5. Binary Search Algorithm


Prompt: Create an ESP32 MicroPython program to implement binary search algorithm on
sorted arrays with step-by-step visualization.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def binary_search(arr, target):


left = 0
right = len(arr) - 1
comparisons = 0

print("Searching for:", target)


print("-" * 50)

while left <= right:


comparisons += 1
mid = (left + right) // 2

print("Step {}: left={}, mid={}, right={}".format(comparisons, left, mid, right))


print("Checking arr[{}] = {}".format(mid, arr[mid]))

if arr[mid] == target:
print("Found at index:", mid)
print("Total comparisons:", comparisons)
return mid
elif arr[mid] < target:
print("Target is in right half")
left = mid + 1
else:
print("Target is in left half")
right = mid - 1

print("-" * 50)
[Link](1)

print("Element not found")


print("Total comparisons:", comparisons)
return -1

print("Binary Search Algorithm")


print("-" * 50)

arr = [5, 12, 18, 23, 31, 42, 56, 67, 89]
print("Sorted Array:", arr)
print("-" * 50)

target = 42
result = binary_search(arr, target)
print("=" * 50)

target = 25
result = binary_search(arr, target)

6. Stack Implementation
Prompt: Create an ESP32 MicroPython program to implement stack data structure with push,
pop, peek operations and overflow/underflow handling.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class Stack:
def __init__(self, size):
[Link] = []
[Link] = size
[Link] = -1
def is_empty(self):
return [Link] == -1

def is_full(self):
return [Link] == [Link] - 1

def push(self, data):


if self.is_full():
print("Stack Overflow! Cannot push", data)
return False
else:
[Link](data)
[Link] += 1
print("Pushed:", data)
return True

def pop(self):
if self.is_empty():
print("Stack Underflow! Cannot pop")
return None
else:
data = [Link]()
[Link] -= 1
print("Popped:", data)
return data

def peek(self):
if self.is_empty():
print("Stack is empty")
return None
else:
return [Link][[Link]]

def display(self):
print("Stack:", [Link])
print("Top index:", [Link])

print("Stack Implementation")
print("-" * 50)

stack = Stack(5)

[Link](10)
[Link](20)
[Link](30)
[Link]()
print("-" * 50)

print("Top element:", [Link]())


print("-" * 50)

[Link]()
[Link]()
[Link]()
print("-" * 50)

[Link](40)
[Link](50)
[Link](60)
[Link](70)
[Link]()

7. Circular Queue
Prompt: Create an ESP32 MicroPython program to implement circular queue with enqueue,
dequeue operations and efficient space utilization.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class CircularQueue:
def __init__(self, size):
[Link] = size
[Link] = [None] * size
[Link] = -1
[Link] = -1

def is_empty(self):
return [Link] == -1
def is_full(self):
return ([Link] + 1) % [Link] == [Link]

def enqueue(self, data):


if self.is_full():
print("Queue Full! Cannot enqueue", data)
return False

if self.is_empty():
[Link] = 0
[Link] = 0
else:
[Link] = ([Link] + 1) % [Link]

[Link][[Link]] = data
print("Enqueued:", data)
return True

def dequeue(self):
if self.is_empty():
print("Queue Empty! Cannot dequeue")
return None

data = [Link][[Link]]

if [Link] == [Link]:
[Link] = -1
[Link] = -1
else:
[Link] = ([Link] + 1) % [Link]

print("Dequeued:", data)
return data

def display(self):
if self.is_empty():
print("Queue is empty")
return

print("Queue:", end=" ")


i = [Link]
while True:
print([Link][i], end=" ")
if i == [Link]:
break
i = (i + 1) % [Link]
print()
print("Front:", [Link], "| Rear:", [Link])

print("Circular Queue Implementation")


print("-" * 50)

cq = CircularQueue(5)

[Link](10)
[Link](20)
[Link](30)
[Link]()
print("-" * 50)

[Link]()
[Link]()
[Link]()
print("-" * 50)

[Link](40)
[Link](50)
[Link](60)
[Link](70)
[Link]()

8. Singly Linked List


Prompt: Create an ESP32 MicroPython program to implement singly linked list with insertion,
deletion, and traversal operations.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class Node:
def __init__(self, data):
[Link] = data
[Link] = None

class SinglyLinkedList:
def __init__(self):
[Link] = None

def insert_at_beginning(self, data):


new_node = Node(data)
new_node.next = [Link]
[Link] = new_node
print("Inserted", data, "at beginning")

def insert_at_end(self, data):


new_node = Node(data)
if not [Link]:
[Link] = new_node
return

temp = [Link]
while [Link]:
temp = [Link]
[Link] = new_node
print("Inserted", data, "at end")

def delete(self, key):


temp = [Link]

if temp and [Link] == key:


[Link] = [Link]
print("Deleted:", key)
return

prev = None
while temp and [Link] != key:
prev = temp
temp = [Link]

if temp is None:
print("Key not found")
return

[Link] = [Link]
print("Deleted:", key)
def display(self):
if not [Link]:
print("List is empty")
return

print("Linked List:", end=" ")


temp = [Link]
while temp:
print([Link], end=" -> ")
temp = [Link]
print("None")

print("Singly Linked List")


print("-" * 50)

sll = SinglyLinkedList()

sll.insert_at_end(10)
sll.insert_at_end(20)
sll.insert_at_end(30)
[Link]()
print("-" * 50)

sll.insert_at_beginning(5)
[Link]()
print("-" * 50)

[Link](20)
[Link]()

9. Doubly Linked List


Prompt: Create an ESP32 MicroPython program to implement doubly linked list with
bidirectional traversal and insertion/deletion operations.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:
import time

class Node:
def __init__(self, data):
[Link] = data
[Link] = None
[Link] = None

class DoublyLinkedList:
def __init__(self):
[Link] = None

def insert_at_end(self, data):


new_node = Node(data)
if not [Link]:
[Link] = new_node
print("Inserted", data)
return

temp = [Link]
while [Link]:
temp = [Link]

[Link] = new_node
new_node.prev = temp
print("Inserted", data)

def delete(self, key):


temp = [Link]

while temp and [Link] != key:


temp = [Link]

if temp is None:
print("Key not found")
return

if [Link]:
[Link] = [Link]
else:
[Link] = [Link]

if [Link]:
[Link] = [Link]
print("Deleted:", key)

def display_forward(self):
if not [Link]:
print("List is empty")
return

print("Forward:", end=" ")


temp = [Link]
while temp:
print([Link], end=" <-> ")
temp = [Link]
print("None")

def display_backward(self):
if not [Link]:
print("List is empty")
return

temp = [Link]
while [Link]:
temp = [Link]

print("Backward:", end=" ")


while temp:
print([Link], end=" <-> ")
temp = [Link]
print("None")

print("Doubly Linked List")


print("-" * 50)

dll = DoublyLinkedList()

dll.insert_at_end(10)
dll.insert_at_end(20)
dll.insert_at_end(30)
dll.insert_at_end(40)

dll.display_forward()
dll.display_backward()
print("-" * 50)
[Link](20)
dll.display_forward()

10. Recursion (Factorial, Fibonacci)


Prompt: Create an ESP32 MicroPython program to demonstrate recursion with factorial and
Fibonacci sequence calculations.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def factorial(n):
print("factorial({})".format(n))
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)

def fibonacci(n):
print("fibonacci({})".format(n))
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

def fibonacci_iterative(n):
if n <= 1:
return n

a, b = 0, 1
for i in range(2, n + 1):
a, b = b, a + b
return b

print("Recursion - Factorial & Fibonacci")


print("=" * 50)

n=5
print("Factorial of", n)
print("-" * 50)
result = factorial(n)
print("Result:", result)
print("=" * 50)

n=6
print("Fibonacci of", n, "(Recursive)")
print("-" * 50)
result = fibonacci(n)
print("Result:", result)
print("=" * 50)

print("Fibonacci Sequence (Iterative):")


for i in range(10):
print("F({}) = {}".format(i, fibonacci_iterative(i)))

11. Sorting Algorithms (Basic)


Prompt: Create an ESP32 MicroPython program to implement basic sorting algorithms: Bubble
Sort, Selection Sort, and Insertion Sort with visualization.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def bubble_sort(arr):
n = len(arr)
print("Bubble Sort")
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
print("Swapped: {} <-> {}".format(arr[j + 1], arr[j]))
print("Pass {}: {}".format(i + 1, arr))
return arr

def selection_sort(arr):
n = len(arr)
print("Selection Sort")
for i in range(n):
min_idx = i
for j in range(i + 1, n):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
print("Pass {}: {}".format(i + 1, arr))
return arr

def insertion_sort(arr):
print("Insertion Sort")
for i in range(1, len(arr)):
key = arr[i]
j=i-1
while j >= 0 and arr[j] > key:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
print("Pass {}: {}".format(i, arr))
return arr

print("Basic Sorting Algorithms")


print("=" * 50)

arr1 = [64, 34, 25, 12, 22]


print("Original:", arr1)
print("-" * 50)
sorted_arr = bubble_sort([Link]())
print("Sorted:", sorted_arr)
print("=" * 50)

arr2 = [64, 25, 12, 22, 11]


print("Original:", arr2)
print("-" * 50)
sorted_arr = selection_sort([Link]())
print("Sorted:", sorted_arr)
print("=" * 50)

arr3 = [12, 11, 13, 5, 6]


print("Original:", arr3)
print("-" * 50)
sorted_arr = insertion_sort([Link]())
print("Sorted:", sorted_arr)
12. Sorting Algorithms (Merge, Quick)
Prompt: Create an ESP32 MicroPython program to implement advanced sorting algorithms:
Merge Sort and Quick Sort with divide-and-conquer approach.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def merge_sort(arr):
if len(arr) <= 1:
return arr

mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])

return merge(left, right)

def merge(left, right):


result = []
i=j=0

while i < len(left) and j < len(right):


if left[i] <= right[j]:
[Link](left[i])
i += 1
else:
[Link](right[j])
j += 1

[Link](left[i:])
[Link](right[j:])
print("Merged:", result)
return result

def quick_sort(arr):
if len(arr) <= 1:
return arr

pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]

print("Pivot: {} | Left: {} | Right: {}".format(pivot, left, right))

return quick_sort(left) + middle + quick_sort(right)

print("Advanced Sorting Algorithms")


print("=" * 50)

arr1 = [38, 27, 43, 3, 9, 82, 10]


print("Merge Sort")
print("Original:", arr1)
print("-" * 50)
sorted_arr = merge_sort([Link]())
print("Sorted:", sorted_arr)
print("=" * 50)

arr2 = [10, 7, 8, 9, 1, 5]
print("Quick Sort")
print("Original:", arr2)
print("-" * 50)
sorted_arr = quick_sort([Link]())
print("Sorted:", sorted_arr)

13. Prefix Sum Technique


Prompt: Create an ESP32 MicroPython program to implement prefix sum technique for efficient
range sum queries.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time
class PrefixSum:
def __init__(self, arr):
[Link] = arr
[Link] = [0] * (len(arr) + 1)
self.build_prefix()

def build_prefix(self):
print("Building prefix sum array...")
for i in range(len([Link])):
[Link][i + 1] = [Link][i] + [Link][i]
print("prefix[{}] = {}".format(i + 1, [Link][i + 1]))

def range_sum(self, left, right):


result = [Link][right + 1] - [Link][left]
print("Sum from index {} to {}: {}".format(left, right, result))
return result

def display(self):
print("Original array:", [Link])
print("Prefix sum:", [Link])

print("Prefix Sum Technique")


print("-" * 50)

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


ps = PrefixSum(arr)
[Link]()
print("-" * 50)

ps.range_sum(2, 5)
ps.range_sum(0, 9)
ps.range_sum(4, 7)
print("-" * 50)

print("Comparing with brute force:")


left, right = 2, 5
brute_sum = sum(arr[left:right + 1])
print("Brute force sum:", brute_sum)

14. Sliding Window Algorithm


Prompt: Create an ESP32 MicroPython program to implement sliding window algorithm for
maximum sum subarray and other window-based problems.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def max_sum_subarray(arr, k):


if len(arr) < k:
print("Array size less than window size")
return -1

window_sum = sum(arr[:k])
max_sum = window_sum

print("Initial window sum:", window_sum)


print("Window:", arr[:k])
print("-" * 50)

for i in range(len(arr) - k):


window_sum = window_sum - arr[i] + arr[i + k]
print("Window:", arr[i + 1:i + k + 1])
print("Window sum:", window_sum)

if window_sum > max_sum:


max_sum = window_sum
print("New max found!")

print("-" * 50)

return max_sum

def first_negative_in_window(arr, k):


result = []

for i in range(len(arr) - k + 1):


window = arr[i:i + k]
first_neg = None

for num in window:


if num < 0:
first_neg = num
break

[Link](first_neg if first_neg else 0)


print("Window: {} | First negative: {}".format(window, first_neg))

return result

print("Sliding Window Algorithm")


print("=" * 50)

arr = [1, 4, 2, 10, 23, 3, 1, 0, 20]


k=4
print("Array:", arr)
print("Window size:", k)
print("-" * 50)

max_sum = max_sum_subarray(arr, k)
print("Maximum sum of subarray:", max_sum)
print("=" * 50)

arr2 = [12, -1, -7, 8, -15, 30, 16, 28]


k2 = 3
print("Array:", arr2)
print("Window size:", k2)
print("-" * 50)

result = first_negative_in_window(arr2, k2)


print("First negatives:", result)

15. Hash Table Implementation


Prompt: Create an ESP32 MicroPython program to implement hash table with collision handling
using chaining method.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time
class HashTable:
def __init__(self, size):
[Link] = size
[Link] = [[] for _ in range(size)]

def hash_function(self, key):


return hash(key) % [Link]

def insert(self, key, value):


hash_index = self.hash_function(key)

for i, (k, v) in enumerate([Link][hash_index]):


if k == key:
[Link][hash_index][i] = (key, value)
print("Updated: {} -> {} at index {}".format(key, value, hash_index))
return

[Link][hash_index].append((key, value))
print("Inserted: {} -> {} at index {}".format(key, value, hash_index))

def search(self, key):


hash_index = self.hash_function(key)

for k, v in [Link][hash_index]:
if k == key:
print("Found: {} -> {}".format(key, v))
return v

print("Key not found:", key)


return None

def delete(self, key):


hash_index = self.hash_function(key)

for i, (k, v) in enumerate([Link][hash_index]):


if k == key:
del [Link][hash_index][i]
print("Deleted:", key)
return True

print("Key not found:", key)


return False
def display(self):
print("Hash Table:")
for i, bucket in enumerate([Link]):
if bucket:
print("Index {}: {}".format(i, bucket))

print("Hash Table Implementation")


print("-" * 50)

ht = HashTable(10)

[Link]("name", "ESP32")
[Link]("temp", 25)
[Link]("humidity", 60)
[Link]("pressure", 1013)
[Link]()
print("-" * 50)

[Link]("temp")
[Link]("voltage")
print("-" * 50)

[Link]("humidity")
[Link]()

16. Binary Tree Traversals


Prompt: Create an ESP32 MicroPython program to implement binary tree with inorder,
preorder, and postorder traversals.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class Node:
def __init__(self, data):
[Link] = data
[Link] = None
[Link] = None

class BinaryTree:
def __init__(self):
[Link] = None

def inorder(self, node):


if node:
[Link]([Link])
print([Link], end=" ")
[Link]([Link])

def preorder(self, node):


if node:
print([Link], end=" ")
[Link]([Link])
[Link]([Link])

def postorder(self, node):


if node:
[Link]([Link])
[Link]([Link])
print([Link], end=" ")

print("Binary Tree Traversals")


print("-" * 50)

tree = BinaryTree()
[Link] = Node(1)
[Link] = Node(2)
[Link] = Node(3)
[Link] = Node(4)
[Link] = Node(5)​
[Link] = Node(6) ​
[Link] = Node(7)

print("Tree Structure:")

print(" 1")

print(" / \\")

print(" 2 3")

print(" / \\ / \\")
print(" 4 5 6 7")

print("-" * 50)

print("Inorder (Left-Root-Right):", end=" ")

[Link]([Link])

print()

print("Preorder (Root-Left-Right):", end=" ")

[Link]([Link])

print()

print("Postorder (Left-Right-Root):", end=" ")

[Link]([Link])

print()

---

## 17. Binary Search Tree Operations

**Prompt:**
Create an ESP32 MicroPython program to implement Binary Search Tree with insertion,
searching, and deletion operations.

**Hardware Requirements:**
- ESP32 Development Board

**MicroPython Code:**
```python
import time

class Node:
def __init__(self, data):
[Link] = data
[Link] = None
[Link] = None

class BST:
def __init__(self):
[Link] = None

def insert(self, data):


if not [Link]:
[Link] = Node(data)
print("Inserted root:", data)
else:
self._insert_recursive([Link], data)

def _insert_recursive(self, node, data):


if data < [Link]:
if [Link] is None:
[Link] = Node(data)
print("Inserted {} to left of {}".format(data, [Link]))
else:
self._insert_recursive([Link], data)
else:
if [Link] is None:
[Link] = Node(data)
print("Inserted {} to right of {}".format(data, [Link]))
else:
self._insert_recursive([Link], data)

def search(self, data):


return self._search_recursive([Link], data)

def _search_recursive(self, node, data):


if node is None:
return False

if [Link] == data:
return True
elif data < [Link]:
return self._search_recursive([Link], data)
else:
return self._search_recursive([Link], data)
def inorder(self, node):
if node:
[Link]([Link])
print([Link], end=" ")
[Link]([Link])

print("Binary Search Tree Operations")


print("-" * 50)

bst = BST()

values = [50, 30, 70, 20, 40, 60, 80]


print("Inserting:", values)
print("-" * 50)

for val in values:


[Link](val)

print("-" * 50)
print("Inorder traversal:", end=" ")
[Link]([Link])
print()
print("-" * 50)

search_values = [40, 25, 80]


for val in search_values:
found = [Link](val)
print("Search {}: {}".format(val, "Found" if found else "Not Found"))

18. Heap (Min & Max)


Prompt: Create an ESP32 MicroPython program to implement Min Heap and Max Heap with
insertion, deletion, and heapify operations.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time
class MinHeap:
def __init__(self):
[Link] = []

def parent(self, i):


return (i - 1) // 2

def left_child(self, i):


return 2 * i + 1

def right_child(self, i):


return 2 * i + 2

def insert(self, key):


[Link](key)
self._heapify_up(len([Link]) - 1)
print("Inserted:", key)

def _heapify_up(self, i):


while i > 0 and [Link][[Link](i)] > [Link][i]:
[Link][i], [Link][[Link](i)] = [Link][[Link](i)], [Link][i]
i = [Link](i)

def extract_min(self):
if not [Link]:
return None

min_val = [Link][0]
[Link][0] = [Link][-1]
[Link]()

if [Link]:
self._heapify_down(0)

print("Extracted min:", min_val)


return min_val

def _heapify_down(self, i):


min_index = i
left = self.left_child(i)
right = self.right_child(i)

if left < len([Link]) and [Link][left] < [Link][min_index]:


min_index = left
if right < len([Link]) and [Link][right] < [Link][min_index]:
min_index = right

if min_index != i:
[Link][i], [Link][min_index] = [Link][min_index], [Link][i]
self._heapify_down(min_index)

def display(self):
print("Heap:", [Link])

print("Min Heap Implementation")


print("-" * 50)

min_heap = MinHeap()

values = [5, 3, 8, 1, 9, 2]
print("Inserting:", values)
for val in values:
min_heap.insert(val)
min_heap.display()

print("-" * 50)
print("Extracting minimum values:")
for _ in range(3):
min_heap.extract_min()
min_heap.display()

19. Priority Queue Scheduler


Prompt: Create an ESP32 MicroPython program to implement priority queue-based task
scheduler with priority levels.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class Task:
def __init__(self, name, priority):
[Link] = name
[Link] = priority

def __lt__(self, other):


return [Link] < [Link]

class PriorityQueue:
def __init__(self):
[Link] = []

def enqueue(self, task):


[Link](task)
[Link]()
print("Added task: {} (Priority: {})".format([Link], [Link]))

def dequeue(self):
if self.is_empty():
print("Queue is empty")
return None
task = [Link](0)
print("Executing task: {} (Priority: {})".format([Link], [Link]))
return task

def is_empty(self):
return len([Link]) == 0

def display(self):
print("Priority Queue:")
for task in [Link]:
print(" {} - Priority: {}".format([Link], [Link]))

print("Priority Queue Scheduler")


print("-" * 50)

scheduler = PriorityQueue()

[Link](Task("Read Sensor", 2))


[Link](Task("Emergency Stop", 1))
[Link](Task("Log Data", 5))
[Link](Task("Send Alert", 1))
[Link](Task("Update Display", 3))

print("-" * 50)
[Link]()
print("-" * 50)

print("Executing tasks in priority order:")


while not scheduler.is_empty():
[Link]()
[Link](1)

20. Graph Representation


Prompt: Create an ESP32 MicroPython program to implement graph representation using
adjacency list and adjacency matrix.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class Graph:
def __init__(self, vertices):
[Link] = vertices
self.adj_list = {i: [] for i in range(vertices)}
self.adj_matrix = [[0] * vertices for _ in range(vertices)]

def add_edge(self, u, v):


self.adj_list[u].append(v)
self.adj_list[v].append(u)

self.adj_matrix[u][v] = 1
self.adj_matrix[v][u] = 1

print("Added edge: {} - {}".format(u, v))

def display_adj_list(self):
print("Adjacency List:")
for vertex in range([Link]):
print("{}: {}".format(vertex, self.adj_list[vertex]))

def display_adj_matrix(self):
print("Adjacency Matrix:")
for row in self.adj_matrix:
print(row)

print("Graph Representation")
print("-" * 50)

g = Graph(5)

edges = [(0, 1), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (3, 4)]

print("Adding edges:")
for u, v in edges:
g.add_edge(u, v)

print("-" * 50)
g.display_adj_list()
print("-" * 50)
g.display_adj_matrix()

21. BFS & DFS Traversals


Prompt: Create an ESP32 MicroPython program to implement Breadth-First Search (BFS) and
Depth-First Search (DFS) graph traversal algorithms.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class Graph:
def __init__(self, vertices):
[Link] = vertices
self.adj_list = {i: [] for i in range(vertices)}

def add_edge(self, u, v):


self.adj_list[u].append(v)
self.adj_list[v].append(u)
def bfs(self, start):
visited = [False] * [Link]
queue = [start]
visited[start] = True

print("BFS Traversal from node {}:".format(start))

while queue:
vertex = [Link](0)
print("Visited:", vertex)

for neighbor in self.adj_list[vertex]:


if not visited[neighbor]:
[Link](neighbor)
visited[neighbor] = True
print(" Enqueued:", neighbor)

def dfs(self, start):


visited = [False] * [Link]
print("DFS Traversal from node {}:".format(start))
self._dfs_recursive(start, visited)

def _dfs_recursive(self, vertex, visited):


visited[vertex] = True
print("Visited:", vertex)

for neighbor in self.adj_list[vertex]:


if not visited[neighbor]:
print(" Moving to:", neighbor)
self._dfs_recursive(neighbor, visited)

print("BFS & DFS Traversals")


print("-" * 50)

g = Graph(6)

edges = [(0, 1), (0, 2), (1, 3), (1, 4), (2, 4), (3, 5), (4, 5)]
for u, v in edges:
g.add_edge(u, v)

print("Graph edges:", edges)


print("=" * 50)

[Link](0)
print("=" * 50)

[Link](0)

22. Dijkstra's Shortest Path


Prompt: Create an ESP32 MicroPython program to implement Dijkstra's algorithm for finding
shortest path in weighted graphs.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

class Graph:
def __init__(self, vertices):
[Link] = vertices
[Link] = [[0 for _ in range(vertices)] for _ in range(vertices)]

def add_edge(self, u, v, weight):


[Link][u][v] = weight
[Link][v][u] = weight
print("Added edge: {} - {} (weight: {})".format(u, v, weight))

def min_distance(self, dist, visited):


min_dist = float('inf')
min_index = -1

for v in range([Link]):
if dist[v] < min_dist and not visited[v]:
min_dist = dist[v]
min_index = v

return min_index

def dijkstra(self, src):


dist = [float('inf')] * [Link]
dist[src] = 0
visited = [False] * [Link]
print("Starting Dijkstra from node", src)
print("-" * 50)

for _ in range([Link]):
u = self.min_distance(dist, visited)
visited[u] = True

print("Visiting node:", u, "| Distance:", dist[u])

for v in range([Link]):
if ([Link][u][v] > 0 and not visited[v] and
dist[v] > dist[u] + [Link][u][v]):
dist[v] = dist[u] + [Link][u][v]
print(" Updated distance to {}: {}".format(v, dist[v]))

print("-" * 50)
print("Shortest distances from node {}:".format(src))
for i in range([Link]):
print("Node {}: {}".format(i, dist[i]))

print("Dijkstra's Shortest Path Algorithm")


print("-" * 50)

g = Graph(6)

g.add_edge(0, 1, 4)
g.add_edge(0, 2, 2)
g.add_edge(1, 2, 1)
g.add_edge(1, 3, 5)
g.add_edge(2, 3, 8)
g.add_edge(2, 4, 10)
g.add_edge(3, 4, 2)
g.add_edge(3, 5, 6)
g.add_edge(4, 5, 3)

print("-" * 50)
[Link](0)

23. Dynamic Programming (Knapsack)


Prompt: Create an ESP32 MicroPython program to implement 0/1 Knapsack problem using
dynamic programming approach.

Hardware Requirements:

●​ ESP32 Development Board

MicroPython Code:

import time

def knapsack(weights, values, capacity):


n = len(weights)
dp = [[0 for _ in range(capacity + 1)] for _ in range(n + 1)]

print("0/1 Knapsack Problem")


print("Capacity:", capacity)
print("Items:", n)
print("-" * 50)

for i in range(1, n + 1):


for w in range(1, capacity + 1):
if weights[i - 1] <= w:
dp[i][w] = max(values[i - 1] + dp[i - 1][w - weights[i - 1]],
dp[i - 1][w])
else:
dp[i][w] = dp[i - 1][w]

print("DP Table (last row):")


print(dp[n])
print("-" * 50)

selected = []
w = capacity
for i in range(n, 0, -1):
if dp[i][w] != dp[i - 1][w]:
[Link](i - 1)
w -= weights[i - 1]

[Link]()

print("Maximum value:", dp[n][capacity])


print("Selected items (0-indexed):", selected)
print("Total weight:", sum(weights[i] for i in selected))
print("-" * 50)
for i in selected:
print("Item {}: Weight={}, Value={}".format(i, weights[i], values[i]))

return dp[n][capacity]

print("Dynamic Programming - Knapsack")


print("=" * 50)

weights = [2, 3, 4, 5]
values = [3, 4, 5, 6]
capacity = 8

print("Weights:", weights)
print("Values:", values)
print("-" * 50)

max_value = knapsack(weights, values, capacity)

Math, Control & Signal Processing -


MicroPython Projects

1. Numerical Integration
Prompt: Create a MicroPython program that performs numerical integration using Trapezoidal
and Simpson's rules to calculate definite integrals of mathematical functions and sensor data.

Hardware Requirements:
●​ ESP32 Development Board / Raspberry Pi Pico / ESP8266
●​ No external components needed (computational only)
●​ USB cable for programming and power

Additional Details:

●​ Implements Trapezoidal rule for general integration


●​ Implements Simpson's 1/3 rule for higher accuracy
●​ Can integrate discrete sensor data points
●​ Useful for calculating areas, signal energy, and accumulated values
●​ Works with any mathematical function

MicroPython Code:

import math
import time

class NumericalIntegrator:
"""Numerical integration using Trapezoidal and Simpson's rules"""

@staticmethod
def trapezoidal(func, a, b, n=1000):
"""
Trapezoidal rule: Integral = h * [f(a)/2 + sum(f(x_i)) + f(b)/2]
func: function to integrate
a, b: integration limits
n: number of subdivisions
"""
h = (b - a) / n
result = 0.5 * (func(a) + func(b))

for i in range(1, n):


x=a+i*h
result += func(x)

return result * h

@staticmethod
def simpson(func, a, b, n=1000):
"""
Simpson's 1/3 rule (n must be even)
More accurate than trapezoidal for smooth functions
"""
if n % 2 == 1:
n += 1
h = (b - a) / n
result = func(a) + func(b)

for i in range(1, n, 2):


x=a+i*h
result += 4 * func(x)

for i in range(2, n-1, 2):


x=a+i*h
result += 2 * func(x)

return result * h / 3

@staticmethod
def integrate_data(data, dx=1.0):
"""
Integrate discrete data points using trapezoidal rule
data: list of y values
dx: spacing between points
"""
result = 0.0
for i in range(len(data) - 1):
result += (data[i] + data[i+1]) / 2.0 * dx
return result

# Test functions
def test_integration():
integrator = NumericalIntegrator()

print("=== Numerical Integration Test ===\n")

# Test 1: sin(x) from 0 to pi (exact = 2.0)


def sin_func(x):
return [Link](x)

result_trap = [Link](sin_func, 0, [Link], 1000)


result_simp = [Link](sin_func, 0, [Link], 1000)

print("Test 1: Integral of sin(x) from 0 to pi")


print(f" Trapezoidal: {result_trap:.6f}")
print(f" Simpson: {result_simp:.6f}")
print(f" Exact: 2.000000")
print(f" Error (Trap): {abs(result_trap - 2.0):.6f}")
print(f" Error (Simp): {abs(result_simp - 2.0):.6f}\n")

# Test 2: x^2 from 0 to 3 (exact = 9.0)


def square(x):
return x * x

result_trap2 = [Link](square, 0, 3, 1000)


result_simp2 = [Link](square, 0, 3, 1000)

print("Test 2: Integral of x^2 from 0 to 3")


print(f" Trapezoidal: {result_trap2:.6f}")
print(f" Simpson: {result_simp2:.6f}")
print(f" Exact: 9.000000\n")

# Test 3: Integrate sensor data


sensor_data = [0, 1, 4, 9, 16, 25, 36] # y = x^2
area = integrator.integrate_data(sensor_data, dx=1.0)
print("Test 3: Sensor data integration")
print(f" Data: {sensor_data}")
print(f" Area under curve: {area:.2f}\n")

print("Integration tests complete!")

# Run test
test_integration()

2. Numerical Differentiation
Prompt: Create a MicroPython program to calculate derivatives of functions and discrete sensor
data using finite difference methods for velocity calculation and rate of change analysis.

Hardware Requirements:

●​ ESP32 Development Board / Raspberry Pi Pico / ESP8266


●​ Optional: Accelerometer/Temperature sensor for real-time differentiation
●​ USB cable for programming

Additional Details:

●​ Forward, backward, and central difference methods


●​ Smoothing filter for noisy data
●​ Essential for calculating velocity from position data
●​ Used in control systems and signal processing
●​ Handles discrete sensor measurements

MicroPython Code:

import math
import time

class NumericalDifferentiator:
"""Numerical differentiation using finite differences"""

@staticmethod
def forward_difference(func, x, h=1e-5):
"""Forward difference: f'(x) ≈ (f(x+h) - f(x)) / h"""
return (func(x + h) - func(x)) / h

@staticmethod
def backward_difference(func, x, h=1e-5):
"""Backward difference: f'(x) ≈ (f(x) - f(x-h)) / h"""
return (func(x) - func(x - h)) / h

@staticmethod
def central_difference(func, x, h=1e-5):
"""Central difference: f'(x) ≈ (f(x+h) - f(x-h)) / (2h)"""
return (func(x + h) - func(x - h)) / (2 * h)

@staticmethod
def differentiate_data(data, dt=1.0, method='central'):
"""
Differentiate discrete data points
data: list of y values
dt: time step between samples
method: 'forward', 'backward', or 'central'
"""
n = len(data)
result = [0.0] * n

if method == 'forward':
for i in range(n - 1):
result[i] = (data[i+1] - data[i]) / dt
result[-1] = result[-2]

elif method == 'backward':


result[0] = result[1] if n > 1 else 0
for i in range(1, n):
result[i] = (data[i] - data[i-1]) / dt

else: # central
result[0] = (data[1] - data[0]) / dt if n > 1 else 0
for i in range(1, n - 1):
result[i] = (data[i+1] - data[i-1]) / (2 * dt)
result[-1] = (data[-1] - data[-2]) / dt if n > 1 else 0

return result

@staticmethod
def smooth_differentiate(data, dt=1.0, window=3):
"""
Differentiate with moving average smoothing
Reduces noise in derivative calculation
"""
smoothed = [0.0] * len(data)
half_window = window // 2

for i in range(len(data)):
start = max(0, i - half_window)
end = min(len(data), i + half_window + 1)
smoothed[i] = sum(data[start:end]) / (end - start)

return NumericalDifferentiator.differentiate_data(smoothed, dt, 'central')

# Test differentiation
def test_differentiation():
diff = NumericalDifferentiator()

print("=== Numerical Differentiation Test ===\n")

# Test 1: Derivative of x^2 at x=5 (exact = 2x = 10)


def square(x):
return x * x

x_test = 5.0
deriv_forward = diff.forward_difference(square, x_test)
deriv_backward = diff.backward_difference(square, x_test)
deriv_central = diff.central_difference(square, x_test)
exact = 2 * x_test

print(f"Test 1: Derivative of x^2 at x={x_test}")


print(f" Forward: {deriv_forward:.6f}")
print(f" Backward: {deriv_backward:.6f}")
print(f" Central: {deriv_central:.6f}")
print(f" Exact: {exact:.6f}")
print(f" Error (Central): {abs(deriv_central - exact):.9f}\n")

# Test 2: Position to velocity (x = t^2)


position = [0, 1, 4, 9, 16, 25, 36, 49] # t = 0,1,2,3,4,5,6,7
velocity = diff.differentiate_data(position, dt=1.0, method='central')

print("Test 2: Velocity from position (x = t^2)")


print(f" Position: {position}")
print(f" Velocity: {[f'{v:.1f}' for v in velocity]}")
print(f" Expected: [0, 2, 4, 6, 8, 10, 12, 14] (approx)\n")

# Test 3: Noisy data with smoothing


noisy_position = [0, 1.2, 3.8, 9.3, 15.7, 25.2, 35.8, 49.1]
velocity_noisy = diff.differentiate_data(noisy_position, dt=1.0, method='central')
velocity_smooth = diff.smooth_differentiate(noisy_position, dt=1.0, window=3)

print("Test 3: Noisy data differentiation")


print(f" Noisy data: {noisy_position}")
print(f" Direct diff: {[f'{v:.1f}' for v in velocity_noisy]}")
print(f" Smoothed diff: {[f'{v:.1f}' for v in velocity_smooth]}\n")

print("Differentiation tests complete!")

# Run test
test_differentiation()

3. FFT Spectrum Analyzer


Prompt: Create an ESP32 MicroPython program to perform Fast Fourier Transform (FFT) on
audio signals to analyze frequency content and detect dominant frequencies in real-time.

Hardware Requirements:

●​ ESP32 Development Board (needs sufficient RAM)


●​ MAX9814 or INMP441 Microphone Module
●​ Optional: 0.96" OLED Display (SSD1306) for spectrum visualization
●​ Connections:
○​ Microphone OUT → GPIO34 (ADC)
○​ OLED SDA → GPIO21, SCL → GPIO22
Additional Details:

●​ Implements Cooley-Tukey FFT algorithm


●​ Works best with power-of-2 sample sizes (64, 128, 256, 512)
●​ Calculates magnitude and power spectrum
●​ Identifies dominant frequency peaks
●​ Useful for audio processing, vibration analysis, signal detection

MicroPython Code:

import math
import time
from machine import Pin, ADC

class FFT:
"""Fast Fourier Transform implementation"""

@staticmethod
def fft(x):
"""
Cooley-Tukey FFT algorithm
x: complex input array (list of [real, imag] pairs)
Returns: complex output array
"""
N = len(x)

if N <= 1:
return x

# Divide
even = [Link]([x[i] for i in range(0, N, 2)])
odd = [Link]([x[i] for i in range(1, N, 2)])

# Conquer
T = []
for k in range(N // 2):
angle = -2 * [Link] * k / N
w_real = [Link](angle)
w_imag = [Link](angle)

# Complex multiplication: w * odd[k]


t_real = w_real * odd[k][0] - w_imag * odd[k][1]
t_imag = w_real * odd[k][1] + w_imag * odd[k][0]
[Link]([t_real, t_imag])
result = [[0, 0] for _ in range(N)]
for k in range(N // 2):
result[k][0] = even[k][0] + T[k][0]
result[k][1] = even[k][1] + T[k][1]
result[k + N//2][0] = even[k][0] - T[k][0]
result[k + N//2][1] = even[k][1] - T[k][1]

return result

@staticmethod
def magnitude_spectrum(fft_result):
"""Calculate magnitude spectrum from FFT result"""
return [[Link](r[0]**2 + r[1]**2) for r in fft_result]

@staticmethod
def power_spectrum(fft_result):
"""Calculate power spectrum from FFT result"""
return [r[0]**2 + r[1]**2 for r in fft_result]

@staticmethod
def find_dominant_frequency(signal, sample_rate):
"""
Find dominant frequency in signal
signal: real-valued input signal
sample_rate: sampling rate in Hz
Returns: (dominant_frequency, magnitude_spectrum)
"""
N = len(signal)

# Pad to power of 2
n_pow2 = 1
while n_pow2 < N:
n_pow2 *= 2

# Convert to complex
complex_signal = [[signal[i] if i < N else 0, 0] for i in range(n_pow2)]

# Perform FFT
fft_result = [Link](complex_signal)

# Calculate magnitude spectrum (only first half)


magnitudes = FFT.magnitude_spectrum(fft_result[:n_pow2//2])

# Find peak (skip DC component at index 0)


max_mag = 0
max_idx = 0
for i in range(1, len(magnitudes)):
if magnitudes[i] > max_mag:
max_mag = magnitudes[i]
max_idx = i

# Convert index to frequency


dominant_freq = max_idx * sample_rate / n_pow2

return dominant_freq, magnitudes

class SpectrumAnalyzer:
"""Real-time spectrum analyzer"""

def __init__(self, adc_pin, sample_rate=8000, fft_size=128):


"""
Initialize spectrum analyzer
adc_pin: GPIO pin number for ADC
sample_rate: sampling rate in Hz
fft_size: number of samples for FFT (power of 2)
"""
[Link] = ADC(Pin(adc_pin))
[Link](ADC.ATTN_11DB) # 0-3.3V range
[Link](ADC.WIDTH_12BIT) # 12-bit resolution

self.sample_rate = sample_rate
self.fft_size = fft_size
self.sample_period_us = int(1000000 / sample_rate)

def capture_samples(self):
"""Capture audio samples"""
samples = []
for _ in range(self.fft_size):
start = time.ticks_us()
sample = [Link]() - 2048 # Center around zero
[Link](sample)

# Wait for next sample


elapsed = time.ticks_diff(time.ticks_us(), start)
if elapsed < self.sample_period_us:
time.sleep_us(self.sample_period_us - elapsed)

return samples
def analyze(self):
"""
Capture and analyze spectrum
Returns: (dominant_freq, magnitudes, frequencies)
"""
# Capture samples
samples = self.capture_samples()

# Perform FFT
dominant_freq, magnitudes = FFT.find_dominant_frequency(samples, self.sample_rate)

# Calculate frequency bins


frequencies = [i * self.sample_rate / self.fft_size for i in range(len(magnitudes))]

return dominant_freq, magnitudes, frequencies

# Test with simulated data


def test_fft():
print("=== FFT Spectrum Analyzer Test ===\n")

# Generate test signal: 440 Hz (A4 note) + 880 Hz (A5 note)


sample_rate = 8000 # Hz
duration = 0.125 # seconds
N = int(sample_rate * duration)

print(f"Generating test signal:")


print(f" Sample rate: {sample_rate} Hz")
print(f" Duration: {duration} s")
print(f" Samples: {N}")
print(f" Frequencies: 440 Hz + 880 Hz\n")

signal = []
for i in range(N):
t = i / sample_rate
value = [Link](2 * [Link] * 440 * t) + 0.5 * [Link](2 * [Link] * 880 * t)
[Link](value)

# Perform FFT analysis


dominant_freq, spectrum = FFT.find_dominant_frequency(signal, sample_rate)

print(f"Dominant frequency detected: {dominant_freq:.2f} Hz")


print(f"Expected: 440 Hz\n")
# Find top frequency components
n = len(spectrum)
freqs = [i * sample_rate / (2 * n) for i in range(n)]

# Sort by magnitude
indexed_spectrum = [(i, spectrum[i]) for i in range(len(spectrum))]
indexed_spectrum.sort(key=lambda x: x[1], reverse=True)

print("Top 5 frequency components:")


for i in range(min(5, len(indexed_spectrum))):
idx, mag = indexed_spectrum[i]
if idx > 0: # Skip DC
print(f" {freqs[idx]:.2f} Hz: magnitude {mag:.2f}")

print("\nFFT test complete!")

# Run test
test_fft()

# Real-time analyzer example (uncomment to use with microphone)


"""
# Initialize spectrum analyzer
analyzer = SpectrumAnalyzer(adc_pin=34, sample_rate=8000, fft_size=128)

print("Real-time Spectrum Analyzer Started")


print("Press Ctrl+C to stop\n")

try:
while True:
# Analyze spectrum
dominant_freq, magnitudes, frequencies = [Link]()

# Display results
print(f"Dominant: {dominant_freq:.1f} Hz", end=" | ")

# Show spectrum bars (simple text visualization)


max_mag = max(magnitudes[1:20]) if max(magnitudes[1:20]) > 0 else 1
for i in range(1, 20, 2):
bar_height = int(10 * magnitudes[i] / max_mag)
print("#" * bar_height, end=" ")
print()

[Link](0.1)
except KeyboardInterrupt:
print("\nAnalyzer stopped")
"""

4. FIR Digital Filter


Prompt: Create a MicroPython program implementing Finite Impulse Response (FIR) digital
filters for signal processing, noise removal, and frequency band extraction from sensor data.

Hardware Requirements:

●​ ESP32 Development Board / Raspberry Pi Pico


●​ Analog sensor (accelerometer, microphone, temperature sensor, etc.)
●​ Optional: Signal generator for testing
●​ Connections: Sensor analog output → GPIO34/35 (ADC pins)

Additional Details:

●​ Implements lowpass, highpass, and bandpass filters


●​ Uses windowed sinc method for filter design
●​ Linear phase response (no signal distortion)
●​ Circular buffer for efficient real-time filtering
●​ Configurable filter order and cutoff frequencies

MicroPython Code:

import math
import time
from machine import Pin, ADC

class FIRFilter:
"""Finite Impulse Response (FIR) Digital Filter"""

def __init__(self, coefficients):


"""
Initialize FIR filter with coefficients
coefficients: filter tap weights (list)
"""
[Link] = coefficients
[Link] = [0.0] * len(coefficients)
[Link] = 0

def filter(self, sample):


"""
Process one sample through the filter
sample: input sample value
Returns: filtered output
"""
# Add new sample to circular buffer
[Link][[Link]] = sample
[Link] = ([Link] + 1) % len([Link])

# Calculate output (convolution)


output = 0.0
buf_idx = [Link]

for coef in [Link]:


buf_idx = (buf_idx - 1) % len([Link])
output += coef * [Link][buf_idx]

return output

def filter_signal(self, signal):


"""Filter entire signal array"""
return [[Link](s) for s in signal]

def reset(self):
"""Clear filter state"""
[Link] = [0.0] * len([Link])
[Link] = 0

@staticmethod
def design_lowpass(cutoff_freq, sample_rate, num_taps=51):
"""
Design lowpass FIR filter using windowed sinc method
cutoff_freq: -3dB frequency in Hz
sample_rate: sampling rate in Hz
num_taps: number of filter coefficients (odd number recommended)
Returns: list of filter coefficients
"""
if num_taps % 2 == 0:
num_taps += 1

# Normalize cutoff frequency


fc = cutoff_freq / sample_rate

# Generate sinc function


coefficients = []
M = (num_taps - 1) // 2

for n in range(num_taps):
m=n-M
if m == 0:
h = 2 * fc
else:
h = [Link](2 * [Link] * fc * m) / ([Link] * m)

# Apply Hamming window


window = 0.54 - 0.46 * [Link](2 * [Link] * n / (num_taps - 1))
[Link](h * window)

# Normalize to unity gain at DC


total = sum(coefficients)
coefficients = [c / total for c in coefficients]

return coefficients

@staticmethod
def design_highpass(cutoff_freq, sample_rate, num_taps=51):
"""
Design highpass FIR filter using spectral inversion
cutoff_freq: -3dB frequency in Hz
sample_rate: sampling rate in Hz
num_taps: number of filter coefficients
Returns: list of filter coefficients
"""
# Design lowpass filter
lp_coef = FIRFilter.design_lowpass(cutoff_freq, sample_rate, num_taps)

# Spectral inversion
hp_coef = [-c for c in lp_coef]
hp_coef[len(hp_coef)//2] += 1

return hp_coef

@staticmethod
def design_bandpass(low_freq, high_freq, sample_rate, num_taps=51):
"""
Design bandpass FIR filter
low_freq: lower cutoff frequency in Hz
high_freq: upper cutoff frequency in Hz
sample_rate: sampling rate in Hz
num_taps: number of filter coefficients
Returns: list of filter coefficients
"""
# Design two lowpass filters and subtract
lp1 = FIRFilter.design_lowpass(high_freq, sample_rate, num_taps)
lp2 = FIRFilter.design_lowpass(low_freq, sample_rate, num_taps)

bp_coef = [lp1[i] - lp2[i] for i in range(num_taps)]

return bp_coef

# Test FIR filter


def test_fir_filter():
print("=== FIR Digital Filter Test ===\n")

# Filter parameters
sample_rate = 1000 # Hz
cutoff = 50 # Hz
num_taps = 31

print(f"Filter Design:")
print(f" Type: Lowpass")
print(f" Cutoff: {cutoff} Hz")
print(f" Sample rate: {sample_rate} Hz")
print(f" Number of taps: {num_taps}\n")

# Design lowpass filter


coefficients = FIRFilter.design_lowpass(cutoff, sample_rate, num_taps)
fir = FIRFilter(coefficients)

print(f"First 5 coefficients: {[f'{c:.6f}' for c in coefficients[:5]]}")


print(f"Last 5 coefficients: {[f'{c:.6f}' for c in coefficients[-5:]]}\n")

# Generate test signal: 25 Hz (pass) + 150 Hz (reject) + noise


print("Generating test signal:")
print(" 25 Hz sine wave (should pass)")
print(" 150 Hz sine wave (should be rejected)")

N = 500
signal = []
for i in range(N):
t = i / sample_rate
s = ([Link](2 * [Link] * 25 * t) +
0.5 * [Link](2 * [Link] * 150 * t))
[Link](s)

# Filter signal
filtered = fir.filter_signal(signal)

# Calculate energy (simple measure of amplitude)


original_energy = sum(s**2 for s in signal) / N
filtered_energy = sum(s**2 for s in filtered) / N

print(f"\nResults:")
print(f" Original signal energy: {original_energy:.4f}")
print(f" Filtered signal energy: {filtered_energy:.4f}")
print(f" Energy reduction: {(1 - filtered_energy/original_energy)*100:.1f}%")
print(" (High frequency component should be attenuated)\n")

# Test highpass filter


print("Highpass Filter Design:")
hp_coef = FIRFilter.design_highpass(cutoff, sample_rate, num_taps)
print(f" Cutoff: {cutoff} Hz")
print(f" Coefficients designed: {len(hp_coef)}\n")

# Test bandpass filter


print("Bandpass Filter Design:")
bp_coef = FIRFilter.design_bandpass(40, 60, sample_rate, num_taps)
print(f" Passband: 40-60 Hz")
print(f" Coefficients designed: {len(bp_coef)}\n")

print("FIR filter test complete!")

# Run test
test_fir_filter()

# Real-time filtering example (uncomment to use with sensor)


"""
# Initialize ADC for sensor
adc = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
[Link](ADC.WIDTH_12BIT)

# Design filter
sample_rate = 100 # Hz
cutoff = 10 # Hz
coefficients = FIRFilter.design_lowpass(cutoff, sample_rate, num_taps=31)
fir_filter = FIRFilter(coefficients)

print("Real-time FIR Filtering Started")


print("Reading from ADC and filtering...")

try:
while True:
# Read sensor
raw_value = [Link]()

# Filter value
filtered_value = fir_filter.filter(raw_value)

print(f"Raw: {raw_value:4d} | Filtered: {filtered_value:7.2f}")

[Link](1.0 / sample_rate)

except KeyboardInterrupt:
print("\nFiltering stopped")
"""

5. IIR Digital Filter


Prompt: Create a MicroPython program implementing Infinite Impulse Response (IIR) digital
filters including Butterworth filters for efficient real-time signal processing with fewer coefficients
than FIR.

Hardware Requirements:

●​ ESP32 Development Board / Raspberry Pi Pico / ESP8266


●​ Analog sensor (accelerometer, temperature, microphone, etc.)
●​ Optional: Potentiometer for cutoff frequency adjustment
●​ Connections: Sensor → GPIO34 (ADC)

Additional Details:

●​ More computationally efficient than FIR filters


●​ Implements Butterworth lowpass and highpass filters
●​ Uses bilinear transform for digital filter design
●​ Direct Form II structure for stability
●​ Exponential moving average for simple smoothing
MicroPython Code:

import math
import time
from machine import Pin, ADC

class IIRFilter:
"""Infinite Impulse Response (IIR) Digital Filter - Direct Form II"""

def __init__(self, b_coeffs, a_coeffs):


"""
Initialize IIR filter
b_coeffs: numerator coefficients [b0, b1, b2, ...]
a_coeffs: denominator coefficients [a0, a1, a2, ...]
H(z) = (b0 + b1*z^-1 + b2*z^-2 + ...) / (a0 + a1*z^-1 + a2*z^-2 + ...)
"""
# Normalize by a0
a0 = a_coeffs[0]
self.b = [b / a0 for b in b_coeffs]
self.a = [a / a0 for a in a_coeffs[1:]] # Skip a0 (now 1)

# State variables for Direct Form II


self.w = [0.0] * max(len(self.b), len(self.a) + 1)

def filter(self, sample):


"""
Process one sample through the filter
sample: input sample
Returns: filtered output
"""
# Calculate current state (feedback)
w0 = sample
for i in range(len(self.a)):
w0 -= self.a[i] * self.w[i]

# Calculate output (feedforward)


output = self.b[0] * w0
for i in range(1, len(self.b)):
if i <= len(self.w):
output += self.b[i] * self.w[i-1]

# Shift state variables


for i in range(len(self.w) - 1, 0, -1):
self.w[i] = self.w[i-1]
self.w[0] = w0

return output

def filter_signal(self, signal):


"""Filter entire signal array"""
return [[Link](s) for s in signal]

def reset(self):
"""Clear filter state"""
self.w = [0.0] * len(self.w)

@staticmethod
def butterworth_lowpass(cutoff_freq, sample_rate, order=2):
"""
Design Butterworth lowpass filter using bilinear transform
cutoff_freq: -3dB frequency in Hz
sample_rate: sampling rate in Hz
order: filter order (1 or 2)
Returns: (b_coeffs, a_coeffs)
"""
# Pre-warp frequency
omega = 2 * [Link] * cutoff_freq
T = 1.0 / sample_rate
omega_d = 2 / T * [Link](omega * T / 2)

if order == 1:
# First order: H(s) = 1 / (1 + s/ωc)
K = omega_d * T / 2
b = [K, K]
a = [1 + K, K - 1]

else: # order == 2
# Second order: H(s) = 1 / (1 + √2*s/ωc + (s/ωc)^2)
K = omega_d * T / 2
sqrt2 = [Link](2)
K2 = K * K

b = [K2, 2*K2, K2]


a = [1 + sqrt2*K + K2, 2*K2 - 2, 1 - sqrt2*K + K2]

return b, a

@staticmethod
def butterworth_highpass(cutoff_freq, sample_rate, order=2):
"""
Design Butterworth highpass filter
cutoff_freq: -3dB frequency in Hz
sample_rate: sampling rate in Hz
order: filter order (1 or 2)
Returns: (b_coeffs, a_coeffs)
"""
omega = 2 * [Link] * cutoff_freq
T = 1.0 / sample_rate
omega_d = 2 / T * [Link](omega * T / 2)

if order == 1:
K = omega_d * T / 2
b = [1, -1]
a = [1 + K, K - 1]

else: # order == 2
K = omega_d * T / 2
sqrt2 = [Link](2)
K2 = K * K

b = [1, -2, 1]
a = [1 + sqrt2*K + K2, 2*K2 - 2, 1 - sqrt2*K + K2]

return b, a

@staticmethod
def exponential_moving_average(alpha):
"""
Design exponential moving average (EMA) filter
alpha: smoothing factor (0 < alpha < 1)
Higher alpha = more responsive, lower alpha = smoother
H(z) = alpha / (1 - (1-alpha)*z^-1)
Returns: (b_coeffs, a_coeffs)
"""
b = [alpha]
a = [1, -(1 - alpha)]
return b, a

# Test IIR filter


def test_iir_filter():
print("=== IIR Digital Filter Test ===\n")
# Filter parameters
sample_rate = 1000 # Hz
cutoff = 50 # Hz
order = 2

print(f"Butterworth Lowpass Filter Design:")


print(f" Cutoff: {cutoff} Hz")
print(f" Sample rate: {sample_rate} Hz")
print(f" Order: {order}\n")

# Design 2nd order Butterworth lowpass


b, a = IIRFilter.butterworth_lowpass(cutoff, sample_rate, order=2)
iir = IIRFilter(b, a)

print(f"Filter Coefficients:")
print(f" B (numerator): {[f'{c:.6f}' for c in b]}")
print(f" A (denominator): {[f'{c:.6f}' for c in a]}\n")

# Generate test signal: 25 Hz (pass) + 150 Hz (reject)


print("Generating test signal:")
print(" 25 Hz sine wave (should pass)")
print(" 150 Hz sine wave (should be rejected)\n")

N = 500
signal = []
for i in range(N):
t = i / sample_rate
s = ([Link](2 * [Link] * 25 * t) +
0.5 * [Link](2 * [Link] * 150 * t))
[Link](s)

# Filter signal
filtered = iir.filter_signal(signal)

# Calculate energy
original_energy = sum(s**2 for s in signal) / N
filtered_energy = sum(s**2 for s in filtered) / N

print(f"Results:")
print(f" Original signal energy: {original_energy:.4f}")
print(f" Filtered signal energy: {filtered_energy:.4f}")
print(f" Energy reduction: {(1 - filtered_energy/original_energy)*100:.1f}%\n")
# Test highpass filter
print("Butterworth Highpass Filter Design:")
b_hp, a_hp = IIRFilter.butterworth_highpass(cutoff, sample_rate, order=2)
print(f" Cutoff: {cutoff} Hz")
print(f" B coefficients: {len(b_hp)}, A coefficients: {len(a_hp)}\n")

# Test EMA filter


print("Exponential Moving Average Filter Design:")
alpha = 0.1
b_ema, a_ema = IIRFilter.exponential_moving_average(alpha)
ema = IIRFilter(b_ema, a_ema)
print(f" Alpha (smoothing factor): {alpha}")
print(f" Lower alpha = smoother, Higher alpha = more responsive\n")

# Test EMA on noisy data


noisy_signal = [10 + (i % 3 - 1) * 2 for i in range(20)]
smoothed = ema.filter_signal(noisy_signal)

print("EMA Smoothing Example:")


print(f" Noisy: {noisy_signal[:10]}")
print(f" Smoothed: {['{:.2f}'.format(s) for s in smoothed[:10]]}")

print("\nIIR filter test complete!")

# Run test
test_iir_filter()

# Real-time filtering example (uncomment to use with sensor)


"""
# Initialize ADC
adc = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
[Link](ADC.WIDTH_12BIT)

# Design filter (Butterworth 2nd order lowpass)


sample_rate = 100 # Hz
cutoff = 10 # Hz
b, a = IIRFilter.butterworth_lowpass(cutoff, sample_rate, order=2)
iir_filter = IIRFilter(b, a)

print("Real-time IIR Filtering Started")


print(f"Butterworth Lowpass: {cutoff} Hz cutoff\n")
try:
while True:
# Read sensor
raw_value = [Link]()

# Filter value
filtered_value = iir_filter.filter(raw_value)

print(f"Raw: {raw_value:4d} | Filtered: {filtered_value:7.2f}")

[Link](1.0 / sample_rate)

except KeyboardInterrupt:
print("\nFiltering stopped")
"""

6. PID Motor Speed Controller


Prompt: Create an ESP32 MicroPython program for precise DC motor speed control using PID
algorithm with rotary encoder feedback for robotics and automation applications.

Hardware Requirements:

●​ ESP32 Development Board


●​ DC Motor with Rotary Encoder (e.g., JGA25-370 with encoder)
●​ L298N Motor Driver Module (or TB6612FNG)
●​ 12V Power Supply for motor
●​ Connections:
○​ Encoder A → GPIO18
○​ Encoder B → GPIO19
○​ Motor PWM → GPIO25
○​ Motor DIR1 → GPIO26
○​ Motor DIR2 → GPIO27

Additional Details:

●​ Uses quadrature encoder for speed measurement


●​ PID control for precise RPM control
●​ Bidirectional motor control
●​ Handles encoder interrupts for accurate counting
●​ Anti-windup and derivative filtering included
MicroPython Code:

import time
from machine import Pin, PWM

class Encoder:
"""Quadrature encoder reader for speed measurement"""

def __init__(self, pin_a, pin_b, ppr=20):


"""
Initialize encoder
pin_a, pin_b: encoder channel A and B pins
ppr: pulses per revolution (encoder resolution)
"""
self.pin_a = Pin(pin_a, [Link], Pin.PULL_UP)
self.pin_b = Pin(pin_b, [Link], Pin.PULL_UP)
[Link] = ppr

[Link] = 0
self.last_time = time.ticks_ms()
[Link] = 0

# Setup interrupt on channel A


self.pin_a.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING,
handler=self._encoder_callback)

def _encoder_callback(self, pin):


"""Encoder interrupt handler"""
# Determine direction based on channel B state
if self.pin_a.value() == self.pin_b.value():
[Link] += 1 # Forward
else:
[Link] -= 1 # Reverse

def get_rpm(self):
"""
Calculate RPM based on encoder counts
Call this periodically (e.g., every 100ms)
Returns: current RPM
"""
current_time = time.ticks_ms()
dt = time.ticks_diff(current_time, self.last_time) / 1000.0 # seconds

if dt > 0:
# RPM = (counts / ppr) * (60 / dt)
[Link] = ([Link] / [Link]) * (60.0 / dt)
[Link] = 0
self.last_time = current_time

return [Link]

def reset(self):
"""Reset encoder count"""
[Link] = 0
self.last_time = time.ticks_ms()

class MotorDriver:
"""DC Motor driver with PWM and direction control"""

def __init__(self, pwm_pin, dir_pin1, dir_pin2):


"""
Initialize motor driver
pwm_pin: PWM pin for speed control
dir_pin1, dir_pin2: direction control pins
"""
[Link] = PWM(Pin(pwm_pin))
[Link](1000) # 1 kHz PWM

self.dir1 = Pin(dir_pin1, [Link])


self.dir2 = Pin(dir_pin2, [Link])

[Link]()

def set_speed(self, speed):


"""
Set motor speed
speed: -100 to +100 (negative = reverse, positive = forward)
"""
# Determine direction
if speed > 0:
[Link](1)
[Link](0)
elif speed < 0:
[Link](0)
[Link](1)
speed = -speed
else:
[Link]()
return

# Set PWM duty cycle (0-1023)


duty = int(abs(speed) * 10.23)
duty = max(0, min(1023, duty))
[Link](duty)

def stop(self):
"""Stop motor (brake)"""
[Link](0)
[Link](0)
[Link](0)

def coast(self):
"""Coast motor (no brake)"""
[Link](0)

class PIDController:
"""PID Controller for motor speed control"""

def __init__(self, kp, ki, kd, setpoint=0, output_limits=(-100, 100)):


"""
Initialize PID controller
kp, ki, kd: PID gains
setpoint: target speed (RPM)
output_limits: (min, max) motor power percentage
"""
[Link] = kp
[Link] = ki
[Link] = kd
[Link] = setpoint
self.output_min, self.output_max = output_limits

[Link] = 0.0
self.prev_error = 0.0
self.prev_time = time.ticks_ms()
self.derivative_filtered = 0.0
self.derivative_filter_alpha = 0.1

def compute(self, measurement):


"""
Compute PID output
measurement: current speed (RPM)
Returns: motor power (-100 to +100)
"""
current_time = time.ticks_ms()
dt = time.ticks_diff(current_time, self.prev_time) / 1000.0

if dt <= 0:
return 0

# Calculate error
error = [Link] - measurement

# Proportional term
p_term = [Link] * error

# Integral term with anti-windup


[Link] += error * dt
i_term = [Link] * [Link]

# Derivative term with filtering


derivative = (error - self.prev_error) / dt
self.derivative_filtered = (self.derivative_filter_alpha * derivative +
(1 - self.derivative_filter_alpha) * self.derivative_filtered)
d_term = [Link] * self.derivative_filtered

# Calculate output
output = p_term + i_term + d_term

# Apply limits with anti-windup


if output > self.output_max:
output = self.output_max
[Link] -= error * dt
elif output < self.output_min:
output = self.output_min
[Link] -= error * dt

self.prev_error = error
self.prev_time = current_time

return output

def set_setpoint(self, setpoint):


"""Update target setpoint"""
[Link] = setpoint

def reset(self):
"""Reset controller state"""
[Link] = 0.0
self.prev_error = 0.0
self.derivative_filtered = 0.0
self.prev_time = time.ticks_ms()

class MotorSpeedController:
"""Motor speed control system using PID"""

def __init__(self, encoder_a, encoder_b, pwm_pin, dir_pin1, dir_pin2,


ppr=20, kp=0.5, ki=0.1, kd=0.05):
"""
Initialize motor speed controller
encoder_a, encoder_b: encoder pins
pwm_pin, dir_pin1, dir_pin2: motor driver pins
ppr: encoder pulses per revolution
kp, ki, kd: PID gains
"""
[Link] = Encoder(encoder_a, encoder_b, ppr)
[Link] = MotorDriver(pwm_pin, dir_pin1, dir_pin2)
[Link] = PIDController(kp, ki, kd, setpoint=0, output_limits=(-100, 100))

self.current_rpm = 0
[Link] = False

def set_speed(self, target_rpm):


"""Set target speed in RPM"""
[Link].set_setpoint(target_rpm)
print(f"Target speed set to: {target_rpm} RPM")

def update(self):
"""
Update controller (call periodically at ~10-20Hz)
Returns: (current_rpm, motor_power)
"""
# Measure current speed
self.current_rpm = [Link].get_rpm()

if not [Link]:
[Link]()
return self.current_rpm, 0

# Compute PID output


motor_power = [Link](self.current_rpm)
# Apply to motor
[Link].set_speed(motor_power)

return self.current_rpm, motor_power

def start(self):
"""Start speed control"""
[Link] = True
[Link]()
[Link]()
print("Motor speed control started")

def stop(self):
"""Stop speed control"""
[Link] = False
[Link]()
print("Motor speed control stopped")

def tune_pid(self, kp, ki, kd):


"""Update PID parameters"""
[Link] = kp
[Link] = ki
[Link] = kd
print(f"PID tuned: Kp={kp}, Ki={ki}, Kd={kd}")

# Main program
print("=== PID Motor Speed Controller ===\n")

# Initialize controller
# Encoder: A=GPIO18, B=GPIO19
# Motor: PWM=GPIO25, DIR1=GPIO26, DIR2=GPIO27
controller = MotorSpeedController(
encoder_a=18,
encoder_b=19,
pwm_pin=25,
dir_pin1=26,
dir_pin2=27,
ppr=20, # Pulses per revolution
kp=0.5, # Proportional gain
ki=0.1, # Integral gain
kd=0.05 # Derivative gain
)
# Set target speed
target_rpm = 100 # RPM
controller.set_speed(target_rpm)

# Start control
[Link]()

print(f"Target: {target_rpm} RPM")


print(f"PID Gains: Kp={[Link]}, Ki={[Link]}, Kd={[Link]}")
print("\nTime(s) | RPM | Power(%) | Error(RPM)")
print("-" * 50)

try:
start_time = [Link]()

while True:
# Update controller
rpm, power = [Link]()

# Calculate error
error = target_rpm - rpm

# Display status
elapsed = [Link]() - start_time
print(f"{elapsed:7.1f} | {rpm:4.0f} | {power:8.1f} | {error:10.1f}")

# Wait for next update (100ms = 10Hz)


[Link](0.1)

except KeyboardInterrupt:
print("\n\nStopping motor controller...")
[Link]()
print("Controller stopped.")

7. Kalman Filter (Sensor Fusion)


Prompt: Create a MicroPython program implementing Kalman Filter for optimal sensor fusion,
combining noisy measurements from multiple sensors (accelerometer, gyroscope, GPS) to
estimate true system state.

Hardware Requirements:
●​ ESP32 Development Board / Raspberry Pi Pico
●​ MPU6050 (Accelerometer + Gyroscope) / IMU sensor
●​ Optional: GPS module, Temperature sensor
●​ Optional: OLED display for visualization

Connections:

●​ MPU6050 → I2C (SCL: GPIO22, SDA: GPIO21)


●​ GPS → UART (TX: GPIO16, RX: GPIO17)

Additional Details:

●​ Optimal state estimation with uncertainty quantification


●​ Recursive filter for real-time processing
●​ Prediction and update steps (measurement correction)
●​ Sensor fusion for position, velocity, or orientation
●​ Handles measurement noise and process uncertainty

MicroPython Code:

import math
import time
from machine import Pin, I2C

class KalmanFilter:
"""1D Kalman Filter for optimal state estimation"""

def __init__(self, process_variance, measurement_variance,


initial_value=0.0, initial_estimate_error=1.0):
"""
Initialize Kalman Filter
process_variance (Q): uncertainty in the process/model
measurement_variance (R): uncertainty in measurements
initial_value: initial state estimate
initial_estimate_error (P): initial estimation error
"""
self.q = process_variance # Process noise covariance
self.r = measurement_variance # Measurement noise covariance
self.x = initial_value # State estimate
self.p = initial_estimate_error # Estimation error covariance

def update(self, measurement):


"""
Update filter with new measurement
Prediction step:
x_pred = x (assuming constant model)
p_pred = p + q

Update step:
K = p_pred / (p_pred + r) # Kalman gain
x = x_pred + K * (z - x_pred)
p = (1 - K) * p_pred
"""
# Prediction
x_pred = self.x
p_pred = self.p + self.q

# Update with measurement


kalman_gain = p_pred / (p_pred + self.r)
self.x = x_pred + kalman_gain * (measurement - x_pred)
self.p = (1 - kalman_gain) * p_pred

return self.x

def update_with_control(self, measurement, control_input, control_matrix=1.0):


"""Update with control input (e.g., known acceleration)"""
# Prediction with control
x_pred = self.x + control_matrix * control_input
p_pred = self.p + self.q

# Update
kalman_gain = p_pred / (p_pred + self.r)
self.x = x_pred + kalman_gain * (measurement - x_pred)
self.p = (1 - kalman_gain) * p_pred

return self.x

def get_state(self):
"""Return current state estimate"""
return self.x

def get_uncertainty(self):
"""Return current estimation uncertainty"""
return self.p

class KalmanFilter2D:
"""2D Kalman Filter for position and velocity tracking"""
def __init__(self, dt, process_variance, measurement_variance):
"""
Initialize 2D Kalman Filter for constant velocity model
dt: time step
State: [position, velocity]
"""
[Link] = dt

# State transition matrix (constant velocity model)


self.F = [[1, dt],
[0, 1]]

# Measurement matrix (we measure position only)


self.H = [[1, 0]]

# Process noise covariance


self.Q = [[process_variance * dt**4 / 4, process_variance * dt**3 / 2],
[process_variance * dt**3 / 2, process_variance * dt**2]]

# Measurement noise covariance


self.R = [[measurement_variance]]

# State estimate [position, velocity]


self.x = [[0.0], [0.0]]

# Estimation error covariance


self.P = [[1.0, 0.0],
[0.0, 1.0]]

def predict(self):
"""Prediction step"""
# x_pred = F * x
x_new = [[0.0], [0.0]]
for i in range(2):
for j in range(2):
x_new[i][0] += self.F[i][j] * self.x[j][0]
self.x = x_new

# P_pred = F * P * F^T + Q
FP = [[0.0, 0.0], [0.0, 0.0]]
for i in range(2):
for j in range(2):
for k in range(2):
FP[i][j] += self.F[i][k] * self.P[k][j]

P_new = [[0.0, 0.0], [0.0, 0.0]]


for i in range(2):
for j in range(2):
for k in range(2):
P_new[i][j] += FP[i][k] * self.F[j][k]
P_new[i][j] += self.Q[i][j]
self.P = P_new

def update(self, measurement):


"""Update step with measurement"""
# Innovation: y = z - H * x
Hx = self.H[0][0] * self.x[0][0] + self.H[0][1] * self.x[1][0]
y = measurement - Hx

# Innovation covariance: S = H * P * H^T + R


HP = [0.0, 0.0]
for j in range(2):
HP[j] = self.H[0][0] * self.P[0][j] + self.H[0][1] * self.P[1][j]

S = HP[0] * self.H[0][0] + HP[1] * self.H[0][1] + self.R[0][0]

# Kalman gain: K = P * H^T * S^-1


K = [[0.0], [0.0]]
for i in range(2):
K[i][0] = (self.P[i][0] * self.H[0][0] + self.P[i][1] * self.H[0][1]) / S

# Update state: x = x + K * y
for i in range(2):
self.x[i][0] += K[i][0] * y

# Update covariance: P = (I - K * H) * P
KH = [[K[0][0] * self.H[0][0], K[0][0] * self.H[0][1]],
[K[1][0] * self.H[0][0], K[1][0] * self.H[0][1]]]

P_new = [[0.0, 0.0], [0.0, 0.0]]


for i in range(2):
for j in range(2):
I_KH = (1.0 if i == j else 0.0) - KH[i][j]
for k in range(2):
P_new[i][j] += I_KH * self.P[k][j] if k == i else KH[i][k] * self.P[k][j]
self.P = P_new
def get_position(self):
"""Return estimated position"""
return self.x[0][0]

def get_velocity(self):
"""Return estimated velocity"""
return self.x[1][0]

# Test Kalman Filter


def test_kalman_filter():
print("=== Kalman Filter Test ===\n")

# Simulate noisy sensor measuring constant value


print("Test 1: Constant Value Estimation")
print("True value: 100.0")
print("Measurement noise: ±10.0\n")

true_value = 100.0
kf = KalmanFilter(
process_variance=0.01, # Low process noise (nearly constant)
measurement_variance=100.0, # High measurement noise
initial_value=0.0
)

print("Sample | Measurement | Kalman Est | Error")


print("-------|-------------|------------|-------")

for i in range(15):
# Simulate noisy measurement
import random
noise = ([Link]() - 0.5) * 20 # ±10 noise
measurement = true_value + noise

# Update Kalman filter


estimate = [Link](measurement)
error = abs(estimate - true_value)

print(f" {i+1:2d} | {measurement:6.2f} | {estimate:6.2f} | {error:5.2f}")

print(f"\nFinal estimate: {kf.get_state():.2f}")


print(f"Uncertainty: {kf.get_uncertainty():.4f}\n")

# Test 2D Kalman Filter


print("\nTest 2: 2D Position/Velocity Tracking")
print("Simulating object moving at constant velocity\n")

dt = 0.1 # 100ms time step


true_velocity = 5.0 # 5 units/sec
kf2d = KalmanFilter2D(
dt=dt,
process_variance=0.1,
measurement_variance=4.0
)

print("Time | True Pos | Meas Pos | Est Pos | Est Vel")


print("------|----------|----------|---------|--------")

for i in range(20):
t = i * dt
true_position = true_velocity * t

# Noisy measurement
noise = ([Link]() - 0.5) * 4
measurement = true_position + noise

# Kalman predict and update


[Link]()
[Link](measurement)

est_pos = kf2d.get_position()
est_vel = kf2d.get_velocity()

print(f"{t:5.2f} | {true_position:8.2f} | {measurement:8.2f} | {est_pos:7.2f} | {est_vel:7.2f}")

print("\nKalman filter converged to true velocity!")


print("Notice how estimates are smoother than measurements\n")

# Run test
test_kalman_filter()

# Real-time sensor fusion example (uncomment to use with MPU6050)


"""
# Initialize I2C for MPU6050
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
# Simple MPU6050 reading function
def read_accel_z():
# Read Z-axis acceleration (example)
data = i2c.readfrom_mem(0x68, 0x3F, 2)
return (data[0] << 8 | data[1]) / 16384.0 # Convert to g's

# Initialize Kalman filter for Z-axis acceleration


kf_accel = KalmanFilter(
process_variance=0.001,
measurement_variance=0.1,
initial_value=0.0
)

print("Real-time Kalman Filtering Started")


print("Filtering accelerometer Z-axis\n")

try:
while True:
# Read noisy sensor
raw_accel = read_accel_z()

# Apply Kalman filter


filtered_accel = kf_accel.update(raw_accel)

print(f"Raw: {raw_accel:6.3f} g | Filtered: {filtered_accel:6.3f} g | Uncertainty:


{kf_accel.get_uncertainty():.6f}")

[Link](0.1)

except KeyboardInterrupt:
print("\nFiltering stopped")
"""

8. State Space Control System


Prompt: Create a MicroPython program implementing State Space control system for
multivariable system control using state feedback, observer design, and optimal control (LQR).

Hardware Requirements:

●​ ESP32 Development Board / Raspberry Pi Pico


●​ DC motors with encoders (2x)
●​ Motor driver (L298N / TB6612FNG)
●​ Power supply (7-12V for motors)

Connections:

●​ Motor 1: IN1→GPIO25, IN2→GPIO26, ENA→GPIO27 (PWM)


●​ Motor 2: IN3→GPIO32, IN4→GPIO33, ENB→GPIO14 (PWM)
●​ Encoder 1: GPIO18, GPIO19
●​ Encoder 2: GPIO21, GPIO22

Additional Details:

●​ Modern control theory implementation


●​ State space representation: ẋ = Ax + Bu, y = Cx
●​ State feedback controller: u = -Kx
●​ Full-state observer for unmeasured states
●​ Discrete-time implementation for microcontrollers

MicroPython Code:

import math
import time
from machine import Pin, PWM

class StateSpaceSystem:
"""Discrete-time State Space System"""

def __init__(self, A, B, C, D=None, dt=0.01):


"""
Initialize state space system
ẋ = Ax + Bu (continuous)
x[k+1] = Ad*x[k] + Bd*u[k] (discrete)
y = Cx + Du

A: state matrix (n×n)


B: input matrix (n×m)
C: output matrix (p×n)
D: feedthrough matrix (p×m)
dt: sampling time
"""
self.A = A
self.B = B
self.C = C
self.D = D if D else [[0.0] * len(B[0]) for _ in range(len(C))]
[Link] = dt
# Number of states, inputs, outputs
self.n = len(A)
self.m = len(B[0])
self.p = len(C)

# State vector
self.x = [[0.0] for _ in range(self.n)]

def matrix_mult(self, A, B):


"""Multiply two matrices"""
rows_A, cols_A = len(A), len(A[0])
rows_B, cols_B = len(B), len(B[0])
result = [[0.0] * cols_B for _ in range(rows_A)]

for i in range(rows_A):
for j in range(cols_B):
for k in range(cols_A):
result[i][j] += A[i][k] * B[k][j]
return result

def matrix_add(self, A, B):


"""Add two matrices"""
return [[A[i][j] + B[i][j] for j in range(len(A[0]))] for i in range(len(A))]

def update(self, u):


"""
Update system state (discrete time step)
x[k+1] = Ad*x[k] + Bd*u[k]
Using forward Euler: Ad ≈ I + A*dt, Bd ≈ B*dt
"""
# Compute A*x
Ax = self.matrix_mult(self.A, self.x)

# Compute B*u (u should be column vector)


u_vec = [[ui] for ui in u] if isinstance(u[0], (int, float)) else u
Bu = self.matrix_mult(self.B, u_vec)

# x_new = x + (Ax + Bu)*dt


for i in range(self.n):
self.x[i][0] += (Ax[i][0] + Bu[i][0]) * [Link]

def output(self):
"""Compute system output: y = C*x"""
y = self.matrix_mult(self.C, self.x)
return [y[i][0] for i in range(self.p)]

def set_state(self, x):


"""Set system state"""
self.x = [[xi] for xi in x]

def get_state(self):
"""Get system state"""
return [self.x[i][0] for i in range(self.n)]

class StateFeedbackController:
"""State feedback controller: u = -K*x + r"""

def __init__(self, K, reference=None):


"""
Initialize state feedback controller
K: feedback gain matrix (m×n)
reference: reference input (optional)
"""
self.K = K
self.m = len(K)
self.n = len(K[0])
[Link] = reference if reference else [0.0] * self.m

def compute_control(self, x):


"""
Compute control input: u = -K*x + r
x: state vector
"""
u = []
for i in range(self.m):
ui = [Link][i]
for j in range(self.n):
ui -= self.K[i][j] * x[j]
[Link](ui)
return u

def set_reference(self, reference):


"""Set reference input"""
[Link] = reference
class StateObserver:
"""Luenberger observer for state estimation"""

def __init__(self, A, B, C, L, dt=0.01):


"""
Initialize state observer
ẋ_hat = A*x_hat + B*u + L*(y - C*x_hat)

A, B, C: system matrices
L: observer gain matrix (n×p)
dt: sampling time
"""
self.A = A
self.B = B
self.C = C
self.L = L
[Link] = dt

self.n = len(A)
self.m = len(B[0])
self.p = len(C)

# Estimated state
self.x_hat = [[0.0] for _ in range(self.n)]

[Link] = StateSpaceSystem(A, B, C, dt=dt)

def update(self, u, y):


"""
Update observer with measurement
u: control input
y: measured output
"""
# Compute C*x_hat (predicted output)
y_hat = [Link].matrix_mult(self.C, self.x_hat)

# Output error: e = y - y_hat


e = [[y[i] - y_hat[i][0]] for i in range(self.p)]

# Correction term: L*e


Le = [Link].matrix_mult(self.L, e)

# Compute A*x_hat
Ax = [Link].matrix_mult(self.A, self.x_hat)
# Compute B*u
u_vec = [[ui] for ui in u]
Bu = [Link].matrix_mult(self.B, u_vec)

# Update: x_hat = x_hat + (A*x_hat + B*u + L*e)*dt


for i in range(self.n):
self.x_hat[i][0] += (Ax[i][0] + Bu[i][0] + Le[i][0]) * [Link]

def get_state_estimate(self):
"""Return estimated state"""
return [self.x_hat[i][0] for i in range(self.n)]

# Test State Space Control


def test_state_space_control():
print("=== State Space Control System Test ===\n")

# Simple 2nd order system (mass-spring-damper)


# ẍ + 2*ζ*ω*ẋ + ω²*x = u
# State: [position, velocity]

print("System: Mass-Spring-Damper")
print("States: [position, velocity]")
print("Control: force input\n")

omega = 2.0 # Natural frequency


zeta = 0.1 # Damping ratio (underdamped)
dt = 0.01 # 10ms sample time

# State space matrices


A = [[0.0, 1.0],
[-omega**2, -2*zeta*omega]]

B = [[0.0],
[1.0]]

C = [[1.0, 0.0]] # Measure position only

print("System Matrices:")
print(f"A = {A}")
print(f"B = {B}")
print(f"C = {C}\n")
# Create system
system = StateSpaceSystem(A, B, C, dt=dt)
system.set_state([1.0, 0.0]) # Initial position = 1.0

# State feedback controller (pole placement)


# Desired closed-loop poles: faster and more damped
K = [[4.0, 1.5]] # Tuned gains
controller = StateFeedbackController(K, reference=[0.0])

print("Controller: u = -K*x")
print(f"K = {K}\n")

# Create observer (faster than system)


L = [[4.0],
[6.0]]
observer = StateObserver(A, B, C, L, dt=dt)

print("Observer gains:")
print(f"L = {L}\n")

# Simulation
print("Time | Position | Velocity | Control | Est Pos | Est Vel")
print("------|----------|----------|---------|---------|--------")

for i in range(100):
t = i * dt

# Get measurement (position only)


y = [Link]()

# Observer estimates full state


x_est = observer.get_state_estimate()

# Controller uses estimated state


u = controller.compute_control(x_est)

# Update observer
[Link](u, y)

# Update system
[Link](u)

# Get true state


x = system.get_state()
if i % 10 == 0:
print(f"{t:5.2f} | {x[0]:8.4f} | {x[1]:8.4f} | {u[0]:7.4f} | {x_est[0]:7.4f} | {x_est[1]:7.4f}")

print("\nSystem stabilized at origin!")


print("Observer successfully estimated velocity from position measurements\n")

# Run test
test_state_space_control()

# Real-time motor control example (uncomment to use with motors)


"""
# Motor control class
class DCMotor:
def __init__(self, in1_pin, in2_pin, en_pin, enc_a_pin, enc_b_pin):
self.in1 = Pin(in1_pin, [Link])
self.in2 = Pin(in2_pin, [Link])
[Link] = PWM(Pin(en_pin), freq=1000)

# Encoder
self.enc_a = Pin(enc_a_pin, [Link])
self.enc_b = Pin(enc_b_pin, [Link])
[Link] = 0
[Link] = 0

# Setup encoder interrupt


self.enc_a.irq(trigger=Pin.IRQ_RISING, handler=self._encoder_callback)

def _encoder_callback(self, pin):


if self.enc_b.value():
[Link] += 1
else:
[Link] -= 1

def set_speed(self, speed):


# speed: -1.0 to 1.0
if speed >= 0:
[Link]()
[Link]()
[Link](int(abs(speed) * 1023))
else:
[Link]()
[Link]()
[Link](int(abs(speed) * 1023))

def get_state(self):
return [[Link], [Link]]

# Initialize motor
motor = DCMotor(25, 26, 27, 18, 19)

# State space model for DC motor


# States: [angle, angular_velocity]
A_motor = [[0.0, 1.0],
[0.0, -10.0]] # Motor damping
B_motor = [[0.0],
[50.0]] # Motor constant
C_motor = [[1.0, 0.0]]

# Create controller
system = StateSpaceSystem(A_motor, B_motor, C_motor, dt=0.01)
K_motor = [[2.0, 0.5]]
controller = StateFeedbackController(K_motor, reference=[100.0]) # Target angle

print("State space motor control started")

try:
while True:
# Get motor state
x = motor.get_state()

# Compute control
u = controller.compute_control(x)

# Apply control (saturate to ±1.0)


u_sat = max(-1.0, min(1.0, u[0]))
motor.set_speed(u_sat)

print(f"Angle: {x[0]:6.1f} | Vel: {x[1]:6.2f} | Control: {u_sat:5.2f}")

[Link](0.01)

except KeyboardInterrupt:
motor.set_speed(0)
print("\nControl stopped")
"""
9. Time Series Analysis
Prompt: Create a MicroPython program implementing Time Series Analysis for trend detection,
seasonality decomposition, forecasting (ARIMA-like), and real-time anomaly detection in sensor
data streams.

Hardware Requirements:

●​ ESP32 Development Board / Raspberry Pi Pico


●​ Any analog sensor (temperature, humidity, light, etc.)
●​ Optional: SD card module for data logging
●​ Optional: RTC module for timestamps

Connections:

●​ Sensor → GPIO34 (ADC)


●​ SD Card → SPI (optional)

Additional Details:

●​ Moving averages and exponential smoothing


●​ Trend and seasonality decomposition
●​ Auto-regressive models for prediction
●​ Statistical analysis (mean, variance, autocorrelation)
●​ Real-time streaming analytics

MicroPython Code:

import math
import time
from machine import Pin, ADC

class TimeSeriesAnalyzer:
"""Time Series Analysis and Forecasting"""

def __init__(self, max_length=1000):


"""Initialize time series analyzer"""
[Link] = []
self.max_length = max_length

def add_point(self, value):


"""Add data point to series"""
[Link](value)
if len([Link]) > self.max_length:
[Link](0)

def get_series(self):
"""Return time series data"""
return [Link]()

def clear(self):
"""Clear all data"""
[Link] = []

# Statistical measures
def mean(self, data=None):
"""Calculate mean"""
d = data if data else [Link]
return sum(d) / len(d) if d else 0.0

def variance(self, data=None):


"""Calculate variance"""
d = data if data else [Link]
if not d:
return 0.0
m = [Link](d)
return sum((x - m) ** 2 for x in d) / len(d)

def std_dev(self, data=None):


"""Calculate standard deviation"""
return [Link]([Link](data))

def autocorrelation(self, lag):


"""
Calculate autocorrelation at given lag
r(k) = Σ[(x_t - μ)(x_{t-k} - μ)] / Σ[(x_t - μ)²]
"""
if len([Link]) <= lag:
return 0.0

m = [Link]()
numerator = 0.0
denominator = 0.0

for i in range(lag, len([Link])):


numerator += ([Link][i] - m) * ([Link][i - lag] - m)
for x in [Link]:
denominator += (x - m) ** 2

return numerator / denominator if denominator != 0 else 0.0

# Smoothing methods
def simple_moving_average(self, window):
"""Simple Moving Average (SMA)"""
if len([Link]) < window:
return [Link]()

sma = []
for i in range(len([Link])):
if i < window - 1:
[Link]([Link]([Link][:i+1]))
else:
[Link]([Link]([Link][i-window+1:i+1]))
return sma

def exponential_smoothing(self, alpha):


"""
Exponential Smoothing
S_t = α*x_t + (1-α)*S_{t-1}
alpha: smoothing factor (0 < alpha < 1)
"""
if not [Link]:
return []

smoothed = [[Link][0]]
for i in range(1, len([Link])):
s = alpha * [Link][i] + (1 - alpha) * smoothed[-1]
[Link](s)
return smoothed

def double_exponential_smoothing(self, alpha, beta):


"""
Double Exponential Smoothing (Holt's method)
Handles trend
alpha: level smoothing
beta: trend smoothing
"""
if len([Link]) < 2:
return [Link]()
# Initialize
level = [Link][0]
trend = [Link][1] - [Link][0]
smoothed = [[Link][0]]

for i in range(1, len([Link])):


last_level = level
level = alpha * [Link][i] + (1 - alpha) * (level + trend)
trend = beta * (level - last_level) + (1 - beta) * trend
[Link](level)
return smoothed

def forecast_next(self, method='sma', window=5, alpha=0.3):


"""
Forecast next value
method: 'sma' or 'ema'
"""
if not [Link]:
return 0.0

if method == 'sma':
w = min(window, len([Link]))
return [Link]([Link][-w:])
elif method == 'ema':
smoothed = self.exponential_smoothing(alpha)
return smoothed[-1]
else:
return [Link][-1]

# Trend detection
def detect_trend(self, window=10):
"""
Detect trend direction using linear regression
Returns: 'increasing', 'decreasing', or 'stable'
"""
if len([Link]) < window:
return 'insufficient_data'

# Use last 'window' points


recent = [Link][-window:]
n = len(recent)

# Linear regression: y = a + b*x


x_mean = (n - 1) / 2
y_mean = sum(recent) / n

numerator = sum((i - x_mean) * (recent[i] - y_mean) for i in range(n))


denominator = sum((i - x_mean) ** 2 for i in range(n))

if denominator == 0:
return 'stable'

slope = numerator / denominator

# Threshold for trend detection


threshold = self.std_dev(recent) * 0.1

if slope > threshold:


return 'increasing'
elif slope < -threshold:
return 'decreasing'
else:
return 'stable'

# Seasonality decomposition (simplified)


def decompose_additive(self, period):
"""
Additive decomposition: Y = T + S + R
T: trend, S: seasonal, R: residual
"""
if len([Link]) < period * 2:
return None, None, None

# 1. Calculate trend using centered moving average


trend = []
for i in range(len([Link])):
if i < period // 2 or i >= len([Link]) - period // 2:
[Link](None)
else:
start = i - period // 2
end = i + period // 2 + 1
[Link]([Link]([Link][start:end]))

# 2. Detrend to get seasonal + residual


detrended = []
for i in range(len([Link])):
if trend[i] is not None:
[Link]([Link][i] - trend[i])
else:
[Link](None)

# 3. Calculate seasonal component


seasonal = [0.0] * len([Link])
for i in range(period):
# Average all values at this phase
values = [detrended[j] for j in range(i, len(detrended), period)
if detrended[j] is not None]
if values:
avg = sum(values) / len(values)
for j in range(i, len(seasonal), period):
seasonal[j] = avg

# 4. Calculate residual
residual = []
for i in range(len([Link])):
if trend[i] is not None:
[Link]([Link][i] - trend[i] - seasonal[i])
else:
[Link](None)

return trend, seasonal, residual

class AnomalyDetector:
"""Real-time anomaly detection"""

def __init__(self, window=50, threshold=3.0):


"""
Initialize anomaly detector
window: lookback window for statistics
threshold: number of standard deviations for anomaly
"""
[Link] = window
[Link] = threshold
[Link] = []

def add_point(self, value):


"""Add point and return if it's anomalous"""
[Link](value)
if len([Link]) > [Link]:
[Link](0)
if len([Link]) < 10: # Need minimum data
return False, 0.0

# Calculate mean and std dev


mean = sum([Link]) / len([Link])
variance = sum((x - mean) ** 2 for x in [Link]) / len([Link])
std_dev = [Link](variance)

if std_dev == 0:
return False, 0.0

# Z-score
z_score = abs(value - mean) / std_dev

is_anomaly = z_score > [Link]


return is_anomaly, z_score

def reset(self):
"""Clear buffer"""
[Link] = []

# Test Time Series Analysis


def test_time_series():
print("=== Time Series Analysis Test ===\n")

# Generate synthetic data with trend, seasonality, and noise


print("Generating synthetic time series:")
print(" - Linear trend")
print(" - Seasonal pattern (period=10)")
print(" - Random noise\n")

ts = TimeSeriesAnalyzer(max_length=100)

for i in range(100):
# Trend: linear increase
trend = 0.5 * i

# Seasonality: sine wave


seasonal = 10 * [Link](2 * [Link] * i / 10)

# Noise
import random
noise = ([Link]() - 0.5) * 2

value = trend + seasonal + noise


ts.add_point(value)

data = ts.get_series()

# Statistics
print("Statistical Summary:")
print(f" Mean: {[Link]():.2f}")
print(f" Std Dev: {ts.std_dev():.2f}")
print(f" Variance: {[Link]():.2f}\n")

# Autocorrelation
print("Autocorrelation:")
for lag in [1, 5, 10]:
acf = [Link](lag)
print(f" Lag {lag}: {acf:.3f}")
print()

# Smoothing
print("Smoothing Methods:")
sma = ts.simple_moving_average(5)
ema = ts.exponential_smoothing(0.3)

print(f" Original (last 5): {[f'{x:.1f}' for x in data[-5:]]}")


print(f" SMA(5) (last 5): {[f'{x:.1f}' for x in sma[-5:]]}")
print(f" EMA(0.3) (last 5): {[f'{x:.1f}' for x in ema[-5:]]}\n")

# Trend detection
trend_direction = ts.detect_trend(window=20)
print(f"Trend Detection (last 20 points): {trend_direction}\n")

# Forecasting
forecast_sma = ts.forecast_next('sma', window=10)
forecast_ema = ts.forecast_next('ema', alpha=0.3)

print("Forecasting:")
print(f" Current value: {data[-1]:.2f}")
print(f" Forecast (SMA): {forecast_sma:.2f}")
print(f" Forecast (EMA): {forecast_ema:.2f}\n")

# Decomposition
print("Seasonal Decomposition (period=10):")
trend_comp, seasonal_comp, residual_comp = ts.decompose_additive(10)

# Show last 10 points


print("Index | Original | Trend | Seasonal | Residual")
print("------|----------|---------|----------|----------")
for i in range(-10, 0):
orig = data[i]
tr = trend_comp[i] if trend_comp[i] is not None else 0.0
seas = seasonal_comp[i]
res = residual_comp[i] if residual_comp[i] is not None else 0.0
print(f" {100+i:3d} | {orig:8.2f} | {tr:7.2f} | {seas:8.2f} | {res:8.2f}")

print("\n")

# Anomaly detection
print("Anomaly Detection Test:")
detector = AnomalyDetector(window=20, threshold=2.5)

# Add normal data


for i in range(30):
value = 50 + ([Link]() - 0.5) * 10
is_anom, z = detector.add_point(value)

# Add anomaly
print("\nInjecting anomalies...")
test_values = [52, 54, 120, 51, 53, -30, 50]

for val in test_values:


is_anom, z_score = detector.add_point(val)
status = "ANOMALY!" if is_anom else "Normal"
print(f" Value: {val:6.1f} | Z-score: {z_score:5.2f} | {status}")

print("\nTime series analysis complete!")

# Run test
test_time_series()

# Real-time sensor monitoring (uncomment to use)


"""
# Initialize ADC
adc = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
[Link](ADC.WIDTH_12BIT)

# Create analyzer and anomaly detector


ts = TimeSeriesAnalyzer(max_length=500)
anomaly_detector = AnomalyDetector(window=30, threshold=3.0)

print("Real-time Time Series Monitoring Started")


print("Collecting sensor data...\n")

sample_count = 0

try:
while True:
# Read sensor
raw_value = [Link]()

# Add to time series


ts.add_point(raw_value)
sample_count += 1

# Check for anomaly


is_anomaly, z_score = anomaly_detector.add_point(raw_value)

# Every 10 samples, show analysis


if sample_count % 10 == 0:
trend = ts.detect_trend(window=20)
forecast = ts.forecast_next('ema', alpha=0.2)

print(f"Samples: {sample_count}")
print(f" Current: {raw_value:4d} | Mean: {[Link]():6.1f} | StdDev: {ts.std_dev():5.1f}")
print(f" Trend: {trend} | Forecast: {forecast:.1f}")

if is_anomaly:
print(f" *** ANOMALY DETECTED! Z-score: {z_score:.2f} ***")
print()

[Link](0.1)

except KeyboardInterrupt:
print("\nMonitoring stopped")
print(f"Total samples collected: {len(ts.get_series())}")
"""
10. Statistical Anomaly Detection
Prompt: Create a MicroPython program implementing Statistical Anomaly Detection using
multiple methods including Z-score, Modified Z-score, IQR, and Isolation Forest-like algorithms
for real-time outlier detection.

Hardware Requirements:

●​ ESP32 Development Board / Raspberry Pi Pico


●​ Any sensors (temperature, pressure, current, vibration)
●​ Optional: LED indicators for anomaly alerts
●​ Optional: Buzzer for alarms

Connections:

●​ Sensor → GPIO34 (ADC)


●​ Alert LED → GPIO2
●​ Buzzer → GPIO4

Additional Details:

●​ Multiple detection algorithms for robust detection


●​ Online learning for adaptive thresholds
●​ Statistical methods and distance-based detection
●​ Configurable sensitivity and window sizes
●​ Real-time alert system

MicroPython Code:

import math
import time
from machine import Pin, ADC

class ZScoreDetector:
"""Standard Z-score anomaly detection"""

def __init__(self, threshold=3.0, window=100):


"""
threshold: number of standard deviations
window: rolling window size
"""
[Link] = threshold
[Link] = window
[Link] = []
def add_sample(self, value):
"""Add sample and detect anomaly"""
[Link](value)
if len([Link]) > [Link]:
[Link](0)

if len([Link]) < 5:
return False, 0.0, None

mean = sum([Link]) / len([Link])


variance = sum((x - mean) ** 2 for x in [Link]) / len([Link])
std_dev = [Link](variance)

if std_dev == 0:
return False, 0.0, {'mean': mean, 'std': std_dev}

z_score = (value - mean) / std_dev


is_anomaly = abs(z_score) > [Link]

stats = {'mean': mean, 'std': std_dev, 'z_score': z_score}


return is_anomaly, abs(z_score), stats

class ModifiedZScoreDetector:
"""Modified Z-score using Median Absolute Deviation (MAD)"""

def __init__(self, threshold=3.5, window=100):


"""
threshold: modified z-score threshold
window: rolling window size
"""
[Link] = threshold
[Link] = window
[Link] = []

def median(self, data):


"""Calculate median"""
sorted_data = sorted(data)
n = len(sorted_data)
if n % 2 == 0:
return (sorted_data[n//2 - 1] + sorted_data[n//2]) / 2
else:
return sorted_data[n//2]
def mad(self, data, median_val):
"""Median Absolute Deviation"""
deviations = [abs(x - median_val) for x in data]
return [Link](deviations)

def add_sample(self, value):


"""Add sample and detect anomaly"""
[Link](value)
if len([Link]) > [Link]:
[Link](0)

if len([Link]) < 5:
return False, 0.0, None

median_val = [Link]([Link])
mad_val = [Link]([Link], median_val)

if mad_val == 0:
return False, 0.0, {'median': median_val, 'mad': mad_val}

# Modified Z-score: 0.6745 * (x - median) / MAD


modified_z = 0.6745 * (value - median_val) / mad_val
is_anomaly = abs(modified_z) > [Link]

stats = {'median': median_val, 'mad': mad_val, 'modified_z': modified_z}


return is_anomaly, abs(modified_z), stats

class IQRDetector:
"""Interquartile Range (IQR) anomaly detection"""

def __init__(self, iqr_multiplier=1.5, window=100):


"""
iqr_multiplier: multiplier for IQR (typical: 1.5 for outliers, 3.0 for extreme)
window: rolling window size
"""
self.iqr_multiplier = iqr_multiplier
[Link] = window
[Link] = []

def percentile(self, data, p):


"""Calculate percentile"""
sorted_data = sorted(data)
n = len(sorted_data)
k = (n - 1) * p
f = [Link](k)
c = [Link](k)
if f == c:
return sorted_data[int(k)]
d0 = sorted_data[int(f)] * (c - k)
d1 = sorted_data[int(c)] * (k - f)
return d0 + d1

def add_sample(self, value):


"""Add sample and detect anomaly"""
[Link](value)
if len([Link]) > [Link]:
[Link](0)

if len([Link]) < 5:
return False, 0.0, None

q1 = [Link]([Link], 0.25)
q3 = [Link]([Link], 0.75)
iqr = q3 - q1

lower_bound = q1 - self.iqr_multiplier * iqr


upper_bound = q3 + self.iqr_multiplier * iqr

is_anomaly = value < lower_bound or value > upper_bound

# Distance from bounds


if value < lower_bound:
distance = abs(value - lower_bound) / iqr if iqr > 0 else 0
elif value > upper_bound:
distance = abs(value - upper_bound) / iqr if iqr > 0 else 0
else:
distance = 0.0

stats = {
'q1': q1, 'q3': q3, 'iqr': iqr,
'lower': lower_bound, 'upper': upper_bound
}
return is_anomaly, distance, stats

class EWMADetector:
"""Exponentially Weighted Moving Average anomaly detection"""
def __init__(self, alpha=0.2, threshold=3.0):
"""
alpha: smoothing factor (0 < alpha < 1)
threshold: number of standard deviations
"""
[Link] = alpha
[Link] = threshold
[Link] = None
self.ewma_std = None
[Link] = False

def add_sample(self, value):


"""Add sample and detect anomaly"""
if not [Link]:
[Link] = value
self.ewma_std = 0.0
[Link] = True
return False, 0.0, {'ewma': [Link], 'std': self.ewma_std}

# Update EWMA
prediction = [Link]
error = abs(value - prediction)
[Link] = [Link] * value + (1 - [Link]) * [Link]

# Update EWMA of standard deviation


self.ewma_std = [Link] * error + (1 - [Link]) * self.ewma_std

if self.ewma_std == 0:
return False, 0.0, {'ewma': [Link], 'std': self.ewma_std}

# Detect anomaly
z_score = error / self.ewma_std
is_anomaly = z_score > [Link]

stats = {'ewma': [Link], 'std': self.ewma_std, 'error': error}


return is_anomaly, z_score, stats

class CUSUMDetector:
"""Cumulative Sum (CUSUM) anomaly detection"""

def __init__(self, threshold=5.0, drift=0.5, window=50):


"""
threshold: detection threshold
drift: allowable drift from mean
window: window for calculating baseline
"""
[Link] = threshold
[Link] = drift
[Link] = window
[Link] = []
self.cusum_pos = 0.0
self.cusum_neg = 0.0
[Link] = 0.0

def add_sample(self, value):


"""Add sample and detect anomaly"""
[Link](value)
if len([Link]) > [Link]:
[Link](0)

if len([Link]) < 5:
return False, 0.0, None

# Update mean
[Link] = sum([Link]) / len([Link])

# Update CUSUM
deviation = value - [Link]
self.cusum_pos = max(0, self.cusum_pos + deviation - [Link])
self.cusum_neg = max(0, self.cusum_neg - deviation - [Link])

# Detect anomaly
is_anomaly = self.cusum_pos > [Link] or self.cusum_neg > [Link]
score = max(self.cusum_pos, self.cusum_neg)

stats = {
'mean': [Link],
'cusum_pos': self.cusum_pos,
'cusum_neg': self.cusum_neg
}
return is_anomaly, score, stats

class EnsembleDetector:
"""Ensemble of multiple anomaly detectors"""
def __init__(self, vote_threshold=0.5):
"""
vote_threshold: fraction of detectors that must agree (0-1)
"""
self.vote_threshold = vote_threshold
[Link] = {
'zscore': ZScoreDetector(threshold=3.0),
'modified_z': ModifiedZScoreDetector(threshold=3.5),
'iqr': IQRDetector(iqr_multiplier=1.5),
'ewma': EWMADetector(alpha=0.2, threshold=3.0),
'cusum': CUSUMDetector(threshold=5.0, drift=0.5)
}

def add_sample(self, value):


"""Add sample and detect with ensemble voting"""
results = {}
votes = 0
total_detectors = len([Link])

for name, detector in [Link]():


is_anomaly, score, stats = detector.add_sample(value)
results[name] = {
'anomaly': is_anomaly,
'score': score,
'stats': stats
}
if is_anomaly:
votes += 1

# Ensemble decision
vote_fraction = votes / total_detectors
ensemble_anomaly = vote_fraction >= self.vote_threshold

return ensemble_anomaly, vote_fraction, results

# Test Anomaly Detection


def test_anomaly_detection():
print("=== Statistical Anomaly Detection Test ===\n")

import random

# Generate normal data with anomalies


print("Generating test data:")
print(" - Normal data: mean=100, std=10")
print(" - Injected anomalies at indices 50, 100, 150\n")

data = []
anomaly_indices = [50, 100, 150]

for i in range(200):
if i in anomaly_indices:
# Inject anomaly
value = 100 + [Link]([-50, 50])
else:
# Normal data
value = 100 + ([Link]() - 0.5) * 20
[Link](value)

# Test each detector


print("Testing Individual Detectors:\n")

detectors = {
'Z-Score': ZScoreDetector(threshold=3.0),
'Modified Z-Score': ModifiedZScoreDetector(threshold=3.5),
'IQR': IQRDetector(iqr_multiplier=1.5),
'EWMA': EWMADetector(alpha=0.2, threshold=3.0),
'CUSUM': CUSUMDetector(threshold=5.0)
}

detections = {name: [] for name in [Link]()}

# Process data
for i, value in enumerate(data):
for name, detector in [Link]():
is_anomaly, score, stats = detector.add_sample(value)
if is_anomaly:
detections[name].append(i)

# Report results
print("Detection Results:")
print(f"True anomalies at indices: {anomaly_indices}\n")

for name, detected_indices in [Link]():


true_positives = sum(1 for idx in detected_indices if idx in anomaly_indices)
false_positives = len(detected_indices) - true_positives
missed = sum(1 for idx in anomaly_indices if idx not in detected_indices)
print(f"{name}:")
print(f" Detected: {len(detected_indices)} anomalies")
print(f" True Positives: {true_positives}")
print(f" False Positives: {false_positives}")
print(f" Missed: {missed}")
print()

# Test Ensemble Detector


print("\nTesting Ensemble Detector (voting):")
ensemble = EnsembleDetector(vote_threshold=0.6) # 60% must agree

ensemble_detections = []
for i, value in enumerate(data):
is_anomaly, vote_fraction, results = ensemble.add_sample(value)
if is_anomaly:
ensemble_detections.append((i, vote_fraction))

print(f"Ensemble detected {len(ensemble_detections)} anomalies")


print("\nDetailed results:")
print("Index | Value | Vote % | Status")
print("------|-------|--------|-------")

for idx, vote_pct in ensemble_detections:


is_true = "TRUE" if idx in anomaly_indices else "FALSE"
print(f" {idx:3d} | {data[idx]:5.1f} | {vote_pct*100:5.1f}% | {is_true}")

print("\nAnomaly detection test complete!")

# Run test
test_anomaly_detection()

# Real-time monitoring with alerts (uncomment to use)


"""
# Initialize hardware
adc = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
[Link](ADC.WIDTH_12BIT)

alert_led = Pin(2, [Link])


buzzer = Pin(4, [Link])

# Create ensemble detector


detector = EnsembleDetector(vote_threshold=0.5)

print("Real-time Anomaly Detection Started")


print("Monitoring sensor for anomalies...\n")

sample_count = 0
anomaly_count = 0

try:
while True:
# Read sensor
raw_value = [Link]()

# Detect anomaly
is_anomaly, vote_fraction, results = detector.add_sample(raw_value)

sample_count += 1

if is_anomaly:
anomaly_count += 1
alert_led.on()
[Link]()

print(f"\n*** ANOMALY DETECTED! (#{anomaly_count}) ***")


print(f"Sample: {sample_count} | Value: {raw_value}")
print(f"Ensemble vote: {vote_fraction*100:.1f}%")

# Show which detectors flagged it


for name, result in [Link]():
if result['anomaly']:
print(f" - {name}: ANOMALY (score: {result['score']:.2f})")
print()

[Link](0.5) # Alert duration


alert_led.off()
[Link]()

else:
# Normal operation
if sample_count % 50 == 0:
print(f"Samples: {sample_count} | Anomalies: {anomaly_count} | Current:
{raw_value}")

[Link](0.1)
except KeyboardInterrupt:
alert_led.off()
[Link]()
print(f"\nMonitoring stopped")
print(f"Total samples: {sample_count}")
print(f"Total anomalies: {anomaly_count} ({anomaly_count/sample_count*100:.2f}%)")
"""

11. Mathematical Expression Parser


Prompt: Create a MicroPython program implementing Mathematical Expression Parser with
tokenization, recursive descent parsing, expression evaluation, and support for variables,
functions, and operators for embedded calculator applications.

Hardware Requirements:

●​ ESP32 Development Board / Raspberry Pi Pico


●​ Optional: Keypad (4x4) for input
●​ Optional: OLED/LCD display for output
●​ Optional: Rotary encoder for variable adjustment

Connections:

●​ Keypad → GPIO pins (rows: 25,26,27,14, cols: 12,13,15,32)


●​ Display → I2C (SCL: GPIO22, SDA: GPIO21)

Additional Details:

●​ Recursive descent parser for mathematical expressions


●​ Support for: +, -, *, /, ^, %, parentheses
●​ Built-in functions: sin, cos, tan, sqrt, log, exp, abs
●​ Variable support and assignment
●​ Operator precedence and associativity
●​ Error handling for invalid expressions

MicroPython Code:

"""

Mathematical Expression Parser for ESP32/Raspberry Pi Pico

Supports tokenization, recursive descent parsing, variables, and functions


"""

import math

import time

from machine import Pin, I2C, ADC

try:

from ssd1306 import SSD1306_I2C

DISPLAY_AVAILABLE = True

except:

DISPLAY_AVAILABLE = False

class Token:

"""Token class for lexer"""

# Token types

NUMBER = 'NUMBER'

OPERATOR = 'OPERATOR'

FUNCTION = 'FUNCTION'

LPAREN = 'LPAREN'

RPAREN = 'RPAREN'

VARIABLE = 'VARIABLE'

COMMA = 'COMMA'

ASSIGN = 'ASSIGN'

EOF = 'EOF'
def __init__(self, type, value):

[Link] = type

[Link] = value

def __repr__(self):

return f'Token({[Link]}, {[Link]})'

class Lexer:

"""Tokenizer for mathematical expressions"""

OPERATORS = {'+', '-', '*', '/', '^', '%'}

FUNCTIONS = {

'sin', 'cos', 'tan', 'asin', 'acos', 'atan',

'sqrt', 'log', 'ln', 'exp', 'abs', 'ceil', 'floor',

'min', 'max', 'pow', 'round'

def __init__(self, text):

[Link] = [Link](' ', '') # Remove whitespace

[Link] = 0

self.current_char = [Link][0] if [Link] else None

def advance(self):
"""Move to next character"""

[Link] += 1

self.current_char = [Link][[Link]] if [Link] < len([Link]) else None

def peek(self):

"""Look at next character without advancing"""

peek_pos = [Link] + 1

return [Link][peek_pos] if peek_pos < len([Link]) else None

def skip_whitespace(self):

"""Skip whitespace characters"""

while self.current_char and self.current_char.isspace():

[Link]()

def read_number(self):

"""Read a number (integer or float)"""

num_str = ''

has_dot = False

while self.current_char and (self.current_char.isdigit() or self.current_char == '.'):

if self.current_char == '.':

if has_dot:

raise ValueError("Invalid number format")

has_dot = True
num_str += self.current_char

[Link]()

return float(num_str)

def read_identifier(self):

"""Read identifier (function or variable name)"""

identifier = ''

while self.current_char and (self.current_char.isalnum() or self.current_char == '_'):

identifier += self.current_char

[Link]()

return identifier

def get_next_token(self):

"""Get next token from input"""

while self.current_char:

if self.current_char.isspace():

self.skip_whitespace()

continue

# Numbers
if self.current_char.isdigit() or self.current_char == '.':

return Token([Link], self.read_number())

# Identifiers (functions or variables)

if self.current_char.isalpha() or self.current_char == '_':

identifier = self.read_identifier()

if identifier in [Link]:

return Token([Link], identifier)

else:

return Token([Link], identifier)

# Operators

if self.current_char in [Link]:

op = self.current_char

[Link]()

return Token([Link], op)

# Assignment

if self.current_char == '=':

[Link]()

return Token([Link], '=')

# Parentheses
if self.current_char == '(':

[Link]()

return Token([Link], '(')

if self.current_char == ')':

[Link]()

return Token([Link], ')')

# Comma

if self.current_char == ',':

[Link]()

return Token([Link], ',')

raise ValueError(f"Invalid character: {self.current_char}")

return Token([Link], None)

class Parser:

"""Recursive descent parser for mathematical expressions"""

def __init__(self, lexer):

[Link] = lexer

self.current_token = [Link].get_next_token()

[Link] = {}
def eat(self, token_type):

"""Consume current token if it matches expected type"""

if self.current_token.type == token_type:

self.current_token = [Link].get_next_token()

else:

raise ValueError(f"Expected {token_type}, got {self.current_token.type}")

def parse(self):

"""Parse expression (handles assignments)"""

# Check for assignment

if self.current_token.type == [Link]:

var_name = self.current_token.value

next_pos = [Link]

next_char = [Link].current_char

# Look ahead for assignment

[Link]([Link])

if self.current_token.type == [Link]:

[Link]([Link])

value = [Link]()

[Link][var_name] = value

return value

else:
# Not an assignment, reset and parse as expression

[Link] = next_pos - len(var_name)

[Link].current_char = [Link][[Link]] if [Link] <


len([Link]) else None

self.current_token = [Link].get_next_token()

return [Link]()

def expression(self):

"""Parse addition and subtraction (lowest precedence)"""

result = [Link]()

while self.current_token.type == [Link] and self.current_token.value in ['+', '-']:

op = self.current_token.value

[Link]([Link])

if op == '+':

result += [Link]()

else:

result -= [Link]()

return result

def term(self):

"""Parse multiplication, division, and modulo"""


result = [Link]()

while self.current_token.type == [Link] and self.current_token.value in ['*', '/',


'%']:

op = self.current_token.value

[Link]([Link])

if op == '*':

result *= [Link]()

elif op == '/':

divisor = [Link]()

if divisor == 0:

raise ValueError("Division by zero")

result /= divisor

else: # %

result %= [Link]()

return result

def power(self):

"""Parse exponentiation (right-associative)"""

result = [Link]()

if self.current_token.type == [Link] and self.current_token.value == '^':

[Link]([Link])
result = result ** [Link]() # Right-associative

return result

def unary(self):

"""Parse unary operators"""

if self.current_token.type == [Link] and self.current_token.value in ['+', '-']:

op = self.current_token.value

[Link]([Link])

if op == '-':

return -[Link]()

else:

return [Link]()

return [Link]()

def factor(self):

"""Parse numbers, variables, functions, and parentheses"""

token = self.current_token

# Numbers

if [Link] == [Link]:

[Link]([Link])
return [Link]

# Variables

if [Link] == [Link]:

var_name = [Link]

[Link]([Link])

if var_name not in [Link]:

raise ValueError(f"Undefined variable: {var_name}")

return [Link][var_name]

# Functions

if [Link] == [Link]:

func_name = [Link]

[Link]([Link])

[Link]([Link])

args = []

[Link]([Link]())

while self.current_token.type == [Link]:

[Link]([Link])

[Link]([Link]())
[Link]([Link])

return self.evaluate_function(func_name, args)

# Parentheses

if [Link] == [Link]:

[Link]([Link])

result = [Link]()

[Link]([Link])

return result

raise ValueError(f"Unexpected token: {token}")

def evaluate_function(self, func_name, args):

"""Evaluate built-in functions"""

if func_name == 'sin':

if len(args) != 1:

raise ValueError("sin() takes 1 argument")

return [Link](args[0])

elif func_name == 'cos':

if len(args) != 1:

raise ValueError("cos() takes 1 argument")


return [Link](args[0])

elif func_name == 'tan':

if len(args) != 1:

raise ValueError("tan() takes 1 argument")

return [Link](args[0])

elif func_name == 'asin':

if len(args) != 1:

raise ValueError("asin() takes 1 argument")

return [Link](args[0])

elif func_name == 'acos':

if len(args) != 1:

raise ValueError("acos() takes 1 argument")

return [Link](args[0])

elif func_name == 'atan':

if len(args) != 1:

raise ValueError("atan() takes 1 argument")

return [Link](args[0])

elif func_name == 'sqrt':

if len(args) != 1:
raise ValueError("sqrt() takes 1 argument")

if args[0] < 0:

raise ValueError("sqrt() of negative number")

return [Link](args[0])

elif func_name == 'log':

if len(args) != 1:

raise ValueError("log() takes 1 argument")

return math.log10(args[0])

elif func_name == 'ln':

if len(args) != 1:

raise ValueError("ln() takes 1 argument")

return [Link](args[0])

elif func_name == 'exp':

if len(args) != 1:

raise ValueError("exp() takes 1 argument")

return [Link](args[0])

elif func_name == 'abs':

if len(args) != 1:

raise ValueError("abs() takes 1 argument")

return abs(args[0])
elif func_name == 'ceil':

if len(args) != 1:

raise ValueError("ceil() takes 1 argument")

return [Link](args[0])

elif func_name == 'floor':

if len(args) != 1:

raise ValueError("floor() takes 1 argument")

return [Link](args[0])

elif func_name == 'round':

if len(args) != 1:

raise ValueError("round() takes 1 argument")

return round(args[0])

elif func_name == 'min':

if len(args) < 2:

raise ValueError("min() takes at least 2 arguments")

return min(args)

elif func_name == 'max':

if len(args) < 2:

raise ValueError("max() takes at least 2 arguments")


return max(args)

elif func_name == 'pow':

if len(args) != 2:

raise ValueError("pow() takes 2 arguments")

return args[0] ** args[1]

else:

raise ValueError(f"Unknown function: {func_name}")

class MathCalculator:

"""Calculator with display and keypad support"""

def __init__(self):

# Keypad configuration (4x4)

[Link] = [25, 26, 27, 14]

[Link] = [12, 13, 15, 32]

self.keypad_layout = [

['7', '8', '9', '/'],

['4', '5', '6', '*'],

['1', '2', '3', '-'],

['C', '0', '=', '+']

]
# Initialize keypad pins

self.row_pins = [Pin(pin, [Link]) for pin in [Link]]

self.col_pins = [Pin(pin, [Link], Pin.PULL_DOWN) for pin in [Link]]

# Display setup

if DISPLAY_AVAILABLE:

try:

i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)

[Link] = SSD1306_I2C(128, 64, i2c)

self.has_display = True

except:

self.has_display = False

print("Display not found")

else:

self.has_display = False

[Link] = ""

[Link] = None

[Link] = {}

def scan_keypad(self):

"""Scan keypad for pressed key"""

for row_idx, row_pin in enumerate(self.row_pins):


row_pin.value(1)

time.sleep_ms(1)

for col_idx, col_pin in enumerate(self.col_pins):

if col_pin.value():

key = self.keypad_layout[row_idx][col_idx]

row_pin.value(0)

# Debounce

while col_pin.value():

time.sleep_ms(10)

return key

row_pin.value(0)

return None

def evaluate_expression(self, expr):

"""Evaluate mathematical expression"""

try:

lexer = Lexer(expr)

parser = Parser(lexer)
# Share variables with parser

[Link] = [Link]

result = [Link]()

# Update variables

[Link] = [Link]

return result

except Exception as e:

raise ValueError(f"Error: {str(e)}")

def update_display(self):

"""Update OLED display"""

if not self.has_display:

return

[Link](0)

# Display expression

[Link]("Expr:", 0, 0)

# Split long expressions

if len([Link]) > 16:


[Link]([Link][-16:], 0, 12)

else:

[Link]([Link], 0, 12)

# Display result

if [Link] is not None:

[Link]("Result:", 0, 30)

result_str = f"{[Link]:.6g}"

if len(result_str) > 16:

result_str = f"{[Link]:.2e}"

[Link](result_str, 0, 42)

[Link]()

def run(self):

"""Main calculator loop"""

print("=== Math Expression Parser ===")

print("Supported operations: +, -, *, /, ^, %, ()")

print("Functions: sin, cos, tan, sqrt, log, exp, abs, min, max, etc.")

print("Variables: x = 5, y = x + 3")

print("Press 'C' to clear, '=' to evaluate")

print()

while True:
# Keypad input

key = self.scan_keypad()

if key:

if key == 'C':

[Link] = ""

[Link] = None

print("\nCleared")

elif key == '=':

if [Link]:

try:

[Link] = self.evaluate_expression([Link])

print(f"\n{[Link]} = {[Link]}")

[Link] = ""

except Exception as e:

print(f"\nError: {e}")

[Link] = None

else:

[Link] += key

print(key, end='')

self.update_display()
time.sleep_ms(50)

def test_parser():

"""Test the expression parser"""

test_expressions = [

"2 + 3 * 4",

"10 / 2 - 3",

"2 ^ 3 ^ 2",

"(2 + 3) * 4",

"sin(0)",

"cos(3.14159)",

"sqrt(16)",

"log(100)",

"abs(-5)",

"min(3, 5, 2, 8)",

"max(1, 9, 3)",

"x = 10",

"y = x + 5",

"x * y",

"2 * (3 + 4) / 7",

"-5 + 3",

"10 % 3"

]
print("=== Expression Parser Tests ===\n")

variables = {}

for expr in test_expressions:

try:

lexer = Lexer(expr)

parser = Parser(lexer)

[Link] = variables

result = [Link]()

variables = [Link]

print(f"{expr:25s} = {result:.6g}")

except Exception as e:

print(f"{expr:25s} => Error: {e}")

print("\nVariables:", variables)

# Main execution

if __name__ == '__main__':

# Run tests first

test_parser()
print("\n" + "="*40)

print("Starting calculator...")

print("="*40 + "\n")

# Start calculator

calculator = MathCalculator()

[Link]()

You might also like