На рисунке показана схема простого ШИМ регулятора напряжения, с диапазоном регулировки от 0 до 25 В с максимальным током нагрузки 3 А при выходном напряжении 25 В.
Точность установки выходного напряжения ±0,1 В. Информация об установленном напряжении выводится на индикатор TM1637. Управление ШИМ регулятора осуществляется при помощи трех кнопок — UP, DW и OUT_ON_OFF.
При при подачи питания на ШИМ регулятор, модуль реле подаст напряжение питания только после активации PWM выхода (D9), при этом на выходе ШИМ регулятора установится 0 В. ШИМ регулятор после подачи питания всегда работает в режиме отключения выхода. При этом на индикаторе будет показано ранее установленное напряжение:
При нажатии на кнопку OUT_ON_OFF на выходе появится выходное напряжение и индикатор будет показывать следующее:
При коротком замыкании выхода ШИМ регулятора, на 3 секунды загорится светодиод, при этом напряжение на выходе установится на 0 В. Далее если нажать на кнопку OUT_ON_OFF на выходе снова появится выходное напряжение.
Так так ШИМ регулятор по сути регулятор мощности, то максимальный ток нагрузки по мере уменьшения выходного напряжения будет расти. Регулировка и стабилизация напряжения и так же защита от короткого замыкания зависит от измеренного выходного напряжения, которое через делитель подается на аналоговый вход контроллера А0 (12 бит). В зависимости от выходного напряжения контроллер будет менять скважность ШИМ сигнала. При большой нагрузке или коротком замыкании выхода скважность ШИМ перейдет допустимы порог и напряжение на выходе установится на 0В.
Выходное напряжение ШИМ регулятора ограничено программно, при желании можно расширить диапазон регулировки выходного напряжения, но при этом возрастет выходная мощность ШИМ регулятора, соответственно необходимо правильно подобрать радиатор охлаждения для силового транзистора. Транзистор КТ815 так же должен быть установлен на небольшой теплоотвод.
Дроссель — намотан на ферритовом кольце диаметром 25-30 мм, проводом 0,8-1 мм, намотка в один слой до заполнения.
Измените калибровочной коэффициент для более точной настройки выходного напряжения:
#define KALL_U 7.405
Скетч:
// 0-25V 3A #define KALL_U 7.405 #define CLK PB4 // TM1637 D11 #define DIO PB3 // TM1637 D12 #include <EEPROM.h> float u,u_iz; int reg; bool w=1,w1,out=0; unsigned long times; void setup(){ if(EEPROM.read(0)==255){EEPROM.update(0,0);} u = float(EEPROM.read(0))/10.0; Serial.begin(9600); // TIMER_1 D9 OUTPUT DDRB |= (1 << PB1)|(1<<PB5); // D9 output pwm | D13 led error DDRD |= (1<<PD2); // D2 RELE PORTD |= (1<<PD3)|(1<<PD4)|(1<<PD5); PORTB |= (1<<PB1); noInterrupts(); TCCR1A = 0;TCCR1B = 0; TCCR1A |= (1 << COM1A1) | (1 << COM1A0) | (1 << WGM11); TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10); TCKCSR = 1 << F2XEN | 1 << TC2XS1; ICR1 = 5000; OCR1A =0; interrupts(); ADMUX = 0b000; ADCSRD |= 1 << REFS2; ADCSRA |= 1 << ADEN | 1 << ADSC | 1 << ADATE | 0b111; delay(300); PORTD &=~ (1 << PD2); } void loop(){ if(((PIND >> PD3) & 1) == 0){u+=0.1;if(u>25){u=25;}w=1;w1=1;times=millis();delay(100);} if(((PIND >> PD4) & 1) == 0){u-=0.1;if(u<0){u=0;}w=1;w1=1;times=millis();delay(100);} if(((PIND >> PD5) & 1) == 0 && out==0){out=1;w=1;delay(300);} if(((PIND >> PD5) & 1) == 0 && out==1){out=0;w=1;delay(300);} while((ADCSRA & (1 << ADIF)) == 0); int u_data = (ADCL|ADCH << 8); u_iz = float(u_data)/1000.0*KALL_U; if(u_iz-u>5){reg-=100;} if(u-u_iz>1){reg+=10;} if(u_iz-u>1){reg-=10;} if(u_iz<u){reg++;} if(u_iz>u){reg--;} if(reg<0){reg=0;}if(reg>4900 && out==1){reg=0;OCR1A=0;PORTB|=(1<<PB5);out=0;w=1;delay(3000);} PORTB&=~(1<<PB5); if(out==0){reg=0;} OCR1A = reg; if(w==1){w=0;tm_print(u*10,1,5);} if(millis()-times>5000 && w1==1){EEPROM.update(0,u*10);w1=0;} } void tm_dec(byte dig){ for(byte i = 0; i < 8; i++) { DDRB |= (1 << CLK);del(); if (dig & 0x01) DDRB &= ~(1 << DIO); else DDRB |= (1 << DIO);del(); DDRB &= ~(1 << CLK);del(); dig = dig >> 1; } DDRB |= (1 << CLK); DDRB &= ~(1 << DIO);del(); DDRB &= ~(1 << CLK);del(); if (((PINB >> DIO) & 1) == 0) DDRB |= (1 << DIO);del(); DDRB |= (1 << CLK);del(); } void tm_stop(){ DDRB |= (1 << DIO);del(); DDRB &= ~(1 << CLK);del(); DDRB &= ~(1 << DIO);del(); } void tm_start(){ DDRB |= (1 << DIO);del(); } void tm_print(int t, byte pd_t, int br){ tm_start();tm_dec(0b10001000 + br); tm_dec(0x40);tm_stop();tm_start(); int data0 = t / 1000 % 10; int data1 = t / 100 % 10; int data2 = t / 10 % 10; int data3 = t % 10; for(byte n = 0; n < 4; n++){ int data; switch(n){ case 0: if(out==1){data = 12;}else{data=10;};break; case 1: if(u<10){data=10;}else{data = data1;}break; case 2: data = data2;break; case 3: data = data3;break; } switch(data){ // XGFEDCBA case 0: data = 0b00111111;break; // 0 case 1: data = 0b00000110;break; // 1 case 2: data = 0b01011011;break; // 2 case 3: data = 0b01001111;break; // 3 case 4: data = 0b01100110;break; // 4 case 5: data = 0b01101101;break; // 5 case 6: data = 0b01111101;break; // 6 case 7: data = 0b00000111;break; // 7 case 8: data = 0b01111111;break; // 8 case 9: data = 0b01101111;break; // 9 case 10: data = 0b00000000;break; // пусто case 11: data = 0b01000000;break; // - case 12: data = 0b00111110;break; // U } if(n == 0){data0 = data;} if(n == 1){data1 = data;} if(n == 2){data2 = data;} if(n == 3){data3 = data;} } switch(pd_t){ case 1 : data2 = data2+0b10000000;break; case 2 : data1 = data1+0b10000000;break; case 3 : data0 = data0+0b10000000;break; } tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop(); } void del(){delayMicroseconds(100);}