Блок питания на LM723 0…28 В 0…2.5 А (Arduino)

Блок питания (БП) основан на регулируемом стабилизаторе LM723, диапазон выходного напряжения от 0 до 28 В при токе нагрузке от 0 до 2,5 А. Максимальное входное напряжение не должно превышать 40 В, в данной схеме можно использовать входное напряжение в диапазоне от 32 до 36 В. Управление выходным напряжением БП осуществляется при помощи модуля MCP4725, который представляет собой 12 битный ЦАП. Выходное напряжение ЦАПа подается на вывод 5 LM723, который используется для регулировки выходного напряжения БП.

Для регулирования выходного напряжения БП от 0 В, используется схема смещения напряжения питания для LM723 на стабилизаторе 78L33 (3.3 В). Трансформатор БП имеет две обмотки, одна силовая (АС 25…28 В), другая маломощная (АС 4…6 В) для питания стабилизатора 78L33. Дополнительно используется стабилизатор 7812 (12 В) для питания платы Arduino Nano, напряжение с стабилизатора подается на вход VIN платы Arduino.

Для ограничения выходного тока и защиты выхода БП от КЗ используется высокоточный измеритель тока на модуле MCP3421 который представляет собой 18 битный ЦАП. В качестве датчика тока используется шунт с сопротивлением 0,01 Ом.

Выходное напряжение и ограничение тока регулируются при помощи энкодера, вся информация выводится на дисплей LCD1602 с модулем I2C. Шаг регулировки напряжения 0,1 В. Точность выходного напряжения не хуже 0,05 В, дополнительно имеется программная компенсация выходного напряжения БП, которая учитывает падение напряжения на шунте. Шаг регулировки ограничения тока 0,01 А. Поворот ручки энкодера позволяет менять настройки выбранного параметра, а кнопка энкодера позволяет переключать параметр регулирования.

MCP3421

MCP4725

ky-040

В первой строке индикатора выводится установленное значение напряжения и измеряемый ток. Во второй строке выводится значение токового ограничения и состояние выхода. Состояние выхода имеет три параметра, ON — выход активен, OFF — выход отключен, ERR — КЗ выхода (отображается 5 секунд после КЗ, потом сменяется на OFF). Состояние выхода  меняется дополнительной кнопкой ON/OFF. При включении БП выход не активен, на индикаторе отображается OFF, при нажатии на кнопку ON/OFF на выходе БП появляется установленное напряжение.

Все параметры сохраняются в энергонезависимой памяти.

#include <Wire.h>
#include <EEPROM.h>
#include <MCP3421.h>  // http://rcl-radio.ru/?p=62308
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 Encoder myEnc(8, 9);//CLK, DT
 MCP3421 mcp;
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 
 unsigned long times,oldPosition  = -999,newPosition;
 int u_out,u_dig,menu,i_out;
 const float u_k = 7.08; // калибровка регулятора напряжения
 const float i_k = 1.007;// калибровка измерителя тока 
 const float r = 0.01;   // сопротивление шунта
 byte power = 1; // при подачи питания выходное напряжение 0 В - OFF
 float i;
 byte w;
 
void setup(){
  Wire.begin();lcd.init();lcd.backlight();
  mcp.setConfig(3,3); 
  MsTimer2::set(3, to_Timer);MsTimer2::start();
  pinMode(10,INPUT);//  SW энкодер MENU
  pinMode(2,INPUT_PULLUP); // кнопка ON/OFF
  u_out=EEPROM.read(0)*256+EEPROM.read(1);i_out=EEPROM.read(2);
  }
 
void loop(){
  i_kz();
  if(digitalRead(10)==LOW){menu++;if(menu>1){menu=0;}delay(200);}
  if(digitalRead(2)==LOW&&power==0){power = 1;delay(300);}
  if(digitalRead(2)==LOW&&power==1){power = 0;delay(300);}
  //////// set out 0-28 V
  if(menu==0){
  if (newPosition != oldPosition){oldPosition = newPosition;
     u_out=u_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;
     if(u_out<0){u_out=0;}if(u_out>280){u_out=280;}u_dig = float(u_out/10.00)/u_k*4096/5.00;}}
  //////// set i 0-2.5 A
  if(menu==1){
  if (newPosition != oldPosition){oldPosition = newPosition;
     i_out=i_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;
     if(i_out<0){i_out=0;}if(i_out>250){i_out=250;}}}
 
  //////// lcd
  i_kz();
  lcd.setCursor(0, 0);if(menu==0){lcd.print("U*= ");}else{lcd.print("U = ");}if(u_out<100){lcd.print(" ");}
  lcd.print(float(u_out/10.00),1);lcd.print(" V ");  
  lcd.setCursor(11, 0);lcd.print(abs(i),3);
  lcd.setCursor(0, 1);if(menu==1){lcd.print("A*= ");}else{lcd.print("I = ");}lcd.print(float(i_out/100.00),2);lcd.print(" A ");
  i_kz();
 
  //////////////// EEPROM
  if(millis()-times>5000&&w==1){EEPROM.update(0,highByte(u_out));EEPROM.update(1,lowByte(u_out));EEPROM.update(2,i_out);menu=0;times=millis();w=0;}
  }//loop
 
void MCP4725(int data){  
  byte buffer[3];
  buffer[0] = 0b01000000;
  // data=0;
  // buffer[0] = 0b01100000; // запись в память ЦАП 0 В 
  buffer[1] = data >> 4;              
  buffer[2] = data << 4;
  Wire.beginTransmission(0x60);
  Wire.write(buffer[0]);
  Wire.write(buffer[1]);
  Wire.write(buffer[2]);
  Wire.endTransmission();
  }  
void i_kz(){  
  i = mcp.readWire()*0.256/131071*i_k/r;
  if(i > float(i_out/100.0)){MCP4725(0);lcd.setCursor(12, 1);lcd.print("ERR");delay(5000);power=1;}
  else{lcd.setCursor(12, 1);
  if(power==0){MCP4725(u_dig+i*5);lcd.print("ON ");}
  if(power==1){MCP4725(0);lcd.print("OFF");}
  }}
 
void to_Timer(){newPosition = myEnc.read()/4;}

Настройка БП

Настройка блока питания сводится к установке (корректировке) коэффициентов для АЦП и ЦАП.

const float u_k = 7.08; // калибровка регулятора напряжения

const float i_k = 1.007;// калибровка измерителя тока

const float r = 0.01; // сопротивление шунта

byte power = 1; // при подачи питания выходное напряжение 0 В — OFF

const float u_k = 7.08 — установите выходное напряжение 25-28 В, проконтролируйте выходное напряжение БП при помощи вольтметра с КТ не менее 0,1, измените коэффициент для получения более точного выходного напряжения БП.

const float i_k = 1.007 подключите нагрузку и проконтролируйте амперметром выходной ток (1…2 А), измените коэффициент для получения более точного измерения выходного тока БП.

const float r = 0.01 — укажите сопротивление шунта (0,01 Ом).

byte power = 1 — если эта переменная равна 1, то при включении БП выход будет не активен (0 В), если переменную изменить на 0, то при включении на выходе появится установленное напряжение.

При включении БП на выходе в течении 1 секунды может появится напряжение которое не соответствует установленному, это связано с тем, что при старте программы еще не произошел опрос ЦАПа MCP4725. Для устранения этого дефекта рекомендую записать в память EEPROM ЦАПа напряжение старта, при подачи питания на выходе ЦАПа будет то напряжение которое записано в EEPROM. Для записи напряжения старта в память ЦАПа необходимо выполнить следующее:

  • найдите в скетче строки:

// data=0;

// buffer[0] = 0b01100000; // запись в память ЦАП 0 В

  • раскомментируйте строчки и загрузите скетч, в память ЦАПа будет записано напряжение 0 В. Далее закомментируйте эти строчки и повторно загрузите скетч.

После подачи питания, на выходе БП всегда будет 0 В.

Тестирование

Нагрузка 10 Ом Нагрузка 10 Ом
Нагрузка 10 Ом Нагрузка 10 Ом
Нагрузка 10 Ом Нагрузка 10 Ом
Нагрузка 10 Ом Нагрузка 10 Ом
Нагрузка 10 Ом Нагрузка 10 Ом


Вариант №2

Во втором варианте БП вместо ЦАП MCP3421 применен ОУ LM358 в качестве усилителя напряжения на шунте. Коэффициент усиления ОУ примерно равен 120, с выхода ОУ напряжение подается на вход А0 платы Arduino. Точность измерения тока в таком варианте схемы немного хуже, но за то увеличивается скорость реагирования токовой защиты по сравнению в вариантом схемы где применен ЦАП.

Как и в первом варианте показания амперметра нуждаются в калибровке, калибровка программная и производится путем подбора коэффициента:

const float i_k = 0.975;// калибровка измерителя тока 

#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 Encoder myEnc(8, 9);//CLK, DT
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 
 unsigned long times,oldPosition  = -999,newPosition;
 int u_out,u_dig,menu,i_out;
 const float u_k = 7.10; // калибровка регулятора напряжения
 const float i_k = 0.975;// калибровка измерителя тока 
 const float r = 0.01;   // сопротивление шунта
 byte power = 1; // при подачи питания выходное напряжение 0 В - OFF
 float i;
 byte w;
 
void setup(){
  Wire.begin();lcd.init();lcd.backlight();
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  pinMode(10,INPUT);//  SW энкодер MENU
  pinMode(2,INPUT_PULLUP); // кнопка ON/OFF
  pinMode(A0,INPUT); // input I
  u_out=EEPROM.read(0)*256+EEPROM.read(1);i_out=EEPROM.read(2);
  }
 
void loop(){i_kz();
  if(digitalRead(10)==LOW){menu++;if(menu>1){menu=0;}delay(200);}
  if(digitalRead(2)==LOW&&power==0){power = 1;delay(200);}
  if(digitalRead(2)==LOW&&power==1){power = 0;delay(200);}
  //////// set out 0-28 V
  if(menu==0){
  if (newPosition != oldPosition){oldPosition = newPosition;
     u_out=u_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;
     if(u_out<0){u_out=0;}if(u_out>280){u_out=280;}u_dig = float(u_out/10.00)/u_k*4096/5.00;}}
  //////// set i 0-2.5 A
  if(menu==1){
  if (newPosition != oldPosition){oldPosition = newPosition;
     i_out=i_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;
     if(i_out<0){i_out=0;}if(i_out>250){i_out=250;}}}
 
  //////// lcd
  i_kz();
  lcd.setCursor(0, 0);if(menu==0){lcd.print("U*= ");}else{lcd.print("U = ");}if(u_out<100){lcd.print(" ");}
  lcd.print(float(u_out/10.00),1);lcd.print(" V ");  
  lcd.setCursor(11, 0);lcd.print(abs(i),2);lcd.print("A");
  lcd.setCursor(0, 1);if(menu==1){lcd.print("A*= ");}else{lcd.print("I = ");}lcd.print(float(i_out/100.00),2);lcd.print(" A ");
  i_kz();
 
  //////////////// EEPROM
  if(millis()-times>5000&&w==1){EEPROM.update(0,highByte(u_out));EEPROM.update(1,lowByte(u_out));EEPROM.update(2,i_out);menu=0;times=millis();w=0;}
  }//loop
 
void MCP4725(int data){  
  byte buffer[3];
  buffer[0] = 0b01000000;
  // data=0;
  // buffer[0] = 0b01100000; // запись в память ЦАП 0 В 
  buffer[1] = data >> 4;              
  buffer[2] = data << 4;
  Wire.beginTransmission(0x60);
  Wire.write(buffer[0]);
  Wire.write(buffer[1]);
  Wire.write(buffer[2]);
  Wire.endTransmission();
  }  
void i_kz(){  
  i = analogRead(A0)/250.00*i_k;
  if(i > float(i_out/100.0)){MCP4725(0);lcd.setCursor(12, 1);lcd.print("ERR");delay(3000);power=1;}
  else{lcd.setCursor(12, 1);
  if(power==0){MCP4725(u_dig+i*4.00);lcd.print("ON ");}
  if(power==1){MCP4725(0);lcd.print("OFF");}
  }}
 
void to_Timer(){newPosition = myEnc.read()/4;}

Измерения проводились с нагрузкой 10 Ом

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=257

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

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