Источник питания 0-25В / 0-2А с токовой стабилизацией и цифровым управлением

На этой странице показан пример создания источника питания с регулируемым выходным напряжением от 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

 

Добавить комментарий

Войти с помощью: