Товары из Китая

Блок питания с автономным режимом, на основе модуля DPH5005, DIY


Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Всем доброго дня!

Случилась как то у меня ситуация, когда в полевых условиях понадобился блок питания, поэтому и возникла идея сооружения даного устройства.

Будет много радиолюбительства, самодельщины и полезных для DIY ссылок.

Конструктивно устройство состоит из блока аккумуляторов, DC-DC преобразователя, AC-DC преобразователя, плат управления, зарядки и индикации.

Принципиальная схема устройства:

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Аккумуляторы, 4 шт, были приобретены более 5 лет назад, еще на живом тогда интернет-аукционе aukro.ua. Они должны были питать переносную паяльную станцию на Т12, но проект так и до сих пор нереализован и утратил актуальность.

Аккумулятор:

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Позже, они были прогнаны на купленой здесь еще старой версии Liitokala 500, избавлены от «родных» плат защиты и смотаны в единый блок. Баночки показали емкость чть больше 6 А/ч.

Разделитель — стеклотекстолит 0,5мм, покупался в Украине. Продают, правда, минимум 2 м.кв. Ну и плата BMS, типа такой.

Я решил использовать польский корпус Z-2A производства Kradex.

Корпус был приобретен в украинском магазине. У нас же в стране они есть в замечательном магазинчике, который занимается корпусами, и, дешевле всего, здесь

Алюминиевый уголок — из строительного магазина. Он очень легко обрабатывается ножовкой, напильником и слабенькой дрелькой. Кернер для алюминия — такой, тоже сильно помог.

Аккумуляторы закрепил стяжкой к корпусу.

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Преобразователь DPH5005 был куплен уже давно, по какой то акции. Kirich сделал на него очень хороший обзор. Есть еще хороший обзор от Lexus—08. Я брал версию с USB. Модуль преобразователя установлен над аккумулятором, на металлических стойках М3. Я покупал в местном магазине, но их много и на али,

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Сверху еще на 2-х стойках расположилась плата управления

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Плата управления меряет напряжение батареи, температуры батареи, радиаторов силового транзистора и выпрямителя, дросселя блока питания, плавно регулирует скорость вентилятора и коммутирует питание преобразователя. еще обеспечивается включение вентилятора на постоянную небольшую мощность во время зарядки и когда преобразователь включает свой обдув. Индикация заряда батареи и температур греющихся узлов осуществляется 8-ю светодиодами и переключается кнопкой.

В закромах был найден древний PIC16F73, по современным меркам — мало на что пригодный. Решил дать ему шанс на жизнь.

Плата управления

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Программа для контроллера:


//PIC16F73
//UPS power source measurer
//Defines

#define CHARGING PORTC.F0
#define POW_SW PORTC.F1
#define POW_CONT PORTC.F3
#define BUTTON PORTC.F4
#define FAN PORTC.F5
#define TEMP_LO 3592.0 // Resistance for low temp, 50'C
#define TEMP_AL_OFF 1735 // Resistance for alarm off, 70'C
#define TEMP_HI 1243.0 // Resistance for high temp, 80'C
#define TEMP_AL_ON 782 // Resistance for alarm on, 95'C
#define INITIAL_FAN_SPEED 50 // Minimal PWM for proper fan operate, 20%
#define CHARGE_FAN_SPEED 75 // PWM for fan if charging, 30%
#define DPH_COOLING_FAN_SPEED 180 // PWM for fan if DPH fan is on, 70%
//Variables
char *digittext = "00000";
int battery_ADC, T_bat_ADC, T_coil_ADC, T_mos_ADC, T_rec_ADC;
unsigned long T_bat_res, T_coil_res, T_mos_res, T_rec_res;
char ADC_channel;
char count_resistance;
float flt_val;
long int fan_task, fan_speed;
bit bat_overH, coil_overH, mos_overH, rec_overH, overheat;
bit bat_hot, coil_hot, mos_hot, rec_hot;
bit batt_ok;
bit blink;
bit send_uart;
bit alarm_off;
char alarm_timer;
bit blink_long;
char blink_long_timer;
char display_mode;
char display_data;
bit button_pressed;
//*************************************************************************************
//battery charge
//Level 0 1 2 3 4 5 6 7 8
//voltage 3.1 3.2 3.4 3.5 3.6 3.7 3.8 3.9 4
//voltage 12.4 12.8 13.6 14 14.4 14.8 15.2 15.6 16
//ADC 182 190 202 208 214 220 226 233 239
const char battery_levels[9] = {182, 190, 202, 208, 214, 220, 226, 233, 239};
//*************************************************************************************
//temperature resistances
//level 0 1 2 3 4 5 6 7
//deg 55 60 65 70 75 80 85 95
//resist 2972 2472 2066 1735 1465 1243 1059 782
const int temper_resistances[8] = {2972, 2472, 2066, 1735, 1465, 1243, 1059, 782};
void WriteInt(long number){
digittext[0] = (number/10000)%10 + 48;
digittext[1] = (number/1000)%10 + 48;
digittext[2] = (number/100)%10 + 48;
digittext[3] = (number/10)%10 + 48;
digittext[4] = number%10 + 48;
UART1_Write_Text(digittext);
}
void Display() {
if (display_mode == 0)
{
WriteInt(Battery_ADC);
UART1_Write_Text("; ");
WriteInt(fan_speed);
if (~(batt_OK)) UART1_Write_Text(" B");
if (overheat) UART1_Write_Text(" H");
}
if (display_mode == 1) WriteInt(T_mos_res);
if (display_mode == 2) WriteInt(T_rec_res);
if (display_mode == 3) WriteInt(T_coil_res);
if (display_mode == 4) WriteInt(T_bat_res);
UART1_Write('r');
}
void TemperatureGauge(long value) {
display_data.F1 = (value < temper_resistances[0]);
display_data.F0 = (value < temper_resistances[1]);
display_data.F3 = (value < temper_resistances[2]);
display_data.F2 = (value < temper_resistances[3]);
display_data.F5 = (value < temper_resistances[4]);
display_data.F4 = (value < temper_resistances[5]);
display_data.F7 = (value < temper_resistances[6]);
display_data.F6 = (value < temper_resistances[7]);
}
int Fan_power(unsigned long resistanse) {
int result = (((INITIAL_FAN_SPEED - 255)*(resistanse - TEMP_HI))/(TEMP_LO - TEMP_HI)) + 255;
return result;
}
unsigned long Get_resistanse(int value) {
unsigned long result;
{flt_val = 255.0 / value; flt_val = flt_val + (-1); result = 10000.0 / flt_val;}
return result;
}
void interrupt() {
if (INTCON.TMR0IF) {
if (ADC_channel == 0) Battery_ADC = ADRES;
if (ADC_channel == 1) T_mos_ADC = ADRES;
if (ADC_channel == 2) T_rec_ADC = ADRES;
if (ADC_channel == 3) T_coil_ADC = ADRES;
if (ADC_channel == 4) T_bat_ADC = ADRES;
count_resistance = ADC_channel;
ADC_channel ++;
if (ADC_channel > 4) ADC_channel = 0;
if (ADC_channel == 0) ADCON0 = 0b01000001;
if (ADC_channel == 1) ADCON0 = 0b01001001;
if (ADC_channel == 2) ADCON0 = 0b01010001;
if (ADC_channel == 3) ADCON0 = 0b01011001;
if (ADC_channel == 4) ADCON0 = 0b01100001;
//ADCON0 = 0b10000001 + (ADC_channel << 3);
//ADCON0.GO = 1;
Delay_ms(2);
ADCON0 = ADCON0 + 0b00000100;
INTCON.TMR0IF = 0;
}
if (PIR1.TMR1IF) {
//Test = ~(Test);
if ( (batt_OK) && (~(overheat)) ) alarm_timer = 0; else {if (alarm_timer < 100) alarm_timer++;}
if (alarm_timer > 38) alarm_off = 1; // 10 000 / 262 (mS)
blink = ~(blink);
blink_long_timer++;
if (blink_long_timer > 4) // 4
{
blink_long_timer = 0;
//blink_long = 0;
//blink_long = 1;
blink_long = ~(blink_long);
}
send_uart = 1; //Display();
PIR1.TMR1IF = 0;
}
}
void main() {
//OPTION_REG = 0b10000101; //pull_ups off, TMR0 = 1*64*256=16384mkS
OPTION_REG = 0b10000110; //pull_ups off, TMR0 = 1*128*256=32768mkS
T1CON = 0b00100001; //Enable timer 1, ovf = 1*4*65535 = 262140 mS
ADCON0 = 0; //0b10000001; //Fosc/32, ADC enable
ADCON1 = 0b00000000; //All for ADC, left alligment
//CMCON = 0b00000111;
TRISA = 0b11111111;
TRISB = 0b00000000;
TRISC = 0b10110011;
// INTCON = 0; //interrupt stop
INTCON = 0b11100000; //interrupt on periphery and TMR0
PIE1 = 0b00000001; // TMR1 ovf interrupt enable
CCP1CON = 0b00001100; //CCP1 as PWM mode
PR2 = 255; //4096 mks
CCPR1L = 0;
T2CON = 0b00000110; //Tmr2 on, prescale 16, for 244Hz PWM
PortA = 0;
PortB = 0;
PortC = 0;
UART1_Init(9600);
// UART1_Write_Text("Hello !");
alarm_off = 0;
alarm_timer = 0;
ADC_channel = 0;
display_mode = 0;
while(1)
{
batt_ok = (Battery_ADC >= battery_levels[0]);
//**************************************************************************************
if (display_mode == 0)
{
if (~(batt_ok)) display_data.F1 = blink;
else {if (~(CHARGING)) display_data.F1 = blink_long; else display_data.F1 = (Battery_ADC >= battery_levels[1]);}
display_data.F0 = (Battery_ADC >= battery_levels[2]);
display_data.F3 = (Battery_ADC >= battery_levels[3]);
if ((mos_hot)|(T_mos_res>80000)) display_data.F2 = blink; else display_data.F2 = (Battery_ADC >= battery_levels[4]);
if ((rec_hot)|(T_rec_res>80000)) display_data.F5 = blink; else display_data.F5 = (Battery_ADC >= battery_levels[5]);
if ((coil_hot)|(T_coil_res>80000)) display_data.F4 = blink; else display_data.F4 = (Battery_ADC >= battery_levels[6]);
if ((bat_hot)|(T_bat_res>80000)) display_data.F7 = blink; else display_data.F7 = (Battery_ADC >= battery_levels[7]);
if (~(FAN)) display_data.F6 = blink; else display_data.F6 = (Battery_ADC >= battery_levels[8]);
}
if (display_mode == 1)
{
if (blink_long) display_data = 0b00000100; else TemperatureGauge(T_mos_res);
}
if (display_mode == 2)
{
if (blink_long) display_data = 0b00100000; else TemperatureGauge(T_rec_res);
}
if (display_mode == 3)
{
if (blink_long) display_data = 0b00010000; else TemperatureGauge(T_coil_res);
}
if (display_mode == 4)
{
if (blink_long) display_data = 0b10000000; else TemperatureGauge(T_bat_res);
}
//**************************************************************************************
PORTB = display_data;
//**************************************************************************************
if ( (~(BUTTON)) && (~(button_pressed)) )
{
Delay_ms(10);
if (~(BUTTON))
{
display_mode ++;
if (display_mode > 4) display_mode = 0;
blink_long = 1;
blink_long_timer = 0;
button_pressed = 1;
}
}
if (BUTTON) button_pressed = 0;
//**************************************************************************************
if (count_resistance > 0)
{
if (count_resistance == 1)
{
//if (T_mos_ADC > 228) T_mos_res = 0; else
//{flt_val = 255.0 / T_mos_ADC; flt_val = flt_val + (-1); T_mos_res = 10000.0 / flt_val;}
T_mos_res = Get_resistanse(T_mos_ADC);
}
if (count_resistance == 2)
{
//if (T_rec_ADC > 228) T_rec_res = 0; else
//{flt_val = 255.0 / T_rec_ADC; flt_val = flt_val + (-1); T_rec_res = 10000.0 / flt_val;}
T_rec_res = Get_resistanse(T_rec_ADC);
}
if (count_resistance == 3)
{
//if (T_coil_ADC > 228) T_coil_res = 0; else
//{flt_val = 255.0 / T_coil_ADC; flt_val = flt_val + (-1); T_coil_res = 10000.0 / flt_val;}
T_coil_res = Get_resistanse(T_coil_ADC);
}
if (count_resistance == 4)
{
//if (T_bat_ADC > 228) T_bat_res = 0; else
//{flt_val = 255.0 / T_bat_ADC; flt_val = flt_val + (-1); T_bat_res = 10000.0 / flt_val;}
T_bat_res = Get_resistanse(T_bat_ADC);
}
count_resistance = 0;
}
//**************************************************************************************
fan_speed = 0;

if (T_mos_res > TEMP_LO) fan_task = 0;
else if (T_mos_res < TEMP_HI) fan_task = 255;
else fan_task = Fan_power(T_mos_res);//(((INITIAL_FAN_SPEED - 255)*(T_mos_res - TEMP_HI))/(TEMP_LO - TEMP_HI)) + 255;
if (fan_task > fan_speed) fan_speed = fan_task;
if (T_rec_res > TEMP_LO) fan_task = 0;
else if (T_rec_res < TEMP_HI) fan_task = 255;
else fan_task = Fan_power(T_rec_res);//(((INITIAL_FAN_SPEED - 255)*(T_rec_res - TEMP_HI))/(TEMP_LO - TEMP_HI)) + 255;
if (fan_task > fan_speed) fan_speed = fan_task;
if (T_coil_res > TEMP_LO) fan_task = 0;
else if (T_coil_res < TEMP_HI) fan_task = 255;
else fan_task = Fan_power(T_coil_res);//(((INITIAL_FAN_SPEED - 255)*(T_coil_res - TEMP_HI))/(TEMP_LO - TEMP_HI)) + 255;
if (fan_task > fan_speed) fan_speed = fan_task;
if (T_bat_res > TEMP_LO) fan_task = 0;
else if (T_bat_res < TEMP_HI) fan_task = 255;
else fan_task = Fan_power(T_bat_res);//(((INITIAL_FAN_SPEED - 255)*(T_bat_res - TEMP_HI))/(TEMP_LO - TEMP_HI)) + 255;
if (fan_task > fan_speed) fan_speed = fan_task;
if (~(CHARGING)) fan_task = CHARGE_FAN_SPEED; else fan_task = 0;
if (fan_task > fan_speed) fan_speed = fan_task;
if (~(FAN)) fan_task = DPH_COOLING_FAN_SPEED; else fan_task = 0;
if (fan_task > fan_speed) fan_speed = fan_task;
CCPR1L = fan_speed;
//***************************************************************************************
if (T_mos_res < TEMP_AL_ON) mos_overH = 1;
if (T_mos_res < TEMP_HI) mos_hot = 1;
if (T_mos_res > TEMP_AL_OFF) { mos_overH = 0; mos_hot = 0;}
if (T_rec_res < TEMP_AL_ON) rec_overH = 1;
if (T_rec_res < TEMP_HI) rec_hot = 1;
if (T_rec_res > TEMP_AL_OFF) { rec_overH = 0; rec_hot = 0;}
if (T_coil_res < TEMP_AL_ON) coil_overH = 1;
if (T_coil_res < TEMP_HI) coil_hot = 1;
if (T_coil_res > TEMP_AL_OFF) { coil_overH = 0; coil_hot = 0;}
if (T_bat_res < TEMP_AL_ON) bat_overH = 1;
if (T_bat_res < TEMP_HI) bat_hot = 1;
if (T_bat_res > TEMP_AL_OFF) { bat_overH = 0; bat_hot = 0;}
overheat = mos_overH | rec_overH | coil_overH | bat_overH;
//***************************************************************************************
POW_CONT = ( (POW_SW) && (~(alarm_off)) );
if ( (~(POW_SW)) && (batt_OK) && (~(overheat)) ) alarm_off = 0;
//***************************************************************************************
if (send_uart)
{
send_uart = 0;
//{WriteInt(T_mos_res); UART1_Write_Text("; "); WriteInt(fan_speed); UART1_Write('r');}
Display();
}
}
}

Параметр для индикации определяется значением переменной display_mode.

При 0 — отображается шкала напряжения. Иначе — перемигиваются шкала температуры и индикатор выбраного узла.

Для измерения температуры используются NTC термисторы на 10к и характеристикой B3600. Он включен последовательно с резистором на 10к. Общая точка их соединения — подключается к входу МК.

Сопротивление термистора вычисляется по формуле

resistance = REF_VALUE / ( (ADC_RECOLUTION / ADC_value) — 1), где

REF_VALUE — сопротивление постоянного резистора;

ADC_RECOLUTION — максимальное значение АЦП;

ADC_value — поточное значение АЦП;

Если постоянный резистор подключить на сторону минуса, а термистор на плюс, формула примет вид:

resistance = REF_VALUE * ( (ADC_RECOLUTION / ADC_value) — 1)

Зная сопротивление термистора — вычисляем температуру:

temperature = ((BETA * DEF_TEMP) / (BETA + (DEF_TEMP * log(resistance / DEF_RES)))) — 273, где

BETA — характеристика термистора, в даном случае 3600;

DEF_TEMP — температура по умолчанию, 25.0 + 273.15;

DEF_RES — сопротивление при температуре по умолчанию, 10000 Ом

Правда, в моем случае — PICу оказалось не по силам считать температуру, так что в моей программе все установки на срабатывание сигналов перегрева и регулировки скорости вентилятора — привязаны к сопротивлению термисторов.

Хотелось бы еще обратить внимание на ШИМ микросхему XL4001. Она выдерживает до 40В на входе, может работать как стабилизатор тока. Из минусов — ключ на биполярнике и, соответственно, нагрев при нагрузке более 1А. я ее успешно применяю для питания микроконтроллеров и как драйвер светодиодов в автомобильной технике.

Задняя крышка

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Здесь расположен сетевой разьем, вентилятор Sunon, и USB преобразователь интерфейса преобразователя. Добавлено крепление разьема USB-B.

Передняя панель

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Использованы два тумблера, одна кнопка и эти клеммы.

Пульт управления модуля DPH пришлось чуть укоротить. Здесь еще видно плату индикации.

Выкройка отверстий нарисована в Corel Draw. Резка пластика произведена лазером на этом ЧПУ.

Блок питания AC-DC я использовал на 24В 12,5А

На него — уже есть обзор от Kirich

Y-конденсаторы — переехали на разьем питания.

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Добавлен разьем 3.96, были перенесены на противоположную сторону диодный мост и выходные конденсаторы, чтобы все поместилось в корпус.

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

В моем экземпляре радиатор силовых транзисторов не был соединен ни с чем. Сами же силовые транзисторы — в пластиковых корпусах. Я соединил радиатор с минусом, иначе из за помех контроллер заряда постоянно включался на заряд.

Общая компоновка

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Между блоком питания и аккумуляторами — на уголках висит плата зарядки. Она обеспечивает заряд батареи током 2,4А. Отдельным тумблером можно понизить напряжение заряда до, примерно, 3,7В на банку, для лучшей сохранности последних. Если ожидается длительное использование прибора в автономном режиме — аккумулятор заряжается на полную.

Контроллер заряда — микросхема CN3765. Вот на нее обзор. Я их в свое время брал на ТаоБао. Ссылка — в обзоре.

Плата зарядки

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Блок питания с автономным режимом, на основе модуля DPH5005, DIY

Медные лепестки находятся в потоке от вентилятора. Охлаждения — хватает.

На платах использованы штекера и розетки XH2.54

угловые штекера XH2.54,

обжатые провода с гнездами

Для сильнотоковых цепей использованы разъемы XT30 и ХТ60

При 50Вт нагрузки от аккумулятора, напряжение на банках сразу же упало до 4 Вольт. Они низкоточные и, видимо, более 3А — для них многовато. Но, до напряжения 3В на банку — батарейка протянула час и 10 мин. Потом плата управления отключила преобразователь, и напряжение плавно поднялось до 3,6В. Еще при 5 Вт нагрузки — аккумулятор тянул 20мин, дальше я включил зарядку.

Часовой тест на 100Вт (больше пока нечем нагрузить) — тоже успешен. Оценить нагрев полупроводниковых компонентов не получилось, так как при нагрузке более 3,5А модуль DPH включает свой вентилятор, следовательно плата управления включила на малые обороты и вентилятор корпуса. Так что радиатор выпрямителя был абсолютно холодный. Чуть теплыми были радиатор силовых транзисторов, магнитопровод трансформатора и дроссель, но все равно менее 55 градусов.


СМОТРИ ТАКЖЕ

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *