Lingonberry – First Leaf!

UnbeLEAFable! This is a tiny leaf growing from a callus culture, produced from a tiny cutting harvested from the wild. This is exactly what I expected (and hoped) would happen with this project. In a few more months, I hope to have rooted plantlets that I can transfer to normal soil media for hardening! Once the plants are rooted in soil, I will write up a detailed procedure on the whole process.

Wide Temperature Range Thermistor Use

Reading a thermistor seems like a pretty straightforward task, and there are a lot of guides on how to do it, either using just the beta value, or using the full set of coefficients for the Steinhart-Hart equation. I wanted and needed to do something a little different, because I wanted to measure temperatures somewhat accurately over a wide range (25-200C) with a single thermistor, for an upgraded version of the PCB hotplate.

Measuring this range is difficult because the resistance of the thermistor changes a lot over the range I care about. at 25C, this particular model is 100k ohms, and at 200C it is about 1k ohms. It is very not linear, changing very rapidly at first. Thermistors are often used in a voltage divider, where the output voltage is related to the temperature of the thermistor:

This causes a problems for my implementation because choosing other resistor in the divider causes the most sensitivity near the value where Rt=R2. That is, the temperature sensing will be easiest near where the thermistor and the other divider resistor have the same value.

This is a chart showing the expected output of a voltage divider with three different resistor values, computed from the temperature-resistance chart plotted above. The steeper the curve, the better, since a small change in temperature will create an easily measurable output. But none of these curves are linear across the whole range that I care about, from 25-200C. Instead, the 100k looks good from 0-50C the 10k looks good from 50-120 and the 1k looks good from 120-200. At the center of each of these ranges is where Rt=R2, and the output of the voltage divider is about half the input voltage.

My solution was to use several different resistor dividers instead of a single resistor divider. The final implementation uses an analog mux instead of discrete FETS, and included a 100k resistor divider as well.

Calibration

While it would be possible, through first principles and careful measurement, to figure out some mega-equation for all these components, I decided it would be a lot easier to write a script to calibrate each “channel” of the measurement. These thermistors are calibrated against a thermocouple, which was the original sensing element on the hotplate. To collect calibration data, I just measured the hotplate with the thermistor and thermocouple taped together. This produced the curves above, as expected from the simple simulation. Shown in black dots are fitted curves- the bottom two fit a sigmoid/logistic curve, and the top one (which didn’t have enough data to fit to a logistic curve easily) is fit to a 4th order polynomial. The 100k resistor values (green, top line) were pretty useless above 40C, quickly flattening out.

These curves give us a value that predicts ADC ticks for an input of temperature. The inverse is really what we are after, but that is easy to do mathematically.

Looking at the two remaining 10k and 1k curves, the question is where to swap from one to the other. The goal is to keep the amount of ADC counts per degree C as high as possible over the whole range. This can be found by inspecting the derivatives of the fitted curves and finding where they meet (in this case, just around 120C).

This chart also shows why exactly a single value for R2 in the resistor divider would be bad. For example, below 40C, the 1k resistor shows less than 1 tick per degree C, so a 1 degree change would be hard to measure there.

Limitations

This was done with a single set of data, so it may not be accurate for all time. Taking more data in the future would be neat, especially because the python script for analyzing the data will just spit out numbers. It would be interesting to compare the calibration coefficients for various data sets to figure out how much they change, run to run. Hopefully it would be a small amount.

Solution Cost

The reason I didn’t go with a thermocouple is that the reader and the thermocouple alone would cost about $10 in parts. I usually buy multiple ICs per prototype (in case of an accident) which would cost something like $15-20 in parts. The parts for the equivalent thermistor solution cost about $2.50 per unit, which is cheaper than just the thermocouple reader IC.

Lingonberry Cell Culture – Rooting

I have reached the point where I have enough lingonberry cell mass to try rooting a few of them. This is done on different media, and since I want to have these develop into plants with leaves and roots, I can’t do it in a petri dish!

Instead of using a purpose-made plant growing container, or even a polypropylene takeout container, I am using some condiment containers I have left over from the original cell culture experiments I did a few years ago. These are half polypropylene, which is autoclavable, and half polystyrene, which is not. To use these, I autoclave the bottom half and soak the other half in bleach while the autoclave is running- when the parts come out, I pour media and fish a lid out of the bleach. it seems to work well enough against contamination.

The media is woody plant media with MS vitamins and zeatin, per the recipe in Plants from Test Tubes. I poured a few CM into each cup (these are large condiment cups, not the tiny ones).

The basement chair of rooting

During rooting, it seems important to have a source of light so that the plants can start making their own sugars. These are growing in a basement, which is roughly “room temperature”, but there is not much light down there. I built a rooting tray with overhead lighting for the plants. It is mostly built off of the hardware for the “SunDown” lamp that I built. The hardware is a little overkill, but modular enough to be recycled into future lighting projects.

Lingonberry Callus Cell Culture

I’m back at trying to propagate a lingonberry plant from a cell culture gathered from the wild! This time, I seem to be having a lot more success in terms of growing something that at least resembles a callus culture. Encouragingly, I have had similar growths from various parts of plants that I plated. I tried to excise buds from the meristem, without magnification, so its hard to say exactly what tissue the cells came from, because they were very small (generally, they are from in the buds).

In the future it might be worth looking at callus induction from leaves, a technique I did not know about.

These cultures are growing relatively slowly (months between re-plating), possibly due to the totally uncontrolled and unoptimized conditions they are in, aka an funky basement. Surprisingly, contamination has not been a huge issue (transfers have been done in a pcr hood).

The next step will be to take some larger cell masses and try to get them to grow a bud, shoot, root or leaf- to start turning back into a plant. My plan is to grow them on a deeper media in a different container, undera lighting, without 2ip on something like WPM with zeatin (although zeatin is expensive, so maybe just WPM!).

DIY Canister Dive Light – Bringup

With the dive light parts in hand and assembled, it was time to test it out and fix all the inevitable mistakes. I expected this to go pretty well, and bringup for most low power functions was a breeze- however, at higher currents, this thing is a pretty good heater. This led to buying a fun tool – a thermal camera!

ESP32 bringup:

This was my first bare-chip-down ESP32 design, and it was actually pretty easy to do. I used the variant with internal flash to save room, so the only external components were a crystal + caps, some passives (R’s and C’s), and a switch for the RESET line, and a switch on the BOOT (gpio 9). However, there are two additional strapping pins (GPIO 0 and 2) that needed pulldowns. This was annoying since these pins were not pulled down on the pcb – some of them were pulled up, so the parts that did that needed to be removed, and the functionality of those circuits needs to be checked some other way.

I think in the future, it would make sense to avoid using the actual boot and reset buttons and use something like the ESP-PROG to toggle all the lines. Needing to push buttons to upload code is a drag!

pink=paste. This footprint has too much

I also consistently had issues soldering the QFN package the ESP comes in- I think this was due to too much paste on the center thermal pad. This causes the chip to float, and sometimes this causes one side of the chip (or a few pins) to lift. Next time I will reduce the amount of paste on the center pad to fix this, but I resolved it here by removing the chip, solder-wicking the thermal pad, and then re-soldering the part. Using low temp solder paste made this really easy.

LM3409 Driver bringup:

The LM3409 bringup went relatively well, but thermal issues started to crop up pretty much immediately. There are some surprising deficiencies in the layout and parts that I will be modifying for future revisions. The thermal camera really helped to visualize the issues quickly, and given the number of thermal/power projects I have worked on recently I am sure I will get to use it quite a bit.

PFET Gate Charge

One hair raising issue was that during bringup, the board started to smoke. This is almost always a bad sign. In my original estimation, this was caused by the buck PFET getting hot due to having a high gate charge. The odd thing is that the freewheel diode also got really hot, and stayed hot even if the led was very dim.

A very basic thermal investigation with two thermocouples showed that the FET was getting hotter than the diode, at least initially. However, I did smoke several diodes in the process.

original fet gate voltage. roughly 200 ns of switching time.

Reducing the gate charge did appear to solve the problem, and there was even a note in the datasheet (that I glossed over) about keeping the gate charge below ~30nC. Having a high gate charge is problematic for two reasons- it keeps the FET in a high RDS region for longer during switching, and it requires more power from the gate driver on the LED controller, which also heats up. However, this was not the real problem.

Overheating and Limp Mode:

Note that initially P1, the driver heats up to ~70C. Once the driver gets hot, P2, the diode, gets VERY hot (150C!)

Gate charge was not the entire story. With the FET replaced with a lower gate charge/higher RDSon model, there was still an issue! With the LED aggressively cooled (to allow it to live), the device would still go into some kind of limp mode after a few minutes of operation at high currents (3.6A avg, 12V, about 42W).

This seems to be due to the driver itself overheating, which is due to my poor thermal design. The driver is marked U in the layout above- this is supposed to have a thermal pad connected with vias to ground. I omitted the vias, essentially insulating the chip- no good.

Gate Voltage

Second, at high currents, the regulator needs to switch frequently to keep in regulation. Estimating from the gate voltage above (in terms of time), and assuming maximum 1A gate drive currents, I estimate that the total switching time is at least 100nS with a period of about 1375nS. The average voltage is about 16.5V, so 16.5V*1A*D = ~1.2W. This would probably be easy do dissipate if I hadn’t insulated the chip. Reducing gate charge helped reduce the power this chip was dissipating, but it was not the root cause.

To make things worse, I didn’t add much copper to dissipate heat on the FET, and at least half the copper is on the side of the driver, which actually makes things worse (its easier to for the FET to heat the driver). Adding some vias to a large plane on the back, and increasing the area on the front will increase the area the heat can easily dissipate from.

The reason the diode gets hot is because usually, the diode only free wheels for a short amount of time- when the FET is off. When the driver goes into limp mode, it has to dissipate all the energy stored in the inductor, many times a second.

So the full story is- this driver will self destruct if the driver overheats and goes into hiccup mode. Better thermal design (and eventually cooling it in the ocean) will probably improve the situation, by preventing driver overheating.

A wiser choice of package for the FET might also help dump heat to the PCB, which will be important when this is running in an enclosure. Convection won’t be an option then, and all the heat will need to go into the case.

Efficiency + Thermals:

With the driver sorted, the next thing to do was to smoke test the lamps at high currents. This went reasonably well, with only one LED burning out. As you can see above, the XHP70.3 required a heat sink and passive water cooling in order to prevent burnout. Given that its running at about 42W and only ~25% of the energy is turning into light, this is a 32W heater in a 70x70mm footprint.

This is at about 70C

This is going to be very hard to keep cool, even with the die almost being in contact with the seawater. The good news is at lower settings (around 2A) I should still get a very respectable 3000 lm out of the LED- more than the sola light!

Overall efficiency from power supply to LED was acceptable- in the mid 90’s for lower currents up to about 1400mA, and in the high 80’s above that. while that might seem like poor efficiency, this takes into account relatively long lead wires to and from the pcb, the multimeter, etc, so I actually expect it to improve in the final product, especially once the thermal design is improved.

Conclusion:

This PCB needs to be re-routed with thermal concerns and strapping pins in mind, but overall, it works! This iteration has given me a lot of confidence that the final design will do what I want it to do. I’m also really excited to keep playing with the thermal camera. It gives me a lot more information than the sizzling finger test, and it lets me dig into the context and sequence of the heating.

Sola 2000 Teardown

My beloved sola 2000 has finally, after many years of service (and after buying it secondhand) flooded. High power LED drivers and seawater do not mix well, and this light is at its EOL.

visible corrosion damage to the PCB

I have always wondered what was in this wonderful light, and now that its toast I don’t have any issues tearing it down to find out! There are a lot of very clever design decisions in this light, and a lot to learn.

Light head

The light head has two rings of LEDS- one for spot lighting and one for flood lighting. the small inner ring of three LEDs is the spot light, and the outer LEDS are the flood light. Given the package size and general shape the LEDS, I assume the inner ones are CREE XP-E2 LEDS, and the outer ones look like CREE XM-L2 LEDs.

from XHP50.3 datasheet- note that 2x current does not reach 2x luminous flux. additionally, 2x current increases Vf, which makes it even less efficient than expected from this plot

Having multiple LEDs is very smart, because LEDs run more efficiently (in terms of light per heat) at lower currents. It also spreads out the heat loading of the PFB- CREE says to estimate 75% of LED power to turn into heat instead of light- that means that a 4W LED needs to dissipate 3W of heat.

Given the stated lumen output of the light, I would guess the flood lighting runs around 9-10W, or 1A at about 9V. The ring of 6 flood LEDs probably run at about the same current (1A) but at about 18V, for an output of 18W. This means that about 7-14W needs to be dissipated. This seems to be done through good contact of the aluminum PCB with the metal ring that goes on the front of the light. If you look at the PCB photo above, you will see a smear of thermal grease along the edge.

Running multiple LEDS efficiently means spreading the heat around, especially for the radial LEDs, which are closer to the heat-sinking bezel. Its also important because the light is powered by a relatively small battery pack.

To prevent overheating, it seems like there is a single thermistor on the PCB as well. This will let the controller throttle the output when the emitters get hot.

Optics

The optics look a lot like they are made by carclo (wild conjecture). There are two styles- reflectors for the spot lights, and a total-internal reflection style optic for the spot light. I do wonder if there is any attempt to collimate the spot beam to make it extra tight, by biasing the three spot beams inwards.

LED driver

The LEDs are driven by an LT3755 wide-input rage LED driver. This driver is probably operating in boost mode all the time, since the battery voltage is too low to drive any of the LEDs. Interestingly, there is only one driver (just like in my design) but there appear to be two current sense resistors. I suspect these resistors are switched in for the spot and flood modes (on the high side, with a PFET), and then the overall brightness is controlled by PWM. This makes sense because these LEDS are probably operating at reasonable efficiency, so there is no advantage to turning down the average operating current.

As you can see, most of the corrosion/damage happened near the boost converter. It is close to where water can come in, and it is also where the highest voltages exist on the board. Seawater can cause a short between the current driver outputs, which would then tend to increase the output voltage until the current set point was reached, or until the driver maxes out or reaches some thermal limit- in other words, its a vulnerable circuit.

Flood sensor?

This board has something pretty unusual on it- a big floppy ribbon with conductors on one side. At first, I thought it might be some kind of temperature sensor, but I think it is a flood detection circuit- if it gets wet, it will alert the micro to shut down the led driver. This makes a lot of sense, both to protect the battery and the PCB. If the lamp is dried out after being protected from a flood, I imagine it would be just fine.

Magnetics + Micro

The micro is a pretty basic PIC16F884. The interface is much cooler. There are three evenly spaced IC’s marked “14E” on the PCB. I am guessing these are made (or were made) by NVE, since a lot of their ultra-low-power magnetic switches have that as a portion of the part number. This allows for control of the light without having an extra hole (leak point) in the case.

Power connections

Surprisingly, the power connections are made by wedging the pcb onto the gold contacts in the back of the case. Never in a million years would I have though that this would work so well, but some clever ribs in the back of the housing push the skinny pcb cutouts/contacts onto the gold plated pins.

Autopsy

I’ve always liked the sola lights because they are “factory sealed” and there are no waterproofing components that need changing regularly. Inspection of the front oring didn’t yield any interesting results, but looking at the light pipe seal, I have some suspicions that this might be where the light failed.

The corrosion is right under this seal, although that is also the most likely place for corrosion to happen, so its not a slam dunk. However, this is a circumferential static seal, and there are things I dont like about it.

Specifically, the surface finish of the light pipe is not very smooth on the contact area of the oring (difficult to photograph), and the whole light pipe can rock gently (although this is somewhat prevented by the bezel). The bend radius of the oring is also pretty tight compared to the diameter. The radius is about 2x the diameter, where the best practice would be about 6x the diameter.

Obviously this is a fine design, given that this light has lasted many many years. That said, I am suspicious of this seal.

Closing thoughts:

puffer-palooza at folly cove, illuminated by this light…

This light is pretty tidy from an engineering prospective, and it was a great dive light. I am still curious about what is shared between different models- how is it different than the sola 1500? from the spot lights (the driver here could easily drive a COB)? How did they reuse parts between the designs? And what on earth is that funny three-tier connector for (different models?).

I won’t be getting the answers to these questions but its fun to see what made this thing tick for so long.

DIY Canister Dive Light – Design

I recently found out my sola 2000 torch is torched- water got in and corroded the connectors. while it might be technically salvageable, I used this as an excuse to start another project- a canister dive light. I love my sola light, but the battery does not quite last two dives, especially at full blast. This means I need to bring two lights, two chargers, and two lights, and that is a little inconvenient. It also means I spend a lot of time futzing around underwater going from low to high power mode. This is surprisingly annoying, especially since I have to use two hands to switch modes.

Armed with google, hubris, and kicad I set out to design my own dive light.

Design Goals:

The goal is to build a dive light, with spot and flood modes, just like the sola lights. I want a burn time of at least 3 hours at a reasonable brightness- this is well over two recreational dives. I want it to be a canister light so I can run it full blast for the whole dive, temperature permitting. And I want it to be about as bright as the sola lights. And small. And I want a pony to go with it (kidding).

Optics and LED choices

There are a lot of constraints on this project, starting with thermal and optical considerations. There are only so many off the shelf optics, and without much in the way of a mechanical prototyping department, I want to minimize iterations. The simplest way to do this was with single LEDs and off the shelf optics. Carclo has not only an impressive array of parts to buy, but they also have charts/images to go with the optics with different base LEDs.

The problem with single LEDS is that the efficiency of the LED suffers at high outputs. This creates a lot of heat. Hopefully I can use the ocean as a heatsink. CREE seems to make hands-down the best high output LEDS, and after some careful considerations of what is available in low quantities, I decided on one XP50.3 and one XP70.3 LED. Two XP70.3’s would be better, but the beam pattern on the spot light would be too wide, since I can only get the XP70.3 with a dome lens.

Driver

Next up was the driver. It seems pretty useless to have spot and flood lighting on at the same time, and as you can see, the PCB does not have a lot of room on it for another big driver and inductor. Instead, I intend to share the high-side LED driver across both LEDs by low-side switching them. The header on top is for programming, and as a breakout for interesting pins.

Microcontroller Selection

I begrudgingly picked the ESP32 as my microcontroller. It seems like a shame to have and not use a ton of the peripherals on there, but its cheap (compared to an attiny), small (but still has a lot of pins), and in stock (unlike the atsamd series). This requires a 3v3 regulator, and due to size and laziness constraints I opted for an integrated DC-DC module. These are awesome, cheap, and easy to assemble, which is nice because I already had a lot of 0402 parts.

Emitter (LED) Board

The emitter board is aluminum, for better heat conductivity. At full blast, this will need to dissipate ~30W! In addition to LEDS, there are a couple thermistors for temperature measurements, placed near the LEDs. Given that each LED is a multi-watt heater that could probably melt itself off the board (with low temp solder), it seems prudent to monitor temperatures.

next up: firing up the retina blaster!

Junk Bin Spincoater

With the tachometer done, the next step was to get the ancient BLDC and ESC wired up and figure out how fast they were spinning. I know that the motor spins very fast but I really didn’t know how fast it was. It turns out that the speed is mostly too fast.

Here I plotted the RPM vs input command, which is basically in “hobby servo degrees” since that is how the ESC expects to get commands- a pulse every 20ms where the width of the pulse corresponds to…something. I mostly care about speeds between 5-10k, which gives me about 4 settings. I suspect that by decreasing the voltage of the power supply, I could decrease the minimum speed by limiting the free-run voltage across the motor.

As I said, its not clear exactly what the mapping is from pulses to rpm, since I don’t really know how the controller works- is it closed loop? is speed control achieved with voltage limiting, or is there actually feedback? Right now it doesn’t matter since my goal is just to make things spin fast. As you can see here, the motor spun fast enough that the tape I was using as part of the encoder ripped itself off and disintegrated all over the inside of the container.

Next Up: A PCB

absolute chaos

Based on a lot of really annoying fiddling and having parts get de-soldered during assembly, I have decided I really need a PCB for this project to prevent it from self-destructing by vibrating my deadbug soldering apart. A display, and maybe some buttons would help make it fully usable.

Junk Bin Tachometer

I ended up with a day to work on my spin coater in between a few other projects. Originally, I wanted to make a nice spin coater but because I am basing the design on a random ESC and motor that I bought 5 years ago, I decided the rest of the build would come from the junk bin as well- at least that would be fast.

One component I don’t often use (aka have in the junk bins) are “fast” analog light sensors, like the kind you would use for a tachometer. However, I do have a lot of LEDs, and I managed to find one single op amp part in my junk bin, and so I figured I could either spend a day designing a pcb that would come in 2 weeks, or spend one day hacking together a tach.

My goal was to get a digital signal out of the system, where one rising or falling edge corresponds to one revolution of the motor. I want to run this motor from about 5-10k RPM, which means each revolution is 100 uS. Detecting something every 100uS is pretty slow in circuit land, so I was not worried about the speed of the electronics.

LED as a photodiode

I know that an LED can be used as a tiny tiny current source, and that there are two common ways to amplify it- with a transistor or with an opamp. I tried a transistor to start, since I knew I had some 3904s stashed away from an old project. However, this did not give me enough gain- the signal was only about 100-200mV with a bright light shining into the LED. I didn’t try the darlington pair, because later I found out I did have three (3) dual op amps in my junk bin.

I ordered three ALM2403QPWPQ1’s for some reason in 2021. I have no idea why, but I was pleased to find out that I had an op amp on hand. Fortunately, these are .65 mm pitch parts- that makes a big difference compared to .5 mm pitch parts for unaided hand soldering, deadbug style (note to self: buy microscope).

With these dual op amps, I could actually get everything I needed out of a single chip. The first stage is a transimpedance amplifier with the photodiode as a current source. This takes the current generated by the photodiode and turns it into a voltage. In theory it should be pretty linear with incident light, but I didn’t test this.

Since I have no idea where my LEDs came from (junk bin leds!) I just stuck in the values from the make article linked above (by Forrest Mims). This seemed to work well enough, but and testing showed that increasing the feedback resistor to 2Mohms gave me suitable gain, with an output around 1.5-2V. This signal gets fed into a comparator block later, so the actual value is not too critical- just that the signal has a wide enough swing.

The comparator block is built out of the second op amp, resistors I had lying around, careful soldering, and this app note on adding hysteresis a comparator. I had to tweak the values to the resistors values I could make, but after some simulation I got a suitable result. Here you can see the .2 V of hysteresis in a plot of input vs output voltage.

As you can see in the title photo, this produces a nice clean edge as the motor body (shiny) transitions to the tape (black, not shiny) that I stuck on it. Now its back to the mechanical drawing board to make a platformt to test/write software, and time to order a VERY simple PCB for when my questionable soldering starts to fall apart.

New Tool: ZOYI ZT-702S

A one new tool that made this way easier was the ZOYI ZT-702S. I bought this to augment my basic multimeter. I was skeptical of the oscilliscope feature after suffering through quite a few substandard scopes.

It turns out to be a total delight to use, and it is great for simple stuff like this where I want to look at some quickly changing value or to measure a rise time or to see if a signal is ok. It physically much easier than breaking out my big scope (because the big scope is VERY big). The portability also seems awesome- I have done all kinds of nonsense where I need to measure a sensor in the field and a multimeter is okay, but a very basic scope would be way better. This thing rules! It can even take screenshots, and the menus are straightforward.

My main gripe so far is that the auto range button exists- since its next to the hold button, I press it by accident sometimes and this resets my measurements and puts the scope in AC mode, instead of restarting the triggered data.

As a basic multimeter it also does fine, and the continuity beeper is very fast, and the probes are pretty nice. I am excited to add this to the toolbox!

USB-C to 300V Troubleshooting

In my last post I described the challenges in using the LT3750 as a high voltage power supply. Namely, the power supply needs to be restarted after it reaches its target voltage, since it is a one-shot “charger”. An additional problem is that when inspecting the output voltage, it didn’t quite match the calculated output.

Output Discrepancy

It was surprising to get this plot of expected vs measured output, as reported by the power supply. I would expect some scaling to be wrong, or to have some DC offset due to reworking the voltage divider with 5% resistors instead of 1%, but the hockey stick on the left side of the plot is pretty egregious. Not only do the values take off there, but the concavity of the line actually seems to change! This needed further investigation.

I actually didn’t believe it at first, but after verifying the plot with a few other instruments, and after testing the ADC, rechecking the voltage divider, and a lot of head scratching I realized the problem was in the LT3750, not in the rest of the circuitry.

This was puzzling because on the surface the circuit seemed to do what I expected, aside from the range of 75-100 counts (RBg max = 970 ohms). After scouring the datasheet, I realized that there is a limit on the current into the RVout pin of 1mA. This is not really highlighted in the datasheet. I had calculated a 12k resistor for Rvout in order to get a wide Vout range. However, this violated the rule for for Rvout, and my suspicion is that the proportional current source cant keep up, meaning Vrbg has a hard time overcoming the voltage in the vout comparator, resulting in an overshoot in the output voltage.

With this hunch, I replaced Rvout with a 27k resistor. This narrowed the usable output range by bringing up the minimum output voltage- ouput voltage is proportional to Rvout/Rbg, so its easy to have a higher voltage. Rbg is limited, per the datasheet, to 2.5k or less. This is annoying, since it would be nice to have a range from about 60V-300V, because my bench supply tops out at 60V. however, at the expected output voltage, the 27k resistor nearly limits the input current to 1mA, so it would be hard to go much smaller.

At least the output is sane now! Ultimately, I could introduce another digipot on the RVout side, but its probably not worth the hassle and the cost of another set of parts for what I want to do with this. The right way to get this power supply might actually be to just use something with continuous feedback to avoid having to kick off another charge cycle.

Output Accuracy:

With the output related to the input, the next step was to relate the potentiometer codes to output voltage. Sadly, this needed to be compared to some instrument, and my multimeter does not have peak hold. So I hooked the supply up to my scope and measured the peak voltage (for a few cycles) per code. I know the expression for the output code is:

Where B is the terminal resistance/parasitic resistance of the digipot (Rbg), and A is a bunch of stuff (turns ratio, a constant, the Rvout resistor value). It doesn’t matter since I am just fitting this curve. The parameters A and B were extracted with scipy, and plugged back into the control code to control output voltage.

Improving ADC reads with rp2040 PIO:

The output stability was initially very bad. This is because the sampling was running very slowly- even running on its own core, reading/writing GPIOs and evaluating expressions takes a lot of time- here you can see the clock rate into the ADC was only 6.7kHz- much lower than the minimum 5 MHz. To put it in perspective, the raspberry pi is only running 6x faster than the max speed that that the adc can be sampled. The slowest sample speed would allow 25 instructions per- reading, including whatever is needed to generate the PWM.

Even at high speeds, it takes a lot of time to get a good sample. Since the output is a bit at a time, each bit only carries one bit of information- this sounds obvious but that means that to get a typical 8 bit resolution, we don’t need to sample 8 bits, we need to sample 256 bits. even running at 20MHz, that still means only one reading every 12.8 microseconds, and that would give worse than 1 volt resolution.

In theory, with proper filtering (which I’m not doing), the adc can provide 16 bit resolution, which is incredible. I decided to settle for taking 12 bits of samples and decimating them, running at about 18 MHz for about a 200 microsecond conversion time (plus some small overhead).

This required using the PIO of the RP2040. PIO is super cool- its like a teeny tiny extra microcontroller that gets run with a tiny(!!!) 9 instruction set. This instruction set is extremely limited- even more so than typical assembly. For example, you can do something like load a number into a 32 bit register, but you cant load a number that is bigger than 31. There is no automatic incrementing of registers, but you can decrement some registers using the jump command. Its a beautiful, but strangely functional (and very fast) mess.

Basically what my code does is load a counter into the y register of how many pwm cycles to do, and loads the maximum number into the x register – 0xFFFFFFFF. Then it starts clocking out pwm cycles, and uses the jump instruction to decrement the x register and y register. When the y register is empty, it reports the x register back to the main program and restarts.

With a little math, this results in how many “high” bits there were in the data. This duty cycle is related back to the read voltage through some simple math from the AMC3306 datasheet and the resistor divider information. This tended to read really high at low voltages (20V when the output was shorted), so I added a correction/adjustment factor to bring it back in line with reality.

Output Stability:

I wanted to get a very rough idea of the output stability. It’s not easy to to claim any kind of stability or even claim a power output without a variable load of some kind, but I wanted to at least be able to set an output voltage and look at how the supply can regulate against the internal bleeder resistors.

Overall its not too bad- the max is within a volt of the setpoint, and the ripple seems to be about 10V, although given the resolution when zoomed out this far on the scope I am not totally confident in that. Given the hackery and amount of new stuff that went into this, I am satisfied with the outcome.

What I would change:

In the scheme of things, this project went pretty well- I tried at least four or five new processes, so anything working at all is a small miracle. However, there are a couple things I would change if I did it again. Here is a very public bug/ wishlist:

Indicators for hazardous voltage presence, CHARGE and nDone would be neat and blinky. Its nice to have activity indicators. I could actually add most of these with some rework, but it would have been smart to put them on the board!

I do have provisions to add an I2C screen, but no real plans to use it at the moment. This is another nice to have, to get feedback instead of using the console or a dmm, which is limiting. Originally I didn’t expect to use the feedback delta sigma modulator, so this information would not have existed in the system. Now that I have it, it seems silly not to display output voltage.

Increasing the allowable output voltage would also be easy with a substitution of output diode and output caps. It would be wise to choose output caps well in excess of the possible output voltage- even at the expense of space. Currently, my power supply can be commanded (accidentally) to self destruct!

Obviously it would also be great to go back and add the right parts for all the r’s and c’s that are bodged in.

Fix the feedback divider for better range!

PIO errata:

side loading is awesome! it basically allows you a free instruction to set output pins while you do other stuff. The “other stuff” I am doing is nopping, but this could be super useful.

labels at the end of your code will get optimized out. even if they have a nop()[x] after them. however, a regular nop() will keep them in the code.

adc pins used in the pio need to be explicitly enabled in the way you want, e.g. pin = Pin(28, Pin.IN) or pin = Pin(28, Pin.OUT). The PIO state machine class will not do this for you.