From efb2e1ee8069333256b2a1dfba89791b7650e487 Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Fri, 14 Aug 2026 16:45:37 +0200 Subject: [PATCH] fix(examples): repair two broken 100-days projects + credit upstream author - IoT Atmospheric Monitoring (ESP32+Blynk): ship the missing bmp180.py driver (BMP180 API over the emulated BMP280), switch SoftI2C -> hardware I2C(0) so the emulator decodes the bus, survive an unreachable Blynk Cloud, and add the BMP280 sensor + wiring to the canvas. - AQI ESP: ship the missing ssd1306.py driver, DHT11 -> DHT22 (the emulated waveform), local AQI fallback when the Flask server is absent, and add the OLED + DHT22 canvas with wiring. - All 49 descriptions now credit Kritish Mohapatra's upstream repo (github.com/kritishmohapatra/100_Days_100_IoT_Projects). Generated by test_100_days/_emit_examples_data.py in velxio-prod (which now supports per-project velxio_diagram.json canvases). --- frontend/src/data/examples-100-days.ts | 946 ++++++++++++++++--------- 1 file changed, 593 insertions(+), 353 deletions(-) diff --git a/frontend/src/data/examples-100-days.ts b/frontend/src/data/examples-100-days.ts index dec2ac69..e06e9c61 100644 --- a/frontend/src/data/examples-100-days.ts +++ b/frontend/src/data/examples-100-days.ts @@ -1,6 +1,6 @@ /** - * 100 Days of IoT — example projects from - * https://github.com/KritishMohapatra/100_Days_100_IoT_Projects + * 100 Days of IoT — example projects by Kritish Mohapatra, from + * https://github.com/kritishmohapatra/100_Days_100_IoT_Projects * * AUTO-GENERATED by `test/test_100_days/_emit_examples_data.py`. * Do not edit by hand. Re-run the generator after pulling new upstream @@ -21,7 +21,7 @@ export const hundredDaysExamples: ExampleProject[] = [ { id: "100d-aqi-esp", title: "AQI ESP", - description: "AQI ESP on ESP32 (MicroPython) \u2014 uses DHT, HTTP server, OLED, Wi-Fi.", + description: "AQI ESP on ESP32 (MicroPython) \u2014 uses DHT, HTTP server, OLED, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "displays", difficulty: "intermediate", boardType: "esp32", @@ -76,8 +76,10 @@ print("WiFi Connected:", wifi.ifconfig()) i2c = I2C(0, scl=Pin(22), sda=Pin(21)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) -# ================= DHT11 ================= -dht_sensor = dht.DHT11(Pin(27)) +# ================= DHT ================= +# Velxio's simulator emulates the DHT22 waveform, so use dht.DHT22 here. +# On real hardware with a DHT11, switch back to dht.DHT11. +dht_sensor = dht.DHT22(Pin(27)) last_temp = 0 last_hum = 0 @@ -132,36 +134,205 @@ while True: aqi = round(result["predicted_aqi"], 2) status = result["status"] - - # ---- OLED DISPLAY ---- - oled.fill(0) - oled.text("AQI MONITOR", 0, 0) - oled.text("AQI: {}".format(aqi), 0, 14) - oled.text(status, 0, 26) - oled.text("Temp: {} C".format(last_temp), 0, 42) - oled.text("Hum : {} %".format(last_hum), 0, 54) - oled.show() - - print("Sent:", payload) - print("AQI:", aqi, status) - except Exception as e: - print("Error:", e) + # No prediction server reachable (SERVER_URL is a placeholder in the + # simulator) — fall back to the same formula app.py applies, locally. + pm25 = payload["pm25"] * 100 + co = payload["co"] / 1000 + no = payload["no"] / 1000 + nox = payload["nox"] / 1000 + aqi = round((pm25 + co + no + nox) / 4, 2) + if aqi <= 50: + status = "Good" + elif aqi <= 100: + status = "Moderate" + elif aqi <= 200: + status = "Unhealthy" + else: + status = "Hazardous" + + # ---- OLED DISPLAY ---- + oled.fill(0) + oled.text("AQI MONITOR", 0, 0) + oled.text("AQI: {}".format(aqi), 0, 14) + oled.text(status, 0, 26) + oled.text("Temp: {} C".format(last_temp), 0, 42) + oled.text("Hum : {} %".format(last_hum), 0, 54) + oled.show() + + print("Sent:", payload) + print("AQI:", aqi, status) time.sleep(5) +` }, + { name: "ssd1306.py", content: `# MicroPython SSD1306 OLED driver, I2C and SPI interfaces +# MIT License; Copyright (c) 2016 Damien P. George (upstream micropython/drivers) +# Shipped with this example because the ESP32 firmware does not freeze it in. + +from micropython import const +import framebuf + +# register definitions +SET_CONTRAST = const(0x81) +SET_ENTIRE_ON = const(0xA4) +SET_NORM_INV = const(0xA6) +SET_DISP = const(0xAE) +SET_MEM_ADDR = const(0x20) +SET_COL_ADDR = const(0x21) +SET_PAGE_ADDR = const(0x22) +SET_DISP_START_LINE = const(0x40) +SET_SEG_REMAP = const(0xA0) +SET_MUX_RATIO = const(0xA8) +SET_COM_OUT_DIR = const(0xC0) +SET_DISP_OFFSET = const(0xD3) +SET_COM_PIN_CFG = const(0xDA) +SET_DISP_CLK_DIV = const(0xD5) +SET_PRECHARGE = const(0xD9) +SET_VCOM_DESEL = const(0xDB) +SET_CHARGE_PUMP = const(0x8D) + + +class SSD1306(framebuf.FrameBuffer): + def __init__(self, width, height, external_vcc): + self.width = width + self.height = height + self.external_vcc = external_vcc + self.pages = self.height // 8 + self.buffer = bytearray(self.pages * self.width) + super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB) + self.init_display() + + def init_display(self): + for cmd in ( + SET_DISP | 0x00, # off + # address setting + SET_MEM_ADDR, + 0x00, # horizontal + # resolution and layout + SET_DISP_START_LINE | 0x00, + SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 + SET_MUX_RATIO, + self.height - 1, + SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 + SET_DISP_OFFSET, + 0x00, + SET_COM_PIN_CFG, + 0x02 if self.width > 2 * self.height else 0x12, + # timing and driving scheme + SET_DISP_CLK_DIV, + 0x80, + SET_PRECHARGE, + 0x22 if self.external_vcc else 0xF1, + SET_VCOM_DESEL, + 0x30, # 0.83*Vcc + # display + SET_CONTRAST, + 0xFF, # maximum + SET_ENTIRE_ON, # output follows RAM contents + SET_NORM_INV, # not inverted + # charge pump + SET_CHARGE_PUMP, + 0x10 if self.external_vcc else 0x14, + SET_DISP | 0x01, + ): # on + self.write_cmd(cmd) + self.fill(0) + self.show() + + def poweroff(self): + self.write_cmd(SET_DISP | 0x00) + + def poweron(self): + self.write_cmd(SET_DISP | 0x01) + + def contrast(self, contrast): + self.write_cmd(SET_CONTRAST) + self.write_cmd(contrast) + + def invert(self, invert): + self.write_cmd(SET_NORM_INV | (invert & 1)) + + def show(self): + x0 = 0 + x1 = self.width - 1 + if self.width == 64: + # displays with width of 64 pixels are shifted by 32 + x0 += 32 + x1 += 32 + self.write_cmd(SET_COL_ADDR) + self.write_cmd(x0) + self.write_cmd(x1) + self.write_cmd(SET_PAGE_ADDR) + self.write_cmd(0) + self.write_cmd(self.pages - 1) + self.write_data(self.buffer) + + +class SSD1306_I2C(SSD1306): + def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False): + self.i2c = i2c + self.addr = addr + self.temp = bytearray(2) + self.write_list = [b"\\x40", None] # Co=0, D/C#=1 + super().__init__(width, height, external_vcc) + + def write_cmd(self, cmd): + self.temp[0] = 0x80 # Co=1, D/C#=0 + self.temp[1] = cmd + self.i2c.writeto(self.addr, self.temp) + + def write_data(self, buf): + self.write_list[1] = buf + self.i2c.writevto(self.addr, self.write_list) + + +class SSD1306_SPI(SSD1306): + def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): + self.rate = 10 * 1024 * 1024 + dc.init(dc.OUT, value=0) + res.init(res.OUT, value=0) + cs.init(cs.OUT, value=1) + self.spi = spi + self.dc = dc + self.res = res + self.cs = cs + import time + + self.res(1) + time.sleep_ms(1) + self.res(0) + time.sleep_ms(10) + self.res(1) + super().__init__(width, height, external_vcc) + + def write_cmd(self, cmd): + self.spi.init(baudrate=self.rate, polarity=0, phase=0) + self.cs(1) + self.dc(0) + self.cs(0) + self.spi.write(bytearray([cmd])) + self.cs(1) + + def write_data(self, buf): + self.spi.init(baudrate=self.rate, polarity=0, phase=0) + self.cs(1) + self.dc(1) + self.cs(0) + self.spi.write(buf) + self.cs(1) ` }, ], code: '', - components: [], - wires: [], + components: [{"type": "wokwi-ssd1306", "id": "aqi-oled1", "x": 420, "y": 60, "properties": {}}, {"type": "wokwi-dht22", "id": "aqi-dht1", "x": 440, "y": 260, "properties": {"temperature": "28", "humidity": "65"}}], + wires: [{"id": "aqi-oled-vcc", "start": {"componentId": "arduino-uno", "pinName": "3V3"}, "end": {"componentId": "aqi-oled1", "pinName": "3V3"}, "color": "#ff4444"}, {"id": "aqi-oled-gnd", "start": {"componentId": "arduino-uno", "pinName": "GND"}, "end": {"componentId": "aqi-oled1", "pinName": "GND"}, "color": "#000000"}, {"id": "aqi-oled-sda", "start": {"componentId": "arduino-uno", "pinName": "21"}, "end": {"componentId": "aqi-oled1", "pinName": "DATA"}, "color": "#22aaff"}, {"id": "aqi-oled-scl", "start": {"componentId": "arduino-uno", "pinName": "22"}, "end": {"componentId": "aqi-oled1", "pinName": "CLK"}, "color": "#ff8800"}, {"id": "aqi-dht-vcc", "start": {"componentId": "arduino-uno", "pinName": "3V3"}, "end": {"componentId": "aqi-dht1", "pinName": "VCC"}, "color": "#ff4444"}, {"id": "aqi-dht-gnd", "start": {"componentId": "arduino-uno", "pinName": "GND"}, "end": {"componentId": "aqi-dht1", "pinName": "GND"}, "color": "#000000"}, {"id": "aqi-dht-data", "start": {"componentId": "arduino-uno", "pinName": "27"}, "end": {"componentId": "aqi-dht1", "pinName": "SDA"}, "color": "#22cc66"}], tags: ["100-days", "dht", "esp32", "http_server", "i2c_oled", "micropython", "wifi"], }, { id: "100d-auto-night-light-using-ldr-esp32-plus-micropython", title: "Auto Night Light using LDR (ESP32 + MicroPython)", - description: "Auto Night Light using LDR (ESP32 + MicroPython) on ESP32 (MicroPython) \u2014 uses LDR.", + description: "Auto Night Light using LDR (ESP32 + MicroPython) on ESP32 (MicroPython) \u2014 uses LDR. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "sensors", difficulty: "beginner", boardType: "esp32", @@ -200,7 +371,7 @@ while True: { id: "100d-battery-monitor-with-blynk-iot", title: "Battery Monitor with Blynk IoT", - description: "Battery Monitor with Blynk IoT on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi.", + description: "Battery Monitor with Blynk IoT on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -546,7 +717,7 @@ while True: { id: "100d-bluetooth-based-wireless-led-control-system", title: "Bluetooth Based Wireless LED Control System", - description: "Bluetooth Based Wireless LED Control System on ESP32 (MicroPython) \u2014 uses BLE.", + description: "Bluetooth Based Wireless LED Control System on ESP32 (MicroPython) \u2014 uses BLE. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -584,10 +755,10 @@ while True: { id: "100d-blynk-based-iot-relay-control-micropython", title: "Blynk Based IoT Relay Control (MicroPython)", - description: "Blynk Based IoT Relay Control (MicroPython) on Raspberry Pi Pico W (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi.", + description: "Blynk Based IoT Relay Control (MicroPython) on Raspberry Pi Pico W (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "BlynkLib.py", content: `# Copyright (c) 2015-2019 Volodymyr Shymanskyy. See the file LICENSE for copying permission. @@ -908,7 +1079,7 @@ while True: { id: "100d-blynk-controlled-dc-brushless-fan", title: "Blynk Controlled DC Brushless Fan", - description: "Blynk Controlled DC Brushless Fan on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi.", + description: "Blynk Controlled DC Brushless Fan on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -1235,7 +1406,7 @@ while True: { id: "100d-clap-toggle-switch-using-esp32-and-digital-sound-sensor-micropython", title: "Clap Toggle Switch using ESP32 & Digital Sound Sensor (MicroPython)", - description: "Clap Toggle Switch using ESP32 & Digital Sound Sensor (MicroPython) on ESP32 (MicroPython).", + description: "Clap Toggle Switch using ESP32 & Digital Sound Sensor (MicroPython) on ESP32 (MicroPython). From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "sensors", difficulty: "beginner", boardType: "esp32", @@ -1278,7 +1449,7 @@ while True: { id: "100d-dc-motor-speed-control-web-slider", title: "DC Motor Speed Control (Web Slider)", - description: "DC Motor Speed Control (Web Slider) on ESP32 (MicroPython) \u2014 uses Servo, Wi-Fi.", + description: "DC Motor Speed Control (Web Slider) on ESP32 (MicroPython) \u2014 uses Servo, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "intermediate", boardType: "esp32", @@ -1381,7 +1552,7 @@ while True: { id: "100d-dht11-web-server-using-esp32-and-micropython", title: "DHT11 Web Server using ESP32 & MicroPython", - description: "DHT11 Web Server using ESP32 & MicroPython on ESP32 (MicroPython) \u2014 uses DHT, Wi-Fi.", + description: "DHT11 Web Server using ESP32 & MicroPython on ESP32 (MicroPython) \u2014 uses DHT, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -1524,7 +1695,7 @@ while True: { id: "100d-dimmer-led-using-potentiometer-micropython", title: "Dimmer LED using Potentiometer (MicroPython)", - description: "Dimmer LED using Potentiometer (MicroPython) on ESP32 (MicroPython) \u2014 uses Servo.", + description: "Dimmer LED using Potentiometer (MicroPython) on ESP32 (MicroPython) \u2014 uses Servo. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "beginner", boardType: "esp32", @@ -1555,7 +1726,7 @@ while True: { id: "100d-dual-ir-entry-exit-detector-with-telegram-alerts", title: "Dual IR Entry Exit Detector with Telegram Alerts", - description: "Dual IR Entry Exit Detector with Telegram Alerts on ESP32 (MicroPython) \u2014 uses Telegram, Wi-Fi.", + description: "Dual IR Entry Exit Detector with Telegram Alerts on ESP32 (MicroPython) \u2014 uses Telegram, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -1650,7 +1821,7 @@ while True: { id: "100d-eeprom-simulation-using-micropython-on-esp32-wokwi", title: "EEPROM Simulation using MicroPython on ESP32 (Wokwi)", - description: "EEPROM Simulation using MicroPython on ESP32 (Wokwi) on ESP32 (MicroPython).", + description: "EEPROM Simulation using MicroPython on ESP32 (Wokwi) on ESP32 (MicroPython). From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "basics", difficulty: "beginner", boardType: "esp32", @@ -1732,7 +1903,7 @@ while True: { id: "100d-esp32-ble-led-control", title: "ESP32 BLE LED Control", - description: "ESP32 BLE LED Control on ESP32 (MicroPython) \u2014 uses BLE.", + description: "ESP32 BLE LED Control on ESP32 (MicroPython) \u2014 uses BLE. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -1839,7 +2010,7 @@ while True: { id: "100d-esp32-hotspot-access-point-setup-micropython", title: "ESP32 Hotspot (Access Point) Setup MicroPython", - description: "ESP32 Hotspot (Access Point) Setup MicroPython on ESP32 (MicroPython) \u2014 uses Wi-Fi.", + description: "ESP32 Hotspot (Access Point) Setup MicroPython on ESP32 (MicroPython) \u2014 uses Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -1869,7 +2040,7 @@ print("🌐 IP Address:", ap.ifconfig()[0]) { id: "100d-esp32-ir-sensor-telegram-alert-micropython", title: "ESP32 IR Sensor Telegram Alert (MicroPython)", - description: "ESP32 IR Sensor Telegram Alert (MicroPython) on ESP32 (MicroPython) \u2014 uses Telegram, Wi-Fi.", + description: "ESP32 IR Sensor Telegram Alert (MicroPython) on ESP32 (MicroPython) \u2014 uses Telegram, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -1940,42 +2111,33 @@ while True: { id: "100d-esp32-oled-smart-ui-eyes-animation-time-and-weather-micropython", title: "ESP32 OLED Smart UI Eyes Animation Time & Weather (MicroPython)", - description: "ESP32 OLED Smart UI Eyes Animation Time & Weather (MicroPython) on ESP32 (MicroPython) \u2014 uses OLED, Wi-Fi.", + description: "ESP32 OLED Smart UI Eyes Animation Time & Weather (MicroPython) on ESP32 (MicroPython) \u2014 uses OLED, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "displays", difficulty: "intermediate", boardType: "esp32", languageMode: 'micropython', files: [ - { name: "main.py", content: `from machine import Pin, I2C + { name: "main.py", content: `from machine import Pin, SoftI2C import ssd1306 from time import sleep, localtime, time import network, ntptime import urequests as requests -import urandom as random +import urandom as random # ================= CONFIG ================= SSID = "ssid" PASSWORD = "pass" # IST Offset: 5 hours 30 mins = (5*3600 + 30*60) = 19800 seconds -UTC_OFFSET = 19800 +UTC_OFFSET = 19800 OWM_API_KEY = "key" CITY = "city" # ================= HARDWARE ================= -# Hardware I2C (peripheral 0) — SoftI2C bit-bangs GPIO and the Velxio -# ESP32 QEMU bridge can't route GPIO toggles back to the wokwi-ssd1306 -# slave registered at 0x3C, so write_cmd fails with ENODEV. Hardware -# I2C goes through the emulated I2C controller and reaches the slave. -i2c = I2C(0, scl=Pin(22), sda=Pin(21)) +i2c = SoftI2C(scl=Pin(22), sda=Pin(21)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) -# PULL_DOWN, not plain Pin.IN: the buttons sit between 3V3 and the pin, so -# without a pull-down the pin FLOATS while the button is open and pin.value() -# is meaningless. On a real board you read noise; here the node resolves to -# 3.3 V and both buttons look pressed forever, with wait_for_release() -# spinning on nothing. Same failure as on real hardware, not an emulator artifact. -touch_next = Pin(14, Pin.IN, Pin.PULL_DOWN) -touch_sel = Pin(27, Pin.IN, Pin.PULL_DOWN) +touch_next = Pin(14, Pin.IN) +touch_sel = Pin(27, Pin.IN) # ================= UTILS ================= def wifi_connect(): @@ -2290,31 +2452,14 @@ class SSD1306_SPI(SSD1306): ` }, ], code: '', - components: [ - { type: 'wokwi-ssd1306', id: 'oled1', x: 420, y: 80, properties: {} }, - { type: 'wokwi-pushbutton', id: 'btn-next', x: 420, y: 280, properties: { color: 'blue' } }, - { type: 'wokwi-pushbutton', id: 'btn-sel', x: 560, y: 280, properties: { color: 'green' } }, - ], - wires: [ - // OLED I2C — SDA = GPIO21, SCL = GPIO22 (matches SoftI2C in code) - { id: 'w-oled-vcc', start: { componentId: 'esp32', pinName: '3V3' }, end: { componentId: 'oled1', pinName: 'VIN' }, color: '#ff4444' }, - { id: 'w-oled-gnd', start: { componentId: 'esp32', pinName: 'GND.1' }, end: { componentId: 'oled1', pinName: 'GND' }, color: '#000000' }, - { id: 'w-oled-sda', start: { componentId: 'esp32', pinName: '21' }, end: { componentId: 'oled1', pinName: 'DATA' }, color: '#22aaff' }, - { id: 'w-oled-scl', start: { componentId: 'esp32', pinName: '22' }, end: { componentId: 'oled1', pinName: 'CLK' }, color: '#ff8800' }, - // Buttons — HIGH-when-pressed (one side to 3V3, other to GPIO). Code - // reads pin.value() == 1 on press, so they sit between 3.3V and the - // input pin, with Pin.PULL_DOWN in the sketch so the open state reads 0. - { id: 'w-btn-next-3v3', start: { componentId: 'esp32', pinName: '3V3' }, end: { componentId: 'btn-next', pinName: '1.l' }, color: '#ff4444' }, - { id: 'w-btn-next-gpio', start: { componentId: 'btn-next', pinName: '2.l' }, end: { componentId: 'esp32', pinName: '14' }, color: '#aa66ff' }, - { id: 'w-btn-sel-3v3', start: { componentId: 'esp32', pinName: '3V3' }, end: { componentId: 'btn-sel', pinName: '1.l' }, color: '#ff4444' }, - { id: 'w-btn-sel-gpio', start: { componentId: 'btn-sel', pinName: '2.l' }, end: { componentId: 'esp32', pinName: '27' }, color: '#22cc22' }, - ], + components: [], + wires: [], tags: ["100-days", "esp32", "i2c_oled", "micropython", "wifi"], }, { id: "100d-flask-server-based-led-control-using-micropython", title: "Flask Server Based LED Control using MicroPython", - description: "Flask Server Based LED Control using MicroPython on ESP32 (MicroPython) \u2014 uses HTTP server, Wi-Fi.", + description: "Flask Server Based LED Control using MicroPython on ESP32 (MicroPython) \u2014 uses HTTP server, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -2392,7 +2537,7 @@ while True: { id: "100d-iot-atmospheric-monitoring-system-using-esp32-wowki-and-blynk", title: "IoT Atmospheric Monitoring System using ESP32, wowki & Blynk", - description: "IoT Atmospheric Monitoring System using ESP32, wowki & Blynk on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi.", + description: "IoT Atmospheric Monitoring System using ESP32, wowki & Blynk on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -2664,12 +2809,95 @@ class Blynk(BlynkProtocol): self.process(data) +` }, + { name: "bmp180.py", content: `''' +bmp180.py — Velxio simulator adaptation. + +Keeps the classic BMP180 driver API the original project uses +(BMP180(i2c), .oversample, .sealevel, .temperature, .pressure, .altitude) +but talks to the BMP280 barometric sensor that the Velxio ESP32 simulator +emulates on the I2C bus (chip id 0x58, address 0x76/0x77) — the BMP180 +itself is not in the simulator's catalogue. + +On real hardware with an actual BMP180, replace this module with the +classic driver: https://github.com/micropython-IMU/micropython-bmp180 +''' + +from ustruct import unpack + + +class BMP180: + + def __init__(self, i2c): + self._i2c = i2c + addrs = i2c.scan() + if 0x76 in addrs: + self._addr = 0x76 + elif 0x77 in addrs: + self._addr = 0x77 + else: + self._addr = 0x76 # sensor not found yet — use the default + # BMP280 trimming coefficients live at 0x88..0x9F + buf = self._i2c.readfrom_mem(self._addr, 0x88, 24) + (self._T1, self._T2, self._T3, + self._P1, self._P2, self._P3, self._P4, self._P5, + self._P6, self._P7, self._P8, self._P9) = unpack('> 4) + adc_t = (b[3] << 12) | (b[4] << 4) | (b[5] >> 4) + return adc_t, adc_p + + # Bosch BMP280 compensation formulas (datasheet section 3.11.3) + def _t_fine(self, adc_t): + v1 = (((adc_t >> 3) - (self._T1 << 1)) * self._T2) >> 11 + s = (adc_t >> 4) - self._T1 + v2 = ((s * s >> 12) * self._T3) >> 14 + return v1 + v2 + + @property + def temperature(self): + '''Temperature in degrees C.''' + adc_t, _ = self._read_raw() + return ((self._t_fine(adc_t) * 5 + 128) >> 8) / 100 + + @property + def pressure(self): + '''Pressure in Pa (same unit as the classic BMP180 driver).''' + adc_t, adc_p = self._read_raw() + tf = self._t_fine(adc_t) + v1 = tf / 2.0 - 64000.0 + v2 = v1 * v1 * self._P6 / 32768.0 + v2 = v2 + v1 * self._P5 * 2.0 + v2 = v2 / 4.0 + self._P4 * 65536.0 + v1 = (self._P3 * v1 * v1 / 524288.0 + self._P2 * v1) / 524288.0 + v1 = (1.0 + v1 / 32768.0) * self._P1 + if v1 == 0: + return 0.0 + p = 1048576.0 - adc_p + p = (p - v2 / 4096.0) * 6250.0 / v1 + p = p + (self._P9 * p * p / 2147483648.0 + + p * self._P8 / 32768.0 + self._P7) / 16.0 + return p + + @property + def altitude(self): + '''Altitude in m, from pressure vs the configured sea-level pressure.''' + try: + return 44330.0 * (1.0 - (self.pressure / self.sealevel) ** (1.0 / 5.255)) + except Exception: + return 0.0 ` }, { name: "main.py", content: ` '''Copyright (c) 2026 Kritish Mohapatra''' import network -from machine import SoftI2C, Pin +from machine import I2C, Pin import BlynkLib from time import sleep from bmp180 import BMP180 @@ -2679,6 +2907,8 @@ wifissid = "Wokwi-GUEST" wifipass = "" # -------- Blynk Token -------- +# Replace with your real Blynk Cloud token to see the data on a dashboard. +# The demo keeps printing sensor readings on the serial monitor either way. auth = "dashboard-token" # Connect WiFi @@ -2687,23 +2917,27 @@ sta_if.active(True) sta_if.connect(wifissid, wifipass) while not sta_if.isconnected(): - pass + sleep(0.1) print("Connected to Wi-Fi:", sta_if.ifconfig()) -# Start Blynk -blynk = BlynkLib.Blynk(auth, insecure=True) +# Start Blynk (optional — skipped gracefully when the cloud is unreachable) +try: + blynk = BlynkLib.Blynk(auth, insecure=True) +except Exception as e: + print("Blynk Cloud unreachable, running offline:", e) + blynk = None # -------- BMP180 I2C -------- -i2c = SoftI2C(scl=Pin(22), sda=Pin(21)) +# The simulator emulates the ESP32's hardware I2C controller, so use +# machine.I2C — a bit-banged SoftI2C bus is not decoded by the emulator. +i2c = I2C(0, scl=Pin(22), sda=Pin(21)) bmp = BMP180(i2c) bmp.oversample = 2 bmp.sealevel = 101325 # sea level pressure # -------- MAIN LOOP -------- while True: - blynk.run() - temp = bmp.temperature pressure = bmp.pressure / 100 # Pa → hPa altitude = bmp.altitude @@ -2714,22 +2948,28 @@ while True: print("----------------------") # Send to Blynk - blynk.virtual_write(0, temp) # V0 Temperature - blynk.virtual_write(1, pressure) # V1 Pressure - blynk.virtual_write(2, altitude) # V2 Altitude + if blynk: + try: + blynk.run() + blynk.virtual_write(0, temp) # V0 Temperature + blynk.virtual_write(1, pressure) # V1 Pressure + blynk.virtual_write(2, altitude) # V2 Altitude + except Exception as e: + print("Blynk error, continuing offline:", e) + blynk = None sleep(2) ` }, ], code: '', - components: [], - wires: [], + components: [{"type": "velxio-bmp280", "id": "atm-bmp1", "x": 430, "y": 150, "properties": {"temperature": "24.5", "pressure": "1013.25"}}], + wires: [{"id": "atm-vcc", "start": {"componentId": "arduino-uno", "pinName": "3V3"}, "end": {"componentId": "atm-bmp1", "pinName": "VCC"}, "color": "#ff4444"}, {"id": "atm-gnd", "start": {"componentId": "arduino-uno", "pinName": "GND"}, "end": {"componentId": "atm-bmp1", "pinName": "GND"}, "color": "#000000"}, {"id": "atm-sda", "start": {"componentId": "arduino-uno", "pinName": "21"}, "end": {"componentId": "atm-bmp1", "pinName": "SDA"}, "color": "#22aaff"}, {"id": "atm-scl", "start": {"componentId": "arduino-uno", "pinName": "22"}, "end": {"componentId": "atm-bmp1", "pinName": "SCL"}, "color": "#ff8800"}], tags: ["100-days", "blynk", "blynk_cloud", "esp32", "micropython", "wifi"], }, { id: "100d-iot-based-dsm-smart-metering", title: "IoT Based DSM Smart Metering", - description: "IoT Based DSM Smart Metering on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, OTA, Wi-Fi.", + description: "IoT Based DSM Smart Metering on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, OTA, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -3400,7 +3640,7 @@ while True: { id: "100d-iot-environment-monitoring-with-anomaly-detection", title: "IoT Environment Monitoring With Anomaly Detection", - description: "IoT Environment Monitoring With Anomaly Detection on ESP32 (MicroPython) \u2014 uses DHT, LDR, ThingSpeak, Wi-Fi.", + description: "IoT Environment Monitoring With Anomaly Detection on ESP32 (MicroPython) \u2014 uses DHT, LDR, ThingSpeak, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -3477,10 +3717,10 @@ while True: { id: "100d-iot-relay-control-web-server-raspberry-pi-pico-2w", title: "IoT Relay Control Web Server (Raspberry Pi Pico 2W)", - description: "IoT Relay Control Web Server (Raspberry Pi Pico 2W) on Raspberry Pi Pico W (MicroPython) \u2014 uses Wi-Fi.", + description: "IoT Relay Control Web Server (Raspberry Pi Pico 2W) on Raspberry Pi Pico W (MicroPython) \u2014 uses Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "main.py", content: `import network @@ -3634,7 +3874,7 @@ while True: { id: "100d-iot-smart-irrigation-system", title: "IoT Smart Irrigation System", - description: "IoT Smart Irrigation System on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi.", + description: "IoT Smart Irrigation System on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -3995,7 +4235,7 @@ while True: { id: "100d-joystick-controlled-servo", title: "Joystick Controlled Servo", - description: "Joystick Controlled Servo on ESP32 (MicroPython) \u2014 uses Servo.", + description: "Joystick Controlled Servo on ESP32 (MicroPython) \u2014 uses Servo. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "beginner", boardType: "esp32", @@ -4044,7 +4284,7 @@ while True: { id: "100d-joystick-direction-display-with-oled", title: "Joystick Direction Display with OLED", - description: "Joystick Direction Display with OLED on Raspberry Pi Pico W (MicroPython) \u2014 uses OLED.", + description: "Joystick Direction Display with OLED on Raspberry Pi Pico W (MicroPython) \u2014 uses OLED. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "displays", difficulty: "intermediate", boardType: "raspberry-pi-pico", @@ -4275,10 +4515,143 @@ class SSD1306_SPI(SSD1306): wires: [], tags: ["100-days", "i2c_oled", "micropython", "raspberry-pi-pico", "rp2040"], }, + { + id: "100d-mq4-gas-leak-detection-system-using-esp32-and-micropython", + title: "MQ4 Gas Leak Detection System using ESP32 and MicroPython", + description: "MQ4 Gas Leak Detection System using ESP32 and MicroPython on ESP32 (MicroPython). From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", + category: "basics", + difficulty: "beginner", + boardType: "esp32", + languageMode: 'micropython', + files: [ + { name: "main.py", content: `from machine import ADC, Pin +import time + +# MQ4 gas sensor setup +mq4 = ADC(Pin(34)) # Analog input pin +mq4.atten(ADC.ATTN_11DB) # Full voltage range +mq4.width(ADC.WIDTH_10BIT) # 10-bit resolution + +# Buzzer setup +buzzer = Pin(15, Pin.OUT) + +# Threshold for gas alert (tune this based on testing) +GAS_THRESHOLD = 240 + +while True: + gas_value = mq4.read() + voltage = gas_value * 3.3 / 1023 + + print("Gas reading (raw):", gas_value) + print("Voltage:", round(voltage, 2), "V") + + # Alert condition + if gas_value > GAS_THRESHOLD: + buzzer.on() + print("⚠️ Gas leak detected! Buzzer ON") + else: + buzzer.off() + + print("----------------------------") + time.sleep(2) + +` }, + ], + code: '', + components: [], + wires: [], + tags: ["100-days", "esp32", "micropython"], + }, + { + id: "100d-mq7-co-gas-detection-esp32", + title: "MQ7 CO Gas Detection ESP32", + description: "MQ7 CO Gas Detection ESP32 on ESP32 (MicroPython). From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", + category: "basics", + difficulty: "beginner", + boardType: "esp32", + languageMode: 'micropython', + files: [ + { name: "main.py", content: `from machine import ADC, Pin +import time + +# MQ-7 analog output on GPIO 35 +mq7 = ADC(Pin(35)) +mq7.atten(ADC.ATTN_11DB) # 0–3.3V +mq7.width(ADC.WIDTH_12BIT) # 12-bit ADC + +print("MQ-7 CO Sensor Test") +print("Warming up MQ-7 sensor (60 seconds)...") + +# Warm-up phase +time.sleep(60) + +print("Start reading MQ-7 values") + +while True: + readings = [] + for i in range(10): + readings.append(mq7.read()) + time.sleep(0.1) + + avg_val = sum(readings) // len(readings) + print("MQ-7 ADC Value:", avg_val) + + time.sleep(2) + +` }, + ], + code: '', + components: [], + wires: [], + tags: ["100-days", "esp32", "micropython"], + }, + { + id: "100d-mq-135-gas-sensor-with-esp32-micropython", + title: "MQ 135 Gas Sensor with ESP32 (MicroPython)", + description: "MQ 135 Gas Sensor with ESP32 (MicroPython) on ESP32 (MicroPython) \u2014 uses OTA. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", + category: "sensors", + difficulty: "advanced", + boardType: "esp32", + languageMode: 'micropython', + files: [ + { name: "main.py", content: `from machine import ADC, Pin +import time + +# MQ-135 connected to GPIO 34 +mq135 = ADC(Pin(34)) +mq135.atten(ADC.ATTN_11DB) # Allow 0–3.3V +mq135.width(ADC.WIDTH_12BIT) # 12-bit ADC (0–4095) + +print("MQ-135 Sensor Test") +print("Warming up sensor...") + +time.sleep(10) # short warm-up for testing + +while True: + total = 0 + samples = 10 + + for i in range(samples): + val = mq135.read() + total += val + time.sleep(0.1) + + avg_val = total // samples + + print("MQ-135 ADC Value:", avg_val) + time.sleep(2) + +` }, + ], + code: '', + components: [], + wires: [], + tags: ["100-days", "esp32", "micropython", "ota"], + }, { id: "100d-micropython-watch", title: "MicroPython Watch", - description: "MicroPython Watch on ESP32 (MicroPython) \u2014 uses OLED, Wi-Fi.", + description: "MicroPython Watch on ESP32 (MicroPython) \u2014 uses OLED, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "displays", difficulty: "intermediate", boardType: "esp32", @@ -4546,143 +4919,10 @@ class SSD1306_SPI(SSD1306): wires: [], tags: ["100-days", "esp32", "i2c_oled", "micropython", "wifi"], }, - { - id: "100d-mq4-gas-leak-detection-system-using-esp32-and-micropython", - title: "MQ4 Gas Leak Detection System using ESP32 and MicroPython", - description: "MQ4 Gas Leak Detection System using ESP32 and MicroPython on ESP32 (MicroPython).", - category: "basics", - difficulty: "beginner", - boardType: "esp32", - languageMode: 'micropython', - files: [ - { name: "main.py", content: `from machine import ADC, Pin -import time - -# MQ4 gas sensor setup -mq4 = ADC(Pin(34)) # Analog input pin -mq4.atten(ADC.ATTN_11DB) # Full voltage range -mq4.width(ADC.WIDTH_10BIT) # 10-bit resolution - -# Buzzer setup -buzzer = Pin(15, Pin.OUT) - -# Threshold for gas alert (tune this based on testing) -GAS_THRESHOLD = 240 - -while True: - gas_value = mq4.read() - voltage = gas_value * 3.3 / 1023 - - print("Gas reading (raw):", gas_value) - print("Voltage:", round(voltage, 2), "V") - - # Alert condition - if gas_value > GAS_THRESHOLD: - buzzer.on() - print("⚠️ Gas leak detected! Buzzer ON") - else: - buzzer.off() - - print("----------------------------") - time.sleep(2) - -` }, - ], - code: '', - components: [], - wires: [], - tags: ["100-days", "esp32", "micropython"], - }, - { - id: "100d-mq7-co-gas-detection-esp32", - title: "MQ7 CO Gas Detection ESP32", - description: "MQ7 CO Gas Detection ESP32 on ESP32 (MicroPython).", - category: "basics", - difficulty: "beginner", - boardType: "esp32", - languageMode: 'micropython', - files: [ - { name: "main.py", content: `from machine import ADC, Pin -import time - -# MQ-7 analog output on GPIO 35 -mq7 = ADC(Pin(35)) -mq7.atten(ADC.ATTN_11DB) # 0–3.3V -mq7.width(ADC.WIDTH_12BIT) # 12-bit ADC - -print("MQ-7 CO Sensor Test") -print("Warming up MQ-7 sensor (60 seconds)...") - -# Warm-up phase -time.sleep(60) - -print("Start reading MQ-7 values") - -while True: - readings = [] - for i in range(10): - readings.append(mq7.read()) - time.sleep(0.1) - - avg_val = sum(readings) // len(readings) - print("MQ-7 ADC Value:", avg_val) - - time.sleep(2) - -` }, - ], - code: '', - components: [], - wires: [], - tags: ["100-days", "esp32", "micropython"], - }, - { - id: "100d-mq-135-gas-sensor-with-esp32-micropython", - title: "MQ 135 Gas Sensor with ESP32 (MicroPython)", - description: "MQ 135 Gas Sensor with ESP32 (MicroPython) on ESP32 (MicroPython) \u2014 uses OTA.", - category: "sensors", - difficulty: "advanced", - boardType: "esp32", - languageMode: 'micropython', - files: [ - { name: "main.py", content: `from machine import ADC, Pin -import time - -# MQ-135 connected to GPIO 34 -mq135 = ADC(Pin(34)) -mq135.atten(ADC.ATTN_11DB) # Allow 0–3.3V -mq135.width(ADC.WIDTH_12BIT) # 12-bit ADC (0–4095) - -print("MQ-135 Sensor Test") -print("Warming up sensor...") - -time.sleep(10) # short warm-up for testing - -while True: - total = 0 - samples = 10 - - for i in range(samples): - val = mq135.read() - total += val - time.sleep(0.1) - - avg_val = total // samples - - print("MQ-135 ADC Value:", avg_val) - time.sleep(2) - -` }, - ], - code: '', - components: [], - wires: [], - tags: ["100-days", "esp32", "micropython", "ota"], - }, { id: "100d-ntp-synchronized-digital-clock-using-esp32-and-max7219", title: "NTP Synchronized Digital Clock using ESP32 & MAX7219", - description: "NTP Synchronized Digital Clock using ESP32 & MAX7219 on ESP32 (MicroPython) \u2014 uses MAX7219, Wi-Fi.", + description: "NTP Synchronized Digital Clock using ESP32 & MAX7219 on ESP32 (MicroPython) \u2014 uses MAX7219, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "displays", difficulty: "intermediate", boardType: "esp32", @@ -4860,10 +5100,10 @@ class Matrix8x8: { id: "100d-ota-update-pico2w", title: "OTA Update Pico2W", - description: "OTA Update Pico2W on Raspberry Pi Pico W (MicroPython) \u2014 uses OTA, Wi-Fi.", + description: "OTA Update Pico2W on Raspberry Pi Pico W (MicroPython) \u2014 uses OTA, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "boot.py", content: `# boot.py - Runs automatically every time Pico starts @@ -4961,10 +5201,42 @@ def check_and_update(): wires: [], tags: ["100-days", "micropython", "ota", "raspberry-pi-pico", "rp2040", "wifi"], }, + { + id: "100d-pir-motion-detector-using-raspberry-pi-pico-2w-and-micropython", + title: "PIR Motion Detector using Raspberry Pi Pico 2W & MicroPython", + description: "PIR Motion Detector using Raspberry Pi Pico 2W & MicroPython on Raspberry Pi Pico W (MicroPython). From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", + category: "basics", + difficulty: "beginner", + boardType: "raspberry-pi-pico", + languageMode: 'micropython', + files: [ + { name: "main.py", content: `from machine import Pin +import time + +pir = Pin(16, Pin.IN, Pin.PULL_DOWN) # PIR sensor pin +led = Pin("LED", Pin.OUT) # Built-in LED + +print("PIR Motion Detector Started...") + +while True: + if pir.value() == 1: + print("Motion Detected!") + led.value(1) + time.sleep(1) + else: + print("No motion") + led.value(0) + time.sleep(0.2)` }, + ], + code: '', + components: [], + wires: [], + tags: ["100-days", "micropython", "pico-w", "raspberry-pi-pico"], + }, { id: "100d-password-lock-system-using-esp32", title: "Password Lock System using ESP32", - description: "Password Lock System using ESP32 on ESP32 (MicroPython) \u2014 uses I\u00b2C LCD.", + description: "Password Lock System using ESP32 on ESP32 (MicroPython) \u2014 uses I\u00b2C LCD. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "displays", difficulty: "intermediate", boardType: "esp32", @@ -5354,10 +5626,10 @@ while True: { id: "100d-pico-2-w-dht11-http-csv-logger", title: "Pico 2 W Dht11 Http Csv Logger", - description: "Pico 2 W Dht11 Http Csv Logger on Raspberry Pi Pico W (MicroPython) \u2014 uses DHT, HTTP server, Wi-Fi.", + description: "Pico 2 W Dht11 Http Csv Logger on Raspberry Pi Pico W (MicroPython) \u2014 uses DHT, HTTP server, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "app.py", content: `from flask import Flask, request @@ -5438,10 +5710,10 @@ while True: { id: "100d-pico-w-async-led-control-micropython", title: "Pico W Async LED Control (MicroPython)", - description: "Pico W Async LED Control (MicroPython) on Raspberry Pi Pico W (MicroPython) \u2014 uses Wi-Fi.", + description: "Pico W Async LED Control (MicroPython) on Raspberry Pi Pico W (MicroPython) \u2014 uses Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "main.py", content: `import uasyncio as asyncio @@ -5559,10 +5831,10 @@ asyncio.run(main()) { id: "100d-pico-w-web-servo-controller", title: "Pico W Web Servo Controller", - description: "Pico W Web Servo Controller on Raspberry Pi Pico W (MicroPython) \u2014 uses OTA, Servo, Wi-Fi.", + description: "Pico W Web Servo Controller on Raspberry Pi Pico W (MicroPython) \u2014 uses OTA, Servo, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "advanced", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "main.py", content: `import network @@ -5822,42 +6094,10 @@ while True: wires: [], tags: ["100-days", "micropython", "ota", "pico-w", "raspberry-pi-pico", "servo", "wifi"], }, - { - id: "100d-pir-motion-detector-using-raspberry-pi-pico-2w-and-micropython", - title: "PIR Motion Detector using Raspberry Pi Pico 2W & MicroPython", - description: "PIR Motion Detector using Raspberry Pi Pico 2W & MicroPython on Raspberry Pi Pico W (MicroPython).", - category: "basics", - difficulty: "beginner", - boardType: "raspberry-pi-pico", - languageMode: 'micropython', - files: [ - { name: "main.py", content: `from machine import Pin -import time - -pir = Pin(16, Pin.IN, Pin.PULL_DOWN) # PIR sensor pin -led = Pin("LED", Pin.OUT) # Built-in LED - -print("PIR Motion Detector Started...") - -while True: - if pir.value() == 1: - print("Motion Detected!") - led.value(1) - time.sleep(1) - else: - print("No motion") - led.value(0) - time.sleep(0.2)` }, - ], - code: '', - components: [], - wires: [], - tags: ["100-days", "micropython", "pico-w", "raspberry-pi-pico"], - }, { id: "100d-potentiometer-visualizer", title: "Potentiometer Visualizer", - description: "Potentiometer Visualizer on ESP32 (MicroPython).", + description: "Potentiometer Visualizer on ESP32 (MicroPython). From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "basics", difficulty: "beginner", boardType: "esp32", @@ -5894,7 +6134,7 @@ while True: { id: "100d-pulse-monitor", title: "Pulse Monitor", - description: "Pulse Monitor on ESP32 (MicroPython) \u2014 uses OLED.", + description: "Pulse Monitor on ESP32 (MicroPython) \u2014 uses OLED. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "displays", difficulty: "intermediate", boardType: "esp32", @@ -6141,13 +6381,80 @@ class SSD1306_SPI(SSD1306): wires: [], tags: ["100-days", "esp32", "i2c_oled", "micropython"], }, + { + id: "100d-rgb-color-mixer-using-potentiometers-esp32-plus-micropython", + title: "RGB Color Mixer using Potentiometers (ESP32 + MicroPython)", + description: "RGB Color Mixer using Potentiometers (ESP32 + MicroPython) on ESP32 (MicroPython) \u2014 uses Servo. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", + category: "robotics", + difficulty: "beginner", + boardType: "esp32", + languageMode: 'micropython', + files: [ + { name: "main.py", content: `# ESP32 MicroPython - RGB controlled by 3 potentiometers (common-cathode example) +from machine import ADC, Pin, PWM +import time + +# PWM pins for RGB +p_r = PWM(Pin(25), freq=1000) # R +p_g = PWM(Pin(26), freq=1000) # G +p_b = PWM(Pin(27), freq=1000) # B + +# ADC pins for pots +a_r = ADC(Pin(36)) # Pot for R +a_r.atten(ADC.ATTN_11DB) +a_g = ADC(Pin(39)) +a_g.atten(ADC.ATTN_11DB) +a_b = ADC(Pin(34)) +a_b.atten(ADC.ATTN_11DB) + +# Helper: map ADC (0-4095) to PWM duty (0-1023) +def map_adc_to_duty(x): + return int((x / 4095) * 1023) +# If you have common-anode LED, set invert = True +invert = False + +while True: + # Read potentiometer values + raw_r = a_r.read() + raw_g = a_g.read() + raw_b = a_b.read() + + # Map to PWM duty + r = map_adc_to_duty(raw_r) + g = map_adc_to_duty(raw_g) + b = map_adc_to_duty(raw_b) + + if invert: + r = 1023 - r + g = 1023 - g + b = 1023 - b + + # Apply PWM + p_r.duty(r) + p_g.duty(g) + p_b.duty(b) + + # Print live values + print("ADC R: {:4d} G: {:4d} B: {:4d} | PWM R: {:4d} G: {:4d} B: {:4d}".format( + raw_r, raw_g, raw_b, r, g, b + )) + + time.sleep_ms(200) + +` }, + ], + code: '', + components: [], + wires: [], + tags: ["100-days", "esp32", "micropython", "servo"], + }, { id: "100d-raspberry-pi-pico-2-w-thingsboard-iot", title: "Raspberry Pi Pico 2 W ThingsBoard IoT", - description: "Raspberry Pi Pico 2 W ThingsBoard IoT on Raspberry Pi Pico W (MicroPython) \u2014 uses DHT, MQTT, Wi-Fi.", + description: "Raspberry Pi Pico 2 W ThingsBoard IoT on Raspberry Pi Pico W (MicroPython) \u2014 uses DHT, MQTT, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "main.py", content: `import network @@ -6158,10 +6465,10 @@ from machine import Pin from umqttsimple import MQTTClient # --- Configuration --- -WIFI_SSID = "Velxio-GUEST" # Velxio simulator's built-in WiFi network -WIFI_PASSWORD = "" # the simulator AP is open +WIFI_SSID = "kritish" # +WIFI_PASSWORD = "@pass" THINGSBOARD_HOST = "eu.thingsboard.cloud" -ACCESS_TOKEN = "tokenn" # replace with YOUR ThingsBoard device token +ACCESS_TOKEN = "tokenn" # --- Hardware Setup --- # Using "LED" for Pico W onboard LED, or Pin(15) for an external LED @@ -6468,77 +6775,10 @@ class MQTTClient: wires: [], tags: ["100-days", "dht", "micropython", "mqtt", "pico-w", "raspberry-pi-pico", "wifi"], }, - { - id: "100d-rgb-color-mixer-using-potentiometers-esp32-plus-micropython", - title: "RGB Color Mixer using Potentiometers (ESP32 + MicroPython)", - description: "RGB Color Mixer using Potentiometers (ESP32 + MicroPython) on ESP32 (MicroPython) \u2014 uses Servo.", - category: "robotics", - difficulty: "beginner", - boardType: "esp32", - languageMode: 'micropython', - files: [ - { name: "main.py", content: `# ESP32 MicroPython - RGB controlled by 3 potentiometers (common-cathode example) -from machine import ADC, Pin, PWM -import time - -# PWM pins for RGB -p_r = PWM(Pin(25), freq=1000) # R -p_g = PWM(Pin(26), freq=1000) # G -p_b = PWM(Pin(27), freq=1000) # B - -# ADC pins for pots -a_r = ADC(Pin(36)) # Pot for R -a_r.atten(ADC.ATTN_11DB) -a_g = ADC(Pin(39)) -a_g.atten(ADC.ATTN_11DB) -a_b = ADC(Pin(34)) -a_b.atten(ADC.ATTN_11DB) - -# Helper: map ADC (0-4095) to PWM duty (0-1023) -def map_adc_to_duty(x): - return int((x / 4095) * 1023) -# If you have common-anode LED, set invert = True -invert = False - -while True: - # Read potentiometer values - raw_r = a_r.read() - raw_g = a_g.read() - raw_b = a_b.read() - - # Map to PWM duty - r = map_adc_to_duty(raw_r) - g = map_adc_to_duty(raw_g) - b = map_adc_to_duty(raw_b) - - if invert: - r = 1023 - r - g = 1023 - g - b = 1023 - b - - # Apply PWM - p_r.duty(r) - p_g.duty(g) - p_b.duty(b) - - # Print live values - print("ADC R: {:4d} G: {:4d} B: {:4d} | PWM R: {:4d} G: {:4d} B: {:4d}".format( - raw_r, raw_g, raw_b, r, g, b - )) - - time.sleep_ms(200) - -` }, - ], - code: '', - components: [], - wires: [], - tags: ["100-days", "esp32", "micropython", "servo"], - }, { id: "100d-servo-motor-control-with-raspberry-pi-pico-2-w-micropython", title: "Servo Motor Control with Raspberry Pi Pico 2 W (MicroPython)", - description: "Servo Motor Control with Raspberry Pi Pico 2 W (MicroPython) on Raspberry Pi Pico W (MicroPython) \u2014 uses Servo.", + description: "Servo Motor Control with Raspberry Pi Pico 2 W (MicroPython) on Raspberry Pi Pico W (MicroPython) \u2014 uses Servo. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "beginner", boardType: "raspberry-pi-pico", @@ -6585,7 +6825,7 @@ while True: { id: "100d-single-digit-seven-segment-display-with-raspberry-pi-pico-micropython", title: "Single Digit Seven Segment Display with Raspberry Pi-Pico (MicroPython)", - description: "Single Digit Seven Segment Display with Raspberry Pi-Pico (MicroPython) on Raspberry Pi Pico W (MicroPython).", + description: "Single Digit Seven Segment Display with Raspberry Pi-Pico (MicroPython) on Raspberry Pi Pico W (MicroPython). From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "basics", difficulty: "beginner", boardType: "raspberry-pi-pico", @@ -6741,7 +6981,7 @@ while True: { id: "100d-smart-home-automation-system", title: "Smart Home Automation System", - description: "Smart Home Automation System on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, DHT, Wi-Fi.", + description: "Smart Home Automation System on ESP32 (MicroPython) \u2014 uses Blynk, Blynk Cloud, DHT, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", boardType: "esp32", @@ -7147,7 +7387,7 @@ while True: { id: "100d-smart-indoor-security-system", title: "Smart Indoor Security System", - description: "Smart Indoor Security System on ESP32 (MicroPython) \u2014 uses Wi-Fi.", + description: "Smart Indoor Security System on ESP32 (MicroPython) \u2014 uses Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -7290,7 +7530,7 @@ while True: { id: "100d-smart-iot-gas-monitoring-system", title: "Smart IoT Gas Monitoring System", - description: "Smart IoT Gas Monitoring System on ESP32 (MicroPython) \u2014 uses DHT, HTTP server, Wi-Fi.", + description: "Smart IoT Gas Monitoring System on ESP32 (MicroPython) \u2014 uses DHT, HTTP server, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "intermediate", boardType: "esp32", @@ -7561,7 +7801,7 @@ while True: { id: "100d-stepper-motor-control-using-esp32-and-a4988-micropython", title: "Stepper Motor Control using ESP32 & A4988 (MicroPython)", - description: "Stepper Motor Control using ESP32 & A4988 (MicroPython) on ESP32 (MicroPython) \u2014 uses Stepper.", + description: "Stepper Motor Control using ESP32 & A4988 (MicroPython) on ESP32 (MicroPython) \u2014 uses Stepper. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "intermediate", boardType: "esp32", @@ -7609,7 +7849,7 @@ while True: { id: "100d-temperature-based-led-indicator-micropython-esp32", title: "Temperature Based LED Indicator (MicroPython ESP32)", - description: "Temperature Based LED Indicator (MicroPython ESP32) on ESP32 (MicroPython) \u2014 uses Servo, Wi-Fi.", + description: "Temperature Based LED Indicator (MicroPython ESP32) on ESP32 (MicroPython) \u2014 uses Servo, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "intermediate", boardType: "esp32", @@ -7712,7 +7952,7 @@ while True: { id: "100d-ultrasonic-led-distance-indicator-esp32-micropython", title: "Ultrasonic LED Distance Indicator ESP32 MicroPython", - description: "Ultrasonic LED Distance Indicator ESP32 MicroPython on ESP32 (MicroPython) \u2014 uses HC-SR04.", + description: "Ultrasonic LED Distance Indicator ESP32 MicroPython on ESP32 (MicroPython) \u2014 uses HC-SR04. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "sensors", difficulty: "beginner", boardType: "esp32", @@ -7829,10 +8069,10 @@ while True: { id: "100d-websocket-led-control-using-raspberry-pi-pico-w", title: "WebSocket LED Control using Raspberry Pi Pico W", - description: "WebSocket LED Control using Raspberry Pi Pico W on Raspberry Pi Pico W (MicroPython) \u2014 uses WebSocket, Wi-Fi.", + description: "WebSocket LED Control using Raspberry Pi Pico W on Raspberry Pi Pico W (MicroPython) \u2014 uses WebSocket, Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "communication", difficulty: "advanced", - boardType: "pi-pico-w", + boardType: "raspberry-pi-pico", languageMode: 'micropython', files: [ { name: "main.py", content: `import socket @@ -7942,7 +8182,7 @@ while True: { id: "100d-wi-fi-controlled-4wd-robot-car", title: "Wi Fi Controlled 4WD Robot Car", - description: "Wi Fi Controlled 4WD Robot Car on ESP32 (MicroPython) \u2014 uses Wi-Fi.", + description: "Wi Fi Controlled 4WD Robot Car on ESP32 (MicroPython) \u2014 uses Wi-Fi. From Kritish Mohapatra's 100 Days of IoT series: https://github.com/kritishmohapatra/100_Days_100_IoT_Projects", category: "robotics", difficulty: "intermediate", boardType: "esp32",