Регулятор мощности. Регулировка задержки таймера по АЦП

Обсуждаем контроллеры компании Atmel.
Ответить
turion
Родился
Сообщения: 3
Зарегистрирован: Пт янв 10, 2014 11:03:27

Регулятор мощности. Регулировка задержки таймера по АЦП

Сообщение turion »

Доброго времени суток.
Решил спаять фазовый регулятор мощности на AVR МК. Программирую в CVAVR. Не могу понять в чем проблема. Я в программировании новичок, строго не судите за код. Принцип работы думаю понятен, пропускаем через симистор часть полуволны, в зависимости от требуемой мощности. Так вот в протеусе собрал схемку с кнопкой, диодом, потенциометром и индикатором.
Для наглядности работы таймера я нажимаю кнопку (имитирую начало полуволны и соответственно запускается таймер, значение задержки которого мы задаем сами в регистр OCR1A). Как только таймер отсчитал нужное значение зажигаем диод на пол секунды. На счет задержки в обрабодчике прерывания это только для эксперимента работоспособности в протеусе. Задержку выставить получается при использовании кнопки. Т.е. я просто тики с определенным шагом на нажатие доп. кнопки увеличиваю или уменьшаю другой кнополчкой. Диод зажигается через разные промежутки времени, в зависимости от того как мы зададим. А вот с использованием АЦП не получается. По индикации видно, напряжение показывает. А диод в любом случае сразу загорается после нажатия кнопки и задержка не выставляется. Буд-то прерывание по совпадению таймера срабатывает еще от чего-то.
Задержку я формировал так:
Умножал значение, которое приходит в регистр ADCW 0-1023 на коэффициент 20. Получается при изменении напряжения потенциометром от 0 до 5В получали задержку от 0 до 20460 и это заметно на глаз. Может первый таймер с АЦП конфликтуют, или тактирование от общего источника не возможно? Уже не знаю что пробовать.
Буду очень благодарен за любую помощь.

#include <mega8.h>
#include <delay.h>
#include <stdio.h>

unsigned char i;
volatile char b; // переменная для задачи задержки через АЦП регистра совпадения

#define ADC_VREF_TYPE ((0<<REFS1) | (1<<REFS0) | (0<<ADLAR)) // выбор опорного напряжения - комбинация первых двух битов,
// последний бит - определяет как результат преобразования запишется в регистры ADCL и ADCH

interrupt [EXT_INT1] void ext_int0_isr(void)
{
#asm("cli")
OCR1A=b; //выставили задержку
TCCR1B=(1<<CS12); // предделитель 256, а по умолчанию МК 1 МГц
TIMSK=(1<<OCIE1A); //разрешение прерывания по совпадению
#asm("sei")
}

interrupt [TIM1_COMPA] void timer1_compa_isr(void) //преравание по совпадению таймера
{
#asm("cli")
PORTD.1=1;
delay_ms(500); //длительность импульса на открытие симистора
PORTD.1=0;
TCNT1=0; // если удалить эту строчку, то первое прерывание сработает согласно задержке в регистре
// совпадения, а следущая аж через ~25 секунд вместо 4х
TCCR1B &= ~((1<<CS12) | (1<<CS10) | (1<<CS11)); //инвертировали биты, т.е. остановили таймер, чтобы он не считал только один раз
#asm("sei")
}

static flash unsigned char display[] = { //индикация
(0b00111111), // 0
(0b00000110), // 1
(0b01011011), // 2
(0b01001111), // 3
(0b01100110), // 4
(0b01101101), // 5
(0b01111101), // 6
(0b00000111), // 7
(0b01111111), // 8
(0b01101111), // 9
};

void ind_volt(unsigned char volt) //вывод на семисегментный индикатор одного первого числа
{
PORTB=display[volt];
delay_ms(5);
}

unsigned int read_adc(unsigned char adc_input) //чтение с ножки напряжения и кодирование этого напряжения диапазонов 0-5В в число 0-1023
{
ADMUX=adc_input | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC); // запуск начала преобразования
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF); // Флаг прерывания от АЦП. Бит устанавливается, когда преобразование закончено
return ADCW; //возвращаем результат измерения напряжения в диапазаоне 0-1023
}


void main(void)
{

PORTB=0x00;
DDRB=0b01111111;

PORTC=0x00; //обнулим на всякий случай порт
DDRC=0x00; //настраеваем порт как вывод, т.е. будем выводить от МК 5В

DDRD=0b00000010; //настраиваем порт как вход, т.е. будем считывать сигнал из вне и определять логический 0/1
PORTD=0b11111101; /*подключаем внутренние подтягивающие резисторы к выводам порта D/
(0-высокоимпедансное состояние, 1-подтягивающий резистор) */

MCUCR=0b00001100; // прерывание по восходящему фронту
GICR=0b10000000; // прерывание на int1

#asm("sei") //разрешаю глобально прерывания

// Read the AD conversion result
ADMUX=ADC_VREF_TYPE; //
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0); // (1<<ADEN)-АЦП включен,
// (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0)- Тактовая частота АЦП СК/64 (т.е. 125 кГц при частоте МК 8МГц)

while (1)
{
read_adc(5);
b = ADCW*20; // будем изменять задержку в пределах 0-20000 тактов (20000/1023=19.55)

for(i=0; i<200; i++) // ind_volt(ADCW*0.0049);
{
ind_volt(ADCW*0.0049); // 5/1023=0.0049
}

//delay_ms(1000);

}
}
Вложения
12345.JPG
(111.59 КБ) 581 скачивание
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Регулятор мощности. Регулировка задержки таймера по АЦП

Сообщение a_skr »

volatile char b;

С размером переменной, для начала, напутали.
turion
Родился
Сообщения: 3
Зарегистрирован: Пт янв 10, 2014 11:03:27

Re: Регулятор мощности. Регулировка задержки таймера по АЦП

Сообщение turion »

Елки палки!!! Спасибо добрый человек! Как всегда мелочь. Причем на кнопках то я поставил volatile int b.
Ответить

Вернуться в «AVR»