100%(1)100% au considerat acest document util (1 vot)
100 vizualizări0 pagini
This document describes a PIC16F876A controlled power supply that can operate in either constant voltage or constant current mode. It has adjustable output voltage from 0 to 25V at 0.1V resolution and one of four current ranges: 0-1A, 0-2A, 0-4A, or 0-8A. The power supply uses a 2 line LCD to display the set and measured voltage and current values and indicates whether it is operating in voltage or current control mode. Adjustments can be made using buttons to change the set voltage and current values.
This document describes a PIC16F876A controlled power supply that can operate in either constant voltage or constant current mode. It has adjustable output voltage from 0 to 25V at 0.1V resolution and one of four current ranges: 0-1A, 0-2A, 0-4A, or 0-8A. The power supply uses a 2 line LCD to display the set and measured voltage and current values and indicates whether it is operating in voltage or current control mode. Adjustments can be made using buttons to change the set voltage and current values.
Drepturi de autor:
Attribution Non-Commercial (BY-NC)
Formate disponibile
Descărcați ca PDF, TXT sau citiți online pe Scribd
This document describes a PIC16F876A controlled power supply that can operate in either constant voltage or constant current mode. It has adjustable output voltage from 0 to 25V at 0.1V resolution and one of four current ranges: 0-1A, 0-2A, 0-4A, or 0-8A. The power supply uses a 2 line LCD to display the set and measured voltage and current values and indicates whether it is operating in voltage or current control mode. Adjustments can be made using buttons to change the set voltage and current values.
Drepturi de autor:
Attribution Non-Commercial (BY-NC)
Formate disponibile
Descărcați ca PDF, TXT sau citiți online pe Scribd
General purpose PIC16F876A controlled power supply
CONSTANT VOLTAGE, 0<25V OR CONSTANT CURRANT, 1, 2, 4 and 8 Amp ver.
SPECIFICATIONS VOLTAGE: - Ajustable from 0 < 25 Volts at a resolution of 100 mV. CURRENT: choice of 4 ranges; - 0 < 1.000A at a resolution of 1 mA. JP1 and JP2 open, C1 = 2000uF filter cap., R7 = 0.5 Ohm, T1 = 24V, 1Amp. - 0 < 2.000A at a resolution of 2 mA. JP1 ground and JP2 open, C1 = 4000uF filter cap., R7 = 0.25 Ohm, T1 = 24V, 2Amp. - 0 < 4.000A at a resolution of 4 mA. JP1 open and JP2 ground, C1 = 8000uF filter cap., R7 = 0.125 Ohm, T1 = 24V, 4Amp. - 0 < 8.000A at a resolution of 8 mA. JP1 and JP2 ground, C1 = 16000uF filter cap., R7 = 0.0625 Ohm, T1 = 24V, 8Amp. 2 lignes LCD display: - The top line shows the settings, the maximum current stays displayed at all times, it is not necessary to short the output terminals to set the maximum current. - The bottom line shows the measured values. - The arrows at the bottom center line show who is in control, the voltage or the current. Ajustments: - Voltage, steps of 1 V and 0.1 V. - Current, steps of 1, 2, 4, 8 mA and 50, 100, 200, 400 mA depending on the Amp range. - Memorisation of the last settings before power off, restarting with thoses same settings. View the schematic Parts list C1 = 2000uF per AMP, 40V (adjust capacity to power supply amps) C2,C3,C12,C15,C18,C21 = 0.1uF CER C4 = 0.01uF CER C5A,C5B,C5C,C5D = 0.01uF CER C6,C7 = 0.05uF CER C8 = Not used C9,C11,C19,C20 = 1uF CER C10 = 470uF 15V EL RADIAL C13 = 4.7F 50V EL RADIAL C14 = 0.001uF CER C16,C17 = 22pF CER D1,D2,D4,D5 = 1N4148 D3 = 1N4004 Br1 = 1<10A BRIDGE RECTIFIER (adjust seize to power supply amps) DZ1 = 1N4751 30V ZENER IC1 = LM317KCS TO220 IC2 = LM337LZ TO92 IC3 = LT1491CN special HV opamp, do not substitute IC4 = PIC16F876A Q1 = 2N3906 Q2A to Q2D = TIP142TU 1 to 5 transistors (adjust quantity to power supply amps) Q3A to Q3D = 2N3904 (adjust quantity to power supply amps) X1 = 20 mHz HC49 DigiKey PN: 300-6042-ND LED1 = T1 3/4 RED OR GREEN LED LCD = LCD, 2X16, HD44780 intelligent controller DigiKey PN: 67-1758-ND insulate from case P1 = 500 Ohms P2 = 10 kOhms P3,P4 = 5 kOhms R1 = 1 kOhms 10W R2 = 1.5 kOhms R3,R11,R12,R13,R14,R16,R17,R25,R26,R27 = 10 kOhms R4 = 56 Ohms R5A to R5D = 0.22 Ohms (adjust quantity to power supply amps) R6,R28,R29 = 47k Ohms R7 = as per schematic (adjust value to power supply amps) R8 = 240 Ohms R9 = 270 Ohms R10 = 390 Ohms R15 = 39 kOhms R18 = 39 kOhms R19 = 8.2 kOhms R20,R22,R23,R32 = 1 kOhms R21 = 5.6 kOhms R24 = 33 Ohms 1/2W R30,R31 = 4.7 kOhms SW1 = SPST min toggle SW2,SW3,SW4,SW5,SW6,SW7,SW8,SW9 = NO_SP push button T1 = 24 V 1<8A (adjust seize to power supply amps) T2 = 6.3 V, 150 mA MISC: 3 Terminals, Transistors Heat Sink, up to: 1A = 30W, 2A = 60W, 4A = 120W, 8A = 240W to dissipate Line filter, Case PCB, IC sockets... View the PCB View the PCB + parts CALIBRATION LCD: - Adjust P2 near ground for a nice contrast. VOLTAGE: - Adjust P1 for a supply of 5.12V. - Measure the voltage output terminals, adjust P3 to for the same voltage reading on the PS LCD and the meter. CURRENT: - Install a 10 Ohm resistor in series with an ammeter in series on the output terminals. - adjust P4 for a correct Amp reading on the LCD. NOTE I recommand the use of a PIC16F876A, it is lower in cost and has a better EEDATA memory. The source program in "C" and the object code (HEX) for the PIC16F876A in alim_v3.zip. //-------------------------- ALIM V3 ---------------------------------------- // ALIMENTATION VARIABLE CONSTANT VOLTAGE, CONSTANT COURANT, 0 < 25V // choix de 4 gammes de courant, 0<1A, 2A, 4A et 8A VERSION: 3.0 // PAR VE2EMM avril 04 //--------------------------------------------------------------------------- #include <16F876a.h> #device ADC=16 // les 10 bits de gauche sont valable #use delay(clock=20000000) #fuses HS,NOWDT,PUT,BROWNOUT,NOPROTECT,NOLVP,NOCPD,NOWRT //#rom 0x2100={0x00,0x00,0x00,0x00,0x00} // zero les premieres 4 cases du EEDATA #use fast_io(A) #use fast_io(B) #use fast_io(C) //------------------------- VARIABLES ------------------- INT8 i; // 0 < + 255 int8 commande; // 0 < + 255 int8 car; // 0 < + 255 int8 nibble; // 0 < + 255 int8 boutons; // 0 < + 255 int8 bit_status; // 0 < + 255 int16 disp_a; // pour gamme de l'affichage Amp int8 disp_ma; // pour gamme de l'affichage mAmp //----------- signed int16 volt_moy[16]; signed int16 amp_moy[16]; signed int16 volt_set=0; // -32768 < +32767 signed int16 volt_lue=0; // " " signed int16 amp_set=0; // " " signed int16 amp_lue=0; // " " //------------------------- FONCTIONS --------------- void pic_ini(void); void lcd_ini(void); void write_cmd_lcd(int8); // LCD void write_car_lcd(INT8); // LCD void send_nibble(int8); // LCD void busy_status(void); // LCD void lire_voltage(void); // lire et afficher E void lire_courant(void); // lire et afficher I void lire_PB(void); // lire les boutons, changer les consignes de voltage et de courant void set_range(void); void comparer_Iset_Ilue(void); // determiner qui est en controle, E ou I //********************************* MAIN *********************************** void main(void) { pic_ini(); lcd_ini(); for(i=0;i<=15;i++) volt_moy[i]=0; for(i=0;i<=15;i++) amp_moy[i]=0; //------- afficher ecran d"acceuil ------- write_cmd_lcd(128); // adresse du debut de la 1 re ligne printf(write_car_lcd,"ALIMENTATION V3 "); write_cmd_lcd(192); // adresse du debut de la 2 ie ligne printf(write_car_lcd," PAR VE2EMM "); for(i=0;i<4;i++) delay_ms(250); // laisser affichage 1 1/2 seconde //---- charger les valeurs du eedata for(i=0;i<2;i++) *(&volt_set+i)=read_eeprom(10+i); // reprendre les consignes if((volt_set>1023)||(volt_set<0))volt_set=0; for(i=0;i<2;i++) *(&_set+i)=read_eeprom(12+i); // du dernier usage if((amp_set>1023)||(amp_set<0))amp_set=0; //---- programme principal while(true) { set_range();// choisir la gamme du courant, 1, 2, 4 ou 8 Amp lire_PB(); // lire les boutons et placer les consignes de voltage et de courant write_cmd_lcd(128); // adresse du debut de la 1ere ligne printf(write_car_lcd,"%01ld,%03ldA SET %02ld,%01ldV",amp_set/disp_a,amp_set*disp_ma,volt_set/40,volt_set/4); SET_PWM1_duty(amp_set); // amp_set SET_PWM2_duty(volt_set); // volt_set lire_voltage(); // lire et afficher lire_courant(); // lire et afficher comparer_Iset_Ilue(); // lire et afficher qui est en controle, E ou I } } //********************************* FIN MAIN ****************************** //************************************ FONCTIONS ***************************** void pic_ini(void) { //-- PORTS output_A(0x00); output_B(0x00); output_C(0x00); set_tris_A(0b11011111); port_B_pullups(true); set_tris_B(0b11111111); set_tris_C(0b00000000); //--- ADC setup_adc_ports(RA0_RA1_RA3_ANALOG); setup_adc(ADC_CLOCK_INTERNAL); //--- PWM SET_PWM1_duty(0); // amp_set SET_PWM2_duty(0); // volt_set setup_timer_2(t2_div_by_16,255,1); setup_ccp1(CCP_PWM_PLUS_3); setup_ccp2(CCP_PWM_PLUS_3); } //------------------------------------------------- void lcd_ini(void) { delay_ms(100); // attendre que le 5V soit stabilise output_bit(PIN_A5,0); // E clock output_bit(PIN_C0,0); // R/W R=1,W=0 output_bit(PIN_C3,0); // R/S 0 pour commande, 1 pour data for(i=1;i<=4;i++) {send_nibble(0x30); delay_ms(5);} // reset du LCD send_nibble(0x20); // interface 4 bits delay_us(43); write_cmd_lcd(0x28); // interface 4 bits, 5X7 write_cmd_lcd(0x08); // display off write_cmd_lcd(0x0C); // display on write_cmd_lcd(0x06); // increment no display shift } //*********************** Fonctions du LCD ***************************** void write_cmd_lcd(commande) { busy_status(); // LCD pret? output_bit(PIN_C3,0); // R/S 0 pour commande send_nibble(commande); // placer commande dans LCD swap(commande); send_nibble(commande); // placer commande dans LCD } //-------------- afficher un caractere sur le LCD -------------------------- void write_car_lcd(car) { busy_status(); // LCD pret? output_bit(PIN_C3,1); // R/S 1 pour data send_nibble(car); // placer commande dans LCD swap(car); send_nibble(car); // placer commande dans LCD } //-------------------- Envoyer un nibble ---------------- void send_nibble(nibble) { output_bit(PIN_C0,0); // R/W R=1, W=0 output_bit(PIN_A5,0); // E line low delay_cycles(3); output_bit(PIN_A5,1); // pulser E high nibble=nibble&0xF0; // vider les 4 bits du bas de la byte nibble=nibble|(input_C()&0x0F); // charger C0-C3 output_C(nibble); delay_cycles(3); output_bit(PIN_A5,0); // E low } //----------------------- void busy_status() // tester si le LCD est pret a accepter un data { do { set_tris_C(0b11110000); output_bit(PIN_A5,0); // E off output_bit(PIN_C0,1); // R/W R=1,W=0 output_bit(PIN_C3,0); // R/S 0 pour commande, 1 pour data delay_cycles(3); output_bit(PIN_A5,1); // pulser E high delay_cycles(3); bit_status=input_C()&0X80; // lire status delay_us(2); output_bit(PIN_A5,0); // E off delay_cycles(3); output_bit(PIN_A5,1); // pulser E high delay_us(1); // faire semblant de lire les 4 bits de status du bas output_bit(PIN_A5,0); // E off delay_cycles(3); } while(bit_status==0x80); set_tris_C(0b00000000); } //***************************** Fin des fonctions LCD ******************************** //************************************************************************************ void lire_voltage() // lire et afficher { SET_ADC_CHANNEL(0); delay_ms(1); for(i=15;i>=1;i--) volt_moy[i]=volt_moy[i-1]; volt_moy[0]=READ_ADC()/64; // tasser a droite la lecture dans les 2 bytes, 6 bits volt_lue=0; for(i=0;i<=15;i++) volt_lue=volt_lue+volt_moy[i]; volt_lue=volt_lue/16; volt_lue=volt_lue+2;// compenser pour le restant de la division a l'affichage //if(volt_lue<=7)volt_lue=0; write_cmd_lcd(203); // adresse du 3/4 de la 2ie ligne printf(write_car_lcd,"%02ld,%01ldV",volt_lue/40,volt_lue/4); } //---------------------------- void lire_courant() // lire et afficher, tester si I depasse la limite et est en controle { SET_ADC_CHANNEL(1); delay_ms(1); for(i=15;i>=1;i--) amp_moy[i]=amp_moy[i-1]; amp_moy[0]=READ_ADC()/64; // tasser a droite la lecture dans les 2 bytes, 6 bits amp_lue=0; for(i=0;i<=15;i++) amp_lue=amp_lue+amp_moy[i]; amp_lue=amp_lue/16; amp_lue=amp_lue+1; write_cmd_lcd(192); // adresse du debut de la 2ie ligne printf(write_car_lcd,"%01ld,%03ldA",amp_lue/disp_a,amp_lue*disp_ma); } //---------------------------- void set_range() { if((input(pin_A2)==1)&&(input(pin_A4)==1)){disp_a=1000;disp_ma=1;} if((input(pin_A2)==0)&&(input(pin_A4)==1)){disp_a=500;disp_ma=2;} if((input(pin_A2)==1)&&(input(pin_A4)==0)){disp_a=250;disp_ma=4;} if((input(pin_A2)==0)&&(input(pin_A4)==0)){disp_a=125;disp_ma=8;} } //-------------------------------------------------------------- void lire_PB() // lire les boutons et setter voltage et le courant { boutons=input_b(); if(boutons!=0xFF) { switch(boutons) { case 0b01111111: // grande reduction du voltage ************* volt_set=volt_set-40; if(volt_set<=0) volt_set=0; break; case 0b10111111: // grande reduction du courant amp_set=amp_set-50; if(amp_set<=0) amp_set=0; break; case 0b11011111: // grande augmentation du voltage ********** volt_set=volt_set+40; if(volt_set>=1000) volt_set=1000; break; case 0b11101111: // grande augmentation du courant amp_set=amp_set+50; if(amp_set>=1000) amp_set=1000; break; case 0b11110111: // petite augmentation du voltage ********** volt_set=volt_set+4; if(volt_set>=1000) volt_set=1000; break; case 0b11111011: // petite augmentation du courant amp_set=amp_set+1; if(amp_set>=1000) amp_set=1000; break; case 0b11111101: // petite reduction du voltage ************* volt_set=volt_set-4; if(volt_set<=0) volt_set=0; break; case 0b11111110: // petite reduction du courant amp_set=amp_set-1; if(amp_set<=0) amp_set=0; break; default: // plus qu'un bouton pese break; } for(i=0;i<2;i++) write_eeprom(10+i,*(&volt_set+i)); for(i=0;i<2;i++) write_eeprom(12+i,*(&_set+i)); delay_ms(350); // taux de repetition } } //------------------------------- comparer_Iset_Ilue() { write_cmd_lcd(198); // milieu de la 2ie ligne if (amp_lue<(amp_set-1)) printf(write_car_lcd," >>> "); else printf(write_car_lcd," <<< "); } //******************************** Fin des fonctions **************************************