Перейти к содержанию

Ловля перехода фазы через ноль - 50Гц на AVR


Гость химик

Рекомендуемые сообщения

Доброго времени. С помощью АЦП микроконтроллера AVR нужно измерять переменное напряжение сети, частотой 50 Гц. Для того чтобы поймать начало полупериода, сравнюю предидущее показание с последним.

Вот мой код:

//====================__чтeниe ADC__====================================================

unsigned int ADC_result(unsigned char adc_input){

  ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
  delay_us(10);
  ADCSRA|=0x40;					// Start the AD conversion
  while ((ADCSRA & 0x10)==0);
  ADCSRA|=0x10;
  return ADCW; 
  
} 

//======================= измеряем напряжение до трансформатора ================================
void Volt_Input(void){			  
							 
unsigned char counter_1;					  // счетчик колличества сэмплов
unsigned long int  buffer_A;				  // буффер для суммы сэмплов
unsigned int compar = 1;					  // предыдущее показание ADC 

  
ADC = ADC_result(0);					   // запускаем первое преобразование, вход PORTC.0

 while(compar == 0 && ADC >= 0){			  // ожидаем в цикле начало полупериода
compar = ADC;	 
ADC = ADC_result(0);						   
} 
 
 flag_A=1;									//  начало измеряемого полупериода
 counter_1=0;								 //  обнуляем счетчик колличества сэмплов
 buffer_A=0;								  //  обнуляем буффер суммы всех сэмплов
 while(flag_A){
ADC = ADC_result(0);					   // запускаем преобразование  
buffer_A = buffer_A + ADC;
counter_1++;							   // увеличиваем счетчик на 1
  if(compar >= 0 && ADC == 0){			 // если полупериод закончился - то
	 flag_A = 0;						   // конец измеряемого полупериода
	 resultat = buffer_A / counter_1;	  // получаем среднее значение ADC 
		}else{							 // если не закончился
		  compar = ADC;					// сохраняем предыдущее состояние
		 };
}


 
 
 
 resultat = resultat * 0.8;				   // коеффициент 0,8 приводит значение 1023 равно 818 вольт
 
 Data_Write(1,resultat);	  

}



//====================================== Main =====================================
void main(void){

PORTB=0x00;
DDRB=0x2C;

PORTC=0x00;
DDRC=0x20;

PORTD=0x00;
DDRD=0x7F;

TCCR0=0x00;
TCNT0=0x00;



// ADC initialization
// ADC Clock frequency: 187,500 kHz
// ADC Voltage Reference: AVCC pin
ADMUX=0x40;
ADCSRA=0x86;

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 750,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x52;
SPSR=0x00;

while (1){

 Volt_Input();			 // измеряем напряжение на входе


 PORTB.2=~PORTB.2;  // мигаем светодиодом

 delay_ms(500);	  

  };
}

 

В итоге и вжелезе, и в протеусе на дисплее один раз в несколько секунд (от 3 до 6 сек) появляется относительно правильное показание, а после, приблизительно 6 - 12 замеров на дисплее нули.

Подозреваю, что в этих замерах за начало полупериода принимается конец полупериода :smile: . Или сэмплирование происходит МЕЖДУ ПОЛУПЕРИОДАМИ.

 

Может быть можно как-то по другому ловить переход, не используя внешние прерывания?

 

P.S. Метод измерения среднеквадратичный, но пока что хочу добиться результата без интегрирования.

Ссылка на комментарий
Поделиться на другие сайты

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

1. Чтобы ловить начало полупериода нужно иметь четкую привязку устройства к фазе сетевого напряжения (опорный сигнал), как это схемотехнически реализовано?

2. Для чего вообще ловить это начало? Может просто измерять постоянное напряжение после грамотно сделанного выпрямителя на ОУ?

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

Извините, если туплю. Интересны цели разработки.

Изменено пользователем metrolog
Ссылка на комментарий
Поделиться на другие сайты

ТЗ - измерение напряжения сети в двох точках, смещенных по фазе. Детекторы фазы на внешних прерываниях делать не хочется.

Замысел - делаю мощный стабилизатор с защитой от перенапряжения. Точность нужна 1-2%. Поетому способ измерения должен быть

среднеквадратичный за полупериод.

Внешние прерывания не хочу использовать, так как контроллер Atmega8 и выводы внешних прерываний используются для других целей. Конечно если выхода не найдем, буду переходить на Atmega16 или подобный, для увеличения лапок и тяговой силы.

Ссылка на комментарий
Поделиться на другие сайты

Внешние прерывания не хочу использовать, так как контроллер Atmega8 и выводы внешних прерываний используются для других целей. Конечно если выхода не найдем, буду переходить на Atmega16 или подобный, для увеличения лапок и тяговой силы.

ИМХО, без внешних прерываний не обойтись, ибо без них не знаешь что (вернее "когда" :smile: ) творится на входе.

Ссылка на комментарий
Поделиться на другие сайты

ИМХО, без внешних прерываний не обойтись, ибо без них не знаешь что (вернее "когда" :smile: ) творится на входе.

Ну как то ж люди делают, с помощью таймера :smile:

Изменено пользователем химик
Ссылка на комментарий
Поделиться на другие сайты

Ну как то ж люди делают. :smile:

Кто этот гений? Это то же самое как получить следствие без причины :smile:

Чтобы оперировать с сигналом (просчитать, измерить, отрезать) его нужно иметь в наличии, даже с таймером.

Ведь таймеру нужна стартовая точка?

Изменено пользователем metrolog
Ссылка на комментарий
Поделиться на другие сайты

Может поможет решить проблему

 

_https://kazus.ru/forums/showthread.php?t=7572&page=5

Из ссылки:

C AVR не пробовал, а на PIC подаю 220V прямо на порт через два резистора по 2 Mom(последовательно). Ноль ловит железно. Код- из примера микрочиповского. Прерывания не использую.

 

//небольшая задержка, для стабилизации питания

for (count=0; count<60; count++) {

while (in_sinhro==0);

while (in_sinhro==1);

}

 

do {

// ждем на входе положительную полуволну

while (in_sinhro==1);

//положительная полуволна была, запускаем программу

prj1();

//ждем перехода через 0

while (in_sinhro==0);

//prj2

prj2();

} while (1);

Изменено пользователем if33
Ссылка на комментарий
Поделиться на другие сайты

  • 3 месяца спустя...
Внешние прерывания не хочу использовать, так как контроллер Atmega8 и выводы внешних прерываний используются для других целей. Конечно если выхода не найдем, буду переходить на Atmega16 или подобный, для увеличения лапок и тяговой силы.

 

Ув. тёзка, получше надо изучать мат.часть у ATmega8, в его родном даташите прямо указано наличие компаратора, его входы заведены на выводы 12 (вход 0) и 13 (вход 1), он вызывает аппаратное прерывание 0х010 (десятичное 17). Для его компаратора достаточно на один вход подать переменное 2х50Гц с ограничением на уровне 4,3...4,7В, на другой вход подать опорное примерно 0,5,,,0,8В и далее по прерыванию делай с ним что нужно, к примеру запустить таймер отрабатывающий нужную задежрку, после его отработки включить симистор (если нужно сделать ФИМ для лампы накаливания). Весь код этого обслуживания займет примерно сотню-другую байт в откомпилированном коде (предполагается что применяется ассемблер).

Ссылка на комментарий
Поделиться на другие сайты

  • 5 месяцев спустя...

Для химика, возможно это уже не интересно, а для других может пригодится...

Предложенные варианты имеют право на жизнь, но к сожалению в нашем "грязном" мире не все так "гладко". Я имею ввиду всем известные помехи в сети. Искажают оные "правду матку" о "нуле" жуть.

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

Так - что будьте внимательны с этим.

Да, кому очень надо с этим разобраться, поищите статью с примерами кода в журнале "Электрик" 4 номер 2012 год ст.72-76. Там довольно доходчиво и просто описано на примере акустического выключателя на МК фирмы PIC.

Ссылка на комментарий
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...