Sep 302018
 

So this is what I’ve come up with for the core controller.

There’s provisions for two versions on this board, one with an ATTiny861 which does high-speed (250kHz) PWM and can drive a buck, boost or buck-boost DC-DC converter.  It features differential I²C interfaces for the input and output INA219 boards, and LVDS for controlling the MOSFET boards.

The other version is built around the ATTiny24A, and just features the ability to turn on and off MOSFETs.  It can drive two statically, or PWM one (at a much lower speed), with the user supplying the driver logic.  Due to the the fact that this device does not do high-speed switching, I’ve forgone the LVDS control over a simple current loop.  The I²C is still differential though as that could be some distance away and is still somewhat high frequency.

The layout of the board is a small 5×5cm 4-layer PCB.

I had to go 4-layer as I needed to route signals both sides and didn’t want to interrupt the power planes.  The two inner layers are VCC and GND.  There’s de-coupling capacitors galore, although the two power planes will probably function as a decent capacitor in their own right.  ICSP is via the interface header at the bottom.

Sep 302018
 

I was originally thinking of one monolithic board which would have everything it needed.

There was provision for the lot, including a separate ATTiny24A so that you could omit all but one of the MOSFETs, swap the remaining MOSFET for a P-channel, drop the MOSFET drivers, one of the INA219s, and the ATTiny861, and you’d have just a monitoring board with a (low-speed) PWMable switch.  It’d plug into the same place and use the same host interface.  The one board could be made into just a boost, or just a buck.  Flexibility.

There was just one snag.  That’ll work for small power supplies with maybe up to 5A capability (~100W) but not for the 50A version.  The MOSFETs will fit, but the tracks will need to be huge, the board will be hideously expensive to make, and they don’t make inductors big enough.

Looking around for inductors, I did see these.  They’re not massive like the 10uH one I saw, and they’re not expensive.  The downside is they’re about 10% of what I really need.  I guess I’ll just make do.  They’re also not PCB-mount (mind you, a 40kg inductor doesn’t PCB-mount either).

Thus, it may be more sensible to separate the MOSFETs and high-power stuff from the controller.  Now here’s the rub.  We’re dealing with sub-15ns pulses.  PWM.

Years ago for my industrial experience, I did work on an electric harvester platform.  The system ran 48V.  The motors were rated at 20kW, and were made in house using windings wound from 5mm diameter enamelled copper wire and neodymium magnets.

We had loads of issues with MOSFETs blowing.  The MOSFET driver was mounted close to the MOSFETs, as I’m proposing to do here, but between DSP and driver, was a long-ish run of ribbon cable. @Bil Herd posted this article covering the challenges involving inductance on PCB layout.  That same problem applies to “long” cable runs too.

10 years ago when we were working on this project, I remember asking about if we had considered maybe using coax cable instead of a ribbon cable.  The idea was rubbished at the time.  Given we were PWMing 400A, I think there might’ve been something in that suggestion.

That ribbon (10~20cm of it) would have had a lovely inductance all of its own, and while I have no idea what frequency the PWM was running at (I might have the code somewhere but I can’t be stuffed digging it up), and we were fundamentally driving a single-ended signal over a fairly long distance.  Yes, ground was close, but probably not enough, a twisted pair would have been better, but even then not perfect.  We blew many MOSFETs on that project.  Big TO-263s!

An earlier article on differential signalling got me thinking: why not use LVDS for the PWM?  A quick search has revealed this receiver and transmitter (Mouser says two receivers on it, but I think that’s a typo).  The idea being that I send the PWM down a differential pair using LVDS.  155Mbps should be plenty fast enough (the ATTiny861 can only do 64MHz) and these parts will run at the 5V needed for fast switching.  In fact they require it.

Using twisted pairs, the inductance should cancel.  I’ll make a MOSFET board that just has these signal pairs:

  • +12V (for the MOSFET driver) and 0V
  • +5V (for the LVDS receiver) and 0V
  • High side PWM + and –
  • Low side PWM + and –

There’s a ground-loop I need to be wary of between the 12V and 5V rails, really it’s the same 0V rail for both.  I suspect they’ll still need to be connected at both ends.  Add in more of those screw terminals to take the input and output power off-board, and I think we should be set.

Similarly, the INA219 should probably be a separate board, with scope for having a chassis-mounted current shunt.  The connection to the current shunt’s sense output is a low-power connection, so no issue there.  You want to keep it short for accuracy reasons, but a simple twisted pair will work fine.

Sep 292018
 

So, I’ve been pondering doing a more capable power controller for the purpose of enhancing or even outright replacing the solar controllers I have now on the Solar-powered cloud computing cluster.

The idea started as a straight DC power meter with a Modbus interface, as there’s pretty much nothing on the market.  Lots of proprietary jobbies, or display-only toys, but nothing that will talk an open protocol.  I started designing a circuit.  I thought: it’d be handy to have digital inputs and outputs.

Lots of mains energy meters have them, and they’re handy for switching loads.  My remote reset facility when porting the mainline kernel to the TS-7670 was a digital output on the CET PMC-519.  If I crashed the TS-7670, I basically fired up ipython, loaded pymodbus, connected to a Modbus/TCP gateway, then issued a few write-coil commands to power-cycle the TS-7670.

Often the digital inputs are hooked to water or gas pulse meters to meter usage: you get a pulse every N litres of water or every N cubic metres of gas.

A meter with digital I/O that’s programmable would be just perfect for the job my little power controller is doing.

I could make the channels PWMable, thus be able to step down the voltage.  Put an INA219 on there, and I’d have current measurement and power control.  The idea evolved to putting the INA219 and a MOSFET on a board, so it was a separate module: just to make board layout easier and to reduce the size of the boards.

For a buck converter, you just add an inductor and a few smoothing capacitors.  Better yet, two INA219s and a MCU would let me measure power in, out, and have localised brains.  Thus the idea of a separate, smart module, was born.  For kicks, I’m also adding the ability to boost as well by tacking a boost converter to the end.

The principle is really quite simple.  A buck converter has this topology (source, Wikipedia):

If you swap out that diode for another MOSFET, you get a synchronous buck converter, which looks like this (same Wikipedia article):

It’s worth noting that a MOSFET switch has a body diode that might be exploitable, I’ll have to check.  You drive the two switches with complimentary outputs.  Both these circuits will step down a voltage, which is what I want to do 99% of the time, but it’s also useful to go up .  A boost converter looks like this (source: Wikipedia):

Again, that diode can be replaced with another MOSFET.  This will step up a voltage, but not down.

There are a few options that allow going both ways:

  • Flyback : which uses a transformer and provides galvanic isolation.  The downside is the secondary must take all the output current, and finding a transformer that can do 50A is EXPENSIVE!  So scratch that.  (And no I am not winding my own transformers… tried that back at uni when a lecturer asked us to build a flyback converter.  Bugger that!)
  • SEPIC is basically a boost plus a buck-boost.  Efficiency is not their strong suite apparently, although there are ways to improve it.  I’m not sure the added complexity of two boost converters sandwiching a buck converter is worth it.
  • Ćuk is no good here because it inverts its output, unless you want an isolated one, which is going to be $$$$ because of the transformer needed.  Yes, I’m chickening out!
  • Split-Pi looks real interesting, in that it’s bi-directional.  In the event I ever decide to buy a front-wheel motor for my bicycle, I could use one of these to do regenerative braking and save some wear on my brake pads.  I haven’t seen many schematics for this though, just generalised ones like the one above.
  • Zeta also looks interesting, but it’s pretty unknown, and has a higher parts requirement.  It could be worth looking at.  It’s a close relative of the SEPIC and Ćuk.

The route I’m looking to try first is the 4-switch buck-boost, which looks like this:

The goal will be to have a simple microcontroller-based switch-mode power supply module with the following characteristics:

  • Up to 50A current switching capability
  • 9-30V input voltage range
  • 12-15V output voltage range
  • 250kHz switching frequency

99% of the time, conditions will be:

  • input voltage: 18~20V
  • output voltage: 13.8~14.6V

So I’m thinking we design for a buck converter, then the boost just comes along for the ride.  There’s a handy primer here for designing a buck converter.  For a 20V input and 14.6V output, their formulas suggest a 33µH inductor should cut the mustard. One of these which can handle >50A is not a big or expensive component.

In the above system, we need to be able to drive up two pairs of complementary outputs at high speed.  We can forget the hacker darling ATTiny85, as with 5 pins, it barely has enough to do the SPI interface, let alone talk I²C and drive four MOSFETs.

A good candidate though is the chip I used for the #Toy Synthesizer — the ATTiny861 .

This chip has the same high-speed PWM, and I already know how to drive it.  It doesn’t have a lot of brains, but I think it’ll do.  The challenge will be in-circuit programming.  There are just 3 PWM outputs that don’t clash with ICSP.

Don’t be fooled by the presence of two DI/DO/USCK pins, it’s the one UCI interface, just you can switch which pins it uses.  That’ll be handy for talking I²C, so I’ve earmarked those pins in purple.  The nRESET pin is marked in green, the PWM pins in blue.  When nRESET is pulled low, PB[012] switch to the functions marked in red.

This doesn’t matter for the toy synthesizer as I only need two PWM channels, and so I chose OC1B and OC1D.  Here, I need nOCID (no problem) and nOC1B (uhh oh).

During run-time, I could put my SPI interface on PA[012] and bit-bang the I²C, but I don’t want MOSFETs chattering when flashing new firmware.  Thus, when in reset, I need to inhibit nOC1B somehow.

The other way of doing this is to just forget about nOC1B altogether.  Consider this:

  • When stepping up: SW1 will be held on , SW2 will be held off , and the PWM will drive SW3/SW4.
  • When stepping down: SW3 will be held off , SW4 will be held on , and the PWM will drive SW1/SW2.

We’re only PWMing two MOSFETs at a time, so could get away with just one complementary pair, OC1D/nOC1D.  We ignore OC1B and can now use it for something else.  We just need a means of “selecting” which pair of MOSFETs we’re driving.  A PWM output with 8-bits resolution and 250kHz cycle frequency has a minimum pulse width of about 15ns (1/64MHz).

A SN74AHC244 tri-state buffer will do nicely.  We can use two GPIOs to control the two enable pins to switch the OC1D/nOC1D and a pair of other pins for manual control.  Perhaps PA[01] to select where the PWM signals get routed, and PA[23] to control the non-PWMed MOSFETs.

Due to switching speed requirements, we will need to run the ATTiny861 at 5V.  So maybe make some room for some level shifting of the SPI interface to support 3V master interfaces as this is much lower speed than the PWM output.

This leaves PB3, PB6, PA1 and PA3 free for GPIOs to use however we wish.  Two of these should probably be made part of the host interface, one for chip select (PB3 seems a good choice) and one for an interrupt (maybe PB6).  Add the 5V/0V power rails, and nRESET, and the same interface can be used for ICSP too.

The idea looks doable.  The challenge will be making the control algorithm work within the constraints of the ATTiny861, but given what people have done with the ’85 which has the same core, I’m sure it can be done.

Sep 272018
 

So, the last few days it’s been overcast.  Monday I had a firmware glitch that caused the mains supply to be brought in almost constantly, so I’d disregard that result.

Basically, the moment the battery dropped below ~12.8V for even a brief second, the mains got brought in.  We were just teetering on the edge of 12.8V all day.  I realised that I really did need a delay on firing off the timer, so I’ve re-worked the logic:

  • If battery drops below V_L, start a 1-hour timer
  • If battery rises above V_L, reset the 1-hour timer
  • If the battery drops below V_CL or the timer expires, turn on the mains charger

That got me better results.  It means V_CL can be quite low, without endangering the battery supply, and V_L can be at 12.8V where it basically ensures that the battery is at a good level for everything to operate.

I managed to get through most of Tuesday until about 4PM, there was a bit of a hump which I think was the solar controller trying to extract some power from the panels.  I really need a good sunny day like the previous week to test properly.

This is leading me to consider my monitoring device.  At the moment, it just monitors voltage (crudely) and controls the logic-level enable input on the mains charger.  Nothing more.  It has done that well.

A thought is that maybe I should re-build this as a Modbus-enabled energy meter with control.  This idea has evolved a bit, enough to be its own project actually.  The thought I have now is a more modular design.

If I take the INA219B and a surface-mount current shunt, I have a means to accurately measure input voltage and current.  Two of these, and I can measure the board’s output too.  Stick a small microcontroller in between, some MOSFETs and other parts, and I can have a switchmode power supply module which can report on its input and output power and vary the PWM of the power supply to achieve any desired input or output voltage or current.

The MCU could be the ATTiny24As I’m using, or a ATTiny861.  The latter is attractive as it can do high-speed PWM, but I’m not sure that’s necessary in this application, and I have loads of SOIC ATTiny24As.  (Then again, I also have loads of PDIP ATTiny861s.)

The board would expose the ICSP pins plus two more for interrupt and chip select, allowing for a simple jig for reprogramming.  I haven’t decided on a topology yet, but the split-pi is looking attractive.  I might start with a buck converter first though.

This would talk to a “master” microcontroller which would provide the UI and Modbus interface.  If the brains of the PSU MCU aren’t sufficient, this could do the more grunty calculations too.

This would allow me to swap out the PSU boards to try out different designs.

May 272017
 

So… a bit of head scratching this afternoon. I had working PWM on the LEDs… which was fantastic.

With the trade-off of LEDs being ⅛ brightness maximum, which is fine since the LED strings that I’ve been given for this project would make Manfred Mann proud…

I was a little stumped with my audio PWM. I could not get a peep out of it, not via the amplifier or anything else. Tracing back, I was getting nothing out of the PWM pin. Real strange. Looked up the data sheets, couldn’t see what I was doing wrong.

My code for initialising Timer1 looked like this:

	/* Timer 1 configuration for PWM */
	OCR1B = 128;			/* Initial PWM value: audio */
	OCR1D = 32;			/* Initial PWM value: light */
	OCR1C = 255;			/* Maximum PWM value */
	TCCR1A = (2 << COM1B0)		/* Clear OC1B on match,
					   nOC1B not used */
		| (1 << PWM1B);		/* Enable PWM channel B */
	TCCR1B = (1 << CS10);		/* No prescaling, max speed */
	TCCR1C = (3 << COM1D0)		/* Set OC1D on match,
					   nOC1D not used */
		| (1 << PWM1D);		/* Enable PWM channel D */
	TCCR1D = (0 << WGM10); /* Fast PWM mode */

It looked fine… even checked the header files to see there wasn’t some cock up in the headers. Never had an issue with avr-libc, but you never know, and of course, no problem there.

In exasperation, I swapped setting up TCCR1A and TCCR1C. Bingo, I had PWM both channels. Why? Turns out there are some bits in TCCR1C that shadow TCCR1A, and I was inadvertently setting those back to 0 when I set up TCCR1C. So my code now:

	/* Timer 1 configuration for PWM */
	OCR1C = 255;			/* Maximum PWM value */
	TC1H = 0;			/* Reset counter high bits */
	TCNT1 = 0;			/* Reset counter low bits */
	OCR1A = 0;			/* Initial PWM value: spare */
	OCR1B = 127;			/* Initial PWM value: audio */
	OCR1D = 127;			/* Initial PWM value: light */
	TCCR1A = (1 << PWM1B);		/*
					 * Clear TCCR1A except for PWM1B,
					 * we'll configure OC1B
					 * via the shadow bits in TCCR1C
					 */
	TCCR1B = (1 << CS10);		/* No prescaling, max speed */
	TCCR1C = (2 << COM1B0S)		/* Clear OC1B on match,
					   nOC1B not used */
		| (3 << COM1D0)		/* Set OC1D on match,
					   nOC1D not used */
		| (1 << PWM1D);		/* Enable PWM channel D */
	TCCR1D = (0 << WGM10);		/* Fast PWM mode */
	TCCR1E = 0;			/* Not used: PWM6 mode */

We still need to turn PWM1B on via TCCR1A… but we set the output control mode via TCCR1C to avoid clobbering our settings.

Having fixed that, I now have a second problem, in my dead-bugging of the amp, I got my left and right arse-about, which would explain why my amp is making no noise. That’ll be a tomorrow job methinks, at 22:30 UTC+10:00 it is too dark to work on PCBs. I’ll just keep myself amused looking at the waveform on the oscilloscope.