feat: update pin mappings and descriptions for Raspberry Pi Pico examples
parent
dc5dfb8635
commit
b900f960ad
|
|
@ -3467,16 +3467,16 @@ void loop() {
|
|||
{
|
||||
id: 'pico-hcsr04',
|
||||
title: 'Pico: HC-SR04 Ultrasonic Distance',
|
||||
description: 'Measure distance with an HC-SR04 sensor on the Raspberry Pi Pico. TRIG on GP9, ECHO on GP10.',
|
||||
description: 'Measure distance with an HC-SR04 sensor on the Raspberry Pi Pico. TRIG on D5 (GP17), ECHO on D6 (GP18).',
|
||||
category: 'sensors',
|
||||
difficulty: 'beginner',
|
||||
boardType: 'raspberry-pi-pico',
|
||||
boardFilter: 'raspberry-pi-pico',
|
||||
code: `// Raspberry Pi Pico — HC-SR04 Ultrasonic Distance Sensor
|
||||
// Wiring: TRIG → GP9 | ECHO → GP10 | VCC → 3.3V | GND → GND
|
||||
// Wiring: TRIG → D5(GP17) | ECHO → D6(GP18) | VCC → 3.3V | GND → GND
|
||||
|
||||
#define TRIG_PIN 9 // GPIO 9
|
||||
#define ECHO_PIN 10 // GPIO 10
|
||||
#define TRIG_PIN 17 // GPIO 17 (D5)
|
||||
#define ECHO_PIN 18 // GPIO 18 (D6)
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
|
@ -3510,22 +3510,22 @@ void loop() {
|
|||
wires: [
|
||||
{ id: 'pcs-vcc', start: { componentId: 'nano-rp2040', pinName: '3.3V' }, end: { componentId: 'pico-sr1', pinName: 'VCC' }, color: '#ff4444' },
|
||||
{ id: 'pcs-gnd', start: { componentId: 'nano-rp2040', pinName: 'GND.1' }, end: { componentId: 'pico-sr1', pinName: 'GND' }, color: '#000000' },
|
||||
{ id: 'pcs-trig', start: { componentId: 'nano-rp2040', pinName: 'GP9' }, end: { componentId: 'pico-sr1', pinName: 'TRIG' }, color: '#ff8800' },
|
||||
{ id: 'pcs-echo', start: { componentId: 'nano-rp2040', pinName: 'GP10' }, end: { componentId: 'pico-sr1', pinName: 'ECHO' }, color: '#22cc22' },
|
||||
{ id: 'pcs-trig', start: { componentId: 'nano-rp2040', pinName: 'D5' }, end: { componentId: 'pico-sr1', pinName: 'TRIG' }, color: '#ff8800' },
|
||||
{ id: 'pcs-echo', start: { componentId: 'nano-rp2040', pinName: 'D6' }, end: { componentId: 'pico-sr1', pinName: 'ECHO' }, color: '#22cc22' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'pico-pir',
|
||||
title: 'Pico: PIR Motion Detector',
|
||||
description: 'Detect movement with a PIR sensor on GP14. The built-in LED (GP25) activates when motion is detected.',
|
||||
description: 'Detect movement with a PIR sensor on D4 (GP16). The built-in LED (GP25) activates when motion is detected.',
|
||||
category: 'sensors',
|
||||
difficulty: 'beginner',
|
||||
boardType: 'raspberry-pi-pico',
|
||||
boardFilter: 'raspberry-pi-pico',
|
||||
code: `// Raspberry Pi Pico — PIR Motion Sensor
|
||||
// Wiring: OUT → GP14 | VCC → 3.3V | GND → GND
|
||||
// Wiring: OUT → D4(GP16) | VCC → 3.3V | GND → GND
|
||||
|
||||
#define PIR_PIN 14 // GPIO 14
|
||||
#define PIR_PIN 16 // GPIO 16 (D4)
|
||||
#define LED_PIN 25 // on-board LED (LED_BUILTIN on Pico)
|
||||
|
||||
bool prevMotion = false;
|
||||
|
|
@ -3557,24 +3557,24 @@ void loop() {
|
|||
wires: [
|
||||
{ id: 'pp-vcc', start: { componentId: 'nano-rp2040', pinName: '3.3V' }, end: { componentId: 'pico-pir1', pinName: 'VCC' }, color: '#ff4444' },
|
||||
{ id: 'pp-gnd', start: { componentId: 'nano-rp2040', pinName: 'GND.1' }, end: { componentId: 'pico-pir1', pinName: 'GND' }, color: '#000000' },
|
||||
{ id: 'pp-out', start: { componentId: 'nano-rp2040', pinName: 'GP14' }, end: { componentId: 'pico-pir1', pinName: 'OUT' }, color: '#ffcc00' },
|
||||
{ id: 'pp-out', start: { componentId: 'nano-rp2040', pinName: 'D4' }, end: { componentId: 'pico-pir1', pinName: 'OUT' }, color: '#ffcc00' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'pico-servo',
|
||||
title: 'Pico: Servo Motor Sweep',
|
||||
description: 'Sweep a servo motor from 0° to 180° and back on the Raspberry Pi Pico using GP15 (PWM).',
|
||||
description: 'Sweep a servo motor from 0° to 180° and back on the Raspberry Pi Pico using D3 / GP15 (PWM).',
|
||||
category: 'robotics',
|
||||
difficulty: 'beginner',
|
||||
boardType: 'raspberry-pi-pico',
|
||||
boardFilter: 'raspberry-pi-pico',
|
||||
code: `// Raspberry Pi Pico — Servo Motor Sweep
|
||||
// Wiring: PWM → GP15 | V+ → 3.3V | GND → GND
|
||||
// Wiring: PWM → D3(GP15) | V+ → 3.3V | GND → GND
|
||||
// Uses built-in Servo library
|
||||
|
||||
#include <Servo.h>
|
||||
|
||||
#define SERVO_PIN 15 // GPIO 15
|
||||
#define SERVO_PIN 15 // GPIO 15 (D3)
|
||||
|
||||
Servo myServo;
|
||||
|
||||
|
|
@ -3596,7 +3596,7 @@ void loop() {
|
|||
wires: [
|
||||
{ id: 'psv-vcc', start: { componentId: 'nano-rp2040', pinName: '3.3V' }, end: { componentId: 'pico-sv1', pinName: 'V+' }, color: '#ff4444' },
|
||||
{ id: 'psv-gnd', start: { componentId: 'nano-rp2040', pinName: 'GND.1' }, end: { componentId: 'pico-sv1', pinName: 'GND' }, color: '#000000' },
|
||||
{ id: 'psv-pwm', start: { componentId: 'nano-rp2040', pinName: 'GP15' }, end: { componentId: 'pico-sv1', pinName: 'PWM' }, color: '#ff8800' },
|
||||
{ id: 'psv-pwm', start: { componentId: 'nano-rp2040', pinName: 'D3' }, end: { componentId: 'pico-sv1', pinName: 'PWM' }, color: '#ff8800' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -3649,18 +3649,18 @@ void loop() {
|
|||
{
|
||||
id: 'pico-joystick',
|
||||
title: 'Pico: Analog Joystick',
|
||||
description: 'Read X/Y axes and button press from an analog joystick. VERT on A0 (GP26), HORZ on A1 (GP27), SEL button on GP14.',
|
||||
description: 'Read X/Y axes and button press from an analog joystick. VERT on A0 (GP26), HORZ on A1 (GP27), SEL button on D4 (GP16).',
|
||||
category: 'sensors',
|
||||
difficulty: 'beginner',
|
||||
boardType: 'raspberry-pi-pico',
|
||||
boardFilter: 'raspberry-pi-pico',
|
||||
code: `// Raspberry Pi Pico — Analog Joystick
|
||||
// Wiring: VERT → A0(GP26) | HORZ → A1(GP27) | SEL → GP14
|
||||
// Wiring: VERT → A0(GP26) | HORZ → A1(GP27) | SEL → D4(GP16)
|
||||
// VCC → 3.3V | GND → GND
|
||||
|
||||
#define JOY_VERT A0 // GP26
|
||||
#define JOY_HORZ A1 // GP27
|
||||
#define JOY_BTN 14 // GP14
|
||||
#define JOY_BTN 16 // GP16 (D4)
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
|
@ -3691,7 +3691,7 @@ void loop() {
|
|||
{ id: 'pj-gnd', start: { componentId: 'nano-rp2040', pinName: 'GND.1' }, end: { componentId: 'pico-joy1', pinName: 'GND' }, color: '#000000' },
|
||||
{ id: 'pj-vert', start: { componentId: 'nano-rp2040', pinName: 'A0' }, end: { componentId: 'pico-joy1', pinName: 'VERT' }, color: '#22aaff' },
|
||||
{ id: 'pj-horz', start: { componentId: 'nano-rp2040', pinName: 'A1' }, end: { componentId: 'pico-joy1', pinName: 'HORZ' }, color: '#22cc44' },
|
||||
{ id: 'pj-sel', start: { componentId: 'nano-rp2040', pinName: 'GP14' }, end: { componentId: 'pico-joy1', pinName: 'SEL' }, color: '#aa44ff' },
|
||||
{ id: 'pj-sel', start: { componentId: 'nano-rp2040', pinName: 'D4' }, end: { componentId: 'pico-joy1', pinName: 'SEL' }, color: '#aa44ff' },
|
||||
],
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -232,10 +232,10 @@ export class RP2040Simulator {
|
|||
const isHigh = state === GPIOPinState.High;
|
||||
this.pinManager.triggerPinChange(pin, isHigh);
|
||||
if (this.onPinChangeWithTime && this.rp2040) {
|
||||
// Use clock cycles if available, otherwise 0
|
||||
// IClock interface exposes `nanos` (not `timeUs`)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const clk = (this.rp2040 as any).clock;
|
||||
const timeMs = clk ? clk.timeUs / 1000 : 0;
|
||||
const timeMs = clk ? (clk.nanos as number) / 1_000_000 : 0;
|
||||
this.onPinChangeWithTime(pin, isHigh, timeMs);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -274,26 +274,72 @@ PartSimulationRegistry.register('servo', {
|
|||
const MAX_PULSE_US = 2400;
|
||||
const CPU_HZ = 16_000_000;
|
||||
|
||||
// ── Primary: cycle-accurate pulse width measurement ────────────────
|
||||
// ── RP2040 path: read PWM CC/TOP registers directly ────────────────
|
||||
// Arduino-Pico Servo library uses analogWriteFreq(50) + analogWriteRange(20000)
|
||||
// Each PWM slice CC value / (TOP+1) * 20000 gives pulse width in µs.
|
||||
// GPIO n → slice = n>>1, channel A (even) or B (odd) of `pwm.channels[slice].cc`.
|
||||
if (avrSimulator instanceof RP2040Simulator && pinSIG !== null) {
|
||||
const rp2040 = (avrSimulator as unknown as Record<string, unknown>).rp2040 as Record<string, unknown> | null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const pwmChannels = (rp2040 as any)?.pwm?.channels as Array<{ cc: number; top: number }> | undefined;
|
||||
if (pwmChannels) {
|
||||
const slice = pinSIG >> 1;
|
||||
const isChannelB = (pinSIG & 1) === 1;
|
||||
let lastPulseUs = -1;
|
||||
let rafId: number | null = null;
|
||||
|
||||
const pollPWM = () => {
|
||||
if (avrSimulator.isRunning()) {
|
||||
const ch = pwmChannels[slice];
|
||||
if (ch && ch.top > 0) {
|
||||
const ccRaw = ch.cc;
|
||||
const ccVal = isChannelB ? (ccRaw >>> 16) & 0xffff : ccRaw & 0xffff;
|
||||
// Servo period is 20ms (50 Hz via analogWriteFreq(50))
|
||||
const pulseUs = Math.round((ccVal / (ch.top + 1)) * 20_000);
|
||||
if (pulseUs !== lastPulseUs) {
|
||||
lastPulseUs = pulseUs;
|
||||
if (pulseUs >= MIN_PULSE_US && pulseUs <= MAX_PULSE_US) {
|
||||
const angle = Math.round(
|
||||
((pulseUs - MIN_PULSE_US) / (MAX_PULSE_US - MIN_PULSE_US)) * 180
|
||||
);
|
||||
el.angle = angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rafId = requestAnimationFrame(pollPWM);
|
||||
};
|
||||
|
||||
rafId = requestAnimationFrame(pollPWM);
|
||||
return () => { if (rafId !== null) cancelAnimationFrame(rafId); };
|
||||
}
|
||||
}
|
||||
|
||||
// ── AVR primary: cycle-accurate pulse width measurement ────────────
|
||||
if (pinSIG !== null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const pinManager = (avrSimulator as any).pinManager as import('../PinManager').PinManager | undefined;
|
||||
if (pinManager) {
|
||||
let riseTime = -1; // cpu.cycles at last rising edge
|
||||
let riseTime = -1; // cycle count at last rising edge
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const getCycles = () => typeof (avrSimulator as any).getCurrentCycles === 'function'
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
? (avrSimulator as any).getCurrentCycles() as number
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
: ((avrSimulator as any).cpu?.cycles ?? 0) as number;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const clockHz = typeof (avrSimulator as any).getClockHz === 'function'
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
? (avrSimulator as any).getClockHz() as number
|
||||
: CPU_HZ;
|
||||
|
||||
const unsubscribe = pinManager.onPinChange(pinSIG, (_pin, state) => {
|
||||
const cpu = (avrSimulator as any).cpu;
|
||||
if (!cpu) return;
|
||||
|
||||
if (state) {
|
||||
// Rising edge — record cycle count
|
||||
riseTime = cpu.cycles;
|
||||
riseTime = getCycles();
|
||||
} else if (riseTime >= 0) {
|
||||
// Falling edge — compute pulse width in µs
|
||||
const pulseCycles = cpu.cycles - riseTime;
|
||||
const pulseUs = (pulseCycles / CPU_HZ) * 1_000_000;
|
||||
const pulseCycles = getCycles() - riseTime;
|
||||
const pulseUs = (pulseCycles / clockHz) * 1_000_000;
|
||||
riseTime = -1;
|
||||
|
||||
// Only update if pulse is in valid RC servo range
|
||||
if (pulseUs >= MIN_PULSE_US && pulseUs <= MAX_PULSE_US) {
|
||||
const angle = Math.round(
|
||||
((pulseUs - MIN_PULSE_US) / (MAX_PULSE_US - MIN_PULSE_US)) * 180
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ export function calculatePinPosition(
|
|||
if (!pin && !pinName.includes('.')) {
|
||||
pin = pinInfo.find((p: any) => p.name === `${pinName}.1`);
|
||||
}
|
||||
// Fallback: GP-prefix → match description field (e.g. 'GP15' → description 'GPIO15')
|
||||
// Needed for Nano RP2040 Connect which uses D-prefix pin names but GPIO descriptions
|
||||
if (!pin && pinName.startsWith('GP')) {
|
||||
const gpioNum = parseInt(pinName.substring(2), 10);
|
||||
if (!isNaN(gpioNum)) {
|
||||
pin = pinInfo.find((p: any) => p.description === `GPIO${gpioNum}`);
|
||||
}
|
||||
}
|
||||
if (!pin) {
|
||||
console.warn(`[pinPositionCalculator] Pin ${pinName} not found on component ${componentId}`);
|
||||
console.warn(`Available pins:`, pinInfo.map((p: any) => p.name));
|
||||
|
|
|
|||
Loading…
Reference in New Issue