///////////////////////////////////////////////////////////////////// // // Scilab file to calculate NCP108x reference platform components. // // $Rev: 1.0.0 $ // $Id: NCP108x Flyback CCM 1.0.0 2011-04-21 kvandeneeckhout$ // $Author: servaess $ // // THE FOLLOWING CODE IS FOR GUIDANCE ONLY ANDAIMS AT PROVIDING // CUSTOMERS WITH INFORMATION REGARDING ON SEMICONDUCTOR PRODUCTS // IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, ON SEMICONDUCTOR // SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL // DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF // SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING // INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. // // Copyright 2011 by ON Semiconductor. // ///////////////////////////////////////////////////////////////////// //********************************************** //*************** EDIT THIS PART *************** //Specifications P_out =40; //Output power V_out =24; //Output voltage V_in =48; //Input voltage V_ripple =V_out * 0.01; //Output ripple desired_pm =70; //Desired Phase Margin //Transformer L_pri =42e-6; //Primairy inductance n =0.5882; //Winding ratio DCR_pri =0.05; //DC resistance, primary DCR_sec =0.03; //DC resistance, secondary T_eff = 0.8; //Transformer efficiency // Power transistor R_dson = 0.08; //On resistance C_sw_out = 85e-12; //Drain-source capacitance Q_sw_gtot = 34e-9; //Total gate charge Q_sw_mill = 7.5e-9; //Miller charge V_sw_gs_th = 3; //Gate-source threshold //NCP108x f_s =250e3; //Switching frequency A_v =2; //Internal NCP108x parameter V_gate_drive = 9; //Gate drive voltage (VDDH) R_gate_drive = 0; //Gate resistance // Opto Coupler f_opto =2000; //Optocoupler bandwidth CTR_opto =0.025; //Current transfer ratio R_bias1 = 1e6; //Optocoupler bias resistance // Other V_drop_d = 0.65; //Secondary rectifier diode drop V_tl431 = 2.5; //Regulation voltage L_out = 1.2e-6; //Output filter inductor R_esr_cpd = 0.36/3; //Input capacitor series resistance //********************************************** //********************************************** // // Function to calculate nearest 1% standard // resistor value. // function [R_std]=GetStandardRes(R_in) d=1;i=0; if R_in > 10 then while R_in/d > 2, d=d*10; end d = d/10; while (R_in-(d*10^(i/96))) > 0, i=i+1; end if abs(R_in-(d/100*round(100*10^((i-1)/96)))) < abs(R_in-(d/100*round(100*10^(i/96)))) then i = i -1; end R_std = d/100*round(100*10^(i/96)); elseif R_in > 1 then i=1; R_small = list(1.5,2.2,3.3,4.7,6.8,15); while (R_in-R_small(i)) >0, i=i+1, end if (abs(R_in-R_small(i-1))) < (abs(R_in-R_small(i))) then i = i-1; end R_std = R_small(i); else R_std = R_in; // just return the original value, will need parallel resistors anyhow. end endfunction // // Function to calculate nearest E12 standard // capacitor value. // function [C_std]=GetStandardCap(C_in) // assume capacitance is always < 1 d=1;i=1; while C_in*d < 1, d=d*10, end E12 = list(1.0,1.2,1.5,1.8,2.2,2.7,3.3,3.9,4.7,5.6,6.8,8.2,10.0) while ((C_in*d)-E12(i))>0, i=i+1 ;end if (abs((C_in*d)-E12(i-1))) < (abs((C_in*d)-E12(i))) then i = i-1; end C_std = E12(i)/d; endfunction // //Calculate the duty cycle from the transfer ratio // D=V_out/(V_out+n*V_in); // // Calculate the secondary inductance // L_sec = L_pri*n^2; // // Calculate the currents during on time of the transistor // I_avg_sec = P_out/V_out/(1-D); I_avg_pri = P_out/V_in/D/T_eff; I_mag_sec = (V_out+V_drop_d)/L_sec*(1-D)/f_s; I_mag_pri = V_in/L_pri*D/f_s; I_peak_pri = I_avg_pri + 0.5*I_mag_pri; // note that I_avg_pri is the average up to 1/2 the triangle I_peak_sec = I_avg_sec + 0.5*I_mag_sec; I_rms_pri = P_out/(V_in*T_eff*sqrt(D)); I_rms_sec = P_out/(V_out*sqrt(1-D)); // //Calculate R_esr and C_out based upon desired ripple //Note that rather than doing the bode plot with the calculated //values, one should take the values from the closest standard capacitor. // C_out = P_out*2*D/(V_out*f_s*V_ripple); C_out = GetStandardCap(C_out); R_esr=V_ripple*(1-D)*V_out/(2*P_out); labels=["C_out";"R_esr"]; s1 = sprintf("%f", C_out); s2 = sprintf("%f", R_esr); [ok,C_out,R_esr]=getvalue("If the calculated C_out and R_esr are not standard, pick the closest standard values.",labels,list("vec",1,"vec",1),[s1;s2]) if ok == %f then // Fill in a desired fixed value C_out = 4523.62*10^(-6); C_out = GetStandardCap(C_out); R_esr = 0.0026527; end // // Calculate output L-C filter. // V_ripple_esr = I_peak_sec * R_esr; if V_ripple_esr < V_ripple then printf("----- NO OUTPUT FILTER REQUIRED -----\n"); C_filter = 0; else C_filter = (V_ripple_esr - V_ripple)/(L_out*V_ripple*((2*%pi*f_s)^2)); C_filter = GetStandardCap(C_filter); f_res_lc = 1/(%pi*((2*L_out*C_filter)^2)); end // // Calculate the load resistance from the output power // R_load =(V_out^2)/P_out; // // For info only, calculate the critical L R and f // R_c = 2*L_pri*f_s*n^2/(1-D)^2; L_c = R_load*(1-D)^2/(2*f_s*n^2); F_c = R_load*(1-D)^2/(2*L_pri*n); // //Calculate R_cs, 0.36 is comparator trip level. // R_cs = 0.36/(I_peak_pri*1.2); R_cs = GetStandardRes(R_cs); // // Calculate the slope control resistor // dV_slope = n*R_cs*V_out/(2*L_pri*(n^2))/f_s; R_sl = (dV_slope-110e-3)/10e-6; R_sl = GetStandardRes(R_sl); // // Calculate zeros and poles of the uncompensated network, or the power stage // // Some disagreement exists in literature concerning the location of the dominant pole // Two formulas for w_p are given below, so that the designer can select the // calculation fitting best with his measurements //w_p =(1+D)/(R_load*C_out); w_p =1/(L_pri/((1-D)^2)*C_out)^0.5; w_zesr =1/(R_esr*C_out); w_zrhp =R_load*(1-D)^2/(D*L_pri*(n^2)); K = R_load*(1-D)/(n*R_cs*A_v*(1+D)); // // To account for the effects of the current mode control, the converter // transfer function is multiplied with a double pole at half the switching frequency // transfer function. Note that the higher the Q, the bigger the peak at f_s/2 will be, increasing // the risk of having a gain bigger than zero at this frequency, possibly leading to instability again. // T_s = 1/f_s; V_pp = dV_slope; V_on = V_in; R_i = R_cs; S_e = V_pp/T_s; S_n = V_on*R_i/L_pri; m_c = 1+S_e/S_n; w_n = %pi*f_s; Q_p = 1/(%pi*( m_c*(1-D) -0.5)); s=poly(0,'s'); HighFreqCurrentSense = syslin('c',1/(1+ s/(w_n*Q_p) + s^2/(w_n^2))); // Transfer function of open loop system PowerStage=syslin('c',(K*(1+s/w_zesr)*(1-s/w_zrhp)/(1+s/w_p))*HighFreqCurrentSense); [pm,f_unitygain] = p_margin(PowerStage); // // Calculate the compensator network cross over frequency // f_zesr=w_zesr/(2*%pi); f_zrhp=w_zrhp/(2*%pi); f_cross=min(f_zrhp/3,f_s/5,f_zesr,f_opto); w_cross=f_cross*2*%pi; // // From the bode plot we get the gain and phase of the uncompensated // network at the chosen f_cross // [frq1,rep]=repfreq(PowerStage,f_cross); [gain_at_f_cross,phase_at_f_cross]=dbphi(rep); pm_at_f_cross=phase_at_f_cross+180; boost=min(85, desired_pm - pm_at_f_cross+90); K_factor=tan(%pi/180*(boost/2+45)); //tan of radians w_cz=w_cross/K_factor; w_cp=w_cross*K_factor; f_cz=w_cz/2/%pi; f_cp=w_cp/2/%pi; gain_at_f_cross=10^(gain_at_f_cross/20); gain_comp=1/gain_at_f_cross; // // Calculate the compensation network components // R_fb1 = 10000; // Fix a value for R_fb1 R_fb2 = 2.5*R_fb1/(V_out-2.5); R_fb2 = GetStandardRes(R_fb2); C_fb1 = 1/(w_cz*R_fb1); C_fb1 = GetStandardCap(C_fb1); C_fb2 = 1/(w_cp*5000); C_fb2 = GetStandardCap(C_fb2); R_fb3 = CTR_opto*(5000*R_bias1/(5000+R_bias1))/gain_comp; R_fb3 = GetStandardRes(R_fb3); // // Transfert function of open loop system DCM // L_sec=L_pri*(n^2); w_dcm_zesr=1/(R_esr*C_out); w_dcm_p=2/(R_load*C_out); f_dcm_zesr=w_dcm_zesr/2/%pi; f_dcm_p=w_dcm_p/2/%pi; K_dcm=n*D*(R_load/2/L_sec/f_s)^(1/2); PowerStage_dcm=syslin('c',(K*(1+s/w_zesr)/(1+s/w_p))*HighFreqCurrentSense); // // Opto coupler biasing // I_led_opto = (V_out-1.1-V_tl431)/R_fb3; // current in the led optocoupler R_bias2 = (V_out-V_tl431)/(1e-3-I_led_opto); // extra resistor used to bias at 1mA the TL431 R_bias2 = GetStandardRes(R_bias2); if I_led_opto > 1e-3 then R_bias2 = 1e12; end //Do not equip a bias resistor // // Efficiency calculation // // Power transistor P_Mosloss_conduction = R_dson*I_rms_pri^2*D; // Calculated switch on time, MOSFET theoretical limit: t_sw = Q_sw_mill*R_gate_drive/(V_gate_drive - V_sw_gs_th); // Clamp the turn on time to the chip limit: if t_sw <50e-9 then t_sw = 50e-9; end; V_ds_max = 1.15*(V_in + (V_out+V_drop_d)/n); P_Mosloss_switching = (t_sw*V_ds_max*I_peak_pri*f_s) + (C_sw_out*(V_ds_max^2)*f_s)/2; I_gate_charge = f_s*Q_sw_gtot; P_Mosloss_gate = I_gate_charge*V_gate_drive; P_Mosloss = P_Mosloss_conduction + P_Mosloss_switching + P_Mosloss_gate; // Power diode P_Dloss = P_out/V_out*V_drop_d; // NCP108x P_Aloss = 0.77 + 0.06; // Magnetics, conduction loss and core loss P_MagLoss_conduction = DCR_pri*(I_rms_pri)^2 + DCR_sec*(I_rms_sec)^2; P_MagLoss_Core = 0; // more data on core material is required. P_Magloss = P_MagLoss_conduction + P_MagLoss_Core; // Capacitance ESR P_Esrloss = R_esr * I_rms_sec^2 + R_esr_cpd * I_rms_pri^2; P_LOSS = P_Aloss + P_Mosloss + P_Dloss + P_Magloss + P_Esrloss; Eff = 100*P_out/(P_out+P_LOSS); // // Output all relevant data // printf("\n\n************************************************\n"); printf(" New analysis\n"); printf("************************************************\n\n\n"); printf("Input system variables\n"); printf("\tP_out \t\tV_out \t\tV_in \t\tV_ripple \tf_s\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f \t%f \t%f \t%f \t%fk\n\n", P_out, V_out, V_in, V_ripple, f_s/10^3); printf("\tn \t\tL_pri \t\tL_sec \t\tf_opto \t\tCTR_opto \tDesired PM\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f \t%fu \t%fu \t%f \t%f \t%f \n\n", n, L_pri*10^6, L_sec*10^6, f_opto, CTR_opto, desired_pm); printf("Power stage frequency response properties\n"); printf("\tPole \t\tZero \t\tRHP Zero \tPhase margin \tCross over freq\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f \t%f \t%f \t%f \t%f\n\n", w_p/(2*%pi), w_zesr/(2*%pi), w_zrhp/(2*%pi), pm+180, f_unitygain); printf("Feedback design properties.\n"); printf("\tZero \t\tPole \t\tCross over freq\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f \t%f \t%f\n\n", f_cz, f_cp, f_cross); printf("Output system variables\n"); printf("\tCurrents, during switch on time:\n"); printf("\tI_avg_pri \tI_mag_pri \tI_peak_pri \tI_rms_pri\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f\t%f\t%f\t%f\n\n", I_avg_pri, I_mag_pri, I_peak_pri, I_rms_pri); printf("\tI_avg_sec \tI_mag_sec \tI_peak_sec \tI_rms_sec\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f\t%f\t%f\t%f\n\n", I_avg_sec, I_mag_sec, I_peak_sec, I_rms_sec); printf("\tD \t\tR_load \t\tI_led_opto\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f \t%f \t%fmA\n\n", D, R_load, I_led_opto*10^3); printf("Feedback network components.\n"); printf("\tR_fb1 \t\tR_fb2 \t\tR_fb3 \t\tC_fb1 \t\tC_fb2 \n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%fK \t%fK \t%fK \t%fuF \t%fuF\n\n", R_fb1/10^3, R_fb2/10^3, R_fb3/10^3, C_fb1*10^6, C_fb2*10^6); printf("Other component values\n"); printf("\tR_cs \t\tR_sl \t\tC_out \t\tR_esr \t\tR_bias2 \tC_filter\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f \t%f \t%f \t%f \t%fK \t%fu\n\n", R_cs, R_sl, C_out, R_esr, R_bias2/10^3, C_filter*10^6); printf("\tL_out \n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%fu\n\n", L_out*10^6); printf("Power and efficiency\n"); printf("\tP_Mosloss \tP_Dloss \tP_Magloss \tP_EsrLoss\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f \t%f \t%f \t%f\n\n", P_Mosloss, P_Dloss, P_Magloss, P_Esrloss); printf("\tEfficiency\n"); printf("\t------------------------------------------------------------------------------------------\n"); printf("\t%f\n\n", Eff); // // Make the bode plot // clf() title='Flyback, CCM'; Compensation=syslin('c',(CTR_opto*(5000*R_bias1/(5000+R_bias1))/(R_fb3*R_fb1*C_fb1))*1/s*(1+s/w_cz)/(1+s/w_cp)); ClosedLoop=syslin('c',PowerStage*Compensation); ClosedLoop_dcm=syslin('c',PowerStage_dcm*Compensation); // plot them all //bode([PowerStage;Compensation;ClosedLoop;ClosedLoop_dcm;HighFreqCurrentSense],1,10*10^6,['PowerStage';'Compensation';'ClosedLoop';'ClosedLoop_DCM';'HighFreqCurrentSense']) //bode([Compensation],1,10*10^6,['Compensation']) //bode([PowerStage],1,1*10^6,['PowerStage']) bode([PowerStage;ClosedLoop],1,10*10^6,['PowerStage';'ClosedLoop']) [pm_cl_ccm,fu_cl_ccm] = p_margin(ClosedLoop); // Phase Margin extraction [gm_cl_ccm,f_gm_cl_ccm] = g_margin(ClosedLoop); // Gain Margin extraction printf("Closed Loop Phase Margin (in CCM) = %f deg \nUnity_Gain (in CCM) = %f KHz \n\n", pm_cl_ccm+180,fu_cl_ccm/1e3); printf("Closed Loop Gain Margin (in CCM) = %f dB at %f KHz \n\n", gm_cl_ccm,f_gm_cl_ccm/1e3);