Here's the picture: -
It's significantly more complex than what I'm going to say but bear with me: -
Firstly I'm going to ask you to imagine that D1 is a switch like SW1 but, it closes when SW1 opens. What you then get at point (2) on the circuit is a square wave; it has a peak of Vin (let's say 10V) and rapidly drops to 0V when SW1 opens (remember I've asked you to consider that D1 is also a switch). This repeats at some arbitrarily high frequency such as 100kHz.
Let's also say that Vd (your output) is desired to be 5V. Now if the 10V squarewave at (2) spent half of its time at 10V and half of its time at 0V then the average value would be 5V i.e. exactly what you want.
Should you in fact require Vd to be 3.3V then the squarewave at (2) would spend about a third of its time at 10V and about two-thirds of its time at 0V. (Remember I'm asking you to consider that D1 is a switch that closes when SW1 opens).
So you've got a squarewave at (2) that has a duty cycle of (say one-third) AND now you have a low pass filter formed by L1 and C1 - the output from this is pretty much a dc voltage at 3.3V.
Then, you put a load resistor on (\$R_L\$) - does this alter the output voltage average level? The answer is virtually "no" because you are using an inductor and capacitor to form a low pass circuit and providing the inductor's internal resistance isn't too big then there won't be too much of a dc voltdrop across L1 and you'll still get 3.3V at the output.
However, if you load the output too much, the 3.3V will start to droop and this is when the control circuit starts to take over and apply a little more than one-third duty cycle to SW1 being on. This control loop is fundamental in all buck regulator circuits but it isn't necessary to understand the ins and outs of this to comprehend the basic working.
So far I've assumed D1 is a switch (like SW1) and what 've described is called a synchronous buck regulator - it uses two MOSFETs; one for SW1 and one in place of D1. I think it's easier to approach synchronous buck regulators first then move on to understanding standard (but less efficient) buck regulators.
Standard buck regulators have D1 (not a switch) and they would like D1 to behave like a switch (as described above) but it doesn't always do this. For a start it drops 0.7V across it when it is acting like a switch (maybe a bit less if you use a schottky diode). It conducts like a switch but the 0.7V across it loses energy in the form of heat - it can never match the efficiency of the synchronous regulator.
How does D1 behave like a switch - when SW1 is closed, a ramping current runs through L1 and when SW1 eventually opens, the back emf from L1 drives (2) negative in order to keep the current through L1 still flowing. This is the nature of inductors and if this is a little alien to you go and study inductors. This negative voltage rapidly falls below 0V until D1 starts to conduct - now it is behaving like a synchronous regulator (albeit with 0.7V drop across it). SW1 eventually starts conducting again and the cycle repeats.
Previously the squarewave described at point (2) was 10V peak and 0V at the bottom - now it is 10V peak but -0.7V at the bottom. L1 and C1 are still a low pass filter (as mentioned previously and if the duty cycle of the square wave was one-third, the voltage at the output would be about 3.1V. The control system would take over and alter the duty cycle until the output was 3.3V.
But there's a further problem when D1 is just a diode (and not a switch) and this really does make non-synchronous buck regulators quite tricky to get to grips with. If the load is very light, D1 doesn't act like a switch (as per a synchronous regulator) and the output voltage rises and rises because the energy stored in L1 keeps getting pumped into C1 and of course the output voltage rises. It's not a big problem because the control loop keeps this in check by applying ever smaller duty cycles the the squarewave at point (2).
I've got the point in my explanation where I need to take a break so if you manage to wade through this and want more let me know. The upshot of what I would explain is surrounds storing energy in the inductor (when SW1 closes), transferring it to the capacitor and making sure that the transferred energy \$\times\$ frequency (cycles per second) matches the power needed by the load resistor at the voltage the regulator is intending to regulate at.
Synchronous regulators are far easier to explain!!
Ok, so this is the scheme i propose.
Disclaimer: in real life you will never do anything like that. This is only good for detailed buck controller study. This is not cost effective, not universal, not very power efficient and not simple at all. If you want a real design, you need to refer to buck controller IC of any descent vendor and read the datasheets accurately.
Disclaimer 2: i am not sure for how long and how deep i will be able to explain the theory. You must study that by yourself, it's not that hard.
So in the scheme i propose, you have a switch MOSFET, inductor and output capacitor that will do a good job for 20kHz PWM (i don't think Arduino can do much better), D1 will allow L1 to keep conducting when the switch is off.
R3 and R4 will provide feedback. Configure them so when the output is stable, the voltage is in the middle of your ADC range, probably it will be 1.65V
Now what made you most of your problems. To drive M1 you need voltage higher than Vs. So there is C2 that will be precharged to VCC at the beginning, and once your output is stable, with VOUT. When M1 will be switched on and the voltage on switching node will rise to VIN, C2 will still be charged, and provide VIN + VOUT voltage, allowing to keep M1 open.
U1 and U2 are used to quickly charge and discharge M1 gate. Pay attention, i use AC optocouplers. For DC optocouplers you may need a bit different input. Under no condition open both of them!!! it will just blow them. Consider logic gate to prevent such event.
Components selection: Define what voltage and current you need on output.
Select the L1 to have 200% of IOUT
C1- 200% of VOUT.
D1- 200% of IOUT and 150% of VIN for reverse bias, low leakage, minimum forward voltage.
C2- 200% of VOUT
C3- 150% of VIN
M1- VDS > 150% of VIN, Idrain > 150% of IOUT, VGS < 80% VOUT, VTH < 80% of VCC
Testing: Start with VIN = 12V and PWM of 20kHz, 50% duty cycle. Put 100R power resistor as load. You will have to measure about 6V, if everything is allright.
Closed loop control OK, this is the hardest part. Mostly because it's a whole theory, but if you have time to discover it, i will provide some basic guidelines to create a PID controller with your Arduino.
Set VFB_Reference = 1.65V
Define interrupt that will be called at the beginning of each PWM cycle
Sample the VFB exactly 200nsec after the start of interrupt
Set VFB_Error_Last = VFB_Error
Set VFB_Error = VFB_Sample - VFB_Reference
Set VFB_Integral = VFB_Integral + VFB_Error
Set VFB_Derivative = VFB_Error - VFB_Error_Last
Set Voltage_Command = A * VFB_Error + B * VFB_Inegral + C * VFB_Derivative
Convert Voltage_Command to PWM_Command.
Pay attention: I make all calculations in volts. This is the best way for debug. So don't forget conversions from ADC to volts, working in floating point, etc. Also the VFB_Integral variable should be limited - otherwise it may roll.
A, B and C are coefficients that you will have to adjust. May be just anything, depends on both power stage and load, but also on how well you make all the circuit.
Be very careful with sampling VFB. It must be as accurate and silent as possible.
Be ready to surprises like overshoots, etc. To avoid them use soft start: VFB_Reference will start with 0V and rise slowly to 1.65V over long time, like 100msec.
Diagnose overvoltage. If you see VFB 10% higher than 1.65V, declare fault condition and set VFB_Reference to 0.
Good Luck! It's a serious project. I would say, for me after years in industry, it's doable, but not trivial. If you succeed, you will become (and i am serious about it) a real specialist in switching power supplies, and a really good candidate to become a control engineer, which in turn is really cool.
Best Answer
When Vo is not the correct value (Ierr != 0) the duty cycle has to be adjusted. If Vo approaches Vref the adjustments become smaller until there's the point where Vo = Vref, and no adjustments are necessary anymore. If you would change the duty cycle to 50% at that point, Vo will no longer be equal to Vref.
Besides, if your duty cycle would always be 50% for the correct Vo, then there wouldn't be any regulation, would it? You would just set it to 50, and that would be that.