На этой странице показан пример создания источника питания с регулируемым выходным напряжением от 0 до 25 В и током нагрузки от 0 до 2 А. В источнике питания предусмотрена токовая стабилизация от 0,2 до 2 А. Регулирование напряжения и тока стабилизации цифровое, выполнено на микроконтроллере LGT8F328 (LGT8F328P-LQFP32 MiniEVB).
Источник питания состоит из двух основных блоков:
- Силовая часть, содержит несколько транзисторов и ОУ, а так же шунт для измерения тока.
- Цифровая часть состоит из микроконтроллера LGT8F328, дисплея 0.96′ I2C 128X64 OLED (SSD1306) и органов управления в виде энкодера и одной кнопки.
Схема источника питания
Параметры дисплея SSD1306:
- Технология дисплея: OLED
- Разрешение дисплея: 128 на 64 точки
- Диагональ дисплея: 0,96 дюйма
- Угол обзора: 160°
- Напряжение питания: 2.8 В ~ 5.5 В
- Мощность: 0,08 Вт
- Габариты: 27.3 мм х 27.8 мм х 3.7 мм
Энкодер KY-040
Регулировка тока стабилизации и выходного напряжения
На дисплей в верхней строке выводятся показания установленного напряжения (1), а так же измеренное напряжение на выходе (3). В нижней строке выводятся показания установленного тока стабилизации (2) и измеренный ток (4). Заначек «*»(5) показывает активный для регулировки параметр. Переключение регулировки тока/напряжения производится нажатием кнопки энкодера. Для включения/отключения выхода необходимо нажать кнопку OUT_ON_OFF.
Измерение напряжения и выходного тока производится с разрешением 12 бит. Все установленные параметры сохраняются в энергонезависимой памяти. Индикатор тока нагрузки начинает работать при токе выше 0,05 А.
Регулировка напряжения |
Регулировка тока стабилизации |
Отключение выхода |
Режим стабилизации тока |
Для прошивки платы LGT8F328P-LQFP32 MiniEVB используется платформа Arduino. Как добавить плату LGT8F328P-LQFP32 MiniEVB в Arduino IDE написано в LGT8F328P-LQFP32 MiniEVB в Arduino IDE.
Скетч
#define ANALOG_I A3 #define ANALOG_U A6 #define U_OUT_K 508 #define I_OUT_K 1970 #define I_STAB_K 1210 #define U_OUT_IND 157 #include <Wire.h> #include <OLED_I2C.h> // http://rcl-radio.ru/wp-content/uploads/2022/01/OLED_I2C.zip #include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip #include <EEPROM.h> #include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip OLED myOLED(SDA, SCL, 8); Encoder myEnc(6, 5);// DT, CLK extern uint8_t SmallFont[],BigNumbers[]; unsigned long u_sum,i_sum,times,times0,oldPosition = -999,newPosition; int u_,ads_i,i_,menu; int u_out,i_stab; bool w=1,w2,out=1; void setup(){ delay(200);Wire.begin();myOLED.begin(); myOLED.setBrightness(100);// ЯРКОСТЬ ДИСПЛЕЯ analogReadResolution(12);// АЦП 12 БИТ analogReference(DEFAULT);//INTERNAL4V096 DEFAULT(Uп) Serial.begin(9600); pinMode(7,INPUT); // SW ENCODER pinMode(4,INPUT_PULLUP); // OUT_ON_OFF MsTimer2::set(3, to_Timer);MsTimer2::start(); if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении // TIMER_1 D9 OUTPUT DDRB = 1 << PB1; noInterrupts(); TCCR1A=0;TCCR1B=0; TCCR1A = 1 << COM1A1 | 1 << WGM11; TCCR1B = 1 << WGM13 | 1 << WGM12 | 1 << CS10; OCR1A = 0; ICR1 = 10000; // TIMER_3 D2 OUTPUT TCCR3A=0;TCCR3B=0; DDRF |= (1<<PF2); HDR = 1 << HDR3; TCCR3A = 1 << COM3B1 | 1 << WGM31; TCCR3B = 1 << WGM33 | 1 << WGM32 | 1 << CS30; OCR3B = 0; ICR3 = 2500; interrupts(); myOLED.clrScr(); myOLED.setFont(SmallFont); myOLED.print(F("Power unit"), CENTER, 10); myOLED.print(F("0-25V"), CENTER, 30); myOLED.print(F("0-2A"), CENTER, 50); myOLED.update(); delay(1000); u_out = EEPROM.read(0);i_stab = EEPROM.read(1); OCR1A = float(u_out)/10.00*U_OUT_K; OCR3B = I_STAB_K*float(i_stab)/100; } void loop() { if(digitalRead(7)==LOW){menu++;delay(300);times0=millis();w=1;w2=1;if(menu>1){menu=0;}} if(digitalRead(4)==LOW && out==1){out=0;;delay(300);OCR1A=0;OCR3B = 0;} if(digitalRead(4)==LOW && out==0){out=1;;delay(300);w=1;} ///////////////////////////////////////////////////////////////////////////////////////////// if(millis()-times>100){times=millis();ads_i++;i_sum = i_sum + analogRead(ANALOG_I);u_sum = u_sum + analogRead(ANALOG_U);} if(ads_i>9){ads_i=0;i_ = i_sum/10;i_sum=0; u_ = u_sum/10;u_sum=0; Serial.print("I_out = ");Serial.println(abs(float(i_)/I_OUT_K),2); Serial.print("I_dig = ");Serial.println(analogRead(ANALOG_I)); Serial.print("U_out = ");Serial.println(abs(float(u_)/U_OUT_IND),2); Serial.print("U_dig = ");Serial.println(analogRead(ANALOG_U)); w=1;} ///////////////////////////////////////////////////////////////////////////////////////////// if(menu==0){ if(newPosition != oldPosition){oldPosition = newPosition;u_out=u_out+newPosition;myEnc.write(0);newPosition=0; if(u_out<0){u_out=0;}if(u_out>250){u_out=250;}times0=millis();w=1;w2=1;}} ///////////////////////////////////////////////////////////////////////////////////////////// if(menu==1){ if(newPosition != oldPosition){oldPosition = newPosition;i_stab=i_stab+newPosition;myEnc.write(0);newPosition=0; if(i_stab<10){i_stab=10;}if(i_stab>200){i_stab=200;}times0=millis();w=1;w2=1;}} ///////////////////////////////////////////////////////////////////////////////////////////// if(w==1){w=0; if(out==1){ OCR1A = float(u_out)/10.00*U_OUT_K; OCR3B = I_STAB_K*float(i_stab)/100; } myOLED.clrScr(); // U ///////// myOLED.setFont(BigNumbers);if(u_out/100>0){myOLED.printNumI(u_out/100, 5, 0);} myOLED.printNumI(u_out/10%10, 20, 0); myOLED.setFont(SmallFont);myOLED.print(F("."), 33, 18);myOLED.setFont(BigNumbers);myOLED.printNumI(u_out%10, 38, 0); myOLED.setFont(SmallFont);myOLED.print(F("V"), 57, 0); if(menu==0){myOLED.setFont(SmallFont);myOLED.print(F("*"), 57, 18);} myOLED.drawLine(0, 30, 128, 30); if(out==1){ long u_iz = (abs(long(u_))*10)/U_OUT_IND; myOLED.setFont(BigNumbers);if(u_iz/100>0){myOLED.printNumI(u_iz/100, 70, 0);} myOLED.printNumI(u_iz/10%10, 85, 0); myOLED.setFont(SmallFont);myOLED.print(F("."), 98, 18);myOLED.setFont(BigNumbers);myOLED.printNumI(u_iz%10, 104, 0);} else{myOLED.setFont(SmallFont);myOLED.print(F("OUT_OFF"), 75, 10);} // I ////////// myOLED.setFont(BigNumbers);myOLED.printNumI(i_stab/100, 5, 35);myOLED.printNumI(i_stab/10%10, 23, 35); myOLED.setFont(SmallFont);myOLED.print(F("."), 18, 53);myOLED.setFont(BigNumbers);myOLED.printNumI(i_stab%10, 38, 35); myOLED.setFont(SmallFont);myOLED.print(F("A"), 57, 35); if(menu==1){myOLED.print(F("*"), 57, 53);} long i_iz = (abs(long(i_))*100)/I_OUT_K; if(i_iz<=5){i_iz=0;} myOLED.setFont(BigNumbers);myOLED.printNumI(i_iz/100, 70, 35);myOLED.printNumI(i_iz/10%10, 90, 35); myOLED.setFont(SmallFont);myOLED.print(F("."), 84, 53);myOLED.setFont(BigNumbers);myOLED.printNumI(i_iz%10, 105, 35); myOLED.update(); } ////////////////////////////////////////////////////////////////////////////////// if(millis()-times0>10000 && w2==1){EEPROM.update(0,u_out);EEPROM.update(1,i_stab);menu=0;w2=0;w=1;} } void to_Timer(){newPosition = myEnc.read()/4;}
Источник питания нуждается в регулировке, регулировка содержит 4 параметра (коэффициента):
#define U_OUT_K 508
#define I_OUT_K 1970
#define I_STAB_K 1210
#define U_OUT_IND 157
Процесс регулировки состоит из нескольких этапов, которые должны быть выполнены в определенной очередности. В процессе регулировки необходимо менять корректирующие коэффициенты и несколько раз загружать измененный скетч.
Настройка выходного напряжения
- К выходу источника питания подключите вольтметр, установите при помощи энкодера выходное напряжение на дисплее (не на выходе ИП) 18 В.
- Подберите коэффициент U_OUT_K таким образом чтобы на выходе источника питания было 18,0 В.
Настройка измерителя напряжения
- Установите при помощи энкодера выходное напряжение на дисплее 18 В.
- Подберите коэффициент U_OUT_IND таким образом чтобы на дисплее было 18,0 В.
Настройка измерителя тока
- Установите при помощи энкодера выходное напряжение на выходе источника питания 18 В.
- Подключите нагрузку 5-10 Ом, так чтобы выходной ток быть больше 1 А.
- Измерьте амперметром полученный ток нагрузки.
- Подберите коэффициент I_OUT_K таким образом чтобы на показания тока на дисплее и измеренное амперметром были равны.
Настройка токовой стабилизации
- Установите при помощи энкодера выходное напряжение на выходе источника питания 18 В.
- Подключите нагрузку 5-10 Ом, так чтобы выходной ток быть больше 1 А.
- Установите значение тока стабилизации на 10-50% меньше тока нагрузки, например если выходной ток 1,45 А, то установите ток стабилизации на 1,00 А
- Если ток нагрузки выше тока стабилизации, то источник питания перейдет в режим стабилизации тока и будет выводить значение выходной тока в режиме стабилизации тока, подберите коэффициент I_STAB_K таким образом, чтобы указанный ток стабилизации и выходной ток стали равными.
В скетче уже указаны необходимые корректирующие коэффициенты, поэтому при правильной сборке уст-ва и соблюдения всех номиналов элементов указанных на схеме, источник питания будет правильно регулировать и измерять ток и напряжение. Настройка корректирующих коэффициентов необходима для получения большой точности источника параметров источника питания.
Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=7461#p7461
Версия №2
Замена дисплея на LCD1602 I2C
Скетч — http://forum.rcl-radio.ru/viewtopic.php?pid=7520#p7520
Измеренное напряжение на выходе источника питания | |
Режим отключения выхода
Версия №3
Добавлен датчик температуры DS18B20 для измерения температуры радиатора силового транзистора, при температуре выше 65 °С выход источника питания будет автоматически отключен.
Скетч — http://forum.rcl-radio.ru/viewtopic.php?pid=7555#p7555