АЦП на attiny13

Обсуждаем контроллеры компании Atmel.
Ответить
Lww
Открыл глаза
Сообщения: 76
Зарегистрирован: Пт сен 09, 2016 23:08:30

АЦП на attiny13

Сообщение Lww »

Здравствуйте, уважаемые форумчане.
Уже 2 дня бьюсь над проблемой, почему не работает правильно код на attiny13.
Суть в том, что тини берет значение напряжения с 3 входов ADC0, ADC1 и ADC2, преобразует их в ацп и в зависимости от того, какое наибольшее, включает соответствующий выход PB0, PB1 или PB3, а остальные выключает.
1) В прерывании ацп (каждые ~10 мкс) происходит запись в переменную и переключение пина ацп, т.е. ADMUX++, а так же запуск нового преобразования.
2) По прерыванию таймера Т0 с предделителем 1024 (около 27мс) происходит сравнивание значений с ацп, выключение всех выходов и включение соответствующего наибольшему напряжению с ацп, после чего все значения с ацп обнуляются и оно заново набирает их.
Беда в том, что оно то работает, то не работает. На скрине например на ADC0 4.6в, самое большое из 3, но почему-то работает выход PB3, а должен PB0. Но если подергать туда-сюда, то начинает работать. Потом опять клинит.
Живая микросхема работает так же, как в симуляторе. Значит ошибка где-то в коде.
Никак не могу найти ошибку, проблема еще в том, что нет толкового отладчика, atmel studio не поддерживает usbasp.
Вот код:
Спойлер

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h>  //Для доступа к функции sei()
#include <avr/signal.h>     //Для доступа к макросу INTERRUPT

volatile uint8_t adcVal[3] = {0, 0, 0};
volatile uint8_t max = 0;
volatile uint8_t max1 = 0;

ISR(ADC_vect)
{
	uint8_t a = ADCH;
	if (a > adcVal[ADMUX - 32])						//если значение с ацп больше записанного, то записываем это значение 
	{
		adcVal[ADMUX - 32] = a;						
	}
	 
	if (ADMUX < 34)									//переключаем пин ацп на следующий
	{
		ADMUX++;
	} else 
	{
		ADMUX = 32;
	}	
	ADCSRA = ADCSRA | 0x40; //Устанавливаем разряд ADSC в регистре ADCSR, чтобы начать новое преобразование
}

ISR(TIM0_OVF_vect)
{	

	max = 0;
	if (adcVal[1]>adcVal[0]) max = 1;
	if (adcVal[2]>adcVal[1]) max = 2;				//Находим наибольшее напряжение
	
	if (max == max1)								//если наиб. напряжение=предыдущему периоду, то устанавливаем выход
	{		
		switch (max)
		{
			case 0:
			PORTB = 1;
			break;
			case 1: 
			PORTB = 2;
			break;
			case 2:
			PORTB = 8;
			break;
		}
	} else                                        //иначе отключаем все выходы
	{
		max1 = max;
		PORTB = 0;		
	}
	adcVal[0] = 0;									//обнуляем ацп каждый период
	adcVal[1] = 0;
	adcVal[2] = 0;

}

int main(void)
{		
	TIMSK0 = 2;
	TCCR0A = 0;
	TCCR0B = 0b00000101;
	ADMUX = 32;
	ADCSRA = 0b11001000;
	DDRB = 0b00001011;
	sei();
    /* Replace with your application code */
    while (1) 
    {		
    }
}
Изображение
Фьюзы:
CLKDIV8: 1
RSTDISBL: 0
CKSEL: 10
SUT: 10
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: АЦП на attiny13

Сообщение Ivanoff-iv »

а нужны ли такие сложности? с массивами..
нужны 3 переменные: одна для хранения значения, вторая для хранения номера, ну, и номер текущего опрашиваемого входа.
пробегаем входы с 0 по 2 (ADMUX=in+ADC_VREF_TYPE)
в прерывании сравнивам ADCW (или его часть) с хранимым значением, если ADCW больше - обновляем переменные значения и номера входа.
когда все входы опрошены, по данным из номера конфигурируем выходы, затем обнуляем переменную значения (переменная номера сама обновится в следующем цикле)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Lww
Открыл глаза
Сообщения: 76
Зарегистрирован: Пт сен 09, 2016 23:08:30

Re: АЦП на attiny13

Сообщение Lww »

Не, без массива никак. Ведь по переполнению таймера должны сравниваться сразу все 3 значения.
Ацп опрашивается тысячи раз в секунду. А таймер только 36 раз в секунду.
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5726
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: АЦП на attiny13

Сообщение >TEHb< »

У них УВХ одно на всех. Надо или холостую выборку канала делать, а потом измерение, либо резко уменьшать выходное сопротивление измерительной цепи, либо увеличивать время выборки. Но не факт, что причина в этом.
"Привет!" - соврал он.
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: АЦП на attiny13

Сообщение veso74 »

Код: Выделить всё

if ((adcVal[0] > adcVal[1]) & (adcVal[0] > adcVal[2]))
    max = 0;
  else if (adcVal[2] > adcVal[1])
    max = 2;
  else max = 1;
Изображение
metan
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Re: АЦП на attiny13

Сообщение metan »

veso74 писал(а):&
&& :)
veso74
Поставщик валерьянки для Кота
Сообщения: 1905
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: АЦП на attiny13

Сообщение veso74 »

[uquote="metan",url="/forum/viewtopic.php?p=4494874#p4494874"]... &&[/uquote]
Да, правильно. Спс. Утром рано, еще спим :P ...
А и с Bitwise AND работало на симуляцией ...
OKF
Это не хвост, это антенна
Сообщения: 1385
Зарегистрирован: Вт июн 07, 2011 08:03:18

Re: АЦП на attiny13

Сообщение OKF »

А в данном случае неважно что побитовое И, что логическое. Просто как то неаккуратненько.)
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15546
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: АЦП на attiny13

Сообщение BOB51 »

"пузырьки" с тремя (и более) значениями
:roll:
Ответить

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