feat(sim): P1 over-voltage for boards + electrolytic capacitors
Extends the over-voltage rule to the two cases the previous slice deferred: - Boards (ESP32 / Pico / Arduino / ...): a board's supply pins all collapse to the self-driven vcc_rail net, so an external source on them makes the .op singular rather than readable. Added a graph-based check (runs before the solve): if a power source is wired to a board supply pin and its nominal voltage exceeds that pin's rating, warn. Threaded boardKind into BoardForSpice so the verifier can look up the board rating. - Electrolytic capacitors: new `voltage` rating property (select, default 25V, on capacitor-electrolytic + cap-elec-* presets, via component-overrides + regenerated metadata). The verifier reads the DC voltage across the +/- pins and warns on over-voltage (vent/burst) and on reverse polarity (a polarized cap wired backwards). Defaults to 25V when the property is unset. Tests: 9V battery -> ESP32 VIN warns, 1.5V doesn't; 24V across a 16V cap warns, 5V across a 25V cap doesn't; reverse-biased cap warns. All real-ngspice.
This commit is contained in:
parent
12ed306efb
commit
4e20d03f4c
|
|
@ -3589,10 +3589,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "1u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "1u"
|
||||
"value": "1u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"id": "cap-elec-1u",
|
||||
|
|
@ -3615,10 +3634,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "10u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "10u"
|
||||
"value": "10u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"id": "cap-elec-10u",
|
||||
|
|
@ -3641,10 +3679,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "100u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "100u"
|
||||
"value": "100u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"id": "cap-elec-100u",
|
||||
|
|
@ -3667,10 +3724,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "1000u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "1000u"
|
||||
"value": "1000u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"id": "cap-elec-1000u",
|
||||
|
|
@ -3693,10 +3769,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "47u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "47u"
|
||||
"value": "47u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"id": "cap-elec-47u",
|
||||
|
|
@ -3719,10 +3814,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "470u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "470u"
|
||||
"value": "470u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"id": "cap-elec-470u",
|
||||
|
|
@ -3744,10 +3858,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "10u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "10u"
|
||||
"value": "10u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"id": "capacitor-electrolytic",
|
||||
|
|
|
|||
|
|
@ -261,6 +261,121 @@ describe('verifyCircuit — over-voltage on rated parts', () => {
|
|||
);
|
||||
});
|
||||
|
||||
describe('verifyCircuit — board over-voltage (graph-based)', () => {
|
||||
function board(id: string, boardKind: string): BuildNetlistInput['boards'][number] {
|
||||
return {
|
||||
id,
|
||||
boardKind,
|
||||
vcc: 3.3,
|
||||
pins: {},
|
||||
groundPinNames: ['GND', 'GND.1', 'GND.2'],
|
||||
vccPinNames: ['3V3', 'VIN', '5V'],
|
||||
};
|
||||
}
|
||||
|
||||
it(
|
||||
'warns when a 9 V battery is wired to an ESP32 VIN pin',
|
||||
{ timeout: 30_000 },
|
||||
async () => {
|
||||
const input: BuildNetlistInput = {
|
||||
components: [{ id: 'bat', metadataId: 'battery-9v', properties: {} }],
|
||||
wires: [
|
||||
{ id: 'w1', start: { componentId: 'bat', pinName: '+' }, end: { componentId: 'esp32', pinName: 'VIN' } },
|
||||
{ id: 'w2', start: { componentId: 'esp32', pinName: 'GND' }, end: { componentId: 'bat', pinName: '−' } },
|
||||
],
|
||||
boards: [board('esp32', 'esp32')],
|
||||
analysis: { kind: 'op' },
|
||||
};
|
||||
const result = await verifyCircuit(input);
|
||||
const ov = result.warnings.find((w) => w.code === 'over-voltage' && w.componentId === 'esp32');
|
||||
expect(ov, JSON.stringify(result.warnings)).toBeDefined();
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
'does NOT warn when an AA battery (1.5 V) powers the VIN pin',
|
||||
{ timeout: 30_000 },
|
||||
async () => {
|
||||
const input: BuildNetlistInput = {
|
||||
components: [{ id: 'bat', metadataId: 'battery-aa', properties: {} }],
|
||||
wires: [
|
||||
{ id: 'w1', start: { componentId: 'bat', pinName: '+' }, end: { componentId: 'esp32', pinName: 'VIN' } },
|
||||
{ id: 'w2', start: { componentId: 'esp32', pinName: 'GND' }, end: { componentId: 'bat', pinName: '−' } },
|
||||
],
|
||||
boards: [board('esp32', 'esp32')],
|
||||
analysis: { kind: 'op' },
|
||||
};
|
||||
const result = await verifyCircuit(input);
|
||||
expect(result.warnings.map((w) => w.code)).not.toContain('over-voltage');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('verifyCircuit — electrolytic capacitor', () => {
|
||||
function cap(id: string, voltage: string): BuildNetlistInput['components'][number] {
|
||||
return { id, metadataId: 'capacitor-electrolytic', properties: { value: '10u', voltage } };
|
||||
}
|
||||
|
||||
it(
|
||||
'warns when the voltage across it exceeds its rating',
|
||||
{ timeout: 30_000 },
|
||||
async () => {
|
||||
// 24 V across a 16 V cap.
|
||||
const input: BuildNetlistInput = {
|
||||
components: [pwr('src', 24), cap('c1', '16')],
|
||||
wires: [
|
||||
w('w1', ['src', 'SIG'], ['c1', '+']),
|
||||
w('w2', ['c1', '−'], ['src', 'GND']),
|
||||
],
|
||||
boards: [],
|
||||
analysis: { kind: 'op' },
|
||||
};
|
||||
const result = await verifyCircuit(input);
|
||||
const ov = result.warnings.find((x) => x.code === 'over-voltage' && x.componentId === 'c1');
|
||||
expect(ov, JSON.stringify(result.warnings)).toBeDefined();
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
'does NOT warn when within its rating',
|
||||
{ timeout: 30_000 },
|
||||
async () => {
|
||||
const input: BuildNetlistInput = {
|
||||
components: [pwr('src', 5), cap('c2', '25')],
|
||||
wires: [
|
||||
w('w1', ['src', 'SIG'], ['c2', '+']),
|
||||
w('w2', ['c2', '−'], ['src', 'GND']),
|
||||
],
|
||||
boards: [],
|
||||
analysis: { kind: 'op' },
|
||||
};
|
||||
const result = await verifyCircuit(input);
|
||||
expect(result.warnings.map((x) => x.code)).not.toContain('over-voltage');
|
||||
expect(result.warnings.map((x) => x.code)).not.toContain('reverse-polarity');
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
'warns on reverse polarity',
|
||||
{ timeout: 30_000 },
|
||||
async () => {
|
||||
// +5 V on the minus pin, plus pin to ground → reverse-biased.
|
||||
const input: BuildNetlistInput = {
|
||||
components: [pwr('src', 5), cap('c3', '25')],
|
||||
wires: [
|
||||
w('w1', ['src', 'SIG'], ['c3', '−']),
|
||||
w('w2', ['c3', '+'], ['src', 'GND']),
|
||||
],
|
||||
boards: [],
|
||||
analysis: { kind: 'op' },
|
||||
};
|
||||
const result = await verifyCircuit(input);
|
||||
const rp = result.warnings.find((x) => x.code === 'reverse-polarity' && x.componentId === 'c3');
|
||||
expect(rp, JSON.stringify(result.warnings)).toBeDefined();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// ── Sanity: shipping examples never trigger errors ─────────────────────────
|
||||
// If any gallery example produces a verifier error, that's a bug in the
|
||||
// example itself. Loop a handful of representative ones to catch
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ export function buildInputFromStore(snap: StoreSnapshot): BuildNetlistInput {
|
|||
const group = BOARD_PIN_GROUPS[b.boardKind] ?? BOARD_PIN_GROUPS.default;
|
||||
return {
|
||||
id: b.id,
|
||||
boardKind: b.boardKind,
|
||||
vcc: group.vcc,
|
||||
pins: b.pinStates,
|
||||
groundPinNames: group.gnd,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ export interface WireForSpice {
|
|||
export interface BoardForSpice {
|
||||
/** Stable unique board id (used as prefix in net names). */
|
||||
id: string;
|
||||
/** Board kind (e.g. 'arduino-uno', 'esp32') — used to look up over-voltage
|
||||
* ratings in the verifier. Optional: older callers may omit it. */
|
||||
boardKind?: string;
|
||||
/** Supply voltage of this board, V. */
|
||||
vcc: number;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export type WarningCode =
|
|||
| 'source-overload'
|
||||
| 'led-overcurrent'
|
||||
| 'over-voltage'
|
||||
| 'reverse-polarity'
|
||||
| 'resistor-overpower'
|
||||
| 'led-no-current';
|
||||
|
||||
|
|
@ -100,6 +101,48 @@ export async function verifyCircuit(
|
|||
const opInput: BuildNetlistInput = { ...input, analysis: { kind: 'op' } };
|
||||
const { netlist, pinNetMap } = buildNetlist(opInput);
|
||||
|
||||
// ── Board over-voltage (graph-based, no solve) ─────────────────────────
|
||||
// Runs BEFORE the solve so it still reports even when an external source on
|
||||
// a board's vcc rail makes the .op singular. A board's supply pins (3V3 /
|
||||
// 5V / VIN / VBUS / VSYS) all collapse to the single self-driven `vcc_rail`
|
||||
// net, so an over-voltage can't be read from node voltages — instead check
|
||||
// the wiring directly: a power source wired to a board supply pin whose
|
||||
// nominal voltage exceeds that pin's rating. Non-blocking.
|
||||
const boardWarned = new Set<string>();
|
||||
for (const board of input.boards) {
|
||||
if (!board.boardKind) continue;
|
||||
const rating = COMPONENT_RATINGS[board.boardKind];
|
||||
if (!rating) continue;
|
||||
for (const wire of input.wires) {
|
||||
if (boardWarned.has(board.id)) break;
|
||||
for (const [boardEnd, srcEnd] of [
|
||||
[wire.start, wire.end],
|
||||
[wire.end, wire.start],
|
||||
] as const) {
|
||||
if (boardEnd.componentId !== board.id) continue;
|
||||
const sp = rating.supplyPins.find((p) => p.name === boardEnd.pinName);
|
||||
if (!sp) continue;
|
||||
const src = input.components.find((c) => c.id === srcEnd.componentId);
|
||||
if (!src) continue;
|
||||
const info = sourceInfo(src);
|
||||
if (!info || !info.posPins.includes(srcEnd.pinName)) continue;
|
||||
if (info.volts > sp.absMaxVoltage) {
|
||||
boardWarned.add(board.id);
|
||||
warnings.push({
|
||||
severity: 'warning',
|
||||
code: 'over-voltage',
|
||||
componentId: board.id,
|
||||
message: `${rating.label} ${board.id} has ${formatVolts(info.volts)} wired to its ${sp.name} pin — above its ${formatVolts(
|
||||
sp.absMaxVoltage,
|
||||
)} maximum. Real hardware would likely be damaged. Use the correct supply voltage (a regulator or level shifter).`,
|
||||
metric: info.volts,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let solve: ElectricalSolveResult | undefined;
|
||||
try {
|
||||
const cooked = await runSpice(netlist);
|
||||
|
|
@ -305,6 +348,45 @@ export async function verifyCircuit(
|
|||
}
|
||||
}
|
||||
|
||||
// ── Rule 6: electrolytic capacitor over-voltage / reverse polarity ─────
|
||||
// Electrolytic caps have a voltage rating (over it they vent / burst) and a
|
||||
// polarity (reverse-biasing destroys them). Their +/- pins are normal nets,
|
||||
// so the DC voltage across them is read straight from the solve.
|
||||
for (const c of input.components) {
|
||||
if (!isElectrolyticCap(c.metadataId)) continue;
|
||||
const posNet = pinNetMap.get(`${c.id}:+`);
|
||||
const negNet = pinNetMap.get(`${c.id}:−`) ?? pinNetMap.get(`${c.id}:-`);
|
||||
if (posNet === undefined || negNet === undefined) continue; // not fully wired
|
||||
const vPos = posNet === '0' ? 0 : solve.nodeVoltages[posNet];
|
||||
const vNeg = negNet === '0' ? 0 : solve.nodeVoltages[negNet];
|
||||
if (vPos === undefined || vNeg === undefined || !Number.isFinite(vPos) || !Number.isFinite(vNeg)) {
|
||||
continue; // a terminal net is floating / unsolved
|
||||
}
|
||||
const v = vPos - vNeg;
|
||||
const rating = parseVolts(c.properties.voltage) ?? 25;
|
||||
if (v > rating) {
|
||||
warnings.push({
|
||||
severity: 'warning',
|
||||
code: 'over-voltage',
|
||||
componentId: c.id,
|
||||
message: `Electrolytic capacitor ${c.id} has ${formatVolts(v)} across it — above its ${formatVolts(
|
||||
rating,
|
||||
)} rating. A real capacitor would vent or burst; use a higher-voltage part.`,
|
||||
metric: v,
|
||||
});
|
||||
} else if (v < -0.5) {
|
||||
warnings.push({
|
||||
severity: 'warning',
|
||||
code: 'reverse-polarity',
|
||||
componentId: c.id,
|
||||
message: `Electrolytic capacitor ${c.id} is reverse-biased (${formatVolts(
|
||||
Math.abs(v),
|
||||
)} backwards). Polarized capacitors are destroyed when connected backwards — swap its + and - terminals.`,
|
||||
metric: v,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
errors,
|
||||
warnings,
|
||||
|
|
@ -313,6 +395,38 @@ export async function verifyCircuit(
|
|||
};
|
||||
}
|
||||
|
||||
/** Nominal positive-output voltage + positive pin names of a power source. */
|
||||
function sourceInfo(
|
||||
comp: BuildNetlistInput['components'][number],
|
||||
): { posPins: string[]; volts: number } | null {
|
||||
const id = comp.metadataId;
|
||||
if (id === 'battery-9v') return { posPins: ['+'], volts: 9 };
|
||||
if (id === 'battery-aa') return { posPins: ['+'], volts: 1.5 };
|
||||
if (id === 'battery-coin-cell') return { posPins: ['+'], volts: 3 };
|
||||
if (id === 'power-supply') {
|
||||
return { posPins: ['+', 'SIG', 'VCC'], volts: Math.abs(Number(comp.properties.voltage ?? 5)) };
|
||||
}
|
||||
if (id === 'signal-generator') {
|
||||
const off = Number(comp.properties.offset ?? 0);
|
||||
const amp = String(comp.properties.waveform ?? 'sine').toLowerCase() === 'dc'
|
||||
? 0
|
||||
: Number(comp.properties.amplitude ?? 0);
|
||||
return { posPins: ['SIG', '+'], volts: Math.abs(off) + Math.abs(amp) };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isElectrolyticCap(metadataId: string): boolean {
|
||||
return metadataId === 'capacitor-electrolytic' || metadataId.startsWith('cap-elec');
|
||||
}
|
||||
|
||||
/** Parse a voltage rating like '25', '25V', '6.3' → volts (null if unparseable). */
|
||||
function parseVolts(raw: unknown): number | null {
|
||||
if (raw === undefined || raw === null) return null;
|
||||
const m = /^\s*([0-9]*\.?[0-9]+)/.exec(String(raw));
|
||||
return m ? parseFloat(m[1]!) : null;
|
||||
}
|
||||
|
||||
// ── Formatting helpers ────────────────────────────────────────────────────
|
||||
|
||||
function formatAmps(a: number): string {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,16 @@
|
|||
"properties": [],
|
||||
"defaultValues": {},
|
||||
"pinCount": 16,
|
||||
"tags": ["a4988", "stepper", "driver", "motor", "step", "dir", "pololu", "motors"],
|
||||
"tags": [
|
||||
"a4988",
|
||||
"stepper",
|
||||
"driver",
|
||||
"motor",
|
||||
"step",
|
||||
"dir",
|
||||
"pololu",
|
||||
"motors"
|
||||
],
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"64\" height=\"64\" fill=\"#1a2332\" rx=\"4\"/>\n <rect x=\"16\" y=\"7\" width=\"32\" height=\"50\" rx=\"3\" fill=\"#0b3d2e\" stroke=\"#2d8f5a\" stroke-width=\"0.8\"/>\n <rect x=\"25\" y=\"25\" width=\"14\" height=\"14\" rx=\"1\" fill=\"#15151a\" stroke=\"#333\"/>\n <text x=\"32\" y=\"19\" text-anchor=\"middle\" font-family=\"sans-serif\" font-size=\"6\" fill=\"#cfe8d8\" font-weight=\"bold\">A4988</text>\n <g fill=\"#d4af37\"><rect x=\"11\" y=\"14\" width=\"5\" height=\"2\"/><rect x=\"11\" y=\"22\" width=\"5\" height=\"2\"/><rect x=\"11\" y=\"30\" width=\"5\" height=\"2\"/><rect x=\"11\" y=\"38\" width=\"5\" height=\"2\"/><rect x=\"48\" y=\"14\" width=\"5\" height=\"2\"/><rect x=\"48\" y=\"22\" width=\"5\" height=\"2\"/><rect x=\"48\" y=\"30\" width=\"5\" height=\"2\"/><rect x=\"48\" y=\"38\" width=\"5\" height=\"2\"/></g>\n <text x=\"32\" y=\"51\" text-anchor=\"middle\" font-family=\"sans-serif\" font-size=\"5\" fill=\"#8fbfa6\">STEP/DIR</text></svg>"
|
||||
},
|
||||
{
|
||||
|
|
@ -1670,10 +1679,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "10u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "10u"
|
||||
"value": "10u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"tags": [
|
||||
|
|
@ -1695,10 +1723,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "1u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "1u"
|
||||
"value": "1u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"tags": [
|
||||
|
|
@ -1721,10 +1768,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "10u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "10u"
|
||||
"value": "10u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"tags": [
|
||||
|
|
@ -1747,10 +1813,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "47u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "47u"
|
||||
"value": "47u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"tags": [
|
||||
|
|
@ -1773,10 +1858,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "100u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "100u"
|
||||
"value": "100u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"tags": [
|
||||
|
|
@ -1799,10 +1903,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "470u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "470u"
|
||||
"value": "470u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"tags": [
|
||||
|
|
@ -1825,10 +1948,29 @@
|
|||
"type": "string",
|
||||
"defaultValue": "1000u",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "voltage",
|
||||
"type": "string",
|
||||
"control": "select",
|
||||
"options": [
|
||||
"6.3",
|
||||
"10",
|
||||
"16",
|
||||
"25",
|
||||
"35",
|
||||
"50",
|
||||
"63",
|
||||
"100",
|
||||
"200",
|
||||
"400"
|
||||
],
|
||||
"defaultValue": "25"
|
||||
}
|
||||
],
|
||||
"defaultValues": {
|
||||
"value": "1000u"
|
||||
"value": "1000u",
|
||||
"voltage": "25"
|
||||
},
|
||||
"pinCount": 0,
|
||||
"tags": [
|
||||
|
|
@ -1919,12 +2061,34 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"4\" y=\"6\" width=\"56\" height=\"48\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"10\" y=\"12\" width=\"44\" height=\"36\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><text x=\"32\" y=\"34\" text-anchor=\"middle\" font-size=\"7\" fill=\"#5a5040\" font-family=\"monospace\">e-Paper</text><rect x=\"22\" y=\"54\" width=\"20\" height=\"6\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-1in54-bw", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 50, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-1in54-bw",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 50,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-1in54-bw", "refreshMs": 50 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-1in54-bw",
|
||||
"refreshMs": 50
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "ssd1681", "1.54", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"ssd1681",
|
||||
"1.54",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "epaper-2in13-bw",
|
||||
|
|
@ -1933,12 +2097,35 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"18\" width=\"60\" height=\"30\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"6\" y=\"22\" width=\"52\" height=\"22\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><text x=\"32\" y=\"36\" text-anchor=\"middle\" font-size=\"6\" fill=\"#5a5040\" font-family=\"monospace\">2.13\"</text><rect x=\"24\" y=\"48\" width=\"16\" height=\"5\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-2in13-bw", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 50, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-2in13-bw",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 50,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-2in13-bw", "refreshMs": 50 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-2in13-bw",
|
||||
"refreshMs": 50
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "ssd1675", "il3897", "2.13", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"ssd1675",
|
||||
"il3897",
|
||||
"2.13",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "epaper-2in13-bwr",
|
||||
|
|
@ -1947,12 +2134,36 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"18\" width=\"60\" height=\"30\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"6\" y=\"22\" width=\"52\" height=\"22\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><circle cx=\"15\" cy=\"32\" r=\"3\" fill=\"#c01818\"/><text x=\"38\" y=\"36\" text-anchor=\"middle\" font-size=\"6\" fill=\"#5a5040\" font-family=\"monospace\">B/W/R</text><rect x=\"24\" y=\"48\" width=\"16\" height=\"5\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-2in13-bwr", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 80, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-2in13-bwr",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 80,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-2in13-bwr", "refreshMs": 80 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-2in13-bwr",
|
||||
"refreshMs": 80
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "ssd1680", "tri-color", "red", "2.13", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"ssd1680",
|
||||
"tri-color",
|
||||
"red",
|
||||
"2.13",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "epaper-2in9-bw",
|
||||
|
|
@ -1961,12 +2172,34 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"16\" width=\"60\" height=\"34\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"6\" y=\"20\" width=\"52\" height=\"26\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><text x=\"32\" y=\"36\" text-anchor=\"middle\" font-size=\"6\" fill=\"#5a5040\" font-family=\"monospace\">2.9\"</text><rect x=\"24\" y=\"50\" width=\"16\" height=\"5\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-2in9-bw", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 50, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-2in9-bw",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 50,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-2in9-bw", "refreshMs": 50 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-2in9-bw",
|
||||
"refreshMs": 50
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "ssd1680", "2.9", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"ssd1680",
|
||||
"2.9",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "epaper-2in9-bwr",
|
||||
|
|
@ -1975,12 +2208,36 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"16\" width=\"60\" height=\"34\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"6\" y=\"20\" width=\"52\" height=\"26\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><circle cx=\"15\" cy=\"32\" r=\"3\" fill=\"#c01818\"/><text x=\"38\" y=\"36\" text-anchor=\"middle\" font-size=\"6\" fill=\"#5a5040\" font-family=\"monospace\">B/W/R</text><rect x=\"24\" y=\"50\" width=\"16\" height=\"5\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-2in9-bwr", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 80, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-2in9-bwr",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 80,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-2in9-bwr", "refreshMs": 80 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-2in9-bwr",
|
||||
"refreshMs": 80
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "ssd1680", "tri-color", "red", "2.9", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"ssd1680",
|
||||
"tri-color",
|
||||
"red",
|
||||
"2.9",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "epaper-4in2-bw",
|
||||
|
|
@ -1989,12 +2246,35 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"6\" width=\"60\" height=\"50\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"6\" y=\"10\" width=\"52\" height=\"38\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><text x=\"32\" y=\"32\" text-anchor=\"middle\" font-size=\"7\" fill=\"#5a5040\" font-family=\"monospace\">4.2\"</text><rect x=\"24\" y=\"56\" width=\"16\" height=\"5\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-4in2-bw", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 80, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-4in2-bw",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 80,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-4in2-bw", "refreshMs": 80 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-4in2-bw",
|
||||
"refreshMs": 80
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "ssd1683", "uc8176", "4.2", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"ssd1683",
|
||||
"uc8176",
|
||||
"4.2",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "epaper-7in5-bw",
|
||||
|
|
@ -2003,12 +2283,35 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"1\" y=\"4\" width=\"62\" height=\"54\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"5\" y=\"8\" width=\"54\" height=\"42\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><text x=\"32\" y=\"32\" text-anchor=\"middle\" font-size=\"8\" fill=\"#5a5040\" font-family=\"monospace\">7.5\"</text><rect x=\"24\" y=\"58\" width=\"16\" height=\"5\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-7in5-bw", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 100, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-7in5-bw",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 100,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-7in5-bw", "refreshMs": 100 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-7in5-bw",
|
||||
"refreshMs": 100
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "uc8179", "gd7965", "7.5", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"uc8179",
|
||||
"gd7965",
|
||||
"7.5",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "epaper-5in65-7c",
|
||||
|
|
@ -2017,12 +2320,36 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"6\" width=\"60\" height=\"50\" rx=\"3\" fill=\"#e8e2d4\" stroke=\"#b8aa90\"/><rect x=\"6\" y=\"10\" width=\"52\" height=\"38\" fill=\"#f4f1e8\" stroke=\"#a89a80\"/><circle cx=\"14\" cy=\"19\" r=\"3\" fill=\"#202020\"/><circle cx=\"22\" cy=\"19\" r=\"3\" fill=\"#c01010\"/><circle cx=\"30\" cy=\"19\" r=\"3\" fill=\"#20a040\"/><circle cx=\"38\" cy=\"19\" r=\"3\" fill=\"#3060c0\"/><circle cx=\"46\" cy=\"19\" r=\"3\" fill=\"#e0c830\"/><circle cx=\"54\" cy=\"19\" r=\"3\" fill=\"#e08020\"/><text x=\"32\" y=\"38\" text-anchor=\"middle\" font-size=\"6\" fill=\"#5a5040\" font-family=\"monospace\">ACeP 7</text><rect x=\"24\" y=\"56\" width=\"16\" height=\"5\" fill=\"#d49a3c\"/></svg>",
|
||||
"properties": [
|
||||
{ "name": "panelKind", "type": "string", "defaultValue": "epaper-5in65-7c", "control": "text" },
|
||||
{ "name": "refreshMs", "type": "number", "defaultValue": 150, "control": "number" }
|
||||
{
|
||||
"name": "panelKind",
|
||||
"type": "string",
|
||||
"defaultValue": "epaper-5in65-7c",
|
||||
"control": "text"
|
||||
},
|
||||
{
|
||||
"name": "refreshMs",
|
||||
"type": "number",
|
||||
"defaultValue": 150,
|
||||
"control": "number"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "panelKind": "epaper-5in65-7c", "refreshMs": 150 },
|
||||
"defaultValues": {
|
||||
"panelKind": "epaper-5in65-7c",
|
||||
"refreshMs": 150
|
||||
},
|
||||
"pinCount": 8,
|
||||
"tags": ["epaper", "e-paper", "e-ink", "display", "uc8159c", "acep", "7-color", "5.65", "gxepd2", "spi"]
|
||||
"tags": [
|
||||
"epaper",
|
||||
"e-paper",
|
||||
"e-ink",
|
||||
"display",
|
||||
"uc8159c",
|
||||
"acep",
|
||||
"7-color",
|
||||
"5.65",
|
||||
"gxepd2",
|
||||
"spi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bmp280",
|
||||
|
|
@ -2033,7 +2360,15 @@
|
|||
"properties": [],
|
||||
"defaultValues": {},
|
||||
"pinCount": 4,
|
||||
"tags": ["sensor", "i2c", "pressure", "temperature", "bmp280", "weather", "barometer"]
|
||||
"tags": [
|
||||
"sensor",
|
||||
"i2c",
|
||||
"pressure",
|
||||
"temperature",
|
||||
"bmp280",
|
||||
"weather",
|
||||
"barometer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$comment": "I2C-backpack variant of LCD1602: reuses the wokwi-lcd1602 web component but renders the 4-pin I2C header (GND/VCC/SDA/SCL) instead of the parallel 16-pin header. ProtocolParts registers the matching HD44780 + PCF8574 decoder so Arduino sketches using LiquidCrystal_I2C work out of the box.",
|
||||
|
|
@ -2055,7 +2390,10 @@
|
|||
"type": "string",
|
||||
"defaultValue": "green",
|
||||
"control": "select",
|
||||
"options": ["green", "blue"],
|
||||
"options": [
|
||||
"green",
|
||||
"blue"
|
||||
],
|
||||
"description": "LCD panel colour"
|
||||
},
|
||||
{
|
||||
|
|
@ -2074,7 +2412,15 @@
|
|||
"backlight": true
|
||||
},
|
||||
"pinCount": 4,
|
||||
"tags": ["lcd", "i2c", "display", "hd44780", "pcf8574", "1602", "liquidcrystal"]
|
||||
"tags": [
|
||||
"lcd",
|
||||
"i2c",
|
||||
"display",
|
||||
"hd44780",
|
||||
"pcf8574",
|
||||
"1602",
|
||||
"liquidcrystal"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$comment": "I2C-backpack variant of LCD2004. Same PCF8574+HD44780 protocol, but 20x4 geometry and 2004 row offsets (0x00, 0x40, 0x14, 0x54).",
|
||||
|
|
@ -2100,7 +2446,15 @@
|
|||
"backlight": true
|
||||
},
|
||||
"pinCount": 4,
|
||||
"tags": ["lcd", "i2c", "display", "hd44780", "pcf8574", "2004", "liquidcrystal"]
|
||||
"tags": [
|
||||
"lcd",
|
||||
"i2c",
|
||||
"display",
|
||||
"hd44780",
|
||||
"pcf8574",
|
||||
"2004",
|
||||
"liquidcrystal"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$comment": "Picker shortcut for SSD1306 in I2C mode — same wokwi-ssd1306 element, but the user finds it by name without having to discover the protocol selector on the generic ssd1306 entry. Issue #101.",
|
||||
|
|
@ -2110,11 +2464,23 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"64\" height=\"64\" fill=\"#0b1226\" rx=\"4\"/><rect x=\"8\" y=\"14\" width=\"48\" height=\"32\" rx=\"2\" fill=\"#000\"/><text x=\"32\" y=\"30\" text-anchor=\"middle\" font-size=\"7\" font-family=\"monospace\" fill=\"#9be1ff\" font-weight=\"bold\">SSD1306</text><text x=\"32\" y=\"40\" text-anchor=\"middle\" font-size=\"6\" font-family=\"monospace\" fill=\"#9be1ff\">I2C 0x3C</text><text x=\"32\" y=\"60\" text-anchor=\"middle\" font-size=\"7\" font-family=\"sans-serif\" fill=\"#e5e7eb\" font-weight=\"bold\">SDA SCL</text></svg>",
|
||||
"properties": [
|
||||
{ "name": "imageData", "type": "string", "control": "text" }
|
||||
{
|
||||
"name": "imageData",
|
||||
"type": "string",
|
||||
"control": "text"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "protocol": "i2c" },
|
||||
"defaultValues": {
|
||||
"protocol": "i2c"
|
||||
},
|
||||
"pinCount": 4,
|
||||
"tags": ["ssd1306", "oled", "display", "i2c", "0x3c"]
|
||||
"tags": [
|
||||
"ssd1306",
|
||||
"oled",
|
||||
"display",
|
||||
"i2c",
|
||||
"0x3c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$comment": "Picker shortcut for SSD1306 in SPI mode — counterpart to ssd1306-i2c.",
|
||||
|
|
@ -2124,11 +2490,22 @@
|
|||
"category": "displays",
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"64\" height=\"64\" fill=\"#0b1226\" rx=\"4\"/><rect x=\"8\" y=\"14\" width=\"48\" height=\"32\" rx=\"2\" fill=\"#000\"/><text x=\"32\" y=\"30\" text-anchor=\"middle\" font-size=\"7\" font-family=\"monospace\" fill=\"#9be1ff\" font-weight=\"bold\">SSD1306</text><text x=\"32\" y=\"40\" text-anchor=\"middle\" font-size=\"6\" font-family=\"monospace\" fill=\"#9be1ff\">SPI mode</text><text x=\"32\" y=\"60\" text-anchor=\"middle\" font-size=\"6\" font-family=\"sans-serif\" fill=\"#e5e7eb\" font-weight=\"bold\">MOSI/SCK/DC</text></svg>",
|
||||
"properties": [
|
||||
{ "name": "imageData", "type": "string", "control": "text" }
|
||||
{
|
||||
"name": "imageData",
|
||||
"type": "string",
|
||||
"control": "text"
|
||||
}
|
||||
],
|
||||
"defaultValues": { "protocol": "spi" },
|
||||
"defaultValues": {
|
||||
"protocol": "spi"
|
||||
},
|
||||
"pinCount": 7,
|
||||
"tags": ["ssd1306", "oled", "display", "spi"]
|
||||
"tags": [
|
||||
"ssd1306",
|
||||
"oled",
|
||||
"display",
|
||||
"spi"
|
||||
]
|
||||
}
|
||||
],
|
||||
"led": {
|
||||
|
|
@ -2181,7 +2558,18 @@
|
|||
"name": "KY-040 Rotary Encoder",
|
||||
"category": "input",
|
||||
"description": "KY-040 incremental rotary encoder with push-button. Turning the knob outputs quadrature pulses on CLK and DT (direction = which leads); the shaft press drives an active-low SW. Reads from any board's GPIO.",
|
||||
"tags": ["rotary", "encoder", "rotary encoder", "rotary-encoder", "ky-040", "ky040", "knob", "quadrature", "dial", "input"],
|
||||
"tags": [
|
||||
"rotary",
|
||||
"encoder",
|
||||
"rotary encoder",
|
||||
"rotary-encoder",
|
||||
"ky-040",
|
||||
"ky040",
|
||||
"knob",
|
||||
"quadrature",
|
||||
"dial",
|
||||
"input"
|
||||
],
|
||||
"thumbnail": "<svg width=\"64\" height=\"64\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"64\" height=\"64\" fill=\"#1a2332\" rx=\"4\"/>\n <rect x=\"12\" y=\"38\" width=\"40\" height=\"18\" rx=\"2\" fill=\"#1f6f43\" stroke=\"#2d8f5a\" stroke-width=\"0.6\"/>\n <rect x=\"17\" y=\"54\" width=\"2.5\" height=\"6\" fill=\"#d8b24a\"/>\n <rect x=\"24\" y=\"54\" width=\"2.5\" height=\"6\" fill=\"#d8b24a\"/>\n <rect x=\"31\" y=\"54\" width=\"2.5\" height=\"6\" fill=\"#d8b24a\"/>\n <rect x=\"38\" y=\"54\" width=\"2.5\" height=\"6\" fill=\"#d8b24a\"/>\n <rect x=\"45\" y=\"54\" width=\"2.5\" height=\"6\" fill=\"#d8b24a\"/>\n <circle cx=\"32\" cy=\"24\" r=\"15\" fill=\"#9aa3ad\" stroke=\"#6b7280\" stroke-width=\"1\"/>\n <circle cx=\"32\" cy=\"24\" r=\"10\" fill=\"#c7cdd4\"/>\n <rect x=\"31\" y=\"11\" width=\"2\" height=\"8\" rx=\"1\" fill=\"#475569\"/>\n <path d=\"M 45 14 A 16 16 0 0 1 49 27\" fill=\"none\" stroke=\"#4ade80\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path d=\"M 49 27 l -4 -1 l 2 -4 z\" fill=\"#4ade80\"/></svg>"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue