Несколько каналов АЦП Atmega 88

Обсуждаем контроллеры компании Atmel.
Ответить
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Добрый день, подскажите пожалуйста, есть ряд непонятных вопросов по АЦП данного МК. Мне необходимо раз в 200 мкс опрашивать один из входов, пусть их будет 3 (2-1-0) и усреднять это значение по 3 выборкам.
Допустим три канала измеряют напряжение от 0 до 2,5В, подключен от внешний ИОН на 2,5В
Мое понимание:
Мультиплексором переключать каждые 200 мс по прерыванию таймера входа?
И как усреднять по выборкам?

Буду благодарен любой помощи.
Последний раз редактировалось Jman Ср авг 09, 2017 09:32:24, всего редактировалось 1 раз.
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

используй массивы (для настройки ацп одномерный (или один из столбцов двумерного) а для усреднения - двумерный(один столбец - один канал)), только таймер на 200/3 мс (к нужному каналу в срок вернётся).
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

По поводу усреднения, читаю например 3 канала дергая мультиплексор таймером по переполнению со значением 200мкс, суммирую, а потом делю на 3? Так нужно сделать?
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

делаешь массив 3х4 (3 — количество каналов, 4 = 1 3 — 1 настройка (то что в мух вписать после замера для включения след. канала) и 3 — количество замеров усреднения).
i и j счетчики, по первому переключаешь каналы, а по второму ячейки масива усреднения.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Эиком - электронные компоненты и радиодетали
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

А можете пример привести кода? Чет не пойму...

Добавлено after 2 hours 16 minutes 36 seconds:
Пытаюсь пока просто переключать каналы. Но что-то совсем не работает... Где я споткнулся?

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

volatile uint8_t adc_result[8];
volatile uint8_t input = 0; 

void ADC_init(void);

int main(void) {
	DDRB = 0xFF; 
	ADC_init();  
	sei(); 
	ADCSRA |= (1 << ADSC); 

	while (1) {

		if (adc_result[0] > 150) {
			PORTB = 0x01;
		} else if (adc_result[0] < 150) {
			PORTB = 0x00;
		}

		if (adc_result[1] > 150) {
			PORTB = 0x02;
		} else if (adc_result[1] < 150) {
			PORTB = 0x00;
		}
	}
	return 0;
}

ISR( ADC_vect ) {
	adc_result[input] = ADCH; 
	if (input < 8)
	input++;
	else
	input = 0;

	ADMUX |= input; 
	ADCSRA |= ( 1 << ADSC ); 
}

void ADC_init() {
    ADMUX |= (1 << ADLAR) | (1 << REFS0); 
	ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2); 
}
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Реклама
Вымогатель припоя
Сообщения: 522
Зарегистрирован: Чт янв 21, 2016 15:59:10

Сообщение ozonn »

если под усреднением вы понимаете нахождение среднего арифметического, то никакие массивы не нужны. Просто суммируете все замеры и потом делите на количество замеров
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

[uquote="ozonn",url="/forum/viewtopic.php?p=3158920#p3158920"]если под усреднением вы понимаете нахождение среднего арифметического, то никакие массивы не нужны. Просто суммируете все замеры и потом делите на количество замеров[/uquote]
и усреднять это значение по 3 выборкам.
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Вымогатель припоя
Сообщения: 522
Зарегистрирован: Чт янв 21, 2016 15:59:10

Сообщение ozonn »

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

.
.
buff = buff+ADCH;
.
.
.
res = buff/3;
.
.
.
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Помогите с настройкой АЦП пожалуйста. Выше код привел. Почему-то не работает.
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Вымогатель припоя
Сообщения: 522
Зарегистрирован: Чт янв 21, 2016 15:59:10

Сообщение ozonn »

[uquote="Jman",url="/forum/viewtopic.php?p=3158927#p3158927"]Помогите с настройкой АЦП пожалуйста. Выше код привел. Почему-то не работает.[/uquote]
вот тут собака порылась:

ADMUX |= input;

потому как:

7 | 0 = 7
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

ADMUX нужно сбросить? А как?
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Вымогатель припоя
Сообщения: 522
Зарегистрирован: Чт янв 21, 2016 15:59:10

Сообщение ozonn »

скажу честно, с 88-й дела не имел. Почитал бегло даташит и сходу не понял, как выбрать Single Conversion. В 8-й есть вит ADFR, который включает и отключает Free Running. В 88-й такого бита не нашел

Добавлено after 2 minutes 56 seconds:
[uquote="Jman",url="/forum/viewtopic.php?p=3158945#p3158945"]ADMUX нужно сбросить? А как?[/uquote]
записать в него нули, потом снова инкрементировать, как вы делаете с input.

просто вместо input инкрементируйте ADMUX, если он больше 7-ми, обнуляйте
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

можно и копить, но тогда результат заранее заказывать, а потом ждать придётся.
с кодом смогу помочь только завтра...
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Друг Кота
Сообщения: 9383
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Сообщение roman.com »

а что даёт усреднение по трём выборкам АЦП?
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

некоторое снижение случайной ошибки, вот например возьмём 10бит шим (младший разряд шумящий) сложим 2 замера и получим 11бит сигнал, младший шумящий - отсекаем его (/2) и получаем обратно 10бит сигнал, но уже стабильней.

Добавлено after 2 hours 59 minutes 28 seconds:
посмотрел настройки этой микры в адмух можно просто номер вода (от 0 по 7й) вписать (поэтому массив сдесь не нужен).
начальные настройки:

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

#include <mega88.h>
#include <delay.h>
#define ADC_VREF_TYPE 0xC0
volatile unsigned int A_adc[9];
...
// ADC initialization
// ADC Clock frequency: 250,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: Off, ADC3: On
// ADC4: On, ADC5: On
DIDR0=0x07;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA1;
ADCSRB&=0xF8;
.6;.
main{...}
этот код вызывать каждые 66мс (3 раза за 200мс)
он заполняет массив

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

{
static unsigned char n_zam=8;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
A_adc[n_zam]=ADCW;
//next conversion
n_imp++;
if (n_imp>8) n_imp=0;
ADMUX=(n_imp%3) | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
}
эта функция выдает среднее по 3м последним замерам по заданному входу

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

unsigned int read_3_adc(unsigned char adc_input)
{
if (adc_input<3) 
 {
 adc_input*=3;
 return ((A_adc[adc_input]+A_adc[adc_input+1]+A_adc[adc_input+2])/3);
 }else{return 0;};
}
основано на сгенерированном CVAVR коде, регистры и работа с ними подсмотрены в AB.
Последний раз редактировалось Ivanoff-iv Чт авг 10, 2017 08:13:40, всего редактировалось 1 раз.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

этот код вызывать каждые 66мс (3 раза за 200мс)
он заполняет массив
Этот код например можно подсунуть в ISR(TIMER0_OVF_Vect) ?
Тут правда 100мкс из кодвижна взял

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

ISR( TIMER0_OVF_vect )
{
	// 66 us oveflow
	TCNT0=BE;
}
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

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

Добавлено after 1 minute 25 seconds:
одно условие - не чаще чем время выполнения преобразования (кстати можно и в его вектор засунуть, просто я не хотел плодить прерывания)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Рабочее прерывание по завершению измерения с автосканированием 4х входов. Как это прикрутить к прерыванию по времени?
Я склеил, но это не правильно, чувствую.

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

ISR( TIMER0_OVF_vect )
{
	// 66 us oveflow
	TCNT0=BE;
	static unsigned char n_zam=8;
	// Wait for the AD conversion to complete
	while ((ADCSRA & 0x10)==0);
	ADCSRA|=0x10;
	A_adc[n_zam]=ADCW;
	//next conversion
	n_imp++;
	if (n_imp>8) n_imp=0;
	ADMUX=(n_imp%3) | (ADC_VREF_TYPE & 0xff);
	// Delay needed for the stabilization of the ADC input voltage
	delay_us(10);
	// Start the AD conversion
	ADCSRA|=0x40;
}



// ADC interrupt service routine
ISR (ADC_vect)
{
	static unsigned char input_index=0;
	// Read the AD conversion result
	adc_data[input_index]=ADCW;
	// Select next ADC input
	if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
	input_index=0;
	ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
	// Delay needed for the stabilization of the ADC input voltage
	_delay_us(100);
	ADCSRA|=(1<<ADSC); //ADCSRA|=0x40
}
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

во первых настраивай таймер не 66 us, а 66 ms overflow.
чтобы настраивать частоту прерывания не так TCNT0=BE; используй СТС режим
про склейку не понял - два разных кода почти одно и тоже делают - ("мучают" АДС)
:)) 6; у меня в коде не знаю кто приписал...
я стараюсь разграничивать код - по ТЗ замер входа каждые 200 мс, 3 входа, а про использование результатов замера ни слова, вот я и оформил отдельно в мелкую функцию, которую когда угодно вызвать можно.
ещё я накосячил - переменная n_zam это переименованная n_imp, только я её не везде переименовал. :))
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

По сути вот эта строчка заменят прерывание ISR (ADC_vect)

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

while ((ADCSRA & 0x10)==0);
	ADCSRA|=0x10;
И мне можно прерывание выбросить.

Со временем так и не понял как сделать по прерыванию таймера, куда вставляется ваш код... Нужен пример... Можете помочь?

Добавлено after 45 minutes 4 seconds:
Если я сделаю
ADC Auto Trigger Source: Timer0 Overflow

Настрою прерывание по таймеру:
ISR( TIMER0_OVF_vect )
{
// 100 us oveflow
// Reinitialize Timer 0 value
TCNT0=0x9C;
}

Это даст мне гарантию на переключение каналов по необходимому времени и по прерыванию завершения измерения?

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

ISR (ADC_vect)
{
	static unsigned char input_index=0;
	// Read the AD conversion result
	adc_data[input_index]=ADCW;
	// Select next ADC input
	if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
	input_index=0;
	ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
	// Delay needed for the stabilization of the ADC input voltage
	_delay_us(100);
	ADCSRA|=(1<<ADSC); //ADCSRA|=0x40
}
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Ответить

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