Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: терморегулятор
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Страницы: 1, 2
Lost_Viking
Собираю терморегулятор. Готова динамическая индикация (спасибо форумчанам). Теперь проблема с АЦП.
Цитата
/*****************************************************
Chip type : ATmega16
Clock frequency : 1,000000 MHz
*****************************************************/
#include <mega16.h>
char Dig[10]; // Массив, с кодами чисел для индикатора с общим анодом
char i=0; // счетчик для переключения анодов
char e=0; // единицы установленной температуры
char d=0; // десятки
char s=0; // сотни
char s2=0; // единицы измеренной температуры
char e2=0; // десятки
char d2=0; // сотни
char res=0; // в эту переменную поочереди записываются e,d,s или e2,d2,s2
char keys_prev=0; // две переменной для правильной работы кнопок
char keys_now=0; //
unsigned int current_temp=0; // измеренная температура
short temp2=0; // временная переменная
short set_temp=0; // установленная температура


char num (void) { // функция, для опроса клавиатуры, и вывода на катоды кода текущего разряда
if (PINB.4!=0){ // если кнопка "нагрев" не нажата, то
if ((keys_prev!=keys_now)&(PINB.0==0)) e++; // если нажата кнопка "единицы", то прибавить 1 к нулевому разряду (единицы)
if (e==10) e=0; // если результат прибавления перевалил за 9, то сбросить его в нуль
if ((keys_prev!=keys_now)&(PINB.1==0)) d++; // если нажата кнопка "десятки", то прибавить 1 к первому разряду (десятки)
if (d==10) d=0; // если результат прибавления перевалил за 9, то сбросить его в нуль
if ((keys_prev!=keys_now)&(PINB.2==0)) s++; // если нажата кнопка "сотни", то прибавить 1 к второму разряду (сотни)
if (s==3) s=0; // если результат прибавления перевалил за 9, то сбросить его в нуль
if (PINB.3==0) { // если нажата кнопка "сброс", то сбросить все разряды в нуль
e=0;
d=0;
s=0;}
switch (i) { // в зависимости от переменной i выбираем что показываем в текущий момент: единицы, десятки, или сотни
case 0:
res=e;
break;
case 1:
res=d;
break;
case 2:
res=s;
break; }
return res;}
else { // если нажата кнопка "нагрев", то

current_temp=ADCL; // в переменную записываем значение из регистра ADCL
current_temp+=((int)ADCH << 8); // прибавляем к переменной значение из регистра ADCH со сдвигом влево на 8 разрядов
current_temp=current_temp/2.5; // преобразовываем (ADCH ADCL) в температуру. Т.к. используется внутренний ИОН 2560 мВ, то 2560/1024=2.5
e2=current_temp%10; // получаем единицы измеренной температуры
temp2=current_temp/10; // промежуточная операция, для понижения степени
d2=temp2%10; // получаем десятки измеренной температуры
s2=temp2/10; // получаем сотни измеренной температуры
// в зависимости от переменной i выбираем что показываем в текущий момент времени
switch (i) {
case 0:
res=e2;
break;
case 1:
res=d2;
break;
case 2:
res=s2;
break; }
return res;


;}}

// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void) //обработка прерывания таймера по совпадению с OCR0
{
keys_prev=keys_now; //для клавиш
keys_now=PINB; //читаем что нажато
if (i==3) i=0; //если показатель текущего разряда перевалил за 2, то зажигаем нулевой разряд
PORTC=Dig[num()]; //выставляем на катодах число, которое получаем из функции num()
switch (i) { //в зависимости от переменной i поочередно подаем питание на аноды
case 0: //если i=0, то включаем разряд для единиц
PORTD.1=1; //гасим ненужные разряды
PORTD.2=1;
PORTD.0=0; //включаем нулевой разряд, активный уровень - 0,т.к. используются p-n-p
break;
case 1: // и т.д.
PORTD.0=1;
PORTD.2=1;
PORTD.1=0;
break;
case 2:
PORTD.0=1;
PORTD.1=1;
PORTD.2=0;
break;}
i++;

}

// Declare your global variables here

void main(void)
{
PORTA=0x00;
DDRA=0x00;
PORTB=0xFF;
DDRB=0x00;
PORTC=0x00;
DDRC=0xFF;
PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 0,977 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x0D;
TCNT0=0x00;
OCR0=0x03; //задаем частоту развертки. подбирал наглаз.

// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00; // free running режим АЦП
ADMUX=0xC0; // Внутренний источник опорного напряжения 2.56В REFS1..0=1; правое выравнивание ADLAR=0,вход ADC0
ADCSRA=0xE4; //ADEN=1(включили АЦП),ADSC=1(начали преобразование),ADATE:1(авто триггер включен),ADIE=0(прерывания от АЦП нам не нужны), делитель на 16

// заполняем массив комбинациями нулей/единиц для катодов
Dig[0] = 0xC0;
Dig[1] = 0xF9;
Dig[2] = 0xA4;
Dig[3] = 0xB0;
Dig[4] = 0x99;
Dig[5] = 0x92;
Dig[6] = 0x82;
Dig[7] = 0xF8;
Dig[8] = 0x80;
Dig[9] = 0x90;

#asm("sei") // включаем прерывания
while (1)
{
if (PINB.4==0) { // если нажата кнопка "нагрев", то
set_temp=e+d*10+s*100; // вычисляем установленную температуру, исходя из того, что в переменных e,d,s
if (current_temp<(set_temp-1)) {PORTD.3=1;}; //если текущая температура ниже установленной на 1 градус, то включаем релюшку
if (current_temp>=set_temp) {PORTD.3=0;};} //если текущая температура больше или равна установленной, то выключаем релюшку
else {PORTD.3=0;}; }; //если кнопка "нагрев" не нажата, то реле должно быть выключенным.
} // game over


почему-то в Proteus переменные e2,s2,d2 неправильно считаются. Залил в мегу - на индикаторе 409. Когда использовал прерывание АЦП, то у меня все работало. Но хочется упростить немного код (пусть хоть потребляет больше)
Схемку прилагаю.

Подскажите что не так, я уже не знаю чего делать.
AHTOXA
Цитата(Lost_Viking @ Jul 30 2008, 18:01) *
почему-то в Proteus переменные e2,s2,d2 неправильно считаются. Залил в мегу - на индикаторе 409.

А сколько должно быть?

Смущает вот что:

Код
current_temp=current_temp/2.5; // преобразовываем (ADCH ADCL) в температуру. Т.к. используется внутренний ИОН 2560 мВ, то 2560/1024=2.5


Во-первых, current_temp у вас unsigned int, то есть это эквивалентно
current_temp=current_temp/2.
Во-вторых, не вижу здесь вычисления значения температуры, вижу только вычисление напряжения.

ЗЫ. Для форматирования кода - кнопочка "код", а не "цитата":)
MrYuran
Код
current_temp=current_temp/2.5; // преобразовываем (ADCH ADCL) в температуру. Т.к. используется внутренний ИОН 2560 мВ, то 2560/1024=2.5

то есть 1 дискрет АЦП = 2,5 мВ.
Причём тогда тут деление?
Наверно, умножить надо? Получим Uadc в милливольтах
ещё такая штучка:
x*2.5=(x<<1)+(x>>1)
domowoj
Протеус 7.2 .2 с авр работает глючно!!!
Мегу 16 не проверял, а 8535 и тиньки - глюк, особенно что касаемо АЦП.
По заверениям разработчиков в версии 7.3 глюки обещали исправить.
Ждем-с.
=GM=
Цитата(Lost_Viking @ Jul 30 2008, 11:01) *
Подскажите что не так, я уже не знаю чего делать

У вас на самом деле последовательно с транзисторами стоят сопротивления 1 Ом? Не боитесь попалить МК и индикатор?

Последовательно с диодом D1 надо бы включить сопротивление, а то и здесь всё попалите.
Lost_Viking
Цитата(=GM= @ Jul 30 2008, 19:50) *
У вас на самом деле последовательно с транзисторами стоят сопротивления 1 Ом? Не боитесь попалить МК и индикатор?

Последовательно с диодом D1 надо бы включить сопротивление, а то и здесь всё попалите.



нет, номиналы там от балды. Не от балды - катушка, емкости, и резистор к питанию АЦП

Цитата(domowoj @ Jul 30 2008, 19:26) *
Протеус 7.2 .2 с авр работает глючно!!!
Мегу 16 не проверял, а 8535 и тиньки - глюк, особенно что касаемо АЦП.
По заверениям разработчиков в версии 7.3 глюки обещали исправить.
Ждем-с.


АЦП в протеусе у меня работает, по крайней мере так говорит ADCL регистр. Но были замеченны другие глюки, например глюкаво работает динамическая индикация.

Цитата(MrYuran @ Jul 30 2008, 16:40) *
Код
current_temp=current_temp/2.5; // преобразовываем (ADCH ADCL) в температуру. Т.к. используется внутренний ИОН 2560 мВ, то 2560/1024=2.5

то есть 1 дискрет АЦП = 2,5 мВ.
Причём тогда тут деление?
Наверно, умножить надо? Получим Uadc в милливольтах

просто я это так назвал "температурой", ну то, что пропорционально.
Насчет деления ты прав. Это я что-то ступил, но сути все равно не изменит

Цитата(AHTOXA @ Jul 30 2008, 16:31) *
А сколько должно быть?


число от 0 до ...
Т.е. кручу переменник - меняется на нем падение напряжения, которое приложенно ко входу АЦП.
Заметил такую вещь: подал на вход АЦП напряжение (1;2;3 вольта) от блока питания - показания изменились. При напряжении 3 вольта опять выдало 409. По сути это 2,56 вольта. Поставил добавочное сопротивление ко входу АЦП, опять все вернул на места (по схеме) - ничего не изменилось, все равно 409. Как ни крути переменник. Померил напряжометром - напряжение действительно >2.56В, амперметр включенный между переменником и входом АЦП вообще ничего не показал. Чудеса.

Цитата(AHTOXA @ Jul 30 2008, 16:31) *
Смущает вот что:

Код
current_temp=current_temp/2.5; // преобразовываем (ADCH ADCL) в температуру. Т.к. используется внутренний ИОН 2560 мВ, то 2560/1024=2.5



Во-первых, current_temp у вас unsigned int, то есть это эквивалентно
current_temp=current_temp/2.

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

Цитата(AHTOXA @ Jul 30 2008, 16:31) *
Во-вторых, не вижу здесь вычисления значения температуры, вижу только вычисление напряжения.

Ну, блин! biggrin.gif Мне для теста хотя бы напряжение показать, а коэффициенты пересчета для температуры потом введу
Цитата(AHTOXA @ Jul 30 2008, 16:31) *
ЗЫ. Для форматирования кода - кнопочка "код", а не "цитата":)

писал на работе, юзая gprs internet Megafon. В целях экономии траффика отключил все картинки, и почему-то вместо (code) вставилось (quote). Сообщение не перечитывал, т.к. рабочий день подходил к концу. sorry 05.gif
AHTOXA
Цитата(Lost_Viking @ Jul 30 2008, 23:04) *
Заметил такую вещь: подал на вход АЦП напряжение (1;2;3 вольта) от блока питания - показания изменились. При напряжении 3 вольта опять выдало 409. По сути это 2,56 вольта. Поставил добавочное сопротивление ко входу АЦП, опять все вернул на места (по схеме) - ничего не изменилось, все равно 409. Как ни крути переменник. Померил напряжометром - напряжение действительно >2.56В, амперметр включенный между переменником и входом АЦП вообще ничего не показал. Чудеса.


А как соотносятся номиналы R1 и переменника? Может переменник просто большой и не до конца выкручивается? smile.gif
defunct
Цитата(Lost_Viking @ Jul 30 2008, 20:04) *
нет, номиналы там от балды.

Уберите их вообще, вместо них поставьте резисторы 390-510om между пинами МК и сегментами индикатора (ABC..GH). Чтобы яркость цифр не менялась взависимости от заполнения. Транзисторы должны быть расчитаны на ток не менее 100ma.
Lost_Viking
Цитата(AHTOXA @ Jul 30 2008, 21:31) *
А как соотносятся номиналы R1 и переменника? Может переменник просто большой и не до конца выкручивается? smile.gif


на работе у меня целая гора переменников разных номиналов. все перепробовал - ну ни как! а вот с блока питания напрямую напряжение на вход АЦП - все работает. чудеса. завтра поколдую.

Цитата(defunct @ Jul 30 2008, 21:45) *
Уберите их вообще, вместо них поставьте резисторы 390-510om между пинами МК и сегментами индикатора (ABC..GH). Чтобы яркость цифр не менялась взависимости от заполнения. Транзисторы должны быть расчитаны на ток не менее 100ma.


упс, извинясь. просто эта схема взята из Proteus'а, и я туда специально воткнул эти резисторы, т.к. без них в протеусе транзисторы не закрывались (чудеса протеуса!). в реале их у меня нет.

Люди, скажите как вычислить абсолютную погрешность, если учесть, что два младших разряда АЦП по даташиту грешат,плюс округление с real до integer?

Т.е. имеем результат измерения 0010101100, младшие 2 разряда могут быть любыми, т.к. по даташиту абсолютная погрещность АЦП +/- 2 младших разряда. Далее, этот результат (dec(172)) умножаем на коэф.пересчета напряжения в температуру, например 2.6, и заносим в переменную unsigned int, соответственно все, что после точки отбрасывается.


Пока попробую в Excel'e покумекать

на катодах у меня по 100 Ом в реале стоят (вроде бы). Завтра гляну. Транзюки нормальные стоят.

Короче, индикация работает на ура! А АЦП что-то мне в морду плюет
AVRdeveloper
Цитата(Lost_Viking @ Jul 30 2008, 21:56) *
Короче, индикация работает на ура! А АЦП что-то мне в морду плюет


Если Вы пробовали подавать разное напряжение на вход АЦП, и на индикаторе отбражалость новое число, значит ваш девайс работает правильно..

Попробуйте замерять мультиметром напряжения на входе АЦП во время подключения к нему переменного резистора, если крутить ручку, и мультиметр будет показывать разные напряжения, то и девас покажет новое значение. Если нет, проверьте номинал переменного резистора он не должен быть слышком большим.. У меня для таких целей 5,1-33кОм прекрасно работают..


Странно, если вы убрали прерывания от АЦП, то где вы считываете текущее значение с регистра данных АЦП? Я бы поставил его в main. т.е. как я понял у вас данные считываються с АЦП только один раз при включении.
MrYuran
Цитата(Lost_Viking @ Jul 30 2008, 22:56) *
Люди, скажите как вычислить абсолютную погрешность, если учесть, что два младших разряда АЦП по даташиту грешат

Я что-то вообще не понял, что за датчик, схема какая-то трудночитабельная. Вообще, имхо, на АВР очень хитро вывернувшись можно, наверно, получить погрешность в пределах +/- 1 градуса... Это при условии калибровки. Про нестабильность внутренней опоры тоже надо подумать...
Lost_Viking
Цитата(AVRdeveloper @ Jul 31 2008, 10:26) *
Если Вы пробовали подавать разное напряжение на вход АЦП, и на индикаторе отбражалость новое число, значит ваш девайс работает правильно..

Попробуйте замерять мультиметром напряжения на входе АЦП во время подключения к нему переменного резистора, если крутить ручку, и мультиметр будет показывать разные напряжения, то и девас покажет новое значение. Если нет, проверьте номинал переменного резистора он не должен быть слышком большим.. У меня для таких целей 5,1-33кОм прекрасно работают..
Странно, если вы убрали прерывания от АЦП, то где вы считываете текущее значение с регистра данных АЦП? Я бы поставил его в main. т.е. как я понял у вас данные считываються с АЦП только один раз при включении.


Там сделано гораздо проще: АЦП преобразовывает все время, т.к. находится в режиме free run, и его не нужно все время запускать. Ну, а значения берутся из АЦП с частотой, равной частоте развертки, т.е. регулируется регистром OCR0. Там при каждом совпадении таймера с OCR0 вызывается фнукция обработчика прерывания:
Код
interrupt [TIM0_COMP] void timer0_comp_isr(void)

в ней есть комманда:
Код
PORTC=Dig[num()]

где num() - это функция, где при нажатой кнопке "нагрев" значения из ADCL и ADCH (ну или в CodevisionAvr - ADCW) помещаются в переменную current_temp. Далее это значение разбивается на 3 десятичных разряда.

Вобщем, я понял в чем ошибка. Смотрите схему. Слева - как было, справа - как стало. Т.е. теперь снимаю напряжение фактически с делителя. Может кто-нибудь объяснить почему при включении, что слева, АЦП не понимает в чем дело? Я не совсем понимаю.
AHTOXA
Цитата(Lost_Viking @ Jul 31 2008, 16:08) *
Вобщем, я понял в чем ошибка. Смотрите схему. Слева - как было, справа - как стало. Т.е. теперь снимаю напряжение фактически с делителя. Может кто-нибудь объяснить почему при включении, что слева, АЦП не понимает в чем дело? Я не совсем понимаю.


А в исходной схеме нарисовано как справаsmile.gif
В левой схеме тоже получается делитель, но его нижнее сопротивление равно бесконечности. Потому на выходе получается всё время 5в.
Lost_Viking
Цитата(MrYuran @ Jul 31 2008, 10:42) *
Я что-то вообще не понял, что за датчик, схема какая-то трудночитабельная. Вообще, имхо, на АВР очень хитро вывернувшись можно, наверно, получить погрешность в пределах +/- 1 градуса... Это при условии калибровки. Про нестабильность внутренней опоры тоже надо подумать...


датчиком будет какой-нибудь терморезистор, или транзистор. А пока для опытов вместо датчика использую обычный переменник на 2.4 кОм.
А такую погрешность можно получить и не выворачиваясь. Самое главное питание стабилизировать. Насчет внутренней опоры я не подумал. Насколько она нестабильна?
MrYuran
Цитата(Lost_Viking @ Jul 31 2008, 14:55) *
датчиком будет какой-нибудь терморезистор, или транзистор.
Какой именно? Платиновый точно не подойдёт, только термистор. У него характеристика покруче, но нелинейная.
Цитата
Насчет внутренней опоры я не подумал. Насколько она нестабильна?

по даташиту +/- 0,1В, то есть почти +/-5%
GDI
Цитата
В левой схеме тоже получается делитель, но его нижнее сопротивление равно бесконечности.

Отнють не бесконечности, а равно входному сопротивлению АЦП, которое составляет около 100к (имеющие даташит под руками меня поправят если что)
Lost_Viking
Цитата(AHTOXA @ Jul 31 2008, 14:53) *
А в исходной схеме нарисовано как справаsmile.gif

опа 07.gif . Ну да, помнится у меня как раз и не получалось что-то, а потом сделал делитель. Только при сборке я про это забыл.

Цитата(AHTOXA @ Jul 31 2008, 14:53) *
В левой схеме тоже получается делитель, но его нижнее сопротивление равно бесконечности. Потому на выходе получается всё время 5в.


Эммм. погоди, а почему? Разве падение напряжения на резисторе будет все время 5В независимо от положения ползунка? Что-то у меня с физикой напряги стали...
Теперь заметил проблему: все время скачет младшая цифра, причем очень быстро. Думаю, что это либо из-за паразитных 50Гц пульсаций, или же как раз погрешность АЦП в 2 младших разряда его 10-и битного результата. Сейчас попробую ADLAR=1 сделать, и читать 8 бит из ADCH.
AHTOXA
Цитата(GDI @ Jul 31 2008, 17:11) *
Отнють не бесконечности, а равно входному сопротивлению АЦП, которое составляет около 100к (имеющие даташит под руками меня поправят если что)


Я писал про делитель, а не про всю схему. А так - да, входное сопротивление снизу.


Цитата(Lost_Viking @ Jul 31 2008, 17:19) *
Эммм. погоди, а почему? Разве падение напряжения на резисторе будет все время 5В независимо от положения ползунка? Что-то у меня с физикой напряги стали...


Падение будет 0в. Ибо току течь некуда, он равен нулюsmile.gif U=IR. Закон Ома wink.gif

Цитата(Lost_Viking @ Jul 31 2008, 17:19) *
Теперь заметил проблему: все время скачет младшая цифра, причем очень быстро. Думаю, что это либо из-за паразитных 50Гц пульсаций, или же как раз погрешность АЦП в 2 младших разряда его 10-и битного результата. Сейчас попробую ADLAR=1 сделать, и читать 8 бит из ADCH.


Чтобы младший разряд не скакал, надо сделать всё очччень аккуратно. Отвязать аналоговое питание, аккуратно развести, и проч. и проч. Можно программно фильтровать. А можно отбросить младшие разряды, если точности 9 или 8 разрядов будет достаточно.
defunct
Цитата(GDI @ Jul 31 2008, 14:11) *
Отнють не бесконечности, а равно входному сопротивлению АЦП, которое составляет около 100к (имеющие даташит под руками меня поправят если что)

Посмотрите рисунок "Analog Input Circuitry" Fig. 105 в ДШ на m16.
Как эти 100k подключены и на что нагружены.

Для постоянного тока эквивалентная схема:
--Rвнешн----Rвнутр----"вникуда".

Rвнутр + "вникуда" => бесконечность.
GDI
Хочу уточнить чтобы не было иллюзий. В левой схеме где ножка переменного резистора не подсоединена к земле, нижним плечем делителя является входное сопротивление АЦП, и диаразон регулировки схемы зависит от сопротивления переменного резистора. Например, если полное сопротивление переменного резистора 100к и входное сопротивление АЦП тоже 100к, то диапазон будет ~0-50% (2,56 - 1,28 В, к примеру), если резистор будет 10к, то диапазон получится порядка 0-10%

P.S. Входное сопротивление всегда считается от земли в однополярной схеме.
_Pasha
Цитата(Lost_Viking @ Jul 31 2008, 14:19) *
Теперь заметил проблему: все время скачет младшая цифра, причем очень быстро.

1. TL431 ему в опору, чтоб не баловался.
2. Noise canceler ему в мозги, иначе у младшего разряда нервный тик не пройдет.
3. Накопление методом скользящего среднего вне зависимости от того, удался ли п.2.

Что же Вы, уважаемый, плохо воспитываете свой девайс ? smile.gif
defunct
Цитата(GDI @ Jul 31 2008, 14:56) *
P.S. Входное сопротивление всегда считается от земли в однополярной схеме.

Схема входа АЦП:
---R---C--GND

Цитата
В левой схеме где ножка переменного резистора не подсоединена к земле, нижним плечем делителя является входное сопротивление АЦП, и диаразон регулировки схемы зависит от сопротивления переменного резистора.

Все вами сказанное относится только к переменке и сильно зависит от частоты сигнала.
Для постоянного тока входное сопротивление АЦП стремится к бесконечности. Иначе как по вашему АЦП выдает всегда одинаковый результат при постоянном Vinp, независимо от выходного сопротивления источника сигнала.

Иными словами в левой схеме положение переменного резистора может управлять только лаем собак на луну.
MrYuran
Цитата(defunct @ Jul 31 2008, 16:04) *
Для постоянного тока входное сопротивление АЦП стремится к бесконечности.

Даже у аналогов девайсов не особо стремится. А уж у АВР... Гусары молчат.
defunct
Цитата(MrYuran @ Jul 31 2008, 15:09) *
Даже у аналогов девайсов не особо стремится. А уж у АВР... Гусары молчат.

Ну дык в идеале естессно. Но и на практике то оно явно больше 100k.
GDI
Заглянул в даташит на atmega48_68_168, там указано Rain = 100Мом, выходит ошибся я на 3 порядка smile.gif но сути это не меняет, надо всегда подключать нижний вывод переменного резистора к земле.
xemul
Цитата(defunct @ Jul 31 2008, 15:55) *
Посмотрите рисунок "Analog Input Circuitry" Fig. 105 в ДШ на m16.
Как эти 100k подключены и на что нагружены.

Для постоянного тока эквивалентная схема:
--Rвнешн----Rвнутр----"вникуда".

Rвнутр + "вникуда" => бесконечность.

Это сопротивление открытого ключа УВХ, причем на схеме указано, что оно может меняться от 1к до 100к (в первую очередь от напряжения питания). 100к и емкость УВХ C=14pF при тактовой АЦП >200 кГц уже не позволяют за 1.5 такта выборки установиться напряжению на С УВХ с достаточной точностью.
Типовое значение для входного сопротивление АЦП указано в таблице "ADC Characteristics" как 100 МОм.
Lost_Viking
Цитата(_Pasha @ Jul 31 2008, 15:57) *
1. TL431 ему в опору, чтоб не баловался.
2. Noise canceler ему в мозги, иначе у младшего разряда нервный тик не пройдет.
3. Накопление методом скользящего среднего вне зависимости от того, удался ли п.2.

Что же Вы, уважаемый, плохо воспитываете свой девайс ? smile.gif

1. насчет TL431 мне тоже пришла идея. А 78L05 пойдет? Только я не помню: 78 - это для плюса, а 79 - это для минуса? Или наоборот?
2. шозах? smile.gif что-то слышал об этом, вроде даже в даташите.
3. По-подробнее плиз. Сдается мне, что в этом пункте я еще больше внесу погрешность измерения.
Просто я пока еще молодой папа wink.gif

Цитата(defunct @ Jul 31 2008, 16:04) *
Иными словами в левой схеме положение переменного резистора может управлять только лаем собак на луну.


подтверждаю a14.gif Хотя немножко напряжение на входе АЦП регулировалось. Совсем чуть-чуть. Переменник 2.4кОм.

Цитата(xemul @ Jul 31 2008, 17:01) *
Типовое значение для входного сопротивление АЦП указано в таблице "ADC Characteristics" как 100 МОм.

предлагаю Мегометром брякнуть его biggrin.gif

Нашел я инфу про ADC Noise Reduction. Как стремно это дело работает: все выключается на время преобразования. Бррр... Щаззз проверим.
xemul
Цитата(Lost_Viking @ Jul 31 2008, 18:47) *
3. По-подробнее плиз. Сдается мне, что в этом пункте я еще больше внесу погрешность измерения.

Это будет погрешность обработки. Если будете правильно округлять, то внесете не более 0.5 LSB.
Цитата
предлагаю Мегометром брякнуть его biggrin.gif

Есть китайские мультиметры с пределом 200 МОм, на шупах при этом не более 2 В.
Корректнее по отношению к АЦП измерять его входной ток, а дальше по закону Ома относительно AVcc/2.
Lost_Viking
Цитата(xemul @ Jul 31 2008, 18:54) *
Это будет погрешность обработки. Если будете правильно округлять, то внесете не более 0.5 LSB.


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

Цитата(xemul @ Jul 31 2008, 18:54) *
Есть китайские мультиметры с пределом 200 МОм, на шупах при этом не более 2 В.
Корректнее по отношению к АЦП измерять его входной ток, а дальше по закону Ома относительно AVcc/2.

у меня есть советский измеритель сопротивления изоляции. там ручка есть такая волшебная: раскручиваешь ее, и на выходе привет santa2.gif

сдается мне, что придется опять использовать прерывание АЦП. Это даже к лучшему.
Мне вот что интересно: когда я начинаю читать данные из ADCL, то работа АЦП останавливается, пока я не прочту данные из ADCH? Так или нет?

Кстати, катушку поставил с индуктивностью 40мкГн, а емкость 0.1мкФ. Такие номиналы вычитал где-то в инете. Просто катушку 10мкГн не нашел
sKWO
Цитата(Lost_Viking @ Jul 31 2008, 17:47) *
78 - это для плюса

да

Цитата(Lost_Viking @ Jul 31 2008, 17:47) *
2. шозах? smile.gif что-то слышал об этом, вроде даже в даташите.

на время преобразования АЦП ядро МК уходит в спячку и просыпается по прерыванию окончания преобразования АЦП.

Цитата(Lost_Viking @ Jul 31 2008, 17:47) *
1. насчет TL431 мне тоже пришла идея. А 78L05 пойдет?

термостабилизация конечно же лучше у TL431, но на худший случай пойдёт.

Цитата(Lost_Viking @ Jul 31 2008, 17:47) *
а 79 - это для минуса? Или наоборот?

гугле - 79L05 Datasheet pdf - Negative-Voltage Regulators

Цитата(Lost_Viking @ Jul 31 2008, 18:29) *
можешь хотя бы примерно рассказать про данный метод? или, хотя бы, алгоритм если есть.

очень просто скользящее среднее,тоже о скользещем среднем
xemul
Цитата(Lost_Viking @ Jul 31 2008, 19:29) *
можешь хотя бы примерно рассказать про данный метод? или, хотя бы, алгоритм если есть.

Метод - просто какой-либо НЧ фильтр в цифре.
Простейший НЧ фильтр 1-го порядка: Yi = a * Yi-1 + b * Xi, a+b = 1
Т.е.
Код
Y = a * Y + b * X;

Для целочисленной арифметики удобно делать a=c/2^N, b=(2^N-c)/2^N.
Чтобы не набегала погрешность при обработке, разрядность Y должна быть не менее (разрядность X) + N.

Найдите что-нибудь вроде "Цифровые фильтры" Р. Хемминга - там все доступно.
Lost_Viking
Цитата(sKWO @ Jul 31 2008, 21:05) *

как я понял - это просто среднее какое-то значение. блин, и там погрешность, и тут ...

Цитата(xemul @ Jul 31 2008, 21:17) *
Найдите что-нибудь вроде "Цифровые фильтры" Р. Хемминга - там все доступно.

07.gif wacko.gif
help.gif я умер от этой книги. ничего не понял. мне проще стабилизировать опорное напряжение и питание, чем разобраться в этих греческих символах
Нашел вот что.Я смотрю там через операционник подают измеряемое напряжение. Только я не понял зачем там обратная связь в операционнике?
xemul
Цитата(Lost_Viking @ Jul 31 2008, 21:38) *
как я понял - это просто среднее какое-то значение. блин, и там погрешность, и тут ...

Вряд ли погрешность обработки превысит погрешность АЦП АВР smile.gif.
Цитата
help.gif я умер от этой книги. ничего не понял. мне проще стабилизировать опорное напряжение и питание, чем разобраться в этих греческих символах

Код
u16_t Yavg;

for(;;)
{
   Yavg -= Yavg/256;
   Yavg += ADCH;
}

Запуск и готовность АЦП за Вами.
Утверждается, что в старшем байте Yavg получим фильтр НЧ с частотой среза = частоте запуска АЦП/256 с погрешностью обработки <0.5 LSB, по АФЧХ эквивалентный RC цепочке с такой же частотой среза. Почему? Хемминг уже рассказал, у меня лучше не получится smile.gif.
Цитата
Нашел вот что.Я смотрю там через операционник подают измеряемое напряжение. Только я не понял зачем там обратная связь в операционнике?

Операционник включен повторителем и согласует входной делитель со входом АЦП. Использование в нем LM358 и заявление "3. Входное напряжение – 0..100В" оставим на совести автора.
Lost_Viking
Цитата(xemul @ Jul 31 2008, 22:10) *
Операционник включен повторителем и согласует входной делитель со входом АЦП. Использование в нем LM358 и заявление "3. Входное напряжение – 0..100В" оставим на совести автора.

lol.gif там и на 1000 вольт есть, если поищешь.

Короче, вот мои соображения:
  1. на вход АЦП повесить ФНЧ из RC цепочки с частотой среза примерно 50Гц.
  2. использовать внешний ИОН на каком-либо стабилизаторе
  3. использовать КР514ИД2 по совету kipmaster'а
  4. наконец перенести все с макетной платы на печатку, предварительно подумав о развязке земли
  5. если все это не поможет, то использовать опцию "подавитель шумов"
  6. если и это не поможет, то использовать цифровой фильтр
подскажите пожалуйста как грамотно отделить питание аналоговой части от цифровой?
Stanislav_S
Цитата(Lost_Viking @ Jul 31 2008, 23:50) *
lol.gif там и на 1000 вольт есть, если поищешь.

Короче, вот мои соображения:
  1. на вход АЦП повесить ФНЧ из RC цепочки с частотой среза примерно 50Гц.
  2. использовать внешний ИОН на каком-либо стабилизаторе
  3. использовать КР514ИД2 по совету kipmaster'а
  4. наконец перенести все с макетной платы на печатку, предварительно подумав о развязке земли
  5. если все это не поможет, то использовать опцию "подавитель шумов"
  6. если и это не поможет, то использовать цифровой фильтр
подскажите пожалуйста как грамотно отделить питание аналоговой части от цифровой?

Через LC фильтр, землю цифровую и аналоговую соединить в одной точке, допустим на конденсаторе фильтра после выпрямителя.
xemul
Цитата(Lost_Viking @ Jul 31 2008, 22:50) *
lol.gif там и на 1000 вольт есть, если поищешь.

Проблема не верхнем пределе, а в нижнем. LM358 не является ОУ с диапазоном rail-to-rail ни по входу, ни по выходу.
Цитата
[*]использовать КР514ИД2 по совету kipmaster'а

имхо, при разумной смехотехнике и трассировке достаточно отключать индикаторы на время преобразования АЦП.
Цитата
[*]если все это не поможет, то использовать опцию "подавитель шумов"

Вы собираетесь биться за 9 честный бит? А "внешний ИОН на каком-либо стабилизаторе" у Вас какую точность опоры обеспечит? А где брать в розницу резисторы 0.25% Вы уже знаете?
Или это задача для души? Тогда все-таки начните с теории.
Цитата
[*]если и это не поможет, то использовать цифровой фильтр

Не поможет от чего? От мельтешения младшего разряда на индикаторе? Да тупо пропустите сигнал с АЦП через цифровой ФНЧ с частотой среза в 0.5 Гц - будет мельтешить не чаще раза в секунду. Только точности это не добавит, хотя и не убавит.
Lost_Viking
Цитата(xemul @ Jul 31 2008, 21:17) *
Метод - просто какой-либо НЧ фильтр в цифре.
Простейший НЧ фильтр 1-го порядка: Yi = a * Yi-1 + b * Xi, a+b = 1
Т.е.
Код
Y = a * Y + b * X;

Для целочисленной арифметики удобно делать a=c/2^N, b=(2^N-c)/2^N.

что такое a и b? для чего они нужны?
как я понял - это Взвешенное скользящее среднее (WMA), взято от сюда
xemul
Цитата(Lost_Viking @ Aug 1 2008, 01:10) *
что такое a и b? для чего они нужны?
как я понял - это Взвешенное скользящее среднее (WMA), взято от сюда

Нет, это Экспоненциальное скользящее среднее (EMA) Yi = Yi-1 + A*(Xi - Yi-1).
С помощью несложных преобразований можно показать, что a = 1 - A, b = A.
оттуда же
Цитата
В случае EMA, коэффициент A - параметр фильтра, определяющий степень сглаживания. Чем он меньше, тем сильнее будет сглаживаться входной временной ряд. При A=0 фильтр перестает реагировать на изменения входного ряда, а при A=1 он будет повторять входной временной ряд.

Попробуйте смоделировать (хоть в ёкселе) реакцию фильтра на единичный скачок (x=0 при i<0, x=1 при i>=0), поиграйтесь с A, и все станет просто и понятно.
rezident
Цитата(xemul @ Aug 1 2008, 02:48) *
Да тупо пропустите сигнал с АЦП через цифровой ФНЧ с частотой среза в 0.5 Гц - будет мельтешить не чаще раза в секунду. Только точности это не добавит, хотя и не убавит.
Извиняюсь, что вмешиваюсь, но мельтешение на индикаторе убирается уменьшением частоты вывода на индикацию. Я считаю, что чаще чем 3 раза в секунду обновлять показания вообще нет смысла. Это связано с инерционностью человеческого мозга при обработке визуальной информации. В большинстве измерительных приборов период обновления показаний - 1 секунда.
Lost_Viking
Такс, собираю ИОН на TL431OEB. Насколько хорош этот стабилизатор?
MrYuran
А может даласовские датчики поставить и не мучиться? +/-1оС точность - лечится калибровкой, дискретность - где-то полградуса...
Хотя, если хочется повозиться с АЦП, то флаг в руки...
Нажмите для просмотра прикрепленного файла
Опора не оказывает влияния на результат (только нестабильность резисторов)
Lost_Viking
Цитата(MrYuran @ Aug 1 2008, 14:50) *
А может даласовские датчики поставить и не мучиться? +/-1оС точность - лечится калибровкой, дискретность - где-то полградуса...
Хотя, если хочется повозиться с АЦП, то флаг в руки...

ДАЛАСОВСКИЕ? DS которые? Они у них диапозон до 120градусов. Мне нужно 160 градусов. У меня такой даласовский лежит уже, купил не прочитав даташит.
Цитата(MrYuran @ Aug 1 2008, 14:50) *
Нажмите для просмотра прикрепленного файла
Опора не оказывает влияния на результат (только нестабильность резисторов)


Как это опора не оказывает влияние на результат? 07.gif Ведь если Uоп = 5В, а Uвх = 2.5В, то 10битный ADC выдаст 512. А если опора 10В, то выдаст 256.

Заметил вот что: записал в ADMUX:
Код
REFS1    REFS0    ADLAR    MUX4    MUX3    MUX2    MUX1    MUX0
0    0    1    0    0    0    0    0

Циферки перестали бегать, а АЦП все еще мерял что-то. Короче, получилось тоже самое, что и с внутренним ИОН, но только стабильнее. На AREF у меня всего лишь кондер висит, и никакого опорного напряжения не подводится.

Объясните мне в чем секрет? Я в чудеса не верю
xemul
Цитата(Lost_Viking @ Aug 1 2008, 17:46) *
Как это опора не оказывает влияние на результат? 07.gif Ведь если Uоп = 5В, а Uвх = 2.5В, то 10битный ADC выдаст 512. А если опора 10В, то выдаст 256.

При таком включении Rt = Nadc * Rоп / (Nadc_max - Nadc),
где
Nadc - результат преобразования АЦП
Nadc_max - максимальное значение АЦП (0x3ff для однополярного 10-битного АЦП)
Цитата
Заметил вот что: записал в ADMUX:
Код
REFS1    REFS0    ADLAR    MUX4    MUX3    MUX2    MUX1    MUX0
0    0    1    0    0    0    0    0

Циферки перестали бегать, а АЦП все еще мерял что-то. Короче, получилось тоже самое, что и с внутренним ИОН, но только стабильнее. На AREF у меня всего лишь кондер висит, и никакого опорного напряжения не подводится.

Объясните мне в чем секрет? Я в чудеса не верю

Вы забыли еще помолиться и свечку затеплить - без этого цифирки все равно иногда будут бегать.
rezident
Цитата(Lost_Viking @ Aug 1 2008, 19:46) *
Как это опора не оказывает влияние на результат? 07.gif Ведь если Uоп = 5В, а Uвх = 2.5В, то 10битный ADC выдаст 512. А если опора 10В, то выдаст 256.
Это называется ратиометрическим способом измерения, от слова ratio - отношение. На вход опоры можно подавать Vcc напрямую, если конечно это допустимо. Либо можно поставить буфер и вход опоры и делитель запитывать от него (т.к. ток по входу опоры в несколько раз выше, чем по входу АЦП). Либо использовать внутреннюю опору и выход опоры использовать для запитки делителя Rоп-Rt. В общем когда резистивный делитель запитывается от того же напряжения что и опора, то через оба резистора протекает один и тот же ток (соединение-то последовательное). Поэтому результат преобразования уже не зависит от величины напряжения, а только от отношения величин резисторов, ну и соответственно от временнОй и температурной стабильности опорного резистора. Результат преобразования АЦП является функцией отношения этих резисторов. Следует это отсюда
Ut=Rt/(Rt+Rоп)*Uref
Поскольку Ut мы получаем в виде результата преобразования АЦП (кодАЦП), а Uref соответствует максимальному коду АЦП = 1023, то получаем что
кодАЦП=Rt/(Rt+Rоп)*1023.
После простейших метематических преобразования получаем формулу
Rt=Rоп*кодАЦП/(1023-кодАЦП).
Где величина опоры никак не участвует, а играет роль только сопротивление опорного резистора Rоп. Конечно же превышать максимально допустимое для АЦП и опоры напряжение нельзя. Так что про "если опора 10В" это вы погорячились smile.gif

Update. Кстати при вычислениях в последней формуле существует вероятная ситуация исключения - деление на нуль, когда кодАЦП=1023. На практике это означает, что Rt>>Rоп (Rt много больше, на несколько порядков больше Rоп) или просто обрыв в цепи измеряемого сопротивления.
_Pasha
Цитата(Lost_Viking @ Aug 1 2008, 17:46) *
Заметил вот что: записал в ADMUX:
Код
REFS1    REFS0    ADLAR    MUX4    MUX3    MUX2    MUX1    MUX0
0    0    1    0    0    0    0    0

Циферки перестали бегать, а АЦП все еще мерял что-то.

Какая чушь! ADLAR=1! Вай-вай-вай! Лучше RTFM, чем вопросы. smile.gif

По поводу усреднения - не забудьте, что отношение сигнал/шум растет пропорционально квадратному корню из числа N усредняемых выборок, т.е. для 256 отсчетов имеем с/ш выросла в 16 раз. Младший разряд должен стоять и бояться. Это если у нас мат. ожидание есть состоятельная оценка. В противном случае придеццо делать обработку медианой.
xemul
Цитата(_Pasha @ Aug 1 2008, 21:30) *
Какая чушь! ADLAR=1! Вай-вай-вай! Лучше RTFM, чем вопросы. smile.gif

ADLAR=1 очень даже удобно, если читать только ADCH.
Вот REFS0 = REFS1 = 0 только с кондюком на AVref гораздо прикольней - опора на входном токе ноги контроллера. Срочно патентовать!!! smile.gif
_Pasha
Цитата(xemul @ Aug 1 2008, 22:01) *
ADLAR=1 очень даже удобно, если читать только ADCH.

Дык автор хочет 10 бит, а получает 8 и радуется smile.gif
Lost_Viking
Цитата(xemul @ Aug 1 2008, 22:01) *
ADLAR=1 очень даже удобно, если читать только ADCH.
Вот REFS0 = REFS1 = 0 только с кондюком на AVref гораздо прикольней - опора на входном токе ноги контроллера. Срочно патентовать!!! smile.gif


Однако работает! Сам не понимаю. Собрал опору на TL431, и радуюсь.10Бит. Вот только наводки иногда проскакивают, теперь займусь ФНЧ, возможно применю цифровую фильтрацию.
Как закончу - выложу полный код на Си с комментами и алгоритмом. Что бы такие же как я не наступали на грабли.

Цитата(_Pasha @ Aug 1 2008, 22:19) *
Дык автор хочет 10 бит, а получает 8 и радуется smile.gif

Для меня и 8 бит хватило бы. Но мне пришла в голову мысль использовать сабж на даче для измерения сетевого напряжения, для регистрации (с записью в EEPROM,и дальнейшей пересылкой в ПК) температуры окружающей среды за промежуток времени, и т.п.
Далее хотелось бы попробовать сделать датчик влажности грунта для автоматической поливалки...
Вот так-то wacko.gif

Цитата(_Pasha @ Aug 1 2008, 21:30) *
Это если у нас мат. ожидание есть состоятельная оценка. В противном случае придеццо делать обработку медианой.

1111493779.gif
а можно без нецензурных выражений? 07.gif
domowoj
Lost_Viking
А мож Вам лучше DS18x20 применить, никаких АЦП и никаких тебе опорных.
Дергай только ножками правильно, читай температуру в цифре и выводи на индикатор.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.