Sunday, February 22, 2026

Port MicroPython to PolarFire SoC

 We have built MicroPython for STM32F429DISC previously.  We'll use it as a guide to port MicroPython to MPFS Discovery Kit, featuring a PolarFire SoC.  It is straightforward to compile for the minimal configuration.  We aim to achieve the same functionalities as STM32F429DISC.  In the hardware-wise comparison, the shortage of non-volatile memory can be overcome by using a micro-SD card.  PolarFire RISC V supports both single and double precision floating point; STM32F429 supports only single precision. 


STM32F429I-DISC1MPFS-DISCO-KIT
CPUCortex-M4FQuad RV64GC
Flash2M128K
SRAM256K1.8M
SDRAM8M1G
Debug/ProgST-LINKFlashPro
USB-UART13
Ext Header2x 2x32RPi + MikroBus
User LEDs28
Push Buttons22
Dip Switches    -8
SensorMEMS gyro-
USBOTG-
Ethernet-1 GigE
Display2.4" QVGA LCD touch-
Storage-microSD

The STM32F429DISC build includes the following modules.

>>> help('modules')
__main__          builtins          json              select
_asyncio          cmath             machine           socket
_onewire          collections       math              stm
array             deflate           micropython       struct
asyncio/__init__  dht               network           sys
asyncio/core      errno             onewire           time
asyncio/event     framebuf          os                uasyncio
asyncio/funcs     gc                platform          uctypes
asyncio/lock      hashlib           pyb               vfs
asyncio/stream    heapq             random
binascii          io                re
Plus any modules on the filesystem

The MicroPython does not seem have a good way to manage configurations.  The #define parameters that affect the build can come from a number of places, many include files and many makefiles.  And the dependencies are not always clear.

First MICROPY_CONFIG_ROM_LEVEL can range from minimum, core, basic, extra to full, which enables more feature.  We can change it from minimum to extra.  This enables the majority of features, including compiler, stack check, helper REPL, EMACS keys in REPL, scheduler, micropython module, etc.  

 Then we add the additional options enabled by STM32.  We include FROZEN_MANIFEST, which requies in the micropython-lib submodule.  We enable VFS, which turns out have some tricky dependencies.  We have to define MICROPY_VFS_FAT in the makefile in order to bring in the oofatfs.  This compiles to about 300K (text+data).  STM32 uses a portion (112K out of 2M) of its Flash to make a file system that stores initialization files like "boot.py" and "main.py". We will make use of the micro SD card.

 Next, we want to enable floating number.  We run it on one of the application cores that support floating number.  We set MICROPY_FLOAT_IMPL to double in the makefile.  This causes additional variable to be set.  This compiles to 360K and the math module is available.

We enable the machine module by defining MICRO_PY_MACHINE.  The machine module supports peripherals such as uart, spi, i2c, timer etc; board specific code has to be write to make them work. Additional python modules can be added to manifest.py.  We also include the network module.  Another useful module in STM32 is stm, which provides access to peripheral registers and we implement a similar module. The compiles to 430K.

At this point, we have the following modules,

>>> help('modules')
__main__          builtins          json              select
_asyncio          cmath             machine           socket
array             collections       math              struct
asyncio/__init__  deflate           micropython       sys
asyncio/core      errno             mpfs              time
asyncio/event     framebuf          network           uasyncio
asyncio/funcs     gc                os                uctypes
asyncio/lock      hashlib           platform          vfs
asyncio/stream    heapq             random
binascii          io                re

Now we have to write some actual code.  As a warm-up, we first add the LED control.  Extra classes can be added by defining MACHINE_EXTRA_GLOBALS in the port modmachine.c, which is inserted into extmod/modmachine.c.  We can borrow code from STM32 and only change the GPIO code.  We can control the LED from Python.  

Before we add the drivers for the peripherals, GPIO, SPI, I2C, UART, Timers, we want to look into the Micropython compilation and assembly code for RISC-V by defining EMIT_RV32 and EMIT_INLINE_RV32.  The decorator @micropython.asm_rv32 seems to work, but @micropython.native does not. It crashes when running the function with that decorator.  Interestingly, it does not work on STM32 either.  We'll have to look into it.

Thursday, February 12, 2026

Sinusoidal Oscillator on PSoC

Sinusoidal signal can be generated with the wave DAC and low pass filter.  But here we will attempt to generate sine wave the analog way.  We will use a servo loop to stabilize the adjustable amplitude.

As a warm-up, we will try the simple classic Wien bridge oscillator using one PSoC opamp and a miniature light bulb.  The bulb has a resistance of 67 Ohms cold and 170 Ohms at 6mA.  It produces a nice sine signal.  




Friday, February 6, 2026

Troubleshooting a Quartz Clock

 A twenty-five year old quartz clock stopped working.  I'm curious to see what has failed.   Opening up the clock, we see a simple one-layer PCB with a COB (chip-on-board), a crystal, a transistor and a magnetic buzzer.  The clock movement comes from the stepper motor with a coil resistance of 545Ω; the coil is driven in the alternative directions every second.  A number gears form the hour, minute and second hand.  The alarm is set with another gear that causes a spring loaded contact to short out two pads when the hour hand coincides with the alarm hand and as the hour hand moves it pushes the contact away from the pads to stop the buzzer.

The clock was not completely dead.  Occasionally, it started, but it would soon stop moving.  All the electrical connections seemed OK.  To be sure of no cold soldering joints, I reflowed all the joints.  I probed all the connections that were possible to get to and it appeared that the voltages were getting to the circuit; both the stepper coil terminals sat at the rail and there were bias voltages on the quartz crystal terminals.  I could not see any obvious wrong.  During the course of troubleshooting, despair set in the first time.  Where should I go from here?

We stepped back and asked, what could possibly go wrong for 25-year old device?  Nothing on the electronics side: the COB was unlikely, the crystal might age and be out of frequency spec but not dead, and the buzzer was irrelevant.  It was more likely the wear-and-tear of the mechanical parts. 

Now I started to take apart of more the mechanical parts.  The gears seemed free to move, so I should see some movement if the electronics were driving it.  I could eventually rule out mechanical issues by noting that some voltages for the alarm were not at the correct values.  The voltages at the crystal leads would be stuck at a higher values and the voltages to the motor coil was static when compared with when it was running (the pulse to the motor was brief but still visibly to the multimeter). It implied the clock was not oscillating and the circuit did not start.  I even replaced the crystal with another one that came from a digital watch, but it did not work.  It was progress but still frustrating.

After somewhat aimlessly and repeatedly probing, I noticed that it could consistently start when the multimeter leads were placed between one of the crystal lead and the negative terminal of the battery.  I could observe the voltage decreasing from around 1V to 0.7V.  Curiously, on the PCB, there is an unpopulated footprint between the crystal lead and the negative terminal of the battery.  So perhaps placing a 10MΩ resistor and/or some capacitor there might work.  And putting the leads on the other crystal terminal stopped the clock.  However, after started, the clock would stop after a short time and leaving the probes on the circuit would not keep it running.

But why would it need an extra capacitor now?  Is aging a factor?  Has the oscillator circuit deteriorated?  Accumulation of dust or FOD causes leakage or stray capacitance?   Here we went back to the fundamentals: how does a crystal clock work?  Quartz is a pure SiO2 crystal with the piezoelectric property, i.e. an electric field physically deforms the crystal structure and vice versa.  There is a restoring force that would result in vibration.  

So dust and FOD are a strong hypothesis.  A thorough cleaning of the PCB with 99% isopropyl alcohol miraculously worked; now it could consistently start.

Analog Ground and Digital Ground

 I think this concept of analog ground and digital ground trips every young engineer.  The school did not teach me about this when going through the standard EE curriculum. You may first encounter this when using analog-to-digital converters or some microcontrollers or other mixed-signal devices.

There are plenty of application notes talking about it.  You might hear about separating analog ground from digital ground because the digital ground is noisy.  It sounds appealing.  So you draw too different ground symbols to keep them separate.  Then the question becomes where and how do you tie them together.  Some suggest tying together with an inductor which would be high impedance to AC to keep noise out.  Some say tying at the power input and others say under the ADC.  There are also ground planes, split planes.

 Why do some ICs have two or more grounds (some power devices have power grounds)?  You have to look at this from an IC designer's point of view; say you are designing a successive approximation analog to digital converter, which has a sample-and-hold, comparators, and voltage reference, and digital decoder and interface circuitry.  Every time, the digital gates switch, small pulse of current flows out of the ground node through the GND pin; if this pin is shared by all these circuit blocks, it generates a common-mode voltages (mostly from the parasitic inductance of the bond wire), which is small enough not to affect the digital circuitry but can be significant to the analog circuitry.  So here you kick the can down to road by using a separate pin and let the board design deal with it.  Now the IC designer does not mean to have the two grounds at different potentials.  So it seems that these ground pins should be tied right under the IC, which is the recommendation of many datasheets and application notes.   

Some mixed-signal devices, like analog to digital converters, should be treated more like analog devices (like opamps).  But for some devices like microcontrollers, the analog circuitry is only a small fraction of the overall device; it does not seem to make sense to be a part of the analog circuitry.

The key to the solution is to consider current flow.  When a digital gate launches an edge transition, which is incredibly fast dvdt driving mostly trace  or pin capacitance.  The return current flows with it; it tries to follow a path of least impedance, which if not properly designed may sweep through board areas with sensitive analog circuitry.

 

Wednesday, November 19, 2025

LED Flashlight Again

I wrote about some LED flashlight that I built or purchased many years ago.   Recently the incandescent bulb on my Garrity flashlight burnt out.  I tried to find an LED replacement bulb.  At the price $3.5 a piece, it was disappointing: 0.3W@3V, 30 Lumens.  The LED bulb went from drawing 100mA at 3V to 7mA at 2.6V and is completely off at 2.4V.  That means it cannot be used with rechargeable NiMH batteries and the Li-Ion battery voltage is too high.  I decided to build my own LED replacement bulb (P13.5S type) again.  I want to run on both two NiMH cells or one Li-Ion cell (1.8-4.2V).  LTC3429 used previously can run on a Lithium-Ion battery but as a linear regulator with the efficiency in the 60s%.  

Here is a simpler solution.  We configure the circuit to be always boost.  We can take advantage of the built-in current limit of converters.  In LT1615, the switch current limit is 350mA.  We eliminate the Schottky diode; only an inductor and a capacitor are needed.  It works down to 1V (single alkaline cell).  Because LT1615 operates with a fixed off-time control, the switching frequency changes with the input voltage, from 200-300KHz. The average current through the LED varies from 85-140mA. The efficiency is around 80%.  It has as few components as it can possibly get.  The deficiency is that LT1615 is relatively expensive ($3 a piece at volume quantity) and its current limit is a little too low.

                                Ink Drawings

Here is the actual implementation. 

 

Thursday, November 13, 2025

Testing Antonki Thermometer/Hygrometer

 Antonki Thermometer/Hygrometer is sold at $8 for two.  It claims a temperature range of -50 to 70°C (-58 to 158°F) with accuracy +/-1°C and relative humidity range 10% to 99% with accuracy of +/-5%.  It is good value if it is indeed accurate.

We use SHT31 and HTU21 breakout boards with Arduino Nano and an OLED display module (0.96" OLED 128x64).  Arduino 3.3V output is used to power the sensors and the display.  Very quickly, we pull together the code needed to read from the sensors and display the data on the OLED module.  It shows the power of Arduino.   We update the reading every 3s.

 For temperature, we also have the analog thermometer, thermocouple, and PRT measured by multimeter, and Fluke non-contact IR thermometer.   The temperatures are measured at four settings, ambient (22°C), refrigerator (3°C), freezer (-18°C), and heater (50°C).

Here are the results.  It is pretty good at the room temperature, likely at which it is calibrated, but the readings deviate greater at the colder temperatures.

Sensor Freezer Refrigerator Ambient Heater
Antonki -15.9 5.5 22.2 46.5
HTU21 -17.3 5.8 22.6 46.5
SHT31 -17.1 5.5 22.4 46.6
TC -21.0 3.0 18.0 46.0
PRT -17.4 6.0 22.8 48.5
Thermometer -19.0 3.0 22.0 51.0
Fluke -16.4 4.2 22.546.5

We compare a few humidity readings.  Since HTU21 and SHT 31 disagree by 10%, it is hard to assess the accuracy.

Sensor Reading 1 (% RH) Reading 2 (% RH) Reading 3 (% RH)
Antonki 55.0 31.0 71.0
HTU21 46.5 26.2 59.0
SHT31 56.4 34.6 69.4

 It should also be noted that the response time of Antonki is slow; it takes time to stabilize the readings, especially the humidity.  

 In conclusion, Antonki Thermometer/Hygrometer is usable at normal room temperature range.

Tuesday, October 14, 2025

A Toaster Oven

 A very simple toaster oven costs about $20.  While the most consumer electrical appliances have microcontrollers inside and some are internet connected; this oven is pretty much mechanically controlled.  It has two quartz heating elements, 500W each  (measured around 4.5A each), at the top and the bottom.  The cold resistance is about 14 Ohms; Over 17A is drawn initially.  A spring winded mechanical timer sets time up to 30min or staying on.  The timer is more or less accurate (off by less than 3 mins for 30 mins).  The mechanical timer switches the live AC wire. 

The neural wire goes to the temperature control knob, which turns to set the temperature up to 450F in the toast mode, which both heat elements are on; the turning just pushes a spring loaded switch.  Turning further to the bake and the broil mode to turn on only the bottom and the top respectively; no temperature control in these two modes.  The temperature is controlled by a heat activated switch.  It does not actually sense the oven temperature, instead a current passes through a metal strip, which can be seen glow red; the heat bends a nearby bimetal strip to actuate the switch.  There is no earth ground connection; that seems risky if the AC wire is shorted to the chassis.


 How would this design compare with a more electronically controlled design in cost and reliability?