Arduino synchronous rectification PWM?

Hi,

Is it possible to have the Arduino generate PWM for both FET switches in a DC-DC boost converter with synchronous rectification?

DC-DC boost converters are explained here:

PWM'ing the main (low side) switch is easy and I've already got it working. But the synchronous (high side) rectifier switch across the flyback diode needs a delayed signal in order to prevent shoot-through. That is, the low side switch needs to close shortly before the high side switch opens, and vice-versa. Can the timers on the AVR chip somehow be prodded into doing this sort of magic?

I need this for a solar energy project where the Arduino controls a boost converter which keeps the solar panel close to its maximum power point (i.e. the voltage where it produces the most power given current solar conditions). A stock DC-DC converter cannot do this and dedicated energy harvesting chips are hard/expensive to come by and impossible to hand-solder.

Synchronous rectification would help increase efficiency if I could figure out how to make it work. Any help is appreciated.

Yes, it is possible if you configure the timers carefully (and choose your Arduino pins carefully to make use of independent timer pins). The basic timer resolution is 1/F where F is the clock frequency of 16 MHz (for most Arduinos). This gives you 62.5ns resolution. You could, for example, delay the SR MOSFET by 62.5ns, 125.0ns, etc.

Consider doing this in hardware however. By adding a resistor in series with the SR MOSFET gate you delay its turn-on; a diode across the resistor (anode at the MOSFET gate) produces fast turn-off however.

--
The Ruggeduino: compatible with Arduino UNO, 24V operation, all I/O's fused and protected

Good point about the hardware solution. I'll try that once I take delivery of my oscilloscope so I can see what's actually going on in the circuit.

Can you point me to any examples of doing it with the internal timers? I'd like to save on component count but am new to these intricacies.

Thanks.

No code examples to point at, but I'd recommend thoroughly reading the section on timers in the ATmega328P datasheet:

Section 16 especially is relevant as it discusses Timer 1, the most flexible of the 3 timers.

--
The Rugged Circuits Yellowjacket: 802.11 WiFi module with ATmega328P microcontroller, only 1.6" x 1.2", bootloader

Will do. Thanks for the pointer.

This is actually very doable. All you have to do is set up PWM on 2 pins, using the same timer, both in "phase correct" mode. Set your PWM timer's frequency so that one timer period is equal to the delay you need to prevent shoot-through. Then, whatever duty cycle you are "commanding" the system to output (say 128) you just set the lower pin duty cycle to 128 and the upper pin duty cycle to 129. The upper pin will switch before the lower one, by a time equal to 1/F_timer, on every PWM cycle.

Thanks for the tip. It would be pretty cool if I could get this to work.

Had a look at the timer sections in the AVR datasheet, though, and am afraid doing this from scratch is going to be a bit too much of a challenge. Just to get get me started, do you think I could get there by somehow adapting the TImer1/3 library here (I'm currently using Timer3 to PWM drive the primary boost switch):
http://www.arduino.cc/playground/Code/Timer1

Not expecting you to do the work for me. But your assessment of feasibility would be helpful, so I don't go down a wrong path.

PS: This is a private, hobbyist project and I'll of course be happy to freely share the results.

RuggedCircuits:
Yes, it is possible if you configure the timers carefully (and choose your Arduino pins carefully to make use of independent timer pins).

I think you actually want dependent pins. Specifically, you probably want to use timer 2, and use the "output compare A" and "output compare B" feature. I think the Arduino itself does the same thing for the "duty cycle" of each pin. However, the Arduino PWM only runs at 490 Hz, for a boost converter you probably want to run at significantly higher frequency. If you clock the timer at 16 MHz, and count up to the full 8 bits, you will be running at about a 62 kHz duty cycle. That's probably sufficient for a boost converter, but not great compared to the megahertz controller parts you can buy...

Duty cycle is a percentage, not a frequency!

I'd go for a more moderate frequency at first, more like 10kHz or so, as its easier to get efficient switching at lower frequencies. A half-H-bridge MOSFET driver is a very good idea, note since boost converter needs high and low-side MOSFETs.

Thanks again for your comments.

FYI I've based the choice of passive components in the boost stage on the values in the datasheet for a basic, integrated regulator (that, alas, doesn't do MPPT). Also based on this, I'm running the PWM at 100 kHz. This may not be optimally efficient compared to mHz setups; on the up side it will hopefully pose less of a challenge re. RF issues with board layout etc - plus copying an existing circuit saves me from doing the inductor math.

The maximum current from the solar panel is less than 1A so I'm using SMD FETs with very low RDSon and pretty low gate threshold voltages (in the 1-2V range). Once I get a chance to look at the waveform over the main (low side/boost) FET I'll know if it needs stronger drive than the MCU can provide. But I'm trying to keep non-MCU component count as low as possible; I'm hoping to run the final code on one of the ATTiny chips that can be programmed with the Arduino (learning how to do this is an important goal of the project) and I don't have much space for other electronics in the design.

I think the road ahead for me will be to experiment with your suggestions using the Timer3 Arduino library as a working starting point. This may take a while, since I'm waiting to take delivery of my "oscilloscope" (I just plumbed for a DSO Quad) and am until then operating "blind".

Setting up timers is very easy. Each timer can hook up to a certain 2 pins.

For each timer, there are 4 registers (basically you can consider them byte variables) you need to worry about--2 control registers for the timer, and an compare register for each pin. All you have to do is write the correct configuration to the config registers, and you get PWM flowing on the pins connected to that timer. The two output compare registers are for each of the 2 PWM pins connected to that timer. You just write whatever duty cycle you want to those registers.

You need 4 pins, so you need 2 timers. You can probably use Timer0 and Timer2. Those are what I use when I need to drive a unipolar stepper. You pseudo code would look like this

void setup(){

//setup timer 0 for 7.8kHz PWM
TCCR0A = 0b00011011   //config register A for timer0: see table in datasheet for what to write
TCCR0B = 0b00000011   //config register B: see table in datasheet
//now you have PWM on pins 6 and 5. 

//setup timer 2 for 7.8kHz PWM
TCCR2A = 0b00011011   //config register A for timer2: see table in datasheet
TCCR2B = 0b00000011   //config register B: see table in datasheet
//now you have PWM on pins 11 and 3. 
}

void loop(){
//set motor 1 to 1/2 power:
OCR0A = 128;  //pin 6
OCR0B = 129;  //pin 5 

//set motor 2 to full power:
OCR2A = 254;  //pin 11
OCR2B = 255;  //pin 3 
}

If it helps you think clearly, you can do do this at the top of your program

#define OCR0A pin6
#define OCR0B pin5
#define OCR2A pin11
#define OCR2B pin3

Then your loop looks more like this:

void loop(){
//set motor 1 to 1/2 power:
pin6 = 128;  
pin5 = 129;  

//set motor 2 to full power:
pin11 = 254;  
pin3 = 255;  
}

BetterSense:
Setting up timers is very easy.

That's an optimistic viewpoint! I'd say its a bit tricky if you are new to reading datasheets. I've got some notes here that might also help: Advanced Arduino: direct use of ATmega counter/timers

MarkT:
Duty cycle is a percentage, not a frequency!

Yeah, that was a brain fart. I meant "62 kHz frequency" to compare to the 490 Hz that the Arduino runtime normally runs PWM at.

Thanks a bunch for the sample code and further info. I'll give it a go and report back when I have results.