Part 1 can be found here:
At this point I had to decide what to try and control. I wanted something that would be slow enough that the processor could keep up, but fast enough that it would present at least some kind of a challenge. In the end I decided to do that most traditional of things, the one that everyone does with a new processor board, I'd light an LED. Here's the LED
it's a 1W warm white LED on a star board. It requires a current of 360mA and the forward voltage at that current is something like 3.4V. To drive it I'm going to throw together a simple buck converter controlled by PWM from the processor. As the PID loop is going to control the current through the LED, rather than the voltage across it, I'll need a way to measure that current. The simple way to do that is to have a low-value resistor in series with the LED and read the voltage across it with the A/D [the voltage being proportional to the current]. To keep things as simple as possible, and because I don't need great accuracy here, I'm going to try doing this single-ended (look away now if you're a professional engineer) with one end of the resistor at ground (this may not work, but the only way I'll find out is to try it). The 12-bit A/D in the processor gives steps of 3.3V/4096 = 805uV and that equates to 3.22mA per step with a 0.25 ohm resistor. That's reasonable for what I'm trying to do - my enemy is going to be noise and dealing with the ripple, not the resolution.
I chose to use 0.25 ohms for the current sense - four 1 ohm resistors in parallel. I always have the option of increasing the value if it doesn't work too well.
Because the current sense is to ground, so is the load, and that means a high-side switch. I've gone for a p-channel MOSFET, though I could have used a transistor. It's a bit messy driving it, with it up in the air like this, but it will do (having a pull-up, rather than an active drive, means that the MOSFET is a bit slow to turn on and off). Because I'm not too worried about efficiency - this isn't a real design that's going to get used for anything - I'm going to use a Schottky diode to catch the coil, rather than try and make it synchronous with a MOSFET to do the job (the Schottky is simple and safe - no possibility of shoot-through destroying the FETs and I won't have to puzzle out how to get two PWM outputs going with a deadband either).
Here's the circuit of the basic converter.
I built it on a piece of pcb material, cutting the lines with a disposable knife (the kind that has a blade with sections that are broken off - the glassfibre blunts the blades very quickly). [Two tips if you decide to try this: 1) don't hurt yourself with the knife - never cut towards yourself because, sooner or later, it will slip and 2) use a continuity tester to prove that the areas are isolated.] The fat traces have low resistance and inductance, so it's not far off what you'd achieve with a pcb in that respect except that there's no ground plane so capacitance to ground is low (which can be a good thing or a bad thing, depending how you look at it).
A buck converter like this is stable open-loop, so I powered it up before doing the PID control just to check that it worked and, guess what, it actually lit the LED (excuse me if I sound a bit surprised there). I started with the PWM on the low side and then increased the on period until the voltage across the sense resistors averaged about 90mV [a current through the LED of about 360mA] - I'm basically mimicing slowly what the PID software would do quickly. At this stage I didn't have the capacitor on the output - that way, I could see the full current ripple in the coil without it being partially smoothed (the LED is quite robust and doesn't mind this.)
Here it is with the LED lit up. The paper is to spare my eyesight.
I'm working with the PWM set to give me approximately 150kHz. I could go faster, but if I do I'm going to run into problems with the resolution - the period here is 256 intervals of the 25nS that I get with the PWM clock set to 40MHz (it took a lot of fiddling about to get the processor clock to 40MHz because I didn't understand at first how the PLL divisor is set).
Here are the waveforms of the input PWM (yellow) and the switching node (blue). You can see how the MOSFET is a bit slow to turn on and off. That shouldn't matter at all once it is closed-loop as the software will tune it out. The MOSFET will cope with the extra dissipation - it's not something you'd be proud of in a proper design, but for experimenting with the PID code it will suffice.
For interest, here's the gate drive (yellow) against the switching node (blue). I probably should have the divider bringing the gate a bit lower than the 6 volts I went for.
Finally, here's the coil current with ripple (blue trace is the sense resistor, yellow is the switching waveform) and a fair amount of noise.
It is what we would expect from a converter like this: when the switch is on, the PSU powers the load through the coil and the current increases, with the magnetic field of the coil storing energy; when the switch is off, the coil drives the switch node negative until the diode conducts, giving it an anchor just below ground, and it then continues to supply the output current which diminishes as energy comes out of the coil's field.
An obvious question that might occur to you here is, if it's stable like this, why bother with the closed-loop control at all?
1) the input voltage may change
2) I might use a different LED or several LEDs in series
3) the forward voltage of the LED drops as its temperature increases and that increases the current (if the output voltage is fixed) causing more heating resulting in the Vf falling further and so on.
To achieve closed-loop control will require me getting to grips with the PID code, which will be part 3 [this is still work in progress, so don't expect another post for a few days yet ... or a week ... or whatever time it takes me to master it. If I'm not back after a couple of weeks, perhaps send out a search party].