From a13eb3e7e27f0a7f432a66f994a057ff35e3aa70 Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Mon, 27 Jul 2026 05:01:49 +0200 Subject: [PATCH] fix(adc,examples): mapa ADC por chip, entradas flotantes y una auditoria de la galeria MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tres cosas que salieron al tirar del hilo de los pull-ups. 1) ESP32_ADC_PIN_MAP era la tabla del ESP32 CLASICO aplicada a toda la familia, y fallaba de dos maneras: - S3: sus pines ADC son GPIO1..20, ninguno esta en esa tabla, asi que la busqueda devolvia undefined y el listener del potenciometro no llegaba a engancharse. El mando no hacia nada. - C3/C6: GPIO0 SI esta en la tabla clasica, como ADC2_CH1 -> canal 9. Pero en esos chips GPIO0 es ADC1_CH0 y sus motores toman un indice de canal de ADC1 (0..4). El valor se empujaba al canal 9, fuera de rango, descartado en silencio mientras el firmware leia el 0. Una respuesta equivocada en vez de ninguna, que es peor. adcPinMapFor(boardKind) devuelve la tabla del chip. 2) El ejemplo de las gafas OLED en MicroPython declaraba sus botones con Pin.IN a secas. Van entre 3V3 y el pin, asi que sin pull-down el pin queda FLOTANDO con el boton abierto. El propio ejemplo ya lo avisaba en un comentario ("Add Pin.PULL_DOWN if the pin floats") — ahora lo hace. Es un fallo de hardware de verdad, no un artefacto del emulador. 3) gallery-run-gate.audit.test.ts: EditorToolbar bloquea el Run cuando el verificador de circuito saca errores, asi que un circuito invalido no es cosmetico, es la diferencia entre un ejemplo que arranca y uno que parece muerto. Y esos defectos se esconden hasta que el circuito resuelve DE PUNTA A PUNTA: c3-button llevaba un LED de 506 mA que nadie veia porque sus cables apuntaban a pines inexistentes. El test reproduce la puerta del Run tal cual (mismo snapshot de peor caso, mismo buildInputFromStore, mismo verifyCircuit, ngspice de verdad) sobre los 227 ejemplos. Encontro tres mas sin resistencia en serie —nano-button-led, mega-led-chase y mega-serial-control, 17 LEDs en total— y ahora quedan 0. A partir de aqui, un ejemplo nuevo con un LED colgado del GPIO salta en CI. --- .../__tests__/gallery-run-gate.audit.test.ts | 116 ++ .../components/simulator/SimulatorCanvas.tsx | 705 ++++----- .../velxio-components/Esp32Element.ts | 39 + frontend/src/data/examples-100-days.ts | 11 +- frontend/src/data/examples.ts | 1378 ++++++++++++++--- 5 files changed, 1685 insertions(+), 564 deletions(-) create mode 100644 frontend/src/__tests__/gallery-run-gate.audit.test.ts diff --git a/frontend/src/__tests__/gallery-run-gate.audit.test.ts b/frontend/src/__tests__/gallery-run-gate.audit.test.ts new file mode 100644 index 00000000..c885c0db --- /dev/null +++ b/frontend/src/__tests__/gallery-run-gate.audit.test.ts @@ -0,0 +1,116 @@ +import { describe, expect, it } from 'vitest'; +import { exampleProjects as examples } from '../data/examples'; +import { buildInputFromStore } from '../simulation/spice/storeAdapter'; +import { BOARD_PIN_GROUPS } from '../simulation/spice/boardPinGroups'; +import { verifyCircuit } from '../simulation/verify/circuitVerifier'; +import { stripBrandPrefix, isBoardComponentType } from '../utils/exampleToBuildNetlistInput'; +import type { PinSourceState } from '../simulation/spice/types'; +import type { BoardKind } from '../store/useSimulatorStore'; + +/** + * Gallery audit: which examples would the Run button REFUSE to start? + * + * EditorToolbar's `checkOrBlock` runs `verifyCircuitFromStore()` before every Run and + * returns false when the verifier reports errors — the compile never fires and the user + * gets a "run anyway?" modal. So a circuit error is not cosmetic: it is the difference + * between an example that runs and one that appears dead. + * + * This mattered because the defects hide until the circuit solves END TO END. c3-button + * wired its button to pins that do not exist, so the netlist never closed and nobody saw + * that its LED had no series resistor. Fixing the pin names surfaced a 506 mA LED that + * had been wrong since the example was written. + * + * Reproduces the Run gate exactly: same worst-case snapshot (every wired digital pin + * forced HIGH at the board's vcc, rails skipped), same buildInputFromStore, same + * verifyCircuit. Real ngspice, no browser. + */ + +function boardKindOf(example: (typeof examples)[number]): BoardKind | null { + const bt = (example as { boardType?: string }).boardType; + return (bt as BoardKind) ?? null; +} + +/** The board component id an example's wires refer to (legacy examples say 'arduino-uno'). */ +function boardIdsOf(example: (typeof examples)[number]): Set { + const declared = new Set(example.components?.map((c) => c.id) ?? []); + const refs = new Set(); + for (const w of example.wires ?? []) { + for (const ep of [w.start, w.end]) if (!declared.has(ep.componentId)) refs.add(ep.componentId); + } + return refs; +} + +async function runGate(example: (typeof examples)[number]) { + const kind = boardKindOf(example); + const components = (example.components ?? []) + .filter((c) => !isBoardComponentType(c.type)) + .map((c) => ({ + id: c.id, + metadataId: stripBrandPrefix(c.type), + properties: c.properties ?? {}, + })); + const wires = (example.wires ?? []).map((w) => ({ + id: w.id, + start: { componentId: w.start.componentId, pinName: w.start.pinName }, + end: { componentId: w.end.componentId, pinName: w.end.pinName }, + color: '#666', + waypoints: [], + })); + + const boards = kind + ? [...boardIdsOf(example)].map((id) => { + const group = BOARD_PIN_GROUPS[kind] ?? BOARD_PIN_GROUPS.default; + const pinStates: Record = {}; + const wired = new Set(); + for (const w of wires) { + if (w.start.componentId === id) wired.add(w.start.pinName); + if (w.end.componentId === id) wired.add(w.end.pinName); + } + for (const pinName of wired) { + if (group.gnd.includes(pinName)) continue; + if (group.vcc_pins.includes(pinName)) continue; + if (Number.isNaN(Number.parseInt(pinName, 10))) continue; + pinStates[pinName] = { type: 'digital', v: group.vcc }; + } + return { id, boardKind: kind, pinStates }; + }) + : []; + + const input = buildInputFromStore({ components, wires, boards }); + return verifyCircuit(input); +} + +describe('gallery: no example is blocked by its own circuit', () => { + const candidates = examples.filter( + (e) => (e.components?.length ?? 0) > 0 && (e.wires?.length ?? 0) > 0, + ); + + it('audits every wired example and reports the blockers', async () => { + const blocked: Array<{ id: string; board: string; codes: string[]; detail: string }> = []; + for (const ex of candidates) { + let res; + try { + res = await runGate(ex); + } catch { + continue; // unbuildable snapshot — the real app treats that as "don't block" + } + if (res.errors.length) { + blocked.push({ + id: ex.id, + board: (ex as { boardType?: string }).boardType ?? '(sin placa)', + codes: [...new Set(res.errors.map((e) => e.code))], + detail: res.errors[0].message.slice(0, 110), + }); + } + } + + if (blocked.length) { + console.log( + `\n=== ${blocked.length} de ${candidates.length} ejemplos con el Run BLOQUEADO ===`, + ); + for (const b of blocked) + console.log(` ${b.board.padEnd(20)} ${b.id.padEnd(36)} ${b.codes.join(',')} ${b.detail}`); + } + expect(blocked.map((b) => `${b.id} [${b.codes.join(',')}]`)).toEqual([]); + }, 600_000); +}); diff --git a/frontend/src/components/simulator/SimulatorCanvas.tsx b/frontend/src/components/simulator/SimulatorCanvas.tsx index 76ce6c25..1912cffd 100644 --- a/frontend/src/components/simulator/SimulatorCanvas.tsx +++ b/frontend/src/components/simulator/SimulatorCanvas.tsx @@ -1,4 +1,8 @@ -import { useSimulatorStore, getEsp32Bridge, getBoardSimulator } from '../../store/useSimulatorStore'; +import { + useSimulatorStore, + getEsp32Bridge, + getBoardSimulator, +} from '../../store/useSimulatorStore'; import { getProBoard } from '../../lib/proBoardRegistry'; import { useElectricalStore } from '../../store/useElectricalStore'; import { openDeviceGateway } from '../../lib/openDeviceGateway'; @@ -6,7 +10,7 @@ import React, { useEffect, useState, useRef, useCallback } from 'react'; import { createPortal } from 'react-dom'; import { Undo2, Redo2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -import { ESP32_ADC_PIN_MAP } from '../velxio-components/Esp32Element'; +import { adcPinMapFor } from '../velxio-components/Esp32Element'; import { ComponentPickerModal } from '../ComponentPickerModal'; import { ComponentPropertyDialog } from './ComponentPropertyDialog'; import { CustomChipDialog } from '../customChips/CustomChipDialog'; @@ -62,7 +66,11 @@ import { useIsCoarsePointer } from '../../utils/useTouchDevice'; import type { ComponentMetadata } from '../../types/component-metadata'; import type { BoardKind } from '../../types/board'; import { BOARD_KIND_FQBN, boardDisplayName } from '../../types/board'; -import { boardGateDecision, proBoardFeatureName, triggerProUpgradePrompt } from '../../lib/proBoardGate'; +import { + boardGateDecision, + proBoardFeatureName, + triggerProUpgradePrompt, +} from '../../lib/proBoardGate'; import { FlashModal } from './FlashModal'; import { isTauri as isTauriRuntimeFn } from '../../desktop/tauriBridge'; import { isEsp32Family } from '../../types/boardOptions'; @@ -266,9 +274,10 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { // body (not a tiny pin overlay) and we want to let them pick a pin from a // list. `kind` distinguishes board vs component so we can pull the right // metadata for the dialog title. - const [pinPicker, setPinPicker] = useState< - { kind: 'component' | 'board'; targetId: string } | null - >(null); + const [pinPicker, setPinPicker] = useState<{ + kind: 'component' | 'board'; + targetId: string; + } | null>(null); // Component property dialog const [showPropertyDialog, setShowPropertyDialog] = useState(false); @@ -459,9 +468,11 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { // DRAG_PROMOTE_THRESHOLD_PX, we cancel the passthrough and start a real // drag — so the user can rearrange interactive parts live without first // pausing the simulation. - const pendingTouchDragRef = useRef< - { componentId: string; startX: number; startY: number } | null - >(null); + const pendingTouchDragRef = useRef<{ + componentId: string; + startX: number; + startY: number; + } | null>(null); const touchOnPinRef = useRef(false); const lastTapTimeRef = useRef(0); @@ -763,9 +774,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { clientY: pending.startY, }), ); - target.dispatchEvent( - new MouseEvent('mouseleave', { bubbles: false }), - ); + target.dispatchEvent(new MouseEvent('mouseleave', { bubbles: false })); } } touchPassthroughRef.current = false; @@ -901,8 +910,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { const cur = useSimulatorStore .getState() .components.find((c) => c.id === touchDraggedComponentIdRef.current); - const snapped = - cur && snapPositionToBreadboard(cur, nx, ny, simState.components); + const snapped = cur && snapPositionToBreadboard(cur, nx, ny, simState.components); if (snapped) { nx = snapped.x; ny = snapped.y; @@ -1085,7 +1093,9 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { world.x, world.y, ); - useSimulatorStore.getState().updateWire(wire.id, { waypoints: newWaypoints, autoRouted: false }); + useSimulatorStore + .getState() + .updateWire(wire.id, { waypoints: newWaypoints, autoRouted: false }); useSimulatorStore.getState().setSelectedWire(wire.id); } lastTapTimeRef.current = 0; @@ -1340,7 +1350,9 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { // Potentiometer: forward analog value as ADC millivolts if (tag === 'wokwi-potentiometer' && selfEndpoint.pinName === 'SIG') { - const adcInfo = ESP32_ADC_PIN_MAP[gpioPin]; + // Per CHIP: the S3's ADC pins are absent from the classic map (knob did + // nothing) and the C3/C6 would have pushed GPIO0 to channel 9 instead of 0. + const adcInfo = adcPinMapFor(lookupKey)[gpioPin]; if (adcInfo) { const onInput = (e: Event) => { const pct = parseFloat((e.target as any).value ?? '0'); // 0–100 @@ -1527,8 +1539,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { const cur = useSimulatorStore .getState() .components.find((c) => c.id === draggedComponentId); - const snapped = - cur && snapPositionToBreadboard(cur, nx, ny, simState.components); + const snapped = cur && snapPositionToBreadboard(cur, nx, ny, simState.components); if (snapped) { nx = snapped.x; ny = snapped.y; @@ -1801,12 +1812,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { // and just opens the property dialog — no history entry needed. const start = dragStartPosRef.current; const isClick = posDiff < 5 && timeDiff < 300; - if ( - !isClick && - start && - draggedComponentId && - !draggedComponentId.startsWith('__board__') - ) { + if (!isClick && start && draggedComponentId && !draggedComponentId.startsWith('__board__')) { // Seat BEFORE recording the move, so undo restores the pre-drag // position in one step instead of leaving the part mid-seat. seatDroppedComponent(draggedComponentId); @@ -1836,9 +1842,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { // convention used in Figma / Miro / draw.io. const leftButton = e.button === 0; const middleOrRight = e.button === 1 || e.button === 2; - const isPanGesture = - middleOrRight || - (leftButton && !wireInProgress && !showPropertyDialog); + const isPanGesture = middleOrRight || (leftButton && !wireInProgress && !showPropertyDialog); if (isPanGesture) { e.preventDefault(); @@ -2229,8 +2233,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { // primary way to pick pins, so the tiny overlay squares are hidden — // they're hard to hit with a finger anyway. Desktop shows overlays on // hover / while wiring only — selection alone doesn't light them up. - const showPinsForComponent = - !dialogOpen && !isTouchDevice && (wireInProgress || isHovered); + const showPinsForComponent = !dialogOpen && !isTouchDevice && (wireInProgress || isHovered); return (
{ // light them up (a selected breadboard lit 170 squares permanently). // Hidden when a dialog is open. Hidden entirely on touch — there the // PinPickerDialog (tap component → list of pins) replaces the overlays. - const showPinsForComponent = - !dialogOpen && !isTouchDevice && (wireInProgress || isHovered); + const showPinsForComponent = !dialogOpen && !isTouchDevice && (wireInProgress || isHovered); // Breadboards are the physical base of a circuit — everything plugs into // them — so they always sit at the very back: below boards (z 0), other @@ -2431,161 +2433,197 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
{(() => { const headerJsx = ( -
-
- {/* Status LED */} - +
+
+ {/* Status LED */} + - {/* Active board selector (multi-board) — hidden when no boards */} - {boards.length > 0 ? ( - - ) : ( - - {t('editor.canvas.noBoard')} - - )} + {/* Active board selector (multi-board) — hidden when no boards */} + {boards.length > 0 ? ( + + ) : ( + + {t('editor.canvas.noBoard')} + + )} - {/* Undo / Redo — canvas-scoped, mirrors the Ctrl+Z / Ctrl+Y + {/* Undo / Redo — canvas-scoped, mirrors the Ctrl+Z / Ctrl+Y handler in EditorPage. Tooltip surfaces the description of the command that would be applied. Disabled when the stack is exhausted in that direction. */} - - - - {/* Serial Monitor toggle */} - - - {/* ESP32-CAM webcam stream toggle */} - {activeBoard?.boardKind === 'esp32-cam' && ( - - )} - - {/* WiFi status indicator + IoT-gateway launcher (ESP32 + Pico W) */} - {activeBoard && - (isEsp32Kind(activeBoard.boardKind) || - activeBoard.boardKind === 'pi-pico-w') && - activeBoard.wifiStatus && - (() => { - // The Pico W virtual net assigns its IP deterministically when - // the sketch connects; the bridge reports 'started' carrying the - // IP. Treat that as got_ip so the badge matches the ESP32 (green, - // clickable → the same /api/gateway proxy). - const rawStatus = activeBoard.wifiStatus.status; - const status = - activeBoard.boardKind === 'pi-pico-w' && - rawStatus === 'started' && - activeBoard.wifiStatus.ip - ? 'got_ip' - : rawStatus; - const hasIp = status === 'got_ip'; - const sessionId = getTabSessionId(); - const clientId = `${sessionId}::${activeBoard.id}`; - const backendBase = - (import.meta.env.VITE_API_BASE as string | undefined) ?? - 'http://localhost:8001/api'; - const gatewayUrl = `${backendBase}/gateway/${clientId}/`; - - const openGateway = () => { - if (!hasIp) return; - // A private overlay (velxio.dev) can install a synchronous - // gate to keep the IoT gateway behind a paid plan. When it - // returns true it has already handled the click (e.g. shown - // an in-place upgrade modal), so we don't open the tab. - // OSS builds have no hook → always open. - const gate = (window as unknown as { - __velxio_iot_gateway_open_gate__?: () => boolean; - }).__velxio_iot_gateway_open_gate__; - if (gate && gate()) return; - // Pico W runs in THIS tab — a new tab would background and - // freeze the emulation. Show the page in an in-app iframe. - if (activeBoard.boardKind === 'pi-pico-w') { - openDeviceGateway(gatewayUrl); - } else { - window.open(gatewayUrl, '_blank'); + + + + {/* Serial Monitor toggle */} + + + {/* ESP32-CAM webcam stream toggle */} + {activeBoard?.boardKind === 'esp32-cam' && ( + + )} + + {/* WiFi status indicator + IoT-gateway launcher (ESP32 + Pico W) */} + {activeBoard && + (isEsp32Kind(activeBoard.boardKind) || activeBoard.boardKind === 'pi-pico-w') && + activeBoard.wifiStatus && + (() => { + // The Pico W virtual net assigns its IP deterministically when + // the sketch connects; the bridge reports 'started' carrying the + // IP. Treat that as got_ip so the badge matches the ESP32 (green, + // clickable → the same /api/gateway proxy). + const rawStatus = activeBoard.wifiStatus.status; + const status = + activeBoard.boardKind === 'pi-pico-w' && + rawStatus === 'started' && + activeBoard.wifiStatus.ip + ? 'got_ip' + : rawStatus; + const hasIp = status === 'got_ip'; + const sessionId = getTabSessionId(); + const clientId = `${sessionId}::${activeBoard.id}`; + const backendBase = + (import.meta.env.VITE_API_BASE as string | undefined) ?? + 'http://localhost:8001/api'; + const gatewayUrl = `${backendBase}/gateway/${clientId}/`; + + const openGateway = () => { + if (!hasIp) return; + // A private overlay (velxio.dev) can install a synchronous + // gate to keep the IoT gateway behind a paid plan. When it + // returns true it has already handled the click (e.g. shown + // an in-place upgrade modal), so we don't open the tab. + // OSS builds have no hook → always open. + const gate = ( + window as unknown as { + __velxio_iot_gateway_open_gate__?: () => boolean; + } + ).__velxio_iot_gateway_open_gate__; + if (gate && gate()) return; + // Pico W runs in THIS tab — a new tab would background and + // freeze the emulation. Show the page in an in-app iframe. + if (activeBoard.boardKind === 'pi-pico-w') { + openDeviceGateway(gatewayUrl); + } else { + window.open(gatewayUrl, '_blank'); + } + }; + return ( + + + + + + + + + ); + })()} + + {/* BLE status indicator (ESP32 boards only) */} + {activeBoard && isEsp32Kind(activeBoard.boardKind) && activeBoard.bleStatus && ( { strokeLinecap="round" strokeLinejoin="round" > - - - - + - ); - })()} + )} - {/* BLE status indicator (ESP32 boards only) */} - {activeBoard && isEsp32Kind(activeBoard.boardKind) && activeBoard.bleStatus && ( - - - - - - )} + + + + {t('editor.canvas.scope')} + +
- {/* Oscilloscope toggle */} - -
+
+ {/* Zoom controls */} +
+ + + +
-
- {/* Zoom controls */} -
- - - + + + + + {t('editor.canvas.add')} + +
- - {/* Component count */} - - - - - - {components.length} - - - {/* Add Component */} - -
-
); return headerSlot ? createPortal(headerJsx, headerSlot) : headerJsx; })()} @@ -2906,8 +2915,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { // Suppressed while a dialog is open. Hidden entirely on touch // since the PinPickerDialog (tap board to open list) replaces // the overlays — fingers can't reliably hit a 12px pin anyway. - const showPins = - !dialogOpen && !isTouchDevice && (wireInProgress || isHovered); + const showPins = !dialogOpen && !isTouchDevice && (wireInProgress || isHovered); return ( { bar is pinned top-center so it never covers pins near the wire. - COMPONENT selection stays touch-only — desktop already has the Delete key + the right-click rotate menu. */} - {!wireInProgress && !interactionRunning && + {!wireInProgress && + !interactionRunning && (() => { if (selectedWireId) { const wire = wires.find((w) => w.id === selectedWireId); @@ -3085,7 +3094,13 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { } else { const c = components.find((x) => x.id === targetId); const rot = c ? Number(c.properties?.rotation) || 0 : 0; - const pos = calculatePinPosition(targetId, pinName, (c?.x ?? 0) + 6, (c?.y ?? 0) + 6, rot); + const pos = calculatePinPosition( + targetId, + pinName, + (c?.x ?? 0) + 6, + (c?.y ?? 0) + 6, + rot, + ); worldX = pos?.x ?? (c?.x ?? 0) + pin.x; worldY = pos?.y ?? (c?.y ?? 0) + pin.y; } @@ -3166,11 +3181,11 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { return ( ) ?? {}, + attrs: (props.attrs as Record) ?? {}, }} onClose={() => setCustomChipComponentId(null)} onSave={(data) => { @@ -3249,11 +3264,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { type="button" title={color} onClick={() => { - recordUpdateWire( - wireContextMenu.wireId, - { color: wire.color }, - { color }, - ); + recordUpdateWire(wireContextMenu.wireId, { color: wire.color }, { color }); setWireContextMenu(null); }} style={{ @@ -3529,13 +3540,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { setFlashModalFor(null); return null; } - return ( - setFlashModalFor(null)} - /> - ); + return setFlashModalFor(null)} />; })()} {/* Board Options modal (ESP32 only) */} @@ -3562,7 +3567,9 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { {boardToRemove && (() => { const board = boards.find((b) => b.id === boardToRemove); - const label = board ? boardDisplayName(board) : t('editor.canvas.removeConfirm.boardFallback'); + const label = board + ? boardDisplayName(board) + : t('editor.canvas.removeConfirm.boardFallback'); const connectedWires = wires.filter( (w) => w.start.componentId === boardToRemove || w.end.componentId === boardToRemove, ).length; diff --git a/frontend/src/components/velxio-components/Esp32Element.ts b/frontend/src/components/velxio-components/Esp32Element.ts index 8af5e9f3..b43afb08 100644 --- a/frontend/src/components/velxio-components/Esp32Element.ts +++ b/frontend/src/components/velxio-components/Esp32Element.ts @@ -350,6 +350,45 @@ export const ESP32_ADC_PIN_MAP: Record = { + 0: { adc: 1, ch: 0, chn: 0 }, + 1: { adc: 1, ch: 1, chn: 1 }, + 2: { adc: 1, ch: 2, chn: 2 }, + 3: { adc: 1, ch: 3, chn: 3 }, + 4: { adc: 1, ch: 4, chn: 4 }, +}; + +/** ESP32-S3: ADC1 channels 0..9 are GPIO1..10. (ADC2 = GPIO11..20 shares the same + * channel indices in the engine, so it is left out rather than aliased wrongly.) */ +const ESP32S3_ADC_PIN_MAP: Record = Object.fromEntries( + Array.from({ length: 10 }, (_, ch) => [ch + 1, { adc: 1 as const, ch, chn: ch }]), +); + +/** The ADC map for a board kind. Unknown kinds fall back to the classic ESP32. */ +export function adcPinMapFor(boardKind: string): Record { + if (boardKind.includes('c3') || boardKind.includes('c6')) return RISCV_C_ADC_PIN_MAP; + if (boardKind.includes('s3')) return ESP32S3_ADC_PIN_MAP; + return ESP32_ADC_PIN_MAP; +} + // ─── Board config by variant ────────────────────────────────────────────────── interface BoardConfig { diff --git a/frontend/src/data/examples-100-days.ts b/frontend/src/data/examples-100-days.ts index d65c8b0e..ff0c2249 100644 --- a/frontend/src/data/examples-100-days.ts +++ b/frontend/src/data/examples-100-days.ts @@ -1969,8 +1969,13 @@ CITY = "city" i2c = I2C(0, scl=Pin(22), sda=Pin(21)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) -touch_next = Pin(14, Pin.IN) -touch_sel = Pin(27, Pin.IN) +# PULL_DOWN, no Pin.IN a secas: los botones van entre 3V3 y el pin, asi que sin +# pull-down el pin queda FLOTANDO cuando el boton esta abierto y pin.value() no +# vale nada. En una placa de verdad se lee ruido; aqui el nodo resuelve a 3,3 V y +# los dos botones parecen pulsados para siempre, con wait_for_release() girando +# en vacio. Es el mismo fallo que en hardware, no un artefacto del emulador. +touch_next = Pin(14, Pin.IN, Pin.PULL_DOWN) +touch_sel = Pin(27, Pin.IN, Pin.PULL_DOWN) # ================= UTILS ================= def wifi_connect(): @@ -2298,7 +2303,7 @@ class SSD1306_SPI(SSD1306): { 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. Add Pin.PULL_DOWN in MicroPython if the pin floats. + // 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' }, diff --git a/frontend/src/data/examples.ts b/frontend/src/data/examples.ts index cf6c12b3..a477196b 100644 --- a/frontend/src/data/examples.ts +++ b/frontend/src/data/examples.ts @@ -153,10 +153,30 @@ void loop() { code: '', components: [{ type: 'velxio-ssd1306-i2c-4pin', id: 'oled', x: 470, y: 100, properties: {} }], wires: [ - { id: 'w-vcc', start: { componentId: 'arduino-uno', pinName: '5V' }, end: { componentId: 'oled', pinName: 'VCC' }, color: '#ff4444' }, - { id: 'w-gnd', start: { componentId: 'arduino-uno', pinName: 'GND.2' }, end: { componentId: 'oled', pinName: 'GND' }, color: '#000000' }, - { id: 'w-sda', start: { componentId: 'arduino-uno', pinName: 'A4' }, end: { componentId: 'oled', pinName: 'SDA' }, color: '#22aaff' }, - { id: 'w-scl', start: { componentId: 'arduino-uno', pinName: 'A5' }, end: { componentId: 'oled', pinName: 'SCL' }, color: '#ff8800' }, + { + id: 'w-vcc', + start: { componentId: 'arduino-uno', pinName: '5V' }, + end: { componentId: 'oled', pinName: 'VCC' }, + color: '#ff4444', + }, + { + id: 'w-gnd', + start: { componentId: 'arduino-uno', pinName: 'GND.2' }, + end: { componentId: 'oled', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-sda', + start: { componentId: 'arduino-uno', pinName: 'A4' }, + end: { componentId: 'oled', pinName: 'SDA' }, + color: '#22aaff', + }, + { + id: 'w-scl', + start: { componentId: 'arduino-uno', pinName: 'A5' }, + end: { componentId: 'oled', pinName: 'SCL' }, + color: '#ff8800', + }, ], }, { @@ -212,10 +232,30 @@ void loop() { code: '', components: [{ type: 'velxio-ssd1306-i2c-4pin', id: 'oled', x: 470, y: 100, properties: {} }], wires: [ - { id: 'w-vcc', start: { componentId: 'esp32', pinName: '3V3' }, end: { componentId: 'oled', pinName: 'VCC' }, color: '#ff4444' }, - { id: 'w-gnd', start: { componentId: 'esp32', pinName: 'GND' }, end: { componentId: 'oled', pinName: 'GND' }, color: '#000000' }, - { id: 'w-sda', start: { componentId: 'esp32', pinName: '21' }, end: { componentId: 'oled', pinName: 'SDA' }, color: '#22aaff' }, - { id: 'w-scl', start: { componentId: 'esp32', pinName: '22' }, end: { componentId: 'oled', pinName: 'SCL' }, color: '#ff8800' }, + { + id: 'w-vcc', + start: { componentId: 'esp32', pinName: '3V3' }, + end: { componentId: 'oled', pinName: 'VCC' }, + color: '#ff4444', + }, + { + id: 'w-gnd', + start: { componentId: 'esp32', pinName: 'GND' }, + end: { componentId: 'oled', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-sda', + start: { componentId: 'esp32', pinName: '21' }, + end: { componentId: 'oled', pinName: 'SDA' }, + color: '#22aaff', + }, + { + id: 'w-scl', + start: { componentId: 'esp32', pinName: '22' }, + end: { componentId: 'oled', pinName: 'SCL' }, + color: '#ff8800', + }, ], }, // ── Pure ESP-IDF (issue #139): user app_main(), no Arduino core. ── @@ -268,9 +308,24 @@ void app_main(void) { type: 'wokwi-led', id: 'led-ext', x: 470, y: 100, properties: { color: 'red' } }, ], wires: [ - { id: 'w-gpio2-r', start: { componentId: 'esp32', pinName: '2' }, end: { componentId: 'r-led', pinName: '1' }, color: '#e74c3c' }, - { id: 'w-r-led', start: { componentId: 'r-led', pinName: '2' }, end: { componentId: 'led-ext', pinName: 'A' }, color: '#e74c3c' }, - { id: 'w-gnd', start: { componentId: 'led-ext', pinName: 'C' }, end: { componentId: 'esp32', pinName: 'GND' }, color: '#2c3e50' }, + { + id: 'w-gpio2-r', + start: { componentId: 'esp32', pinName: '2' }, + end: { componentId: 'r-led', pinName: '1' }, + color: '#e74c3c', + }, + { + id: 'w-r-led', + start: { componentId: 'r-led', pinName: '2' }, + end: { componentId: 'led-ext', pinName: 'A' }, + color: '#e74c3c', + }, + { + id: 'w-gnd', + start: { componentId: 'led-ext', pinName: 'C' }, + end: { componentId: 'esp32', pinName: 'GND' }, + color: '#2c3e50', + }, ], }, { @@ -329,10 +384,30 @@ void loop() { code: '', components: [{ type: 'velxio-ssd1306-i2c-4pin', id: 'oled', x: 470, y: 100, properties: {} }], wires: [ - { id: 'w-vcc', start: { componentId: 'raspberry-pi-pico', pinName: '3V3' }, end: { componentId: 'oled', pinName: 'VCC' }, color: '#ff4444' }, - { id: 'w-gnd', start: { componentId: 'raspberry-pi-pico', pinName: 'GND.3' }, end: { componentId: 'oled', pinName: 'GND' }, color: '#000000' }, - { id: 'w-sda', start: { componentId: 'raspberry-pi-pico', pinName: 'GP4' }, end: { componentId: 'oled', pinName: 'SDA' }, color: '#22aaff' }, - { id: 'w-scl', start: { componentId: 'raspberry-pi-pico', pinName: 'GP5' }, end: { componentId: 'oled', pinName: 'SCL' }, color: '#ff8800' }, + { + id: 'w-vcc', + start: { componentId: 'raspberry-pi-pico', pinName: '3V3' }, + end: { componentId: 'oled', pinName: 'VCC' }, + color: '#ff4444', + }, + { + id: 'w-gnd', + start: { componentId: 'raspberry-pi-pico', pinName: 'GND.3' }, + end: { componentId: 'oled', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-sda', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP4' }, + end: { componentId: 'oled', pinName: 'SDA' }, + color: '#22aaff', + }, + { + id: 'w-scl', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP5' }, + end: { componentId: 'oled', pinName: 'SCL' }, + color: '#ff8800', + }, ], }, { @@ -389,10 +464,30 @@ void loop() { code: '', components: [{ type: 'velxio-ssd1306-i2c-4pin', id: 'oled', x: 470, y: 100, properties: {} }], wires: [ - { id: 'w-vcc', start: { componentId: 'stm32-bluepill', pinName: '3V3' }, end: { componentId: 'oled', pinName: 'VCC' }, color: '#ff4444' }, - { id: 'w-gnd', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'oled', pinName: 'GND' }, color: '#000000' }, - { id: 'w-sda', start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, end: { componentId: 'oled', pinName: 'SDA' }, color: '#22aaff' }, - { id: 'w-scl', start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, end: { componentId: 'oled', pinName: 'SCL' }, color: '#ff8800' }, + { + id: 'w-vcc', + start: { componentId: 'stm32-bluepill', pinName: '3V3' }, + end: { componentId: 'oled', pinName: 'VCC' }, + color: '#ff4444', + }, + { + id: 'w-gnd', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'oled', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-sda', + start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, + end: { componentId: 'oled', pinName: 'SDA' }, + color: '#22aaff', + }, + { + id: 'w-scl', + start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, + end: { componentId: 'oled', pinName: 'SCL' }, + color: '#ff8800', + }, ], }, { @@ -442,15 +537,38 @@ void loop() { delay(200); // simple debounce } }`, - components: [ - { type: 'wokwi-ky-040', id: 'enc1', x: 360, y: 90, properties: {} }, - ], + components: [{ type: 'wokwi-ky-040', id: 'enc1', x: 360, y: 90, properties: {} }], wires: [ - { id: 'w-enc-clk', start: { componentId: 'enc1', pinName: 'CLK' }, end: { componentId: 'arduino-uno', pinName: '2' }, color: '#f59e0b' }, - { id: 'w-enc-dt', start: { componentId: 'enc1', pinName: 'DT' }, end: { componentId: 'arduino-uno', pinName: '3' }, color: '#10b981' }, - { id: 'w-enc-sw', start: { componentId: 'enc1', pinName: 'SW' }, end: { componentId: 'arduino-uno', pinName: '4' }, color: '#3b82f6' }, - { id: 'w-enc-vcc', start: { componentId: 'enc1', pinName: 'VCC' }, end: { componentId: 'arduino-uno', pinName: '5V' }, color: '#ef4444' }, - { id: 'w-enc-gnd', start: { componentId: 'enc1', pinName: 'GND' }, end: { componentId: 'arduino-uno', pinName: 'GND' }, color: '#1f2937' }, + { + id: 'w-enc-clk', + start: { componentId: 'enc1', pinName: 'CLK' }, + end: { componentId: 'arduino-uno', pinName: '2' }, + color: '#f59e0b', + }, + { + id: 'w-enc-dt', + start: { componentId: 'enc1', pinName: 'DT' }, + end: { componentId: 'arduino-uno', pinName: '3' }, + color: '#10b981', + }, + { + id: 'w-enc-sw', + start: { componentId: 'enc1', pinName: 'SW' }, + end: { componentId: 'arduino-uno', pinName: '4' }, + color: '#3b82f6', + }, + { + id: 'w-enc-vcc', + start: { componentId: 'enc1', pinName: 'VCC' }, + end: { componentId: 'arduino-uno', pinName: '5V' }, + color: '#ef4444', + }, + { + id: 'w-enc-gnd', + start: { componentId: 'enc1', pinName: 'GND' }, + end: { componentId: 'arduino-uno', pinName: 'GND' }, + color: '#1f2937', + }, ], tags: ['rotary', 'encoder', 'ky-040', 'input', 'knob', 'arduino'], }, @@ -1273,14 +1391,32 @@ void loop() { }, ], code: '', - components: [ - { type: 'wokwi-mpu6050', id: 'mpu1', x: 460, y: 150, properties: {} }, - ], + components: [{ type: 'wokwi-mpu6050', id: 'mpu1', x: 460, y: 150, properties: {} }], wires: [ - { id: 'mpu-vcc', start: { componentId: 'stm32-bluepill', pinName: '3V3' }, end: { componentId: 'mpu1', pinName: 'VCC' }, color: '#ff4444' }, - { id: 'mpu-gnd', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'mpu1', pinName: 'GND' }, color: '#000000' }, - { id: 'mpu-sda', start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, end: { componentId: 'mpu1', pinName: 'SDA' }, color: '#22aaff' }, - { id: 'mpu-scl', start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, end: { componentId: 'mpu1', pinName: 'SCL' }, color: '#ff8800' }, + { + id: 'mpu-vcc', + start: { componentId: 'stm32-bluepill', pinName: '3V3' }, + end: { componentId: 'mpu1', pinName: 'VCC' }, + color: '#ff4444', + }, + { + id: 'mpu-gnd', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'mpu1', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'mpu-sda', + start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, + end: { componentId: 'mpu1', pinName: 'SDA' }, + color: '#22aaff', + }, + { + id: 'mpu-scl', + start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, + end: { componentId: 'mpu1', pinName: 'SCL' }, + color: '#ff8800', + }, ], tags: ['stm32', 'blue pill', 'i2c', 'mpu6050', 'imu', 'sensor', 'qemu'], }, @@ -1330,14 +1466,32 @@ void loop() { }, ], code: '', - components: [ - { type: 'wokwi-ds1307', id: 'rtc1', x: 460, y: 150, properties: {} }, - ], + components: [{ type: 'wokwi-ds1307', id: 'rtc1', x: 460, y: 150, properties: {} }], wires: [ - { id: 'rtc-vcc', start: { componentId: 'stm32-bluepill', pinName: '3V3' }, end: { componentId: 'rtc1', pinName: 'VCC' }, color: '#ff4444' }, - { id: 'rtc-gnd', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'rtc1', pinName: 'GND' }, color: '#000000' }, - { id: 'rtc-sda', start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, end: { componentId: 'rtc1', pinName: 'SDA' }, color: '#22aaff' }, - { id: 'rtc-scl', start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, end: { componentId: 'rtc1', pinName: 'SCL' }, color: '#ff8800' }, + { + id: 'rtc-vcc', + start: { componentId: 'stm32-bluepill', pinName: '3V3' }, + end: { componentId: 'rtc1', pinName: 'VCC' }, + color: '#ff4444', + }, + { + id: 'rtc-gnd', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'rtc1', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'rtc-sda', + start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, + end: { componentId: 'rtc1', pinName: 'SDA' }, + color: '#22aaff', + }, + { + id: 'rtc-scl', + start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, + end: { componentId: 'rtc1', pinName: 'SCL' }, + color: '#ff8800', + }, ], tags: ['stm32', 'blue pill', 'i2c', 'ds1307', 'rtc', 'clock', 'qemu'], }, @@ -1395,10 +1549,30 @@ void loop() { code: '', components: [{ type: 'wokwi-ssd1306', id: 'bpoled1', x: 460, y: 120, properties: {} }], wires: [ - { id: 'bpo-vcc', start: { componentId: 'stm32-blackpill', pinName: '3V3' }, end: { componentId: 'bpoled1', pinName: 'VIN' }, color: '#ff4444' }, - { id: 'bpo-gnd', start: { componentId: 'stm32-blackpill', pinName: 'GND' }, end: { componentId: 'bpoled1', pinName: 'GND' }, color: '#000000' }, - { id: 'bpo-sda', start: { componentId: 'stm32-blackpill', pinName: 'PB7' }, end: { componentId: 'bpoled1', pinName: 'DATA' }, color: '#22aaff' }, - { id: 'bpo-scl', start: { componentId: 'stm32-blackpill', pinName: 'PB6' }, end: { componentId: 'bpoled1', pinName: 'CLK' }, color: '#ff8800' }, + { + id: 'bpo-vcc', + start: { componentId: 'stm32-blackpill', pinName: '3V3' }, + end: { componentId: 'bpoled1', pinName: 'VIN' }, + color: '#ff4444', + }, + { + id: 'bpo-gnd', + start: { componentId: 'stm32-blackpill', pinName: 'GND' }, + end: { componentId: 'bpoled1', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'bpo-sda', + start: { componentId: 'stm32-blackpill', pinName: 'PB7' }, + end: { componentId: 'bpoled1', pinName: 'DATA' }, + color: '#22aaff', + }, + { + id: 'bpo-scl', + start: { componentId: 'stm32-blackpill', pinName: 'PB6' }, + end: { componentId: 'bpoled1', pinName: 'CLK' }, + color: '#ff8800', + }, ], tags: ['stm32', 'black pill', 'f411', 'i2c', 'ssd1306', 'oled', 'qemu'], }, @@ -1407,7 +1581,12 @@ void loop() { title: 'STM32: Weather Station (BMP280 + OLED)', description: 'A complete I2C dashboard on the STM32 Blue Pill: read temperature and pressure from a BMP280 and render them live on an SSD1306 OLED, both sharing the same I2C1 bus (BMP280 0x76, OLED 0x3C, SCL=PB6/SDA=PB7). Exercises I2C read and write on one bus.', - libraries: ['Adafruit BMP280 Library', 'Adafruit Unified Sensor', 'Adafruit SSD1306', 'Adafruit GFX Library'], + libraries: [ + 'Adafruit BMP280 Library', + 'Adafruit Unified Sensor', + 'Adafruit SSD1306', + 'Adafruit GFX Library', + ], category: 'sensors', difficulty: 'intermediate', boardFilter: 'stm32-bluepill', @@ -1454,18 +1633,64 @@ void loop() { ], code: '', components: [ - { type: 'velxio-bmp280', id: 'wbmp1', x: 470, y: 80, properties: { temperature: '23.5', pressure: '1011.2' } }, + { + type: 'velxio-bmp280', + id: 'wbmp1', + x: 470, + y: 80, + properties: { temperature: '23.5', pressure: '1011.2' }, + }, { type: 'wokwi-ssd1306', id: 'woled1', x: 470, y: 250, properties: {} }, ], wires: [ - { id: 'w-bmp-vcc', start: { componentId: 'stm32-bluepill', pinName: '3V3' }, end: { componentId: 'wbmp1', pinName: 'VCC' }, color: '#ff4444' }, - { id: 'w-bmp-gnd', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'wbmp1', pinName: 'GND' }, color: '#000000' }, - { id: 'w-bmp-sda', start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, end: { componentId: 'wbmp1', pinName: 'SDA' }, color: '#22aaff' }, - { id: 'w-bmp-scl', start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, end: { componentId: 'wbmp1', pinName: 'SCL' }, color: '#ff8800' }, - { id: 'w-oled-vcc', start: { componentId: 'wbmp1', pinName: 'VCC' }, end: { componentId: 'woled1', pinName: 'VIN' }, color: '#ff4444' }, - { id: 'w-oled-gnd', start: { componentId: 'wbmp1', pinName: 'GND' }, end: { componentId: 'woled1', pinName: 'GND' }, color: '#000000' }, - { id: 'w-oled-sda', start: { componentId: 'wbmp1', pinName: 'SDA' }, end: { componentId: 'woled1', pinName: 'DATA' }, color: '#22aaff' }, - { id: 'w-oled-scl', start: { componentId: 'wbmp1', pinName: 'SCL' }, end: { componentId: 'woled1', pinName: 'CLK' }, color: '#ff8800' }, + { + id: 'w-bmp-vcc', + start: { componentId: 'stm32-bluepill', pinName: '3V3' }, + end: { componentId: 'wbmp1', pinName: 'VCC' }, + color: '#ff4444', + }, + { + id: 'w-bmp-gnd', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'wbmp1', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-bmp-sda', + start: { componentId: 'stm32-bluepill', pinName: 'PB7' }, + end: { componentId: 'wbmp1', pinName: 'SDA' }, + color: '#22aaff', + }, + { + id: 'w-bmp-scl', + start: { componentId: 'stm32-bluepill', pinName: 'PB6' }, + end: { componentId: 'wbmp1', pinName: 'SCL' }, + color: '#ff8800', + }, + { + id: 'w-oled-vcc', + start: { componentId: 'wbmp1', pinName: 'VCC' }, + end: { componentId: 'woled1', pinName: 'VIN' }, + color: '#ff4444', + }, + { + id: 'w-oled-gnd', + start: { componentId: 'wbmp1', pinName: 'GND' }, + end: { componentId: 'woled1', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-oled-sda', + start: { componentId: 'wbmp1', pinName: 'SDA' }, + end: { componentId: 'woled1', pinName: 'DATA' }, + color: '#22aaff', + }, + { + id: 'w-oled-scl', + start: { componentId: 'wbmp1', pinName: 'SCL' }, + end: { componentId: 'woled1', pinName: 'CLK' }, + color: '#ff8800', + }, ], tags: ['stm32', 'blue pill', 'i2c', 'bmp280', 'ssd1306', 'weather', 'dashboard', 'qemu'], }, @@ -1510,14 +1735,54 @@ void loop() { { type: 'wokwi-7segment', id: 'seg1', x: 470, y: 140, properties: { common: 'cathode' } }, ], wires: [ - { id: 's-a', start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, end: { componentId: 'seg1', pinName: 'A' }, color: '#ff5555' }, - { id: 's-b', start: { componentId: 'stm32-bluepill', pinName: 'PA1' }, end: { componentId: 'seg1', pinName: 'B' }, color: '#ff9955' }, - { id: 's-c', start: { componentId: 'stm32-bluepill', pinName: 'PA2' }, end: { componentId: 'seg1', pinName: 'C' }, color: '#ffdd55' }, - { id: 's-d', start: { componentId: 'stm32-bluepill', pinName: 'PA3' }, end: { componentId: 'seg1', pinName: 'D' }, color: '#88dd55' }, - { id: 's-e', start: { componentId: 'stm32-bluepill', pinName: 'PA4' }, end: { componentId: 'seg1', pinName: 'E' }, color: '#55ddcc' }, - { id: 's-f', start: { componentId: 'stm32-bluepill', pinName: 'PA5' }, end: { componentId: 'seg1', pinName: 'F' }, color: '#5599ff' }, - { id: 's-g', start: { componentId: 'stm32-bluepill', pinName: 'PA6' }, end: { componentId: 'seg1', pinName: 'G' }, color: '#aa77ff' }, - { id: 's-com', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'seg1', pinName: 'COM' }, color: '#000000' }, + { + id: 's-a', + start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, + end: { componentId: 'seg1', pinName: 'A' }, + color: '#ff5555', + }, + { + id: 's-b', + start: { componentId: 'stm32-bluepill', pinName: 'PA1' }, + end: { componentId: 'seg1', pinName: 'B' }, + color: '#ff9955', + }, + { + id: 's-c', + start: { componentId: 'stm32-bluepill', pinName: 'PA2' }, + end: { componentId: 'seg1', pinName: 'C' }, + color: '#ffdd55', + }, + { + id: 's-d', + start: { componentId: 'stm32-bluepill', pinName: 'PA3' }, + end: { componentId: 'seg1', pinName: 'D' }, + color: '#88dd55', + }, + { + id: 's-e', + start: { componentId: 'stm32-bluepill', pinName: 'PA4' }, + end: { componentId: 'seg1', pinName: 'E' }, + color: '#55ddcc', + }, + { + id: 's-f', + start: { componentId: 'stm32-bluepill', pinName: 'PA5' }, + end: { componentId: 'seg1', pinName: 'F' }, + color: '#5599ff', + }, + { + id: 's-g', + start: { componentId: 'stm32-bluepill', pinName: 'PA6' }, + end: { componentId: 'seg1', pinName: 'G' }, + color: '#aa77ff', + }, + { + id: 's-com', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'seg1', pinName: 'COM' }, + color: '#000000', + }, ], tags: ['stm32', 'blue pill', 'gpio', '7-segment', 'display', 'counter'], }, @@ -1560,14 +1825,32 @@ void loop() { }, ], code: '', - components: [ - { type: 'wokwi-rgb-led', id: 'rgb1', x: 470, y: 150, properties: {} }, - ], + components: [{ type: 'wokwi-rgb-led', id: 'rgb1', x: 470, y: 150, properties: {} }], wires: [ - { id: 'rgb-r', start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, end: { componentId: 'rgb1', pinName: 'R' }, color: '#ff3333' }, - { id: 'rgb-g', start: { componentId: 'stm32-bluepill', pinName: 'PA1' }, end: { componentId: 'rgb1', pinName: 'G' }, color: '#33cc33' }, - { id: 'rgb-b', start: { componentId: 'stm32-bluepill', pinName: 'PA2' }, end: { componentId: 'rgb1', pinName: 'B' }, color: '#3366ff' }, - { id: 'rgb-com', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'rgb1', pinName: 'COM' }, color: '#000000' }, + { + id: 'rgb-r', + start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, + end: { componentId: 'rgb1', pinName: 'R' }, + color: '#ff3333', + }, + { + id: 'rgb-g', + start: { componentId: 'stm32-bluepill', pinName: 'PA1' }, + end: { componentId: 'rgb1', pinName: 'G' }, + color: '#33cc33', + }, + { + id: 'rgb-b', + start: { componentId: 'stm32-bluepill', pinName: 'PA2' }, + end: { componentId: 'rgb1', pinName: 'B' }, + color: '#3366ff', + }, + { + id: 'rgb-com', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'rgb1', pinName: 'COM' }, + color: '#000000', + }, ], tags: ['stm32', 'blue pill', 'gpio', 'rgb-led', 'led'], }, @@ -1614,8 +1897,18 @@ void loop() { { type: 'wokwi-pushbutton', id: 'btn1', x: 470, y: 160, properties: { color: 'green' } }, ], wires: [ - { id: 'btn-sig', start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, end: { componentId: 'btn1', pinName: '1.l' }, color: '#22aaff' }, - { id: 'btn-gnd', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'btn1', pinName: '2.l' }, color: '#000000' }, + { + id: 'btn-sig', + start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, + end: { componentId: 'btn1', pinName: '1.l' }, + color: '#22aaff', + }, + { + id: 'btn-gnd', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'btn1', pinName: '2.l' }, + color: '#000000', + }, ], tags: ['stm32', 'blue pill', 'gpio', 'button', 'input', 'pushbutton'], }, @@ -1657,13 +1950,26 @@ void loop() { }, ], code: '', - components: [ - { type: 'wokwi-slide-switch', id: 'sw1', x: 470, y: 160, properties: {} }, - ], + components: [{ type: 'wokwi-slide-switch', id: 'sw1', x: 470, y: 160, properties: {} }], wires: [ - { id: 'sw-sig', start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, end: { componentId: 'sw1', pinName: '2' }, color: '#22aaff' }, - { id: 'sw-gnd', start: { componentId: 'stm32-bluepill', pinName: 'GND' }, end: { componentId: 'sw1', pinName: '1' }, color: '#000000' }, - { id: 'sw-vcc', start: { componentId: 'stm32-bluepill', pinName: '3V3' }, end: { componentId: 'sw1', pinName: '3' }, color: '#ff4444' }, + { + id: 'sw-sig', + start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, + end: { componentId: 'sw1', pinName: '2' }, + color: '#22aaff', + }, + { + id: 'sw-gnd', + start: { componentId: 'stm32-bluepill', pinName: 'GND' }, + end: { componentId: 'sw1', pinName: '1' }, + color: '#000000', + }, + { + id: 'sw-vcc', + start: { componentId: 'stm32-bluepill', pinName: '3V3' }, + end: { componentId: 'sw1', pinName: '3' }, + color: '#ff4444', + }, ], tags: ['stm32', 'blue pill', 'gpio', 'switch', 'input', 'slide-switch'], }, @@ -1710,14 +2016,32 @@ void loop() { }, ], code: '', - components: [ - { type: 'wokwi-stepper-motor', id: 'stp1', x: 470, y: 150, properties: {} }, - ], + components: [{ type: 'wokwi-stepper-motor', id: 'stp1', x: 470, y: 150, properties: {} }], wires: [ - { id: 'stp-ap', start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, end: { componentId: 'stp1', pinName: 'A+' }, color: '#ff5555' }, - { id: 'stp-an', start: { componentId: 'stm32-bluepill', pinName: 'PA1' }, end: { componentId: 'stp1', pinName: 'A-' }, color: '#ff9955' }, - { id: 'stp-bp', start: { componentId: 'stm32-bluepill', pinName: 'PA2' }, end: { componentId: 'stp1', pinName: 'B+' }, color: '#55aaff' }, - { id: 'stp-bn', start: { componentId: 'stm32-bluepill', pinName: 'PA3' }, end: { componentId: 'stp1', pinName: 'B-' }, color: '#aa77ff' }, + { + id: 'stp-ap', + start: { componentId: 'stm32-bluepill', pinName: 'PA0' }, + end: { componentId: 'stp1', pinName: 'A+' }, + color: '#ff5555', + }, + { + id: 'stp-an', + start: { componentId: 'stm32-bluepill', pinName: 'PA1' }, + end: { componentId: 'stp1', pinName: 'A-' }, + color: '#ff9955', + }, + { + id: 'stp-bp', + start: { componentId: 'stm32-bluepill', pinName: 'PA2' }, + end: { componentId: 'stp1', pinName: 'B+' }, + color: '#55aaff', + }, + { + id: 'stp-bn', + start: { componentId: 'stm32-bluepill', pinName: 'PA3' }, + end: { componentId: 'stp1', pinName: 'B-' }, + color: '#aa77ff', + }, ], tags: ['stm32', 'blue pill', 'gpio', 'stepper', 'motor'], }, @@ -1760,12 +2084,42 @@ void loop() { { type: 'wokwi-stepper-motor', id: 'stp1', x: 560, y: 120, properties: {} }, ], wires: [ - { id: 'u-step', start: { componentId: 'arduino-uno', pinName: '3' }, end: { componentId: 'drv1', pinName: 'STEP' }, color: '#f59e0b' }, - { id: 'u-dir', start: { componentId: 'arduino-uno', pinName: '4' }, end: { componentId: 'drv1', pinName: 'DIR' }, color: '#10b981' }, - { id: 'u-1a', start: { componentId: 'drv1', pinName: '1A' }, end: { componentId: 'stp1', pinName: 'B+' }, color: '#ff5555' }, - { id: 'u-1b', start: { componentId: 'drv1', pinName: '1B' }, end: { componentId: 'stp1', pinName: 'B-' }, color: '#ff9955' }, - { id: 'u-2a', start: { componentId: 'drv1', pinName: '2A' }, end: { componentId: 'stp1', pinName: 'A+' }, color: '#55aaff' }, - { id: 'u-2b', start: { componentId: 'drv1', pinName: '2B' }, end: { componentId: 'stp1', pinName: 'A-' }, color: '#aa77ff' }, + { + id: 'u-step', + start: { componentId: 'arduino-uno', pinName: '3' }, + end: { componentId: 'drv1', pinName: 'STEP' }, + color: '#f59e0b', + }, + { + id: 'u-dir', + start: { componentId: 'arduino-uno', pinName: '4' }, + end: { componentId: 'drv1', pinName: 'DIR' }, + color: '#10b981', + }, + { + id: 'u-1a', + start: { componentId: 'drv1', pinName: '1A' }, + end: { componentId: 'stp1', pinName: 'B+' }, + color: '#ff5555', + }, + { + id: 'u-1b', + start: { componentId: 'drv1', pinName: '1B' }, + end: { componentId: 'stp1', pinName: 'B-' }, + color: '#ff9955', + }, + { + id: 'u-2a', + start: { componentId: 'drv1', pinName: '2A' }, + end: { componentId: 'stp1', pinName: 'A+' }, + color: '#55aaff', + }, + { + id: 'u-2b', + start: { componentId: 'drv1', pinName: '2B' }, + end: { componentId: 'stp1', pinName: 'A-' }, + color: '#aa77ff', + }, ], tags: ['arduino', 'uno', 'stepper', 'motor', 'a4988', 'driver'], }, @@ -1808,12 +2162,42 @@ void loop() { { type: 'wokwi-stepper-motor', id: 'stp1', x: 560, y: 120, properties: {} }, ], wires: [ - { id: 'e-step', start: { componentId: 'esp32', pinName: '26' }, end: { componentId: 'drv1', pinName: 'STEP' }, color: '#f59e0b' }, - { id: 'e-dir', start: { componentId: 'esp32', pinName: '27' }, end: { componentId: 'drv1', pinName: 'DIR' }, color: '#10b981' }, - { id: 'e-1a', start: { componentId: 'drv1', pinName: '1A' }, end: { componentId: 'stp1', pinName: 'B+' }, color: '#ff5555' }, - { id: 'e-1b', start: { componentId: 'drv1', pinName: '1B' }, end: { componentId: 'stp1', pinName: 'B-' }, color: '#ff9955' }, - { id: 'e-2a', start: { componentId: 'drv1', pinName: '2A' }, end: { componentId: 'stp1', pinName: 'A+' }, color: '#55aaff' }, - { id: 'e-2b', start: { componentId: 'drv1', pinName: '2B' }, end: { componentId: 'stp1', pinName: 'A-' }, color: '#aa77ff' }, + { + id: 'e-step', + start: { componentId: 'esp32', pinName: '26' }, + end: { componentId: 'drv1', pinName: 'STEP' }, + color: '#f59e0b', + }, + { + id: 'e-dir', + start: { componentId: 'esp32', pinName: '27' }, + end: { componentId: 'drv1', pinName: 'DIR' }, + color: '#10b981', + }, + { + id: 'e-1a', + start: { componentId: 'drv1', pinName: '1A' }, + end: { componentId: 'stp1', pinName: 'B+' }, + color: '#ff5555', + }, + { + id: 'e-1b', + start: { componentId: 'drv1', pinName: '1B' }, + end: { componentId: 'stp1', pinName: 'B-' }, + color: '#ff9955', + }, + { + id: 'e-2a', + start: { componentId: 'drv1', pinName: '2A' }, + end: { componentId: 'stp1', pinName: 'A+' }, + color: '#55aaff', + }, + { + id: 'e-2b', + start: { componentId: 'drv1', pinName: '2B' }, + end: { componentId: 'stp1', pinName: 'A-' }, + color: '#aa77ff', + }, ], tags: ['esp32', 'stepper', 'motor', 'a4988', 'driver'], }, @@ -1856,12 +2240,42 @@ void loop() { { type: 'wokwi-stepper-motor', id: 'stp1', x: 560, y: 120, properties: {} }, ], wires: [ - { id: 'p-step', start: { componentId: 'raspberry-pi-pico', pinName: 'GP3' }, end: { componentId: 'drv1', pinName: 'STEP' }, color: '#f59e0b' }, - { id: 'p-dir', start: { componentId: 'raspberry-pi-pico', pinName: 'GP4' }, end: { componentId: 'drv1', pinName: 'DIR' }, color: '#10b981' }, - { id: 'p-1a', start: { componentId: 'drv1', pinName: '1A' }, end: { componentId: 'stp1', pinName: 'B+' }, color: '#ff5555' }, - { id: 'p-1b', start: { componentId: 'drv1', pinName: '1B' }, end: { componentId: 'stp1', pinName: 'B-' }, color: '#ff9955' }, - { id: 'p-2a', start: { componentId: 'drv1', pinName: '2A' }, end: { componentId: 'stp1', pinName: 'A+' }, color: '#55aaff' }, - { id: 'p-2b', start: { componentId: 'drv1', pinName: '2B' }, end: { componentId: 'stp1', pinName: 'A-' }, color: '#aa77ff' }, + { + id: 'p-step', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP3' }, + end: { componentId: 'drv1', pinName: 'STEP' }, + color: '#f59e0b', + }, + { + id: 'p-dir', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP4' }, + end: { componentId: 'drv1', pinName: 'DIR' }, + color: '#10b981', + }, + { + id: 'p-1a', + start: { componentId: 'drv1', pinName: '1A' }, + end: { componentId: 'stp1', pinName: 'B+' }, + color: '#ff5555', + }, + { + id: 'p-1b', + start: { componentId: 'drv1', pinName: '1B' }, + end: { componentId: 'stp1', pinName: 'B-' }, + color: '#ff9955', + }, + { + id: 'p-2a', + start: { componentId: 'drv1', pinName: '2A' }, + end: { componentId: 'stp1', pinName: 'A+' }, + color: '#55aaff', + }, + { + id: 'p-2b', + start: { componentId: 'drv1', pinName: '2B' }, + end: { componentId: 'stp1', pinName: 'A-' }, + color: '#aa77ff', + }, ], tags: ['raspberry pi pico', 'rp2040', 'stepper', 'motor', 'a4988', 'driver'], }, @@ -2858,37 +3272,146 @@ void loop() { } `, components: [ - { type: 'wokwi-ili9341', id: 'tft1', x: 460, y: 60, properties: {} }, - { type: 'wokwi-pushbutton', id: 'btn-fwd', x: 220, y: 420, properties: { color: 'red', label: 'FWD' } }, - { type: 'wokwi-pushbutton', id: 'btn-back', x: 220, y: 520, properties: { color: 'blue', label: 'BACK' } }, - { type: 'wokwi-pushbutton', id: 'btn-left', x: 130, y: 470, properties: { color: 'green', label: 'LEFT' } }, - { type: 'wokwi-pushbutton', id: 'btn-right', x: 310, y: 470, properties: { color: 'green', label: 'RIGHT' } }, + { type: 'wokwi-ili9341', id: 'tft1', x: 460, y: 60, properties: {} }, + { + type: 'wokwi-pushbutton', + id: 'btn-fwd', + x: 220, + y: 420, + properties: { color: 'red', label: 'FWD' }, + }, + { + type: 'wokwi-pushbutton', + id: 'btn-back', + x: 220, + y: 520, + properties: { color: 'blue', label: 'BACK' }, + }, + { + type: 'wokwi-pushbutton', + id: 'btn-left', + x: 130, + y: 470, + properties: { color: 'green', label: 'LEFT' }, + }, + { + type: 'wokwi-pushbutton', + id: 'btn-right', + x: 310, + y: 470, + properties: { color: 'green', label: 'RIGHT' }, + }, ], wires: [ // Power - { id: 'w-tft-vcc', start: { componentId: 'raspberry-pi-pico', pinName: '3V3' }, end: { componentId: 'tft1', pinName: 'VCC' }, color: '#ff0000' }, - { id: 'w-tft-gnd', start: { componentId: 'raspberry-pi-pico', pinName: 'GND.5' }, end: { componentId: 'tft1', pinName: 'GND' }, color: '#000000' }, + { + id: 'w-tft-vcc', + start: { componentId: 'raspberry-pi-pico', pinName: '3V3' }, + end: { componentId: 'tft1', pinName: 'VCC' }, + color: '#ff0000', + }, + { + id: 'w-tft-gnd', + start: { componentId: 'raspberry-pi-pico', pinName: 'GND.5' }, + end: { componentId: 'tft1', pinName: 'GND' }, + color: '#000000', + }, // SPI bus + control lines to the ILI9341. MISO is GP16 — the // sketch's 3-arg Adafruit_ILI9341(CS, DC, RST) constructor uses // hardware SPI0, whose MISO pin is GP16. The driver writes only // (no register reads), so MISO is electrically idle, but the // wire is included so the circuit is didactically complete. - { id: 'w-tft-sck', start: { componentId: 'raspberry-pi-pico', pinName: 'GP18' }, end: { componentId: 'tft1', pinName: 'SCK' }, color: '#ff8800' }, - { id: 'w-tft-mosi', start: { componentId: 'raspberry-pi-pico', pinName: 'GP19' }, end: { componentId: 'tft1', pinName: 'MOSI' }, color: '#ff8800' }, - { id: 'w-tft-miso', start: { componentId: 'raspberry-pi-pico', pinName: 'GP16' }, end: { componentId: 'tft1', pinName: 'MISO' }, color: '#ffaa44' }, - { id: 'w-tft-cs', start: { componentId: 'raspberry-pi-pico', pinName: 'GP17' }, end: { componentId: 'tft1', pinName: 'CS' }, color: '#00aaff' }, - { id: 'w-tft-dc', start: { componentId: 'raspberry-pi-pico', pinName: 'GP20' }, end: { componentId: 'tft1', pinName: 'D/C' }, color: '#00cc00' }, - { id: 'w-tft-rst', start: { componentId: 'raspberry-pi-pico', pinName: 'GP21' }, end: { componentId: 'tft1', pinName: 'RST' }, color: '#cc0000' }, - { id: 'w-tft-led', start: { componentId: 'raspberry-pi-pico', pinName: 'GP22' }, end: { componentId: 'tft1', pinName: 'LED' }, color: '#ffffff' }, + { + id: 'w-tft-sck', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP18' }, + end: { componentId: 'tft1', pinName: 'SCK' }, + color: '#ff8800', + }, + { + id: 'w-tft-mosi', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP19' }, + end: { componentId: 'tft1', pinName: 'MOSI' }, + color: '#ff8800', + }, + { + id: 'w-tft-miso', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP16' }, + end: { componentId: 'tft1', pinName: 'MISO' }, + color: '#ffaa44', + }, + { + id: 'w-tft-cs', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP17' }, + end: { componentId: 'tft1', pinName: 'CS' }, + color: '#00aaff', + }, + { + id: 'w-tft-dc', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP20' }, + end: { componentId: 'tft1', pinName: 'D/C' }, + color: '#00cc00', + }, + { + id: 'w-tft-rst', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP21' }, + end: { componentId: 'tft1', pinName: 'RST' }, + color: '#cc0000', + }, + { + id: 'w-tft-led', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP22' }, + end: { componentId: 'tft1', pinName: 'LED' }, + color: '#ffffff', + }, // Buttons signal + GND each - { id: 'w-btn-fwd', start: { componentId: 'raspberry-pi-pico', pinName: 'GP10' }, end: { componentId: 'btn-fwd', pinName: '1.l' }, color: '#ff4444' }, - { id: 'w-btn-back', start: { componentId: 'raspberry-pi-pico', pinName: 'GP11' }, end: { componentId: 'btn-back', pinName: '1.l' }, color: '#4477ff' }, - { id: 'w-btn-left', start: { componentId: 'raspberry-pi-pico', pinName: 'GP12' }, end: { componentId: 'btn-left', pinName: '1.l' }, color: '#44cc44' }, - { id: 'w-btn-right', start: { componentId: 'raspberry-pi-pico', pinName: 'GP13' }, end: { componentId: 'btn-right', pinName: '1.l' }, color: '#cccc44' }, - { id: 'w-gnd-fwd', start: { componentId: 'btn-fwd', pinName: '2.l' }, end: { componentId: 'raspberry-pi-pico', pinName: 'GND.1' }, color: '#000000' }, - { id: 'w-gnd-back', start: { componentId: 'btn-back', pinName: '2.l' }, end: { componentId: 'raspberry-pi-pico', pinName: 'GND.2' }, color: '#000000' }, - { id: 'w-gnd-left', start: { componentId: 'btn-left', pinName: '2.l' }, end: { componentId: 'raspberry-pi-pico', pinName: 'GND.3' }, color: '#000000' }, - { id: 'w-gnd-right', start: { componentId: 'btn-right', pinName: '2.l' }, end: { componentId: 'raspberry-pi-pico', pinName: 'GND.4' }, color: '#000000' }, + { + id: 'w-btn-fwd', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP10' }, + end: { componentId: 'btn-fwd', pinName: '1.l' }, + color: '#ff4444', + }, + { + id: 'w-btn-back', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP11' }, + end: { componentId: 'btn-back', pinName: '1.l' }, + color: '#4477ff', + }, + { + id: 'w-btn-left', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP12' }, + end: { componentId: 'btn-left', pinName: '1.l' }, + color: '#44cc44', + }, + { + id: 'w-btn-right', + start: { componentId: 'raspberry-pi-pico', pinName: 'GP13' }, + end: { componentId: 'btn-right', pinName: '1.l' }, + color: '#cccc44', + }, + { + id: 'w-gnd-fwd', + start: { componentId: 'btn-fwd', pinName: '2.l' }, + end: { componentId: 'raspberry-pi-pico', pinName: 'GND.1' }, + color: '#000000', + }, + { + id: 'w-gnd-back', + start: { componentId: 'btn-back', pinName: '2.l' }, + end: { componentId: 'raspberry-pi-pico', pinName: 'GND.2' }, + color: '#000000', + }, + { + id: 'w-gnd-left', + start: { componentId: 'btn-left', pinName: '2.l' }, + end: { componentId: 'raspberry-pi-pico', pinName: 'GND.3' }, + color: '#000000', + }, + { + id: 'w-gnd-right', + start: { componentId: 'btn-right', pinName: '2.l' }, + end: { componentId: 'raspberry-pi-pico', pinName: 'GND.4' }, + color: '#000000', + }, ], }, { @@ -3338,16 +3861,56 @@ void loop() { ], wires: [ // SDA bus (shared) - { id: 'wire-sda', start: { componentId: 'arduino-uno', pinName: 'A4' }, end: { componentId: 'ssd1306-1', pinName: 'DATA' }, color: '#2196f3' }, - { id: 'wire-sda-rtc', start: { componentId: 'ssd1306-1', pinName: 'DATA' }, end: { componentId: 'rtc1', pinName: 'SDA' }, color: '#2196f3' }, + { + id: 'wire-sda', + start: { componentId: 'arduino-uno', pinName: 'A4' }, + end: { componentId: 'ssd1306-1', pinName: 'DATA' }, + color: '#2196f3', + }, + { + id: 'wire-sda-rtc', + start: { componentId: 'ssd1306-1', pinName: 'DATA' }, + end: { componentId: 'rtc1', pinName: 'SDA' }, + color: '#2196f3', + }, // SCL bus (shared) - { id: 'wire-scl', start: { componentId: 'arduino-uno', pinName: 'A5' }, end: { componentId: 'ssd1306-1', pinName: 'CLK' }, color: '#ff9800' }, - { id: 'wire-scl-rtc', start: { componentId: 'ssd1306-1', pinName: 'CLK' }, end: { componentId: 'rtc1', pinName: 'SCL' }, color: '#ff9800' }, + { + id: 'wire-scl', + start: { componentId: 'arduino-uno', pinName: 'A5' }, + end: { componentId: 'ssd1306-1', pinName: 'CLK' }, + color: '#ff9800', + }, + { + id: 'wire-scl-rtc', + start: { componentId: 'ssd1306-1', pinName: 'CLK' }, + end: { componentId: 'rtc1', pinName: 'SCL' }, + color: '#ff9800', + }, // Power + ground for both devices - { id: 'wire-gnd', start: { componentId: 'arduino-uno', pinName: 'GND.1' }, end: { componentId: 'ssd1306-1', pinName: 'GND' }, color: '#000000' }, - { id: 'wire-gnd-rtc', start: { componentId: 'ssd1306-1', pinName: 'GND' }, end: { componentId: 'rtc1', pinName: 'GND' }, color: '#000000' }, - { id: 'wire-vcc', start: { componentId: 'arduino-uno', pinName: '5V' }, end: { componentId: 'ssd1306-1', pinName: 'VIN' }, color: '#ff0000' }, - { id: 'wire-vcc-rtc', start: { componentId: 'ssd1306-1', pinName: 'VIN' }, end: { componentId: 'rtc1', pinName: 'VCC' }, color: '#ff0000' }, + { + id: 'wire-gnd', + start: { componentId: 'arduino-uno', pinName: 'GND.1' }, + end: { componentId: 'ssd1306-1', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'wire-gnd-rtc', + start: { componentId: 'ssd1306-1', pinName: 'GND' }, + end: { componentId: 'rtc1', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'wire-vcc', + start: { componentId: 'arduino-uno', pinName: '5V' }, + end: { componentId: 'ssd1306-1', pinName: 'VIN' }, + color: '#ff0000', + }, + { + id: 'wire-vcc-rtc', + start: { componentId: 'ssd1306-1', pinName: 'VIN' }, + end: { componentId: 'rtc1', pinName: 'VCC' }, + color: '#ff0000', + }, ], }, { @@ -3429,10 +3992,30 @@ void loop() { { type: 'wokwi-ds1307', id: 'rtc1', x: 480, y: 200, properties: {} }, ], wires: [ - { id: 'w-sda', start: { componentId: 'arduino-uno', pinName: 'A4' }, end: { componentId: 'rtc1', pinName: 'SDA' }, color: '#0066cc' }, - { id: 'w-scl', start: { componentId: 'arduino-uno', pinName: 'A5' }, end: { componentId: 'rtc1', pinName: 'SCL' }, color: '#ffaa00' }, - { id: 'w-vcc', start: { componentId: 'arduino-uno', pinName: '5V' }, end: { componentId: 'rtc1', pinName: 'VCC' }, color: '#ff0000' }, - { id: 'w-gnd', start: { componentId: 'arduino-uno', pinName: 'GND' }, end: { componentId: 'rtc1', pinName: 'GND' }, color: '#000000' }, + { + id: 'w-sda', + start: { componentId: 'arduino-uno', pinName: 'A4' }, + end: { componentId: 'rtc1', pinName: 'SDA' }, + color: '#0066cc', + }, + { + id: 'w-scl', + start: { componentId: 'arduino-uno', pinName: 'A5' }, + end: { componentId: 'rtc1', pinName: 'SCL' }, + color: '#ffaa00', + }, + { + id: 'w-vcc', + start: { componentId: 'arduino-uno', pinName: '5V' }, + end: { componentId: 'rtc1', pinName: 'VCC' }, + color: '#ff0000', + }, + { + id: 'w-gnd', + start: { componentId: 'arduino-uno', pinName: 'GND' }, + end: { componentId: 'rtc1', pinName: 'GND' }, + color: '#000000', + }, ], }, { @@ -5021,7 +5604,7 @@ void loop() { id: 'dual-pico-bidirectional-handshake', title: '[2× Pico W] Bidirectional Digital Handshake', description: - 'Two Picos signal each other over independent digital lines. Pico A drives GP15 (data) and watches GP14 (ack); Pico B reads GP15 and pulses GP14 on every transition to acknowledge. Each board\'s Serial Monitor logs every event, so you can see the round-trip on both sides.', + "Two Picos signal each other over independent digital lines. Pico A drives GP15 (data) and watches GP14 (ack); Pico B reads GP15 and pulses GP14 on every transition to acknowledge. Each board's Serial Monitor logs every event, so you can see the round-trip on both sides.", category: 'communication', difficulty: 'beginner', boardFilter: 'raspberry-pi-pico', @@ -5162,7 +5745,7 @@ void loop() { id: 'dual-pico-digital-mirror', title: '[2× Pico W] Digital GPIO Mirror', description: - 'Simplest possible cross-board test. Pico A toggles GP15 every 500 ms; Pico B reads GP15 as a digital input and mirrors its state to its built-in LED. Watch each Pico\'s Serial Monitor to confirm the wire is alive.', + "Simplest possible cross-board test. Pico A toggles GP15 every 500 ms; Pico B reads GP15 as a digital input and mirrors its state to its built-in LED. Watch each Pico's Serial Monitor to confirm the wire is alive.", category: 'basics', difficulty: 'beginner', boardFilter: 'raspberry-pi-pico', @@ -5343,6 +5926,10 @@ void loop() { components: [ { type: 'wokwi-pushbutton', id: 'btn1', x: 420, y: 120, properties: {} }, { type: 'wokwi-led', id: 'led1', x: 420, y: 260, properties: { color: 'red' } }, + // 220 ohm entre cada GPIO y su LED — (5V - ~2V) / 220R ~= 14 mA, por debajo + // de los 20 mA del LED. La resistencia en serie que le faltaba: sin ella el verificador de + // circuito calcula un cortocircuito y se niega a ejecutar el ejemplo. + { type: 'wokwi-resistor', id: 'r-led1', x: 420, y: 200, properties: { value: '220' } }, ], wires: [ { @@ -5354,7 +5941,7 @@ void loop() { { id: 'w-led', start: { componentId: 'arduino-uno', pinName: '13' }, - end: { componentId: 'led1', pinName: 'A' }, + end: { componentId: 'r-led1', pinName: '1' }, color: '#ff4444', }, { @@ -5369,6 +5956,12 @@ void loop() { end: { componentId: 'arduino-uno', pinName: 'GND' }, color: '#000000', }, + { + id: 'w-led-r', + start: { componentId: 'r-led1', pinName: '2' }, + end: { componentId: 'led1', pinName: 'A' }, + color: '#ff4444', + }, ], }, { @@ -5534,54 +6127,65 @@ void loop() { { type: 'wokwi-led', id: 'led7', x: 620, y: 80, properties: { color: 'purple' } }, { type: 'wokwi-led', id: 'led8', x: 660, y: 80, properties: { color: 'white' } }, { type: 'wokwi-led', id: 'led9', x: 700, y: 80, properties: { color: 'red' } }, + // 220 ohm entre cada GPIO y su LED — (5V - ~2V) / 220R ~= 14 mA, por debajo + // de los 20 mA del LED. Una resistencia en serie por LED. Sin ellas el verificador de circuito + // ve un cortocircuito y bloquea el Run del ejemplo entero. + { type: 'wokwi-resistor', id: 'mr-led2', x: 420, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'mr-led3', x: 460, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'mr-led4', x: 500, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'mr-led5', x: 540, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'mr-led6', x: 580, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'mr-led7', x: 620, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'mr-led8', x: 660, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'mr-led9', x: 700, y: 20, properties: { value: '220' } }, ], wires: [ { id: 'w2', start: { componentId: 'arduino-uno', pinName: '2' }, - end: { componentId: 'led2', pinName: 'A' }, + end: { componentId: 'mr-led2', pinName: '1' }, color: '#ff2222', }, { id: 'w3', start: { componentId: 'arduino-uno', pinName: '3' }, - end: { componentId: 'led3', pinName: 'A' }, + end: { componentId: 'mr-led3', pinName: '1' }, color: '#ff8800', }, { id: 'w4', start: { componentId: 'arduino-uno', pinName: '4' }, - end: { componentId: 'led4', pinName: 'A' }, + end: { componentId: 'mr-led4', pinName: '1' }, color: '#ffcc00', }, { id: 'w5', start: { componentId: 'arduino-uno', pinName: '5' }, - end: { componentId: 'led5', pinName: 'A' }, + end: { componentId: 'mr-led5', pinName: '1' }, color: '#22bb22', }, { id: 'w6', start: { componentId: 'arduino-uno', pinName: '6' }, - end: { componentId: 'led6', pinName: 'A' }, + end: { componentId: 'mr-led6', pinName: '1' }, color: '#2244ff', }, { id: 'w7', start: { componentId: 'arduino-uno', pinName: '7' }, - end: { componentId: 'led7', pinName: 'A' }, + end: { componentId: 'mr-led7', pinName: '1' }, color: '#aa44ff', }, { id: 'w8', start: { componentId: 'arduino-uno', pinName: '8' }, - end: { componentId: 'led8', pinName: 'A' }, + end: { componentId: 'mr-led8', pinName: '1' }, color: '#ffffff', }, { id: 'w9', start: { componentId: 'arduino-uno', pinName: '9' }, - end: { componentId: 'led9', pinName: 'A' }, + end: { componentId: 'mr-led9', pinName: '1' }, color: '#ff2222', }, { @@ -5632,6 +6236,54 @@ void loop() { end: { componentId: 'arduino-uno', pinName: 'GND' }, color: '#000000', }, + { + id: 'w2-r', + start: { componentId: 'mr-led2', pinName: '2' }, + end: { componentId: 'led2', pinName: 'A' }, + color: '#ff2222', + }, + { + id: 'w3-r', + start: { componentId: 'mr-led3', pinName: '2' }, + end: { componentId: 'led3', pinName: 'A' }, + color: '#ff8800', + }, + { + id: 'w4-r', + start: { componentId: 'mr-led4', pinName: '2' }, + end: { componentId: 'led4', pinName: 'A' }, + color: '#ffcc00', + }, + { + id: 'w5-r', + start: { componentId: 'mr-led5', pinName: '2' }, + end: { componentId: 'led5', pinName: 'A' }, + color: '#22bb22', + }, + { + id: 'w6-r', + start: { componentId: 'mr-led6', pinName: '2' }, + end: { componentId: 'led6', pinName: 'A' }, + color: '#2244ff', + }, + { + id: 'w7-r', + start: { componentId: 'mr-led7', pinName: '2' }, + end: { componentId: 'led7', pinName: 'A' }, + color: '#aa44ff', + }, + { + id: 'w8-r', + start: { componentId: 'mr-led8', pinName: '2' }, + end: { componentId: 'led8', pinName: 'A' }, + color: '#ffffff', + }, + { + id: 'w9-r', + start: { componentId: 'mr-led9', pinName: '2' }, + end: { componentId: 'led9', pinName: 'A' }, + color: '#ff2222', + }, ], }, { @@ -5687,54 +6339,64 @@ void loop() { { type: 'wokwi-led', id: 'mled7', x: 620, y: 80, properties: { color: 'purple' } }, { type: 'wokwi-led', id: 'mled8', x: 660, y: 80, properties: { color: 'white' } }, { type: 'wokwi-led', id: 'mled9', x: 700, y: 80, properties: { color: 'red' } }, + // 220 ohm entre cada GPIO y su LED — (5V - ~2V) / 220R ~= 14 mA, por debajo + // de los 20 mA del LED. Una resistencia en serie por LED, como en el resto de la galeria. + { type: 'wokwi-resistor', id: 'msr-mled2', x: 420, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'msr-mled3', x: 460, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'msr-mled4', x: 500, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'msr-mled5', x: 540, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'msr-mled6', x: 580, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'msr-mled7', x: 620, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'msr-mled8', x: 660, y: 20, properties: { value: '220' } }, + { type: 'wokwi-resistor', id: 'msr-mled9', x: 700, y: 20, properties: { value: '220' } }, ], wires: [ { id: 'mw2', start: { componentId: 'arduino-uno', pinName: '2' }, - end: { componentId: 'mled2', pinName: 'A' }, + end: { componentId: 'msr-mled2', pinName: '1' }, color: '#ff2222', }, { id: 'mw3', start: { componentId: 'arduino-uno', pinName: '3' }, - end: { componentId: 'mled3', pinName: 'A' }, + end: { componentId: 'msr-mled3', pinName: '1' }, color: '#ff8800', }, { id: 'mw4', start: { componentId: 'arduino-uno', pinName: '4' }, - end: { componentId: 'mled4', pinName: 'A' }, + end: { componentId: 'msr-mled4', pinName: '1' }, color: '#ffcc00', }, { id: 'mw5', start: { componentId: 'arduino-uno', pinName: '5' }, - end: { componentId: 'mled5', pinName: 'A' }, + end: { componentId: 'msr-mled5', pinName: '1' }, color: '#22bb22', }, { id: 'mw6', start: { componentId: 'arduino-uno', pinName: '6' }, - end: { componentId: 'mled6', pinName: 'A' }, + end: { componentId: 'msr-mled6', pinName: '1' }, color: '#2244ff', }, { id: 'mw7', start: { componentId: 'arduino-uno', pinName: '7' }, - end: { componentId: 'mled7', pinName: 'A' }, + end: { componentId: 'msr-mled7', pinName: '1' }, color: '#aa44ff', }, { id: 'mw8', start: { componentId: 'arduino-uno', pinName: '8' }, - end: { componentId: 'mled8', pinName: 'A' }, + end: { componentId: 'msr-mled8', pinName: '1' }, color: '#ffffff', }, { id: 'mw9', start: { componentId: 'arduino-uno', pinName: '9' }, - end: { componentId: 'mled9', pinName: 'A' }, + end: { componentId: 'msr-mled9', pinName: '1' }, color: '#ff2222', }, { @@ -5785,6 +6447,54 @@ void loop() { end: { componentId: 'arduino-uno', pinName: 'GND' }, color: '#000000', }, + { + id: 'mw2-r', + start: { componentId: 'msr-mled2', pinName: '2' }, + end: { componentId: 'mled2', pinName: 'A' }, + color: '#ff2222', + }, + { + id: 'mw3-r', + start: { componentId: 'msr-mled3', pinName: '2' }, + end: { componentId: 'mled3', pinName: 'A' }, + color: '#ff8800', + }, + { + id: 'mw4-r', + start: { componentId: 'msr-mled4', pinName: '2' }, + end: { componentId: 'mled4', pinName: 'A' }, + color: '#ffcc00', + }, + { + id: 'mw5-r', + start: { componentId: 'msr-mled5', pinName: '2' }, + end: { componentId: 'mled5', pinName: 'A' }, + color: '#22bb22', + }, + { + id: 'mw6-r', + start: { componentId: 'msr-mled6', pinName: '2' }, + end: { componentId: 'mled6', pinName: 'A' }, + color: '#2244ff', + }, + { + id: 'mw7-r', + start: { componentId: 'msr-mled7', pinName: '2' }, + end: { componentId: 'mled7', pinName: 'A' }, + color: '#aa44ff', + }, + { + id: 'mw8-r', + start: { componentId: 'msr-mled8', pinName: '2' }, + end: { componentId: 'mled8', pinName: 'A' }, + color: '#ffffff', + }, + { + id: 'mw9-r', + start: { componentId: 'msr-mled9', pinName: '2' }, + end: { componentId: 'mled9', pinName: 'A' }, + color: '#ff2222', + }, ], }, @@ -9710,30 +10420,121 @@ void loop() { } `, components: [ - { type: 'wokwi-ili9341', id: 'tft1', x: 380, y: 40, properties: {} }, - { type: 'wokwi-pushbutton', id: 'btn_fwd', x: 360, y: 330, properties: { color: 'green' } }, - { type: 'wokwi-pushbutton', id: 'btn_back', x: 470, y: 330, properties: { color: 'red' } }, - { type: 'wokwi-pushbutton', id: 'btn_left', x: 580, y: 330, properties: { color: 'blue' } }, - { type: 'wokwi-pushbutton', id: 'btn_right', x: 690, y: 330, properties: { color: 'yellow' } }, + { type: 'wokwi-ili9341', id: 'tft1', x: 380, y: 40, properties: {} }, + { type: 'wokwi-pushbutton', id: 'btn_fwd', x: 360, y: 330, properties: { color: 'green' } }, + { type: 'wokwi-pushbutton', id: 'btn_back', x: 470, y: 330, properties: { color: 'red' } }, + { type: 'wokwi-pushbutton', id: 'btn_left', x: 580, y: 330, properties: { color: 'blue' } }, + { + type: 'wokwi-pushbutton', + id: 'btn_right', + x: 690, + y: 330, + properties: { color: 'yellow' }, + }, ], wires: [ - { id: 'd-sck', start: { componentId: 'esp32', pinName: '18' }, end: { componentId: 'tft1', pinName: 'SCK' }, color: '#27ae60' }, - { id: 'd-mosi', start: { componentId: 'esp32', pinName: '23' }, end: { componentId: 'tft1', pinName: 'MOSI' }, color: '#3498db' }, - { id: 'd-miso', start: { componentId: 'esp32', pinName: '19' }, end: { componentId: 'tft1', pinName: 'MISO' }, color: '#9b59b6' }, - { id: 'd-cs', start: { componentId: 'esp32', pinName: '5' }, end: { componentId: 'tft1', pinName: 'CS' }, color: '#e67e22' }, - { id: 'd-dc', start: { componentId: 'esp32', pinName: '2' }, end: { componentId: 'tft1', pinName: 'D/C' }, color: '#f1c40f' }, - { id: 'd-rst', start: { componentId: 'esp32', pinName: '4' }, end: { componentId: 'tft1', pinName: 'RST' }, color: '#ecf0f1' }, - { id: 'd-vcc', start: { componentId: 'esp32', pinName: '3V3' }, end: { componentId: 'tft1', pinName: 'VCC' }, color: '#e74c3c' }, - { id: 'd-led', start: { componentId: 'esp32', pinName: '3V3' }, end: { componentId: 'tft1', pinName: 'LED' }, color: '#e74c3c' }, - { id: 'd-gnd', start: { componentId: 'esp32', pinName: 'GND' }, end: { componentId: 'tft1', pinName: 'GND' }, color: '#2c3e50' }, - { id: 'd-bf-s', start: { componentId: 'esp32', pinName: '32' }, end: { componentId: 'btn_fwd', pinName: '1.l' }, color: '#16a085' }, - { id: 'd-bf-g', start: { componentId: 'esp32', pinName: 'GND' }, end: { componentId: 'btn_fwd', pinName: '2.l' }, color: '#000000' }, - { id: 'd-bb-s', start: { componentId: 'esp32', pinName: '33' }, end: { componentId: 'btn_back', pinName: '1.l' }, color: '#c0392b' }, - { id: 'd-bb-g', start: { componentId: 'esp32', pinName: 'GND2' }, end: { componentId: 'btn_back', pinName: '2.l' }, color: '#000000' }, - { id: 'd-bl-s', start: { componentId: 'esp32', pinName: '25' }, end: { componentId: 'btn_left', pinName: '1.l' }, color: '#2980b9' }, - { id: 'd-bl-g', start: { componentId: 'esp32', pinName: 'GND' }, end: { componentId: 'btn_left', pinName: '2.l' }, color: '#000000' }, - { id: 'd-br-s', start: { componentId: 'esp32', pinName: '26' }, end: { componentId: 'btn_right', pinName: '1.l' }, color: '#f39c12' }, - { id: 'd-br-g', start: { componentId: 'esp32', pinName: 'GND2' }, end: { componentId: 'btn_right', pinName: '2.l' }, color: '#000000' }, + { + id: 'd-sck', + start: { componentId: 'esp32', pinName: '18' }, + end: { componentId: 'tft1', pinName: 'SCK' }, + color: '#27ae60', + }, + { + id: 'd-mosi', + start: { componentId: 'esp32', pinName: '23' }, + end: { componentId: 'tft1', pinName: 'MOSI' }, + color: '#3498db', + }, + { + id: 'd-miso', + start: { componentId: 'esp32', pinName: '19' }, + end: { componentId: 'tft1', pinName: 'MISO' }, + color: '#9b59b6', + }, + { + id: 'd-cs', + start: { componentId: 'esp32', pinName: '5' }, + end: { componentId: 'tft1', pinName: 'CS' }, + color: '#e67e22', + }, + { + id: 'd-dc', + start: { componentId: 'esp32', pinName: '2' }, + end: { componentId: 'tft1', pinName: 'D/C' }, + color: '#f1c40f', + }, + { + id: 'd-rst', + start: { componentId: 'esp32', pinName: '4' }, + end: { componentId: 'tft1', pinName: 'RST' }, + color: '#ecf0f1', + }, + { + id: 'd-vcc', + start: { componentId: 'esp32', pinName: '3V3' }, + end: { componentId: 'tft1', pinName: 'VCC' }, + color: '#e74c3c', + }, + { + id: 'd-led', + start: { componentId: 'esp32', pinName: '3V3' }, + end: { componentId: 'tft1', pinName: 'LED' }, + color: '#e74c3c', + }, + { + id: 'd-gnd', + start: { componentId: 'esp32', pinName: 'GND' }, + end: { componentId: 'tft1', pinName: 'GND' }, + color: '#2c3e50', + }, + { + id: 'd-bf-s', + start: { componentId: 'esp32', pinName: '32' }, + end: { componentId: 'btn_fwd', pinName: '1.l' }, + color: '#16a085', + }, + { + id: 'd-bf-g', + start: { componentId: 'esp32', pinName: 'GND' }, + end: { componentId: 'btn_fwd', pinName: '2.l' }, + color: '#000000', + }, + { + id: 'd-bb-s', + start: { componentId: 'esp32', pinName: '33' }, + end: { componentId: 'btn_back', pinName: '1.l' }, + color: '#c0392b', + }, + { + id: 'd-bb-g', + start: { componentId: 'esp32', pinName: 'GND2' }, + end: { componentId: 'btn_back', pinName: '2.l' }, + color: '#000000', + }, + { + id: 'd-bl-s', + start: { componentId: 'esp32', pinName: '25' }, + end: { componentId: 'btn_left', pinName: '1.l' }, + color: '#2980b9', + }, + { + id: 'd-bl-g', + start: { componentId: 'esp32', pinName: 'GND' }, + end: { componentId: 'btn_left', pinName: '2.l' }, + color: '#000000', + }, + { + id: 'd-br-s', + start: { componentId: 'esp32', pinName: '26' }, + end: { componentId: 'btn_right', pinName: '1.l' }, + color: '#f39c12', + }, + { + id: 'd-br-g', + start: { componentId: 'esp32', pinName: 'GND2' }, + end: { componentId: 'btn_right', pinName: '2.l' }, + color: '#000000', + }, ], }, @@ -9785,8 +10586,18 @@ except KeyboardInterrupt: { type: 'wokwi-led', id: 'pi3b-led', x: 540, y: 160, properties: { color: 'red' } }, ], wires: [ - { id: 'w-sig', start: { componentId: 'raspberry-pi-3', pinName: 'GPIO17' }, end: { componentId: 'pi3b-led', pinName: 'A' }, color: '#e74c3c' }, - { id: 'w-gnd', start: { componentId: 'pi3b-led', pinName: 'C' }, end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, color: '#000000' }, + { + id: 'w-sig', + start: { componentId: 'raspberry-pi-3', pinName: 'GPIO17' }, + end: { componentId: 'pi3b-led', pinName: 'A' }, + color: '#e74c3c', + }, + { + id: 'w-gnd', + start: { componentId: 'pi3b-led', pinName: 'C' }, + end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, + color: '#000000', + }, ], }, { @@ -9839,16 +10650,66 @@ except KeyboardInterrupt: { type: 'wokwi-led', id: 'pi3r-led5', x: 540, y: 380, properties: { color: 'blue' } }, ], wires: [ - { id: 'w1', start: { componentId: 'raspberry-pi-3', pinName: 'GPIO17' }, end: { componentId: 'pi3r-led1', pinName: 'A' }, color: '#e74c3c' }, - { id: 'w2', start: { componentId: 'raspberry-pi-3', pinName: 'GPIO27' }, end: { componentId: 'pi3r-led2', pinName: 'A' }, color: '#e67e22' }, - { id: 'w3', start: { componentId: 'raspberry-pi-3', pinName: 'GPIO22' }, end: { componentId: 'pi3r-led3', pinName: 'A' }, color: '#f1c40f' }, - { id: 'w4', start: { componentId: 'raspberry-pi-3', pinName: 'GPIO5' }, end: { componentId: 'pi3r-led4', pinName: 'A' }, color: '#2ecc71' }, - { id: 'w5', start: { componentId: 'raspberry-pi-3', pinName: 'GPIO6' }, end: { componentId: 'pi3r-led5', pinName: 'A' }, color: '#3498db' }, - { id: 'g1', start: { componentId: 'pi3r-led1', pinName: 'C' }, end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, color: '#000000' }, - { id: 'g2', start: { componentId: 'pi3r-led2', pinName: 'C' }, end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, color: '#000000' }, - { id: 'g3', start: { componentId: 'pi3r-led3', pinName: 'C' }, end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, color: '#000000' }, - { id: 'g4', start: { componentId: 'pi3r-led4', pinName: 'C' }, end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, color: '#000000' }, - { id: 'g5', start: { componentId: 'pi3r-led5', pinName: 'C' }, end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, color: '#000000' }, + { + id: 'w1', + start: { componentId: 'raspberry-pi-3', pinName: 'GPIO17' }, + end: { componentId: 'pi3r-led1', pinName: 'A' }, + color: '#e74c3c', + }, + { + id: 'w2', + start: { componentId: 'raspberry-pi-3', pinName: 'GPIO27' }, + end: { componentId: 'pi3r-led2', pinName: 'A' }, + color: '#e67e22', + }, + { + id: 'w3', + start: { componentId: 'raspberry-pi-3', pinName: 'GPIO22' }, + end: { componentId: 'pi3r-led3', pinName: 'A' }, + color: '#f1c40f', + }, + { + id: 'w4', + start: { componentId: 'raspberry-pi-3', pinName: 'GPIO5' }, + end: { componentId: 'pi3r-led4', pinName: 'A' }, + color: '#2ecc71', + }, + { + id: 'w5', + start: { componentId: 'raspberry-pi-3', pinName: 'GPIO6' }, + end: { componentId: 'pi3r-led5', pinName: 'A' }, + color: '#3498db', + }, + { + id: 'g1', + start: { componentId: 'pi3r-led1', pinName: 'C' }, + end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'g2', + start: { componentId: 'pi3r-led2', pinName: 'C' }, + end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'g3', + start: { componentId: 'pi3r-led3', pinName: 'C' }, + end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'g4', + start: { componentId: 'pi3r-led4', pinName: 'C' }, + end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'g5', + start: { componentId: 'pi3r-led5', pinName: 'C' }, + end: { componentId: 'raspberry-pi-3', pinName: 'GND' }, + color: '#000000', + }, ], }, { @@ -9895,10 +10756,30 @@ except KeyboardInterrupt: { type: 'wokwi-led', id: 'pi4-led', x: 540, y: 300, properties: { color: 'blue' } }, ], wires: [ - { id: 'w-btn', start: { componentId: 'raspberry-pi-4', pinName: 'GPIO2' }, end: { componentId: 'pi4-btn', pinName: '1.l' }, color: '#00aaff' }, - { id: 'w-btn-gnd', start: { componentId: 'pi4-btn', pinName: '2.l' }, end: { componentId: 'raspberry-pi-4', pinName: 'GND' }, color: '#000000' }, - { id: 'w-led', start: { componentId: 'raspberry-pi-4', pinName: 'GPIO17' }, end: { componentId: 'pi4-led', pinName: 'A' }, color: '#3498db' }, - { id: 'w-led-gnd', start: { componentId: 'pi4-led', pinName: 'C' }, end: { componentId: 'raspberry-pi-4', pinName: 'GND' }, color: '#000000' }, + { + id: 'w-btn', + start: { componentId: 'raspberry-pi-4', pinName: 'GPIO2' }, + end: { componentId: 'pi4-btn', pinName: '1.l' }, + color: '#00aaff', + }, + { + id: 'w-btn-gnd', + start: { componentId: 'pi4-btn', pinName: '2.l' }, + end: { componentId: 'raspberry-pi-4', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-led', + start: { componentId: 'raspberry-pi-4', pinName: 'GPIO17' }, + end: { componentId: 'pi4-led', pinName: 'A' }, + color: '#3498db', + }, + { + id: 'w-led-gnd', + start: { componentId: 'pi4-led', pinName: 'C' }, + end: { componentId: 'raspberry-pi-4', pinName: 'GND' }, + color: '#000000', + }, ], }, { @@ -9946,14 +10827,32 @@ except KeyboardInterrupt: }, }, ], - components: [ - { type: 'wokwi-rgb-led', id: 'pi4-rgb', x: 560, y: 160, properties: {} }, - ], + components: [{ type: 'wokwi-rgb-led', id: 'pi4-rgb', x: 560, y: 160, properties: {} }], wires: [ - { id: 'w-r', start: { componentId: 'raspberry-pi-4', pinName: 'GPIO17' }, end: { componentId: 'pi4-rgb', pinName: 'R' }, color: '#e74c3c' }, - { id: 'w-g', start: { componentId: 'raspberry-pi-4', pinName: 'GPIO27' }, end: { componentId: 'pi4-rgb', pinName: 'G' }, color: '#2ecc71' }, - { id: 'w-b', start: { componentId: 'raspberry-pi-4', pinName: 'GPIO22' }, end: { componentId: 'pi4-rgb', pinName: 'B' }, color: '#3498db' }, - { id: 'w-com', start: { componentId: 'pi4-rgb', pinName: 'COM' }, end: { componentId: 'raspberry-pi-4', pinName: 'GND' }, color: '#000000' }, + { + id: 'w-r', + start: { componentId: 'raspberry-pi-4', pinName: 'GPIO17' }, + end: { componentId: 'pi4-rgb', pinName: 'R' }, + color: '#e74c3c', + }, + { + id: 'w-g', + start: { componentId: 'raspberry-pi-4', pinName: 'GPIO27' }, + end: { componentId: 'pi4-rgb', pinName: 'G' }, + color: '#2ecc71', + }, + { + id: 'w-b', + start: { componentId: 'raspberry-pi-4', pinName: 'GPIO22' }, + end: { componentId: 'pi4-rgb', pinName: 'B' }, + color: '#3498db', + }, + { + id: 'w-com', + start: { componentId: 'pi4-rgb', pinName: 'COM' }, + end: { componentId: 'raspberry-pi-4', pinName: 'GND' }, + color: '#000000', + }, ], }, { @@ -9999,11 +10898,36 @@ except KeyboardInterrupt: { type: 'wokwi-led', id: 'pi5-led', x: 560, y: 320, properties: { color: 'red' } }, ], wires: [ - { id: 'w-vcc', start: { componentId: 'raspberry-pi-5', pinName: '5V' }, end: { componentId: 'pi5-pir', pinName: 'VCC' }, color: '#e74c3c' }, - { id: 'w-pir-gnd', start: { componentId: 'pi5-pir', pinName: 'GND' }, end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, color: '#000000' }, - { id: 'w-out', start: { componentId: 'pi5-pir', pinName: 'OUT' }, end: { componentId: 'raspberry-pi-5', pinName: 'GPIO4' }, color: '#f1c40f' }, - { id: 'w-led', start: { componentId: 'raspberry-pi-5', pinName: 'GPIO17' }, end: { componentId: 'pi5-led', pinName: 'A' }, color: '#e74c3c' }, - { id: 'w-led-gnd', start: { componentId: 'pi5-led', pinName: 'C' }, end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, color: '#000000' }, + { + id: 'w-vcc', + start: { componentId: 'raspberry-pi-5', pinName: '5V' }, + end: { componentId: 'pi5-pir', pinName: 'VCC' }, + color: '#e74c3c', + }, + { + id: 'w-pir-gnd', + start: { componentId: 'pi5-pir', pinName: 'GND' }, + end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'w-out', + start: { componentId: 'pi5-pir', pinName: 'OUT' }, + end: { componentId: 'raspberry-pi-5', pinName: 'GPIO4' }, + color: '#f1c40f', + }, + { + id: 'w-led', + start: { componentId: 'raspberry-pi-5', pinName: 'GPIO17' }, + end: { componentId: 'pi5-led', pinName: 'A' }, + color: '#e74c3c', + }, + { + id: 'w-led-gnd', + start: { componentId: 'pi5-led', pinName: 'C' }, + end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, + color: '#000000', + }, ], }, { @@ -10055,12 +10979,42 @@ except KeyboardInterrupt: { type: 'wokwi-led', id: 'pi5-green', x: 540, y: 320, properties: { color: 'green' } }, ], wires: [ - { id: 'w-r', start: { componentId: 'raspberry-pi-5', pinName: 'GPIO17' }, end: { componentId: 'pi5-red', pinName: 'A' }, color: '#e74c3c' }, - { id: 'w-y', start: { componentId: 'raspberry-pi-5', pinName: 'GPIO27' }, end: { componentId: 'pi5-yellow', pinName: 'A' }, color: '#f1c40f' }, - { id: 'w-g', start: { componentId: 'raspberry-pi-5', pinName: 'GPIO22' }, end: { componentId: 'pi5-green', pinName: 'A' }, color: '#2ecc71' }, - { id: 'g-r', start: { componentId: 'pi5-red', pinName: 'C' }, end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, color: '#000000' }, - { id: 'g-y', start: { componentId: 'pi5-yellow', pinName: 'C' }, end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, color: '#000000' }, - { id: 'g-g', start: { componentId: 'pi5-green', pinName: 'C' }, end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, color: '#000000' }, + { + id: 'w-r', + start: { componentId: 'raspberry-pi-5', pinName: 'GPIO17' }, + end: { componentId: 'pi5-red', pinName: 'A' }, + color: '#e74c3c', + }, + { + id: 'w-y', + start: { componentId: 'raspberry-pi-5', pinName: 'GPIO27' }, + end: { componentId: 'pi5-yellow', pinName: 'A' }, + color: '#f1c40f', + }, + { + id: 'w-g', + start: { componentId: 'raspberry-pi-5', pinName: 'GPIO22' }, + end: { componentId: 'pi5-green', pinName: 'A' }, + color: '#2ecc71', + }, + { + id: 'g-r', + start: { componentId: 'pi5-red', pinName: 'C' }, + end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'g-y', + start: { componentId: 'pi5-yellow', pinName: 'C' }, + end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, + color: '#000000', + }, + { + id: 'g-g', + start: { componentId: 'pi5-green', pinName: 'C' }, + end: { componentId: 'raspberry-pi-5', pinName: 'GND' }, + color: '#000000', + }, ], }, ];