Hi,
I am working with Photon Counters, which require low current high voltage biasing. And I wish to design a power supply for its operation. My requirements are:
I need help understanding the main() function in order to compare the adc read from the output voltage and my set value (fb_value = 130), but I am guessing the adc reading speed, the code running speed do not match and one of it lags, resulting in faulty readings and high fluctuations. I may have understood some PWM part wrong too creating this blunderous output.
Also if there are some easier designs out there using similar PWM with MOSFET based Power supplies using ATmega or other components please help me out.
Thanks!!
I am working with Photon Counters, which require low current high voltage biasing. And I wish to design a power supply for its operation. My requirements are:
- VIN = 5 V
- VOUT = 50 - 80 V ; IOUT = 2 mA
C:
#----------------------------power supply code for atmega16---------------------------------------
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#define F_CPU 4000000UL
unsigned int adc1, adc2;
int fp;
float v_ref = 4.90; // Actual output value from the 7805 IC
float supply_ratio = 10.986; // Supply ratio for supply adc reading
float osc_freq = 4; // Tried switching between 4 and 8
float L_Ipeak = 67; // Peak current value of Inductor = 0.67 A, but Inductor value = 100 (hence 67)
int fb_value = 130; // Calculated value of 130 should give about 80V, 65 gives ~40 V
float supply_multiplier, period_multiplier, v_feedback, v_supply;
float final_duty, final_period, t_rise, SMPS_duty, t_period, SMPS_period;
int read_adc(uint8_t ch)
{
ADMUX = (1<<REFS0);
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
// select the corresponding channel 0~7
// ANDing with '7' will always keep the value
// of 'ch' between 0 and 7
ch &= 0b00000111; // AND operation with 7
ADMUX = (ADMUX & 0xF8)|ch; // clears the bottom 3 bits before ORing
// start single conversion
// write '1' to ADSC
ADCSRA |= (1<<ADSC);
// wait for conversion to complete
// ADSC becomes '0' again
// till then, run loop continuously
while(ADCSRA & (1<<ADSC));
return (ADC);
}
int upd_smps()
{
adc1 = read_adc(0);
v_feedback = adc1;
v_supply = v_feedback/1024;
supply_multiplier = v_ref*supply_ratio;
v_supply = v_supply*supply_multiplier; //v_supply is converted back from ADC count to actual value of ~5V
period_multiplier=(4/osc_freq);
t_rise = L_Ipeak/v_supply;
SMPS_duty=t_rise*osc_freq;
final_duty=SMPS_duty ;
t_period=(t_rise*1.33);
SMPS_period=(t_period/period_multiplier);
final_period=SMPS_period-1.0;
return final_period;
}
int main(void)
{
DDRD = 0xff;
TCCR1A = 0; //----- I need -------------------------------
TCCR1B = 0;
TCCR1A |= ( 1<<COM1B1 | 1<<COM1B0 | 1<<WGM11 ); //----- help ---------------------------------
TCCR1B |= ( 1<<WGM12 | 1<<WGM13 | 1<<CS10); //----- understanding ------------------------
ICR1 = 40;
while(1)
{
adc2 = read_adc(1);
fp = upd_smps();
if (adc2<fb_value) //----- this whole ---------------------------
{
OCR1B = fp; //----- part as I know -----------------------
}
else
{
OCR1B = ICR1; //----- something is probably wrong ----------
}
}
}
Also if there are some easier designs out there using similar PWM with MOSFET based Power supplies using ATmega or other components please help me out.
Thanks!!
Attachments
-
30.8 KB Views: 8