Страница 1 из 1
AVR, АЦП - подбор резистора
Добавлено: Вс янв 26, 2014 13:26:37
ZhukV
Доброго времени суток форумчани.
Была поставлена задача: вычислить температуру в большом диапазоне (50 - 700 C). Взял резистивный датчик (
http://www.e-voron.dp.ua/catalog/020094 ), номиналом в 100Ом (таблица изменений сопротивления есть на сайте). После чего начал разбираться с АЦП в атмеги (Для тестов взял 8535). Вроде как подключил, работает, но не могу понять одного: почему АЦП не видит сопротивления в 100 Ом (изменений почти не заметно), в то время, если поставить сопротивление в 2МОм, то изменения видно, но они очень маленькие.
Скрин:
http://prntscr.com/2moirz
Конфигурация АЦП:
Код: Выделить всё
ADMUX &= ~(1 << ADLAR);
ADMUX &= ~((0 << REFS0) | (1 << REFS1));
ADCSRA |= (1 << ADEN) | (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2);
Простите, если вопрос очень уж глупый, разбираюсь только

Re: AVR, АЦП - подбор резистора
Добавлено: Вс янв 26, 2014 15:31:47
pyzhman
При таком подключении вы изменяете ток при изменении температуры(изменении сопротивления датчика). При большом входном сопротивлении АЦП, коим обладает АВР, смысл сего - 0, что вы и видите(малое изменение значений). Вам же нужно менять напряжение, подаваемое на вход АЦП. Сделайте простой делитель напряжения, в одном из плеч которого будет ваш датчик. Сразу всё станет на места.
Re: AVR, АЦП - подбор резистора
Добавлено: Вт янв 28, 2014 14:20:05
YS
Плюсую, АЦП измеряет напряжение. Соберите делитель.
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 12:39:47
ZhukV
Здраствуйте. Разобрался с делителем, подключил.
Но не могу понять, почему АЦП изменяет свое значение? Но при этом напряжение не меняется.
Controller: ATmega 8535
Конфигурация АЦП:
Частота процессора 1 MHz, делитель для АЦП выбрал 16 (62500 Hz)
Схема подключение простейшая: AVCC, AREF подключены к питанию схемы, на АЦП проходит через делитель.
Данные АЦП (ADCW) вывожу на дисплей, и там заметил, что показания всегда разные.
Спасибо.
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 14:29:57
YS
Но не могу понять, почему АЦП изменяет свое значение? Но при этом напряжение не меняется.
Немножко так скачут, да? В пределах десятка?
Потому что все на свете шумит. Вот вы и познакомились с таким понятием, как "шумы АЦП".

Как вариант - нестабильный контакт (если показания скачут уж слишком сильно). Да и в самом напряжении питания тоже есть шумы.
Вообще, не стоит надеяться получить от встроенного АЦП разрешение больше восьми бит без калибровки и хорошего опорного источника. Если не предпринимать особых мер, два последних бита содержат в основном шум и ошибку смещения.
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 14:50:39
ZhukV
Та дело в том, что погрешности уж слишком большие. Изменяются высшие биты.
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 14:54:59
ZhukV
Вот, к примеру, только что запустил:
Изменения:
0b0000001110111010
0b0000000001111010
Питание беру с USB (USBasp).
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 16:15:26
pyzhman
Всю программу можно посмотреть?
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 16:53:30
ZhukV
Да, без проблем:
Код: Выделить всё
/*
* Diploma.c
*
* Created: 30.01.2014 21:18:39
* Author: Vitaliy Zhuk
*/
#define F_CPU 1000000
#define KS0066_DATA_DDR DDRA
#define KS0066_DATA_PORT PORTA
#define KS0066_CTRL_DDR DDRA
#define KS0066_CTRL_PORT PORTA
#define KS0066_CTRL_STROBE_PIN PINA6
#define KS0066_CTRL_RW_PIN PINA5
#define KS0066_CTRL_RS_PIN PINA4
#define KS0066_4BIT 1
#define KS0066_4BIT_HIGH_BYTE 0
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include "lcd/ks0066.c"
void lcdWriteByteAsChars(uint16_t byte, uint16_t counts)
{
for (uint8_t i = 1; i <= counts; i++) {
if (1 & (byte >> (i - 1))) {
lcdPuts("1");
} else {
lcdPuts("0");
}
}
}
int main(void)
{
_delay_ms(100);
// Initialize LCD
lcdInit();
lcdWriteCommand(0b00000001);
lcdWriteCommand(0b00001100);
lcdWriteCommand(0b00000110);
// Initialize ADC in PORTA.7
ADMUX = 0b00100111;
ADCSRA = 0b10000100;
while(1)
{
_delay_ms(500);
ADCSRA |= (1 << ADSC); // Start conversion
_delay_us(25);
while ((ADCSRA & (1 << ADIF))==0);
uint16_t adc = ADCW;
lcdWriteCommand(1);
lcdWriteByteAsChars(adc, 16);
lcdGoto(0, 1);
lcdWriteByteAsChars(ADCL, 8);
lcdWriteByteAsChars(ADCH, 8);
}
}
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 18:40:39
ZhukV
Наверное проблему нашел, но не могу понять, почему так, и как исправить?
Питание схемы было через программатор (Ну там есть два проводка для питания). Когда отключил программатор и подключил через батарейки, то все стабилизировалось. Скачков вообще не было.
Подскажите пожалуйста, могут ли быть такие колебание, и чем они обумовленны? Как исправить? LC фильтр?
Спасибо!
Re: AVR, АЦП - подбор резистора
Добавлено: Сб фев 01, 2014 20:37:53
YS
Да, если такие скачки, значит питание скачет. Я бы для начала ткнулся в питание осциллографом.
Есть вероятность, то дело в нестабильном контакте, либо недостаточной нагрузочной способности программатора.
А что за программатор, кстати? Например, в AVRISP mkII пин Vcc служит только для определения напряжения на плате, но не для ее запитки. В таком случае схема может получать только паразитное питание через защитные диоды, ну а при таком режиме может твориться что угодно...

Re: AVR, АЦП - подбор резистора
Добавлено: Вс фев 02, 2014 00:13:57
ZhukV
К сожалению осцилографа нету, да пока покупать его неохтно в виду его цены (Ну если нормальный брать).
Програматор USBasp. Где-то в инете читал, что его можно использовать как запитку для платы (ну вполне вероятно, что это "фигня").
А можно ли вообще как-то обезопасить себя от таких скачков? Если не сложно, натолкните, куда именно нужно смотреть, в какую степь? Заранее благодарен!
P.S.
YS большое Вам спасибо за помощь!
Re: AVR, АЦП - подбор резистора
Добавлено: Вс фев 02, 2014 01:18:46
pyzhman
В регистре ADMUX вы выбрали в качестве источника опорного напряжения вход Vref. И подключили его к питанию. А попробуйте выбрать внутреннюю опору.
Re: AVR, АЦП - подбор резистора
Добавлено: Вс фев 02, 2014 15:13:56
YS
Где-то в инете читал, что его можно использовать как запитку для платы
Судя по
его схеме (хотя, возможно, есть много ее вариантов) для этого надо установить перемычку.
YS большое Вам спасибо за помощь!
Да не за что.
В регистре ADMUX вы выбрали в качестве источника опорного напряжения вход Vref. И подключили его к питанию.
Ну, эт еще не показатель проблемы. Я тоже так делал. Да, шумело, но не так глобально.
ADMUX = 0b00100111;
Хе-хе. Да у вас же установлен ADLAR.
Картинку копипастить лень.
Вот тут на странице 222 указан его эффект.
Вкратце - результат смещается в ADCH. Расчет как раз на тот случай, когда мы игнорируем последние два бита.
При этом вы выводите сначала ADCL, потом ADCH, начиная с левого края дисплея.
Код: Выделить всё
lcdGoto(0, 1);
lcdWriteByteAsChars(ADCL, 8);
lcdWriteByteAsChars(ADCH, 8);
И получаете
То есть, побайтно:
ADCL -> [00000011] ADCH -> [10111010]
ADCL -> [00000000] ADCH -> [01111010]
Тут конечно вопрос, в каком порядке та библиотека выводит биты, но очень похоже, что начиная с младшего. Тогда все получается логично - меняются четыре младших бита из десяти, остальные стоят как вкопанные.