Repository navigation
v0.6.0
Minor Changes
-
2c6ba7d:
current_sourcenow drives its programmed current out of itspospin, through the external circuit and back intoneg, 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 atposand left byneg. 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+ tonegand its n- topos, soI1 0 out 1mstill liftsoutto +1 V across 1k, andrunSpice's.opreports an I card's element current in its own n+ -> n- order, equal to its value, as before. A hand-builtSimCircuitthat wiredcurrent_sourcein 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.galvanicGroupshook; 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_genor a PWM pin, which never goes negative) never registered:detectedHzstayed 0 andsoundingstayed 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/envLoin 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? }, withtoneHzpresent only while a passive buzzer detects a tone, and{ kind: "speaker", sounding }. Both arebehavioral-estimatequality, read throughengine.getIcState. -
990232e: Potentiometer and trimmer
positionis now shaft rotation from the counter-clockwise stop (0) to the clockwise stop (1): position 1 puts the wiper at thecwterminal, as on a real pot turned fully clockwise. It used to put the wiper atccw, 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, save1 - 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_maxstill 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 aresistanceparam that the stamp ignored.
Patch Changes
- bc1cfd6: A Pico sleeping in MicroPython now costs the host almost nothing. rp2040js's
USBCDCanswered 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 intime.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.RP2040Mcunow 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:
RP2040Mcuno longer floods the console. rp2040js defaults to a Debug-levelConsoleLogger, 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 includingreset(). Errors still print and throw as before. Arduino (avr8js) never logged, so it is unchanged. - 3497700:
RP2040Mcu.setAnalogVoltsnow converts the pin voltage to 12-bit ADC counts. rp2040js readsadc.channelValuesas 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'sADC(Pin(26)).read_u16()returned 48 instead of 65535. The voltage is now clamped to 0..vccand scaled toround(volts / vcc * 4095), withvccthe 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:
RP2040Mcunow 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'sADC(4).read_u16()returned 0 and the datasheet formula27 - (V - 0.706) / 0.001721gave 437 °C. Each boot, includingreset(), 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.
RP2040Mcufed the whole program, plus the Ctrl-D that runs it, into rp2040js'sUSBCDCtx 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.