Skip to content

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 12:57
· 60 commits to main since this release
d48d4b4

Minor Changes

  • 2c6ba7d: current_source now drives its programmed current out of its pos pin, through the external circuit and back into neg, like a battery's +. It used the SPICE I-element's naming, where the current flows from n+ THROUGH the source to n-, so it entered at pos and left by neg. A part labelled + (de:volt's Current Source) therefore ran backwards: 1 mA into 220 ohm from + to - read -220 mV across the resistor instead of +220 mV. The transient stamp, the published element current (pin0 -> pin1, so a sourcing current_source now reads -I, plus its parallel shunt's current) and the small-signal input injection all flip together. SPICE decks keep their meaning: the parser attaches an I card's n+ to neg and its n- to pos, so I1 0 out 1m still lifts out to +1 V across 1k, and runSpice's .op reports an I card's element current in its own n+ -> n- order, equal to its value, as before. A hand-built SimCircuit that wired current_source in the SPICE sense must swap its two pins.

  • bd90847: Circuits with an electrically isolated section now solve. A second battery's loop, an optocoupler's LED side, a transformer's secondary or a relay coil on its own supply has no path to ground, so its potential rested on the 1e-12 S node shunt alone and the matrix was singular to rounding. Once a closed switch stamped 1000 S into such a section, LU noise moved the whole section by tenths of a volt between Newton iterates; on a 4N35 board whose LED ran from a second battery, every step was rejected for as long as the button was held. Each isolated section now gets its own reference, a 1 S tie to ground from one node (a source's negative terminal where it has one), which carries only the shunts' ~1e-11 A. The section's voltages read against that terminal instead of averaging 0 V. Device models declare galvanically separate pins through the new optional DeviceModel.galvanicGroups hook; the optocoupler, coupled inductor and relay do. Circuits in which every net has a path to ground are bit-identical.

  • df16d52: A passive buzzer now detects its tone from a 0-5 V drive. The detector counted sign changes of the terminal voltage around 0 V, so the square wave the part's own help recommends (a clock_gen or a PWM pin, which never goes negative) never registered: detectedHz stayed 0 and sounding stayed 0. Crossings are now taken around the drive's own midpoint, from an envelope that follows each new extreme and relaxes over 0.1 s, with a Schmitt band of 10% of the swing. The frequency is timed over a full period (two crossings in the same direction), so a PWM pin at 25% duty reads its drive frequency rather than alternating between two wrong ones. Sine and bipolar drives still read the same frequency.

    The readout also follows the drive now. A tone clears two periods after the last crossing, so a buzzer whose drive stops falls silent. Before, the last frequency latched forever. A reading counts only inside the audible band (20 Hz to 20 kHz, previously 1 Hz to 100 kHz), so one press of a button across a passive buzzer is two clicks rather than a 2 Hz tone. Swings under 50 mV peak-to-peak (the speaker's signal-present floor) are silence.

    The envelope (envHi/envLo in the buzzer's IC state) is skipped by the step-error estimate. It is readout-only and moves on every step by an amount that depends on h, so comparing it would let the readout shrink the step. The crossing times are still compared.

    Physics telemetry reports the state as modelState: { kind: "buzzer", buzzerType, sounding, toneHz? }, with toneHz present only while a passive buzzer detects a tone, and { kind: "speaker", sounding }. Both are behavioral-estimate quality, read through engine.getIcState.

  • 990232e: Potentiometer and trimmer position is now shaft rotation from the counter-clockwise stop (0) to the clockwise stop (1): position 1 puts the wiper at the cw terminal, as on a real pot turned fully clockwise. It used to put the wiper at ccw, so a knob turned clockwise moved the wiper away from the CW pin. The audio (log) taper now grows the wiper-to-CCW resistance with rotation, so a volume control wired CCW to ground gives a tenth of its input at mid-rotation and rises steeply toward the CW stop. This inverts every saved position other than 0.5 (linear): to keep a circuit's wiper where it was, save 1 - position (linear taper). Linear pots at 0.5 are bit-identical.

    A pot or trimmer no longer fails open when its wiper carries an ordinary load current near or at a stop. Each track segment's share of p_max still scales with its length but is now floored at a quarter of the rating (POT_SEGMENT_MIN_RATING_SHARE), since a short segment shares its heat with the substrate and the track beside it. Before, the share fell to zero at a stop, and in the last few percent of travel the rule amounted to a 4.5 mA wiper limit for a 10 kΩ 0.2 W pot. A 5 V pot driving a red LED through 220 Ω failed at the stop with "dissipated 0.000 W ... above that segment's 0.000 W share", and also at 1-2% of travel (5% for the 0.1 W trimmer). That board now runs at every position. A rheostat overloading a short segment, or a wiper shorted across the supply at a stop, still fails. The failure check also rates the track resistance the simulation uses (rTotal, default 10 kΩ); before, it read a resistance param that the stamp ignored.

Patch Changes

  • bc1cfd6: A Pico sleeping in MicroPython now costs the host almost nothing. rp2040js's USBCDC answered every read the firmware armed on the serial OUT endpoint with an empty packet 10 µs later. TinyUSB re-armed after each one, so a program in time.sleep() took about 35,700 USB interrupts a second and its core was busy about 90% of the time: the default Blink ran at 0.93x real time and every Pico project read SLOW. RP2040Mcu now holds an armed read until it has REPL bytes to send, the way a real host does. Blink now costs about 4 ms of CPU per simulated second instead of 1,078 ms, with its pins toggling at the same times. Busy-loop programs, such as polling a button with no sleep, still keep the core fully busy, as they would on hardware.
  • b70be41: RP2040Mcu no longer floods the console. rp2040js defaults to a Debug-level ConsoleLogger, so every USB transfer, SEV and unimplemented peripheral access was printed: a Pico booting MicroPython logged 2,000+ lines in its first seconds, and in de:volt the worker fell behind real time and the page stopped responding. The core now logs errors only, set on every boot including reset(). Errors still print and throw as before. Arduino (avr8js) never logged, so it is unchanged.
  • 3497700: RP2040Mcu.setAnalogVolts now converts the pin voltage to 12-bit ADC counts. rp2040js reads adc.channelValues as raw conversion results (0 to 4095 for 0 V to ADC_VREF), but the core wrote volts there, so 3.3 V on GP26 read as 3 counts and MicroPython's ADC(Pin(26)).read_u16() returned 48 instead of 65535. The voltage is now clamped to 0..vcc and scaled to round(volts / vcc * 4095), with vcc the Pico's 3V3 rail that the engine already passes (on the Pico, ADC_VREF is that rail filtered). This covers ADC0 to ADC2 (GP26 to GP28).
  • fccd8bd: RP2040Mcu now holds the on-die temperature sensor (ADC4) at 27 °C. The engine never fed that channel and rp2040js starts it at 0 counts, so MicroPython's ADC(4).read_u16() returned 0 and the datasheet formula 27 - (V - 0.706) / 0.001721 gave 437 °C. Each boot, including reset(), now seeds 876 counts (the datasheet's 0.706 V at 27 °C against 3.3 V), which reads back as 27.04 °C.
  • a05089b: A MicroPython program longer than about 510 bytes now runs on the Pico. RP2040Mcu fed the whole program, plus the Ctrl-D that runs it, into rp2040js's USBCDC tx FIFO in one go. That FIFO holds 512 bytes and silently drops the rest, so the tail and the Ctrl-D were lost and the program never started. The REPL feed now keeps its own unbounded queue and moves the next chunk into the FIFO each time the firmware arms a read, so programs of any length arrive whole.