Существует ли разница между АЦП в Atmega8A?

Обсуждаем контроллеры компании Atmel.
Ответить
Gap
Открыл глаза
Аватара пользователя
Сообщения: 55
Зарегистрирован: Вт дек 15, 2015 23:13:32

Сообщение Gap »

Решил собрать устройство измеряющую температуру с помощью двух термопар.
Собрал печатную плату, по следующей схеме:
СпойлерИзображение
*Красной линией обвёл часть отвечающую за усиление сигнала с термопар.

Написал код:
Спойлер

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

#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

void Display(char Rank, char Number, char Point)
{
	switch(Rank)
	{
		case 0:
		PORTB = 0b00000000;
		break;
		case 1:
		PORTB = 0b00000001;
		break;
		case 2:
		PORTB = 0b01000000;
		break;
		case 3:
		PORTB = 0b10000000;
		break;
	}
	
	switch(Number)
	{
		case 0:
		PORTD = 0b00010100;
		break;
		case 1:
		PORTD = 0b01110111;
		break;
		case 2:
		PORTD = 0b01001100;
		break;
		case 3:
		PORTD = 0b01000101;
		break;
		case 4:
		PORTD = 0b00100111;
		break;
		case 5:
		PORTD = 0b10000101;
		break;
		case 6:
		PORTD = 0b10000100;
		break;
		case 7:
		PORTD = 0b01010111;
		break;
		case 8:
		PORTD = 0b00000100;
		break;
		case 9:
		PORTD = 0b00000101;
		break;
	}
	
	if(Point == 1)
	PORTD &= 0b11111011;
	
	_delay_ms(1);
}
void Complex_Display(int Number, char Point1, char Point2, char Point3)
{
	int Number1, Number2, Number3;
	
	Number1 = (char) (Number / 100);
	Number2 = (char) (Number - Number1*100)/10;
	Number3 = (char) (Number - Number1*100 - Number2*10)/1;
	
	Display(3, Number1, Point1);
	Display(2, Number2, Point2);
	Display(1, Number3, Point3);
}

int main(void)
{
	int data = 0;  //+++
	int Real_Temperature = 0;  //+++
	
	//PD5 - A, PD7 - B, PD3 - C, PD1 - D, PD0 - E, PD6 - F, PD4 - G, PD2 - DP;
	DDRD = 0xFF;
	PORTD = 0x00;
	
	//PB7 - 0 разряд, PB6 - 1 разряд, PB0 - 2 разряд; 
	DDRB = 0b11000001;
	PORTB = 0b00001110;
	
	SFIOR = 0x00;  //+++
	ADCSRA = 0x85;   //+++
	while(1)  
	{
		//Первый режим
		while(1)
		{
			ADMUX = 0x40;    //+++
			ADCSRA |= 0x40;     //+++
			data = ADCW;    //+++
			
			Real_Temperature = data*0.0048828*170;     //+++
			Real_Temperature = Real_Temperature;     //+++
			
			for(int x = 0; x < 100; x++)
			Complex_Display(Real_Temperature, 0, 0, 0);
			
			if(!((1 << PINB1)&PINB))
			{
				while(!((1 << PINB1)&PINB)){}
				break;
			}
		}
		
		//Второй режим
		while(1)
		{
			ADMUX = 0x42;    //+++
			ADCSRA |= 0x40;    //+++
			data = ADCW;    //+++
			
			Real_Temperature = data*0.0048828*200;    //+++
			Real_Temperature = Real_Temperature;    //+++
			
			for(int x = 0; x < 100; x++)
			Complex_Display(Real_Temperature, 0, 0, 0);
			
			if(!((1 << PINB1)&PINB))
			{
				while(!((1 << PINB1)&PINB)){}
				break;
			}
		}
	}
}
*Код отвечающий непосредственно за измерения пометил комментарием: "//+++".

Как видно, обе части отвечающих за измерение температуры построены абсолютно одинаково, как аппаратно, так и программно.
Но значения меряют по разному. Если подышать на термопары, то термопара подключённая к PC0 покажет изменения в температуре, а термопара подключённая к PC2 никак не отреагирует. В теплой воде PC0 показывает температуру примерно на 7 выше, чем PC2. Температуру пара в чайнике показывают одну и туже. Это не просто разница в чувствительности, разница между PC0 и PC2 не стабильно 7 градусов.

*Термопары одинаковые. Менял местами, ничего не изменилось.

В чем может быть проблема?
Последний раз редактировалось Gap Ср июн 14, 2017 10:15:21, всего редактировалось 1 раз.
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1802
Зарегистрирован: Ср сен 07, 2011 21:40:30

Сообщение Flasher »

C такой смехатехникой, не удивительно...
Зачем R4 R8 ?
Кто разрешил 358 нагружать на емкость? Почему не нагружен на активное сопротивление?
Кто решил ставить в обратной связи подстроечники?
У тебя там самовозбуд, наверняка...
Реклама
Gap
Открыл глаза
Аватара пользователя
Сообщения: 55
Зарегистрирован: Вт дек 15, 2015 23:13:32

Сообщение Gap »

Подсмотрел в гугле...)
СпойлерИзображение
Изображение
Изображение
Ещё тут: http://avrproject.ru/publ/kak_podkljuch ... u/2-1-0-70

Насколько я понимаю R4, R8 с составляющие фильтра. А подстроечные резисторы для калибровки термопары.

А можно по подробнее, как правильно?
Мудрый кот
Аватара пользователя
Сообщения: 1802
Зарегистрирован: Ср сен 07, 2011 21:40:30

Сообщение Flasher »

Обрати внимание на последнюю картинку-схему. Она самая грамотная, так как является вольной переделкой весьма продуманной схемы от аналог девайсес.
Там хоть и поставили подстроечник, но при этом избавились от возбуда, добавив конденсатор в ОС. R9 там является частью схемы усилителя, а не просто последовательным резистором.
А 358 нагрузи 10 кОм.
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

1. При однополярном питании на входы + ОУ принято подавать некоторое напряжение смещения. После усиления это напряжение вычитают.
2. Перед чтением результата АЦП
data = ADCW; //+++
рекомендуется подождать флага готовности. АЦП - штука медленная и не выдаёт ответ сразу.
Реклама
Gap
Открыл глаза
Аватара пользователя
Сообщения: 55
Зарегистрирован: Вт дек 15, 2015 23:13:32

Сообщение Gap »

Ради интереса... провёл эксперимент. Налил в кружку кипяток и каждые 30 секунд мерял температуру. Построил график:
СпойлерИзображение
*Температура приведена без компенсации холодного спая.

Добавлено after 16 minutes 52 seconds:
Flasher, спасибо за указание правильного направления. Но, обвязка неправильная как на PC0, так и на PC2, тогда почему измерения разные?
Реклама
Мучитель микросхем
Сообщения: 453
Зарегистрирован: Ср июн 08, 2011 20:25:20

Сообщение bob1 »

[uquote="Gap",url="/forum/viewtopic.php?p=3126209#p3126209"]В чем может быть проблема?[/uquote] Отсоединить один выход LM358. Соединить PC0 и PC2 вместе. Определитесь камень или аналоговая часть. Можно в принципе и цешкой замерить на выходах LM358. АЦП работает в диапазоне до 100ед.....???
Контактная информация:
Gap
Открыл глаза
Аватара пользователя
Сообщения: 55
Зарегистрирован: Вт дек 15, 2015 23:13:32

Сообщение Gap »

uk8amk, добавил флаг готовности следующим образом:

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

while(ADCSRA != 0x95){}
data = ADCW;
ADCSRA |= 0x10;
Ничего не изменилось.

Добавлено after 1 hour 4 minutes 22 seconds:
bob1, отсоединил один выход LM385, которая идет к PC2. И соединил на Atmega8A PC0 и PC2. Разница есть, причем чем выше температура, тем выше разница. При измерении температуры пара в чайнике, разница в 13 градусов. Причем PC0 < PC2.

P.s. Забыл сказать. Прежде, когда PC0 не было соединено c PC1. Я, когда мерял температуру пара, с помощью подстроечных резисторов настроил термопары так, что б они показывали одинаковую температуру. Возможно именно поэтому на графике в моей предыдущем сообщении, чем ниже температура, тем выше разница.

P.s.s. Сейчас вспомнил... Достаточно давно, я случайно сделал КЗ на этом микроконтроллере (подключил AREF и AVCC к земле), которое заметил, только после того как он раскалился. Возможно здесь собака и зарыта. К сожалению на данный момент не имею другого кристалла для проверки.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Код ужасен. Динамическую индикацию обычно делают на прерывании таймера либо в бесконечном цикле с низкой частотой (порядка 200-1000 Гц), делать как у вас сейчас - нарываться на неодинаковую яркость сегментов, гашение первых и засветы. Для выбора комбинации диодов для каждой цифры заводят массив констант, из которого выбирают по индексу. Также и с разрядами. Отдельные биты стоит оборачивать в макросы чтобы было удобно изменять если что:

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

#define SEG_A (1<<0)
#define SEG_B (1<<4)
#define SEG_C (1<<7)
...
#define SEG_PORT PORTA
const uint8_t segs[] = {
  SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, //0
  SEG_B | SEG_C, //1
  SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,
...
};
#define DIGIT_1 (1<<0)
#define DIGIT_2 (1<<1)
#define DIGIT_3 (1<<5)
const uint8_t digits[3] = {DIGIT_1, DIGIT_2, DIGIT_3};
#define DIGIT_PORT PORTB

uint8_t videobuf[3] = {0,0,0};

ISR( TIMER0_OVF_vect){
  static uint8_t digit = 0;
  SEG_PORT = 0;
  DIGIT_PORT |= digits[ digit ];
  digit++;
  if(digit > 3)digit = 0;
  DIGIT_PORT &=~ digits[ digit ];
  SEG_PORT |= videobuf[ digit ];
}

void display_int(uint8_t x){
  videobuf[0] = x % 10;
  x /= 10;
  videobuf[1] = x % 10;
  videobuf[2] = x / 10;
}
примерно так. Писал из головы, только чтобы общая идея была понятна. Тут - полноценная реализация.

ADMUX = 0x42; //+++
ADCSRA |= 0x40; //+++
data = ADCW;
Почему не дожидаетесь окончания преобразования?
У вас вроде еще PC1 свободен, что если подключить его в параллель к PC0 или PC2 - может он более линеен? Соединять AREF с VCC - плохая идея.
Gap
Открыл глаза
Аватара пользователя
Сообщения: 55
Зарегистрирован: Вт дек 15, 2015 23:13:32

Сообщение Gap »

COKPOWEHEU, спасибо за наводку по индикации.
К PC1 у меня подключён терморезистор, который измеряет температуру помещения для компенсации холодного спая.
В одном из моих предыдущих комментариев, добавил в код ожидание окончания преобразования.
Gap
Открыл глаза
Аватара пользователя
Сообщения: 55
Зарегистрирован: Вт дек 15, 2015 23:13:32

Сообщение Gap »

Короче говоря... Поставил другую Atmega8A, разница в измерениях осталась, как PC0 показывал меньше PC2 так и показывает... и тут я в панике вспоминаю код... вспоминаю следующие строки:

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

Real_Temperature = data*0.0048828*170;     //+++
Real_Temperature = data*0.0048828*200;    //+++
Температуру на PC0 я рассчитывал по одной формуле, а на PC2 по другой)
В общем одинаковые значения показывают АЦП PC0 и PC2. Значит ошибка где то в аналоговой части.
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Динамическая индикация реализуется и в основном цикле. Если итерация основного цикла выполняется с запасом по значению времени системного тика.
Контактная информация:
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Можно и в основном цикле. Главное чтобы за одну итерацию обрабатывалось не более одного разряда. Тем более что требования к точности временных интервалов там минимальны.
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=3128807#p3128807"]Главное чтобы за одну итерацию обрабатывалось не более одного разряда.[/uquote]
Пффф. Дык этта... Флаги или программные таймеры. И точность обеспечена. Плюс-минус десяток-другой мкс в расчет не берем.

Добавлено after 9 hours 42 minutes 11 seconds:
Кстати, жареный мк лучше либо выбросить, либо отказаться от ацп.
Контактная информация:
Ответить

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