Проблема со стабилизатором напряжения | Крымский форум

Проблема со стабилизатором напряжения

  • Добро пожаловать на форум! Рады видеть вас здесь! Зарегистрируйтесь или Войдите в аккаунт, чтобы иметь полный доступ к площадке!

svip

Местный житель
Ветеран
Сообщения
1,535
Реакции
9
Репутация
13
Стабилизатор собран. Работает, но проблематично. Проверял в нагрузке до 4 киловат все работает. но время от времени в режиме переключения обмоток сгорает один из предохранителей, показанных на рисунке красным.

В чем проблема? Возможно неправильно организовано переключение в прошивке?

Код
void FU(unsigned int v_in)
{
if (v_in<100) {fout=0b00000000; er=1;}
else if (v_in<160) {fout=0b00000001; er=0;}
else if (v_in<180) {fout=0b00000010; er=0;}
else if (v_in<200) {fout=0b00000100; er=0;}
else if (v_in<220) {fout=0b00001000; er=0;}
else if (v_in<240) {fout=0b00010000; er=0;}
else if (v_in<260) {fout=0b00100000; er=0;}
else {fout=0b00000000; er=1;}
PORTC=fout;
}



Возможно проблема в деталях? Уже перерыл все возможные проблемы, не могу понять из-за чего возникает такой ток? тем более при малых нагрузках (100-200 Ватт), в то время как при больших нагрузках работает.

Проблема именно во время переключения обмоток, но не постоянно дефект проявляется, а примерно 1 раз на 20-50 переключений.

Использованы симисторы ВТА 40-800, оптика MOC3061
[attachmentid=8940]

P.S. Надеюсь поможете разобраться с проблемой
 

Вложения

  • barier.png
    barier.png
    115.6 KB · Просмотры: 4
Контролируй переход синусоиды через 0 тогда и включай.
 
Да, походу дело в управлении. Один тиристор включается в тот момент когда предыдущий еще не выключился.
Надо следить за переходом через 0 и после этого переключать.
Причем этот переход надо ловить не у напряжения а у тока нагрузки.
 
сначала снимать питание, выдерживть паузу в долю секунды, подавать с другой обмотки.
 
Проблемы возникают при малых мощностях из-за индуктивности трансформатора. Её влияние на общий ток нагрузки становится большим и при переходе сетевого напряжения через 0, ток еще не равен 0. Соответственно, тиристор не успевает закрытся перед тем как откроется другой.

Чем вообще переход через 0 измеряется, приведите всю схему.
 
Цитата(gccrim @ 17 Декабря, 2008, 15:13)
Один тиристор включается в тот момент когда предыдущий еще не выключился.


Получается банальный коротыш.
 
в оптике MOC3061 встроенный детектор перехода через ноль. Да я тоже подозреваю что коротят две обмотки, но пробовал во
void FU(unsigned int v_in) перед переключением отключать все тиристоры (PORTC=0b00000000;) и делать небольшую задержку - не помогло. Думаю дальше.
 
Цитата(svip @ 18 Декабря, 2008, 10:37)
в оптике MOC3061 встроенный детектор перехода через ноль.


Это не совсем тот детектор, который нужен. "Zero Crossing Circuit" который там стоит, просто не позволяет включить тиристор, при падении напряжения на нем более 20В.

В вашем случае, надо мерять переход через 0 ТОКА нагрузки, а не напряжения! Соответственно "Zero Crossing Circuit" абсолютно бесполезен.

Если нет желания городить детектор тока, то надо просто делать паузу между переключениями. Длительность паузы должна равнятся как минимум длительности 2-х полупериодов сетевого напряжения( 2*10mS для 50Hz), чтобы гарантированно все тиристоры выключились перед включением.

Я бы написал так:

void FU(unsigned int v_in)
{
static unsigned char f_out_temp = 0b00000000;

if (v_in<100) {fout=0b00000000; er=1;}
else if (v_in<160) {fout=0b00000001; er=0;}
else if (v_in<180) {fout=0b00000010; er=0;}
else if (v_in<200) {fout=0b00000100; er=0;}
else if (v_in<220) {fout=0b00001000; er=0;}
else if (v_in<240) {fout=0b00010000; er=0;}
else if (v_in<260) {fout=0b00100000; er=0;}
else {fout=0b00000000; er=1;}

if (f_out_temp != f_out) //проверка, изменился ли f_out
{
PORTC = 0b00000000; //Выключим все

Delay(20); //20mS пауза

PORTC = f_out; //включим необходимый

f_out_temp = f_out; //Сохраним текущее значение как прерыдущее
}

}
 
gccrim спасибо попробую с такой паузой сделать.
 
Да, еще тут пришло на ум. Неплохо бы сделать небольшой гистерезис для порогов переключения.
Сейчас, если напряжение 180В то включена одна обмотка, а если 179 - то другая.
Получается, что при небольших колебаниях напряжения около 180В девайс будет постоянно включать то одну то другую обмотки.
Лучше сделать так- переключение на 1-ю при Uin<(180-dU), а переключение обратно на вторую при Uin>(180+dU).
dU взять примерно 2..3В.
 
gccrim
да так и хотел сделать, но, как не стыдно сказать, ничего толком не получилось. Или мозги кипели или еще что - хз. но так я и не догнал как сделать плавающую точку переключения.
 
Цитата(svip @ 19 Декабря, 2008, 12:29)
но так я и не догнал как сделать плавающую точку переключения


Примерно так:

void FU(unsigned int v_in)
{
static unsigned char f_out_temp = 0b00000000;
static unsigned int v_in_prev = 0; //предыдущее значение v_in

const signed int dU_const = 2; //величина гест.
signed int dU;

//Выбираем в какую сторону сдвигать точку перекл.
//В зависимости от того, куда меняется входное напряжение
if (v_in_prev < v_in) dU = dU_const; else dU = -dU_const;


if ( v_in < 100 ) {fout=0b00000000; er=1;}
else if ( (signed int)v_in < (160+dU) ) {fout=0b00000001; er=0;}
else if ( (signed int)v_in < (180+dU) ) {fout=0b00000010; er=0;}
else if ( (signed int)v_in < (200+dU) ) {fout=0b00000100; er=0;}
else if ( (signed int)v_in < (220+dU) ) {fout=0b00001000; er=0;}
else if ( (signed int)v_in < (240+dU) ) {fout=0b00010000; er=0;}
else if ( (signed int)v_in < (260+dU) ) {fout=0b00100000; er=0;}
else {fout=0b00000000; er=1;}

v_in_prev = v_in; //Сохр. текущее значение как предыдущее

if (f_out_temp != f_out) //проверка, изменился ли f_out
{
PORTC = 0b00000000; //Выключим все

Delay(20); //20mS пауза

PORTC = f_out; //включим необходимый

f_out_temp = f_out; //Сохраним текущее значение как прерыдущее
}

}
 
Отлично, только не понял зачем в
Код
else if ( (signed int)v_in < (160+dU) ) {fout=0b00000001; er=0;}

использовать Код
signed int
? тут то все положительное.
 
Затем, чтобы компиллер не генерил варнинги мол "сравниваем знаковые и беззнаковые переменные".

Судя по синтаксису gcc используется?
 
да. в cvAVR писал
 
НЕ прокатил этот вариант. часа два проработал и сдох один из предохранителей. (пробовал разные варинаты задержки) - все равно сдыхает. Нужно будет нарисовать всю схему и прошивку, может где напортачил.
 
Задержку 20mS сам делаешь или библиотечную функцию используеш? Лучше делать самому, на любом из свободный таймеров, а не на NOP-ах.

Еще смотреть на какой частоте запущен контроллер и от чего тактируется.
Какие фьюс биты прошиваются?
 
задержку делал библиотечной delay_ms()
частота 1 (или 4) МГц от внутреннего RC.
фьюзы никакие не прошивал, кроме отключение JTAG (у меги 16)
 
О... ну так с этого и надо было начинать.

Частоту тактирования надо устанавливать однозначно, это ведь не операционка.

Библиотечные delay_ms() просто выполняют некоторое кол-во NOPов, при этом полагаясь на "какую-то" константу которая должна соответствовать тактовой частоте. Что то вроде:
#define Fclk 1200000
в Libr_Name.h файле.

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


Что касается фьюс битов, то хоть они и называются битами, физически записываются в контроллер побайтово. И если их писать, то устанавливать надо все. Иначе ХЗ что запишится на место неустановленных.
Тем более что фьюсы определяют кучу основных параметров, в том числе и источник тактирования, коэффициент деления тактовой, вотчдог и пр.

Вообщем, нет никакой гарантии, что 20mS пауза действительно длится именно это время.
 
Цитата
Частоту тактирования надо устанавливать однозначно, это ведь не операционка.

так установлена 1 мгц. пробовал и 4 мгц тоже.

прошивал avr studio. И фьюзы зашиты те которые были зашиты при производстве, менял только JTAG(Отключил), и поставил тактовую частоту (1 мгц + 64ms).

Вот вся прошивка (тут без Ваших изменений)
Цитата
#include <mega16.h>
#include <delay.h>
#include <stdlib.h>
#include <math.h>

#define ADC_VREF_TYPE 0x20

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>


// Declare your global variables here

unsigned int i;
unsigned int f1=0;
unsigned int f2=0;
unsigned int v_in;
unsigned int v_out;
unsigned int volt;
unsigned char fout;
unsigned char er=0;
unsigned int Vpr=0;



void lcd_clear_my()
{
lcd_gotoxy(6,0);
lcd_putsf(" ");
lcd_gotoxy(6,1);
lcd_putsf(" ");
}

void in(unsigned int v_in)
{
int temp[4];
if (f2>=10){lcd_clear_my();f2=0;}
else f2++;
//lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("INPUT ");
itoa(v_in,temp);
lcd_puts(temp);
lcd_putsf(" VOLT");
}


void out(unsigned int v_out)
{
int temp[4];
if (f1>=10){lcd_clear_my();f1=0;}
else f1++;
lcd_gotoxy(0,1);
if (er==1) lcd_putsf("OUT OF 140-260");
else
{
itoa(v_out,temp);
lcd_putsf("OUTPUT ");
lcd_puts(temp);
lcd_putsf(" VOLT");
}
}


void FU(unsigned int v_in)
{
if (v_in<100) {fout=0b00000000; er=1;}
else if (v_in<160) {fout=0b00000001; er=0;}
else if (v_in<180) {fout=0b00000010; er=0;}
else if (v_in<200) {fout=0b00000100; er=0;}
else if (v_in<220) {fout=0b00001000; er=0;}
else if (v_in<240) {fout=0b00010000; er=0;}
else if (v_in<260) {fout=0b00100000; er=0;}
else {fout=0b00000000; er=1;}
PORTC=fout;
}

unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}



void main(void)
{
PORTA=0x00;
DDRA=0x00;

PORTB=0x00;
DDRB=0x00;

PORTC=0x00;
DDRC=0x00;

PORTD=0x00;
DDRD=0xff;

TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;
MCUCSR=0x00;

TIMSK=0x00;

ACSR=0x80;
SFIOR=0x00;

ADMUX=ADC_VREF_TYPE & 0xff;

ADCSRA=0x81;

lcd_init(16);

while (1)
{
v_in=0;
v_out=0;

for (i=0;i<100;i++)
{
volt=read_adc(1);
Vpr=(float)volt;
v_in=fmax(v_in,Vpr);
}
if (v_in > 126) v_in=(v_in-127)*3.43678;
else v_in=0;

for (i=0;i<100;i++)
{
volt=read_adc(0);
Vpr=(float)volt;
v_out=fmax(v_out,Vpr);
}
if(v_out>126) v_out=(v_out-127)*3.43678;
else v_out=0;
in((int)v_in);
out((int)v_out);
FU((int)v_in);
};
}


Схему нарисую - скину, нужно вспоминать что там да как делал.
 
Назад
Сверху