In this project I’m using an Uno to control a buck-boost converter, I am able to test the design but it doesn’t seem the duty cycle is updating depending on the input/output voltages. I am relatively green when it comes to timerPWM. Need a higher frequency, I’m using pins 5 and 6’s Fast PWM function to get 62.5 khz.
#define RELAY_ENABLE 0
#define BOOST_PWM 5
#define BUCK_PWM 6
#define VIN A4
#define IIN A1
#define VOUT A3
#define IOUT A2
#define BUCK_ENABLE_VOLTAGE 26.0
#define BUCK_DISABLE_VOLTAGE 24.0
#define BOOST_ENABLE_VOLTAGE 5.0
#define BOOST_DISABLE_VOLTAGE 23.9
#define BUCK_THRESHOLD 25.0
#define BOOST_THRESHOLD 15.0
#define OUTPUT_TARGET_VOLTAGE_LOW 17.8
#define OUTPUT_TARGET_VOLTAGE_HIGH 17.9
#define INPUT_CURRENT_LIMIT 4.0
#define OUTPUT_CURRENT_LIMIT 6.0
#define INPUT_CURRENT_MINIMUM 0.1
//Duty cycle limits
#define DUTY_CYCLE_MINIMUM 10
#define DUTY_CYCLE_MAXIMUM 240
//Duty cycle mode
uint8_t duty_cycle = 115;
String mode="";
bool startup=true;
//This compenstates for the timer running at a clock that is 64 faster than usual
#define DELAY_FACTOR 64
#define VIN_MULTIPLIER 0.0576
#define VOUT_MULTIPLIER 0.02738
//Set up the LCD library
#include <LiquidCrystal.h>
#define LCD_RS 12
#define LCD_RW 11
#define LCD_EN 10
#define LCD_D7 8
#define LCD_D6 2
#define LCD_D5 3
#define LCD_D4 4
LiquidCrystal lcd(LCD_RS, LCD_RW, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
//Some global variables
uint8_t bb_dutycycle;
float input_voltage;
float input_current;
float output_voltage;
float output_current;
//Set up the step-down DC-DC converter
void bb_setup()
{
pinMode(RELAY_ENABLE, OUTPUT);
digitalWrite(RELAY_ENABLE, LOW);
//Half-bridge driver PWM signal
pinMode(BOOST_PWM, OUTPUT);
pinMode(BUCK_PWM, OUTPUT);
//Fast PWM (mode 3) on OC0A (Arduino pin 5 & 6)
TCCR0A = 0b00000011;
TCCR0B = 0b00000001; //Prescaler=1
//Set dutycycle
bb_dutycycle = 0;
OCR0A = bb_dutycycle;
}
//Turn on the DC-DC converter
void relay_enable()
{
// Clock source enabled with prescaler=1
TCCR0A &= 0b10111111;
TCCR0A |= 0b10000000;
//Enable signal high
digitalWrite(RELAY_ENABLE, HIGH);
}
//Turn off the DC-DC converter
void relay_disable()
{
//Enable signal low
digitalWrite(RELAY_ENABLE, LOW);
// Clock source disabled
TCCR0A &= 0b00111111;
bb_dutycycle = 0;
}
//Set the duty-cycle for the DC-DC converter
void bb_duty(uint8_t duty)
{
//The buck needs some off-time to keep the bootstrap capacitor of the upper FET charged
//To ensure this we set a duty cycle clearly below 100%
if(duty>DUTY_CYCLE_MAXIMUM)
{
duty = DUTY_CYCLE_MAXIMUM;
}
//A synchronous buck like ours can pump energy from the output to the input if the duty cycle drops below 50%
//Eliminate this possibility by enforcing a duty cycle clearly above 50%
if(duty<DUTY_CYCLE_MINIMUM)
{
duty = DUTY_CYCLE_MINIMUM;
}
bb_dutycycle = duty;
OCR0A = duty;
}
//Shows measured voltages and currents on the LCD
void write_display()
{
lcd.setCursor(0, 0);
lcd.print(" V ");
lcd.setCursor(0, 0);
lcd.print(input_voltage);
lcd.setCursor(8, 0);
lcd.print(" V ");
lcd.setCursor(8, 0);
lcd.print(output_voltage);
lcd.setCursor(0, 1);
lcd.print(" A ");
lcd.setCursor(0, 1);
lcd.print(input_current);
lcd.setCursor(8, 1);
lcd.print(" A ");
lcd.setCursor(8, 1);
lcd.print(output_current);
// delay(30000);
// lcd.clear();
//
// lcd.setCursor(0,0);
// lcd.print("Duty Cycle = ");
// lcd.setCursor(14,0);
// lcd.print(duty_cycle);
//
// lcd.setCursor(0,1);
// lcd.print("Mode = ");
// lcd.setCursor(8,1);
// lcd.print(mode);
//
// delay(300000);
}
//Measure input and output voltage and current
//Each value is measured 16 times and then averaged
void read_values()
{
float vin_dac = 0;
float iin_dac = 0;
float vout_dac = 0;
float iout_dac = 0;
for(int i = 0; i < 16; i++)
{
vin_dac += analogRead(VIN);
vout_dac += analogRead(VOUT);
iin_dac += (.0742 * analogRead(IIN) - 37.1);
iout_dac += (.0742 * analogRead(IOUT) - 37.1);
//.742 * analogRead(A0) -37.8
}
input_voltage = vin_dac * VIN_MULTIPLIER / 16;
output_voltage = vout_dac * VOUT_MULTIPLIER / 16;
input_current = iin_dac / 16;
output_current = iout_dac / 16;
}
//Check if the duty cycle needs to be increased or decreased
//Also check if the DC-DC converter needs to be turned on or off
void buck_update()
{
if(bb_dutycycle) //DC-DC converter is currently running
{
mode="";
mode="Buck";
analogWrite(BOOST_PWM,LOW); //Disable Boost FET
//Disable
if((input_voltage<BUCK_DISABLE_VOLTAGE) || (input_current<INPUT_CURRENT_MINIMUM))
{
relay_disable();
}
//Update
else
{
//Reduce duty cycle
if((input_voltage<BUCK_THRESHOLD) || (output_voltage>OUTPUT_TARGET_VOLTAGE_HIGH) || (input_current>INPUT_CURRENT_LIMIT) || (output_current>OUTPUT_CURRENT_LIMIT))
{
bb_duty(bb_dutycycle-1);
}
//Increase duty cycle
if((input_voltage>BUCK_THRESHOLD) && (output_voltage<OUTPUT_TARGET_VOLTAGE_LOW))
{
bb_duty(bb_dutycycle+1);
}
}
}
else //DC-DC converter is turned off
{
//Enable
if(input_voltage>BUCK_ENABLE_VOLTAGE)
{
bb_duty((uint8_t) (255*output_voltage/input_voltage));
relay_enable();
}
}
}
void boost_update()
{
mode="";
mode="Boost";
analogWrite(BUCK_PWM,HIGH); //Keep Buck FET on.
if(bb_dutycycle) //DC-DC converter is currently running
{
//Disable
if((input_voltage<BOOST_ENABLE_VOLTAGE) || (input_current<INPUT_CURRENT_MINIMUM))
{
relay_disable();
}
//Update
else
{
//Increase duty cycle
if((input_voltage<BOOST_THRESHOLD) || (output_voltage<OUTPUT_TARGET_VOLTAGE_LOW) || (input_current>INPUT_CURRENT_LIMIT) || (output_current>OUTPUT_CURRENT_LIMIT))
{
bb_duty(bb_dutycycle+1);
}
//Decrease duty cycle
if((input_voltage<BOOST_THRESHOLD) && (output_voltage<OUTPUT_TARGET_VOLTAGE_HIGH))
{
bb_duty(bb_dutycycle-1);
}
}
}
else //DC-DC converter is turned off
{
//Enable
if(input_voltage>BOOST_ENABLE_VOLTAGE)
{
bb_duty((uint8_t) (255*output_voltage/input_voltage));
relay_enable();
}
}
}
void setup()
{
//Show startup screen
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
//Set up DC-DC convert er
bb_setup();
//Wait a bit to show the startup screen
delay(500*DELAY_FACTOR);
}
//This function is called forever once setup() has completed
//Again, this is Arduino-specific behaviour
void loop()
{
for(uint8_t i=0; i<32; ++i)
{
read_values();
buck_update();
boost_update();
delay(10*DELAY_FACTOR);
}
write_display();
}
I'm using pins 5 and 6's Fast PWM function to get 62.5 khz.
This code only puts PWM output on Timer0 output A pin 6. BUCK_PWM.
I am able to test the design but it doesn't seem the duty cycle is updating depending on the input/output voltages
Can you get any serial output to help you debug?
What are the values of our input/output voltages and currents?
Is the bb_duty() function getting called and is the value of OCR0A being updated?
This code only puts PWM output on Timer0 output A pin 6. BUCK_PWM.
Is there a way to call on both? or do I need to define each separately and use which ever one is being used?
Can you get any serial output to help you debug?
What are the values of our input/output voltages and currents?
Is the bb_duty() function getting called and is the value of OCR0A being updated?
I'm not sure how to accomplish this, I set it to display the duty cycle and it never changed from the initial value it was set to "Duty Cycle = 115".
my input voltage range from 15 - 30 volts and I kept the current only .7 A. I was getting the same the output voltage boosted maybe 2 volts above the input and the current dropped a little.
I set it to display the duty cycle and it never changed from the initial value it was set to "Duty Cycle = 115".
I see no place in your code where the displayed variable "duty_cycle" (which is initialized to 115) is ever changed.
You probably should be displaying bb_dutycycle.
You really need to get displayed output for everything which goes into changing the variable which drives the value of OCR0A.
Is there a way to call on both? or do I need to define each separately and use which ever one is being used?
It appears that to operate in buck mode, the boost mode fet is not driven with pwm but is set LOW. I'd try and get the buck mode operating first, before figuring out how to enable pwm on the B pin. If you can't figure out how to update OCR0A it won't help you to be trying to update OCR0B.
It appears that to operate in buck mode, the boost mode fet is not driven with pwm but is set LOW. I'd try and get the buck mode operating first, before figuring out how to enable pwm on the B pin. If you can't figure out how to update OCR0A it won't help you to be trying to update OCR0B.
That's the way buck boost works. When the device is in buck mode the the boost FET is open and the buck is oscillating like so . When the in boost mode the buck FET stays on and boost oscillates.
when I set TCCR0A it sets both pins 5 and 6 to the frequency of 62.5k?
Not exactly. The frequency is set by the prescaler which is actually a bit in TCCR0B. Both pins 5 and 6 will output at this frequency, but they must both be in OUTPUT mode, and enabled with settings in COM0A1, COM0A0, COM0B1 and COM0B0. The duty cycle will be set by OCR0A and OCR0B.
That's the way buck boost works. When the device is in buck mode the the boost FET is open and the buck is oscillating like so . When the in boost mode the buck FET stays on and boost oscillates.
I understand that. Do you have BUCK mode operating as you want it? Is OCR0A and the duty cycle changing as you desire?
Using a oscilloscope, I can see the frequency is coming out to 62.5 and the duty cycle is adjusting but seems to be boosting no matter what.
I'm not a hardware guy, and whether or not your circuit and code work as a buck converter is a separate issue from varying the duty cycle of an input which you appear to be doing successfully.
I recommend that you start a new thread in the general electronics section of this forum. Be prepared to post the code you have and a schematic of your circuit. The original soldernerd reference may be useful, but you must post a schematic. Hand drawn will be OK.
I'm not a hardware guy, and whether or not your circuit and code work as a buck converter is a separate issue from varying the duty cycle of an input which you appear to be doing successfully.
I recommend that you start a new thread in the general electronics section of this forum. Be prepared to post the code you have and a schematic of your circuit. The original soldernerd reference may be useful, but you must post a schematic. Hand drawn will be OK.
Actually I figured out my issue, the Vgs on the MOSFETs is 10v and the Arduino only supplies 5v meaning I need to change the FETs. Do you mind helping me understand how to set up the PWM on the Boost pin (5)?
Do you mind helping me understand how to set up the PWM on the Boost pin (5)?
Here are the places in the code where you manage the timer modified for A and B output. If the comments are not enough, ask specific questions. It also helps to have an ATmega 328 data sheet at hand for reference.
void bb_setup()
{
pinMode(RELAY_ENABLE, OUTPUT);
digitalWrite(RELAY_ENABLE, LOW);
//Half-bridge driver PWM signal
pinMode(BOOST_PWM, OUTPUT);//#define BOOST_PWM 5
pinMode(BUCK_PWM, OUTPUT); //#define BUCK_PWM 6
//Fast PWM (mode 3) on Timer0
TCCR0A = 0b00000011; //fast pwm to 255
TCCR0B = 0b00000001; //Prescaler=1
//Set dutycycle
bb_dutycycle = 0;
OCR0A = bb_dutycycle; //pin 6 outputA compare match
OCR0B = bb_dutycycle;//pin 5 outputB compare match
}
void relay_enable()
{
TCCR0A |= 0b10100000;//pwm outputs A and B enabled Clear on Compare Match, set at BOTTOM (non-inverting mode)
//Enable signal high
digitalWrite(RELAY_ENABLE, HIGH);
}
//Turn off the DC-DC converter
void relay_disable()
{
//Enable signal low
digitalWrite(RELAY_ENABLE, LOW);
TCCR0A &= 0b00000011;//pwm outputs A and B disabled
bb_dutycycle = 0;
}
void bb_duty(uint8_t duty)
{
//The buck needs some off-time to keep the bootstrap capacitor of the upper FET charged
//To ensure this we set a duty cycle clearly below 100%
if(duty>DUTY_CYCLE_MAXIMUM)
{
duty = DUTY_CYCLE_MAXIMUM;
}
//A synchronous buck like ours can pump energy from the output to the input if the duty cycle drops below 50%
//Eliminate this possibility by enforcing a duty cycle clearly above 50%
if(duty<DUTY_CYCLE_MINIMUM)
{
duty = DUTY_CYCLE_MINIMUM;
}
bb_dutycycle = duty;
OCR0A = duty;
OCR0B = duty;
}
EDIT: I’m unsure about some of the timing issues, and whether or not the calling of the buck/boost update functions and the relay enable/disable functions possibly allow for both outputs to be active at the same time.
I also think that these lines should be changed, because HIGH ==1
// analogWrite(BUCK_PWM,HIGH); //Keep Buck FET on.
analogWrite(BUCK_PWM, 255);// will default to digitalWrite(BUCK_PWM,HIGH)
//analogWrite(BOOST_PWM,LOW); //Disable Boost FET
analogWrite(BOOST_PWM,0);// will default to digitalWrite(BOOST_PWM, LOW)
cattledog:
Here are the places in the code where you manage the timer modified for A and B output. If the comments are not enough, ask specific questions. It also helps to have an ATmega 328 data sheet at hand for reference.
EDIT: I'm unsure about some of the timing issues, and whether or not the calling of the buck/boost update functions and the relay enable/disable functions possibly allow for both outputs to be active at the same time.
Thank you!
I check if this with the addition of the right FETs works and let you know.
I check if this with the addition of the right FETs works and let you know.
Put in the new FETs, they shorted and burnt up for some reason.. I believe it's accruing in the Boost mode FET (N-Channel), when I pull it out, it stops the shorting. Maybe I ordered the wrong ones some how? Anyways, I ordering new ones from Sparkfun that are proven to work with Arduino.
What are you using as a power supply, does it have current limiting, if not FIT A FUSE!!!
Where does power go in and go out?
Please connect your wires, not make us play search a word, when you connect your wires you can see your signal flow.
What does K1 do and the red circled areas, something missing?
I'm using a bench power supply 60V/5A, I am using a constant current flow act as the battery.
I didn't mean to make you play word search, the K1 is a relay switch. I building this for a wind turbine so if the battery capacity is full it will dump the excess energy. When there is enough voltage it will switch the relay to position "87" completing the circuit. Otherwise, it's in position "87a".
Wawa:
Currently any voltage on the input (C1) will appear on the output (C2) of you don't PWM the fets.
And will short the input or blow the fets if you do.
Leo..
Can you explain why this occurs? I have a buck converter built in the same fashion and it works fine..