Вольтамперметр (100В, 30А на ATMega16)
Здравствуйте уважаемые радиолюбители. У меня возникла проблема при измерении тока с помощью Меги16 и встроенного дифференциального усилителя. В настройках всё выставляю как надо, беру пример из Datasheet: на один из входов подаю 300мВ на другой 500мВ, моделирую в Протеусе, но вместо указанного в Datasheet значения 400, получаю 800. В чём можеть быть проблема? Пожалуйста кто может помочь в этом вопросе отзовитесь. Очень нужно!!!
- Реклама
Что это за значения? Откуда?prv1984 писал(а):вместо указанного в Datasheet значения 400, получаю 800
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
На этой странице (http://microsin.ru/content/view/1145/44/) есть следующий пример из datashеet:
Пытаюсь повторить, но результат моделирования совсем другой
Код: Выделить всё
Пример: ADMUX = 0xED (дифференциальная пара входов ADC3 - ADC2, GAIN = 10, VREF =2.56В, результат с левосторонним выравниванием), напряжение на входе ADC3 = 300 мВ, а на входе ADC2 = 500 мВ, тогда:
ADCR = 512 * 10 * (300 - 500) / 2560 = -400 = 0x270
С учетом выбранного формата размещения результата (левосторонний) ADCL = 0x00, а ADCH = 0x9C. Если же выбран правосторонний формат (ADLAR=0), то ADCL = 0x70, ADCH = 0x02.
Надо код смотреть. И схему Шпротеусовскую.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Код проекта:
Спойлер
Код: Выделить всё
#include <iom16.h>
#include <intrinsics.h>
// Библиотека для работы с симфольным ЖКИ-дисплеем
#include "lcd_lib.h"
// Макросы для работы с битами микроконтроллера
#define PRV_SetBit(reg, bit) reg |= (1<<bit)
#define PRV_ClearBit(reg, bit) reg &= (~(1<<bit))
#define PRV_InvBit(reg, bit) reg ^= (1<<bit)
#define PRV_BitIsSet(reg, bit) ((reg & (1<<bit)) != 0)
#define PRV_BitIsClear(reg, bit) ((reg & (1<<bit)) == 0)
// Функция инициализации АЦП ---------------------------------------------------
void PRV_InitADC(void)
{
DDRA=0;
// Выбор опорного источника напряжения на 2.56В
PRV_SetBit(ADMUX, REFS0); PRV_SetBit(ADMUX, REFS1);
// Выбор дифференциального режима по входам ADC3, ADC3 (Ку=10) ADMUX 4..0 01101
PRV_SetBit(ADMUX, MUX0); PRV_ClearBit(ADMUX, MUX1);
PRV_SetBit(ADMUX, MUX2); PRV_SetBit(ADMUX, MUX3);
PRV_ClearBit(ADMUX, MUX4);
// Правостороннее выравнивание результата
PRV_ClearBit(ADMUX, ADLAR);
// Включение АЦП
PRV_SetBit(ADCSRA, ADEN);
// Активация режима однотактного преобразования
PRV_SetBit(ADCSRA, ADSC);
// Деактивация режима автоматического перезапуска АЦП
PRV_ClearBit(ADCSRA, ADIF);
// Разрешение прерывания АЦП
PRV_SetBit(ADCSRA, ADIE);
// Предделитель АЦП = Fcpu/16
PRV_ClearBit(ADCSRA, ADPS0); PRV_ClearBit(ADCSRA, ADPS1);
PRV_SetBit(ADCSRA, ADPS2);
// Запуск преобразования
PRV_SetBit(ADCSRA, ADSC);
}
// -----------------------------------------------------------------------------
// Функция вывода приветствия при включении устройства -------------------------
void PRV_Intro(void)
{
LCD_Init(); LCD_Clear();
LCD_Goto(6,0); LCD_SendString("COPYRIGHT");
LCD_Goto(5,1); LCD_SendString("DTG-ELCTRIC");
__delay_cycles(F_CPU * 1); LCD_Clear();
}
// -----------------------------------------------------------------------------
unsigned char PRV_Buffer[4];
unsigned char PRV_NumbersLCD[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
// Функция преобразования числа в символы ЖКИ ----------------------------------
void PRV_INTtoLCD(unsigned int number)
{
unsigned int PRV_Temp;
for(unsigned char i = 0; i < 4; i++)
{
PRV_Temp = number % 10;
PRV_Buffer[3-i] = PRV_NumbersLCD[PRV_Temp];
number /= 10;
}
LCD_WriteData(PRV_Buffer[0]);
LCD_WriteData(PRV_Buffer[1]);
//LCD_WriteData(',');
LCD_WriteData(PRV_Buffer[2]);
LCD_WriteData(PRV_Buffer[3]);
}
// Переменная буффера для хранения среднего знаячения напряжения
volatile unsigned int PRV_BufferADC = 0;
// Обработчик прерывания АЦП +++++++++++++++++++++++++++++++++++++++++++++++++++
#pragma vector=ADC_vect
__interrupt void adc_my(void)
{
unsigned char PRV_ADCL = 0;
unsigned char PRV_ADCH = 0;
PRV_ADCL = ADCL;
PRV_ADCH = ADCH;
PRV_BufferADC = PRV_ADCL | (PRV_ADCH << 8);
// Запуск преобразования
PRV_SetBit(ADCSRA, ADSC);
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
__monitor unsigned int ADC_GetBuf(void)
{
return PRV_BufferADC;
}
int main( void )
{
unsigned int VOLTS = 0;
// Инициализация АЦП
PRV_InitADC();
// Разрешение прерываний
__enable_interrupt();
PRV_SetBit(SREG, 7);
// Вывод приветствия
//PRV_Intro();
LCD_Init(); LCD_Clear();
while(1)
{
VOLTS = ADC_GetBuf();
LCD_Goto(0,0);
// Вывод результата на LCD
PRV_INTtoLCD(VOLTS);
__delay_cycles(1000000);
}
}
- Вложения
-
- 1.png
- Схема в proteus
- (167.31 КБ) 351 скачивание
- Реклама
Это 3,14здец. Обычно пишут в одну строчку типа (1<<Refs0)|(1<<Refs1)...prv1984 писал(а): // Выбор опорного источника напряжения на 2.56В
PRV_SetBit(ADMUX, REFS0); PRV_SetBit(ADMUX, REFS1);
// Выбор дифференциального режима по входам ADC3, ADC3 (Ку=10) ADMUX 4..0 01101
PRV_SetBit(ADMUX, MUX0); PRV_ClearBit(ADMUX, MUX1);
PRV_SetBit(ADMUX, MUX2); PRV_SetBit(ADMUX, MUX3);
PRV_ClearBit(ADMUX, MUX4);
// Правостороннее выравнивание результата
PRV_ClearBit(ADMUX, ADLAR);
Чего-чего? Вообще-то, флаг прерывания сбрасывается записью в него "1".// Деактивация режима автоматического перезапуска АЦП
PRV_ClearBit(ADCSRA, ADIF);
А так не знаю чем помочь.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
- Сообщения: 1163
- Зарегистрирован: Ср янв 05, 2011 16:25:15
... код не смотрел, а знак учитывается?prv1984 писал(а):моделирую в Протеусе, но вместо указанного в Datasheet значения 400, получаю 800. В чём можеть быть проблема?
Чтобы не было лишних ошибок выводы подключены таким образом, что знак положительный и всё равно результат не совпадает с расчётной формулой из datasheetChipKiller писал(а):... код не смотрел, а знак учитывается?prv1984 писал(а):моделирую в Протеусе, но вместо указанного в Datasheet значения 400, получаю 800. В чём можеть быть проблема?
Кто вообще может привести пример измерения силы тока с помощью диф. усилителя в ATmega16 (программно и схемно). Хотя бы самый примитивный??? Все сроки поджимают, а я уже неделю не могу ничего путёвого сделать.
Говно. ИМХО.prv1984 писал(а):диф. усилитель в ATmega16
The device also supports 16 differential voltage input combinations. ... If 1x or 10x gain is used, 8-bit resolution can be expected. If 200x gain is used, 7-bit resolution can be expected.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Сейчас вопрос стоит не в качестве и способностях усилителя, а в алгоритме его использования совместно с АЦП. Мне не нужна большая точность.Говно. ИМХО.
А что алгоритм? На 2 входа подаётся напряжение, на выходе имеем код, пропорциональный их разности.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Как правильно преобразовать полученный код в значение разности напряжений, а далее в ток??? Например, я получаю значение АЦП, равное 800 - сколько это в Вольтах и в Амперах? И насколько такое значение соответствует действительности???Gudd-Head писал(а):А что алгоритм? На 2 входа подаётся напряжение, на выходе имеем код, пропорциональный их разности.
800, если в десятичной системе, будет 800/1024*Vref = 2 В при Vref = 2,56 В.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Ваш расчёт актуален для определения напряжения при одиночном включении входа. В случае с дифференциальным включением это не срабатывает. Например у маня на одном из входов 2,56 в на другом 2,46. Результат АЦП-410. По приведённой Вами формуле 410 в десятичной системе это 410/1024*2,56 = 1,025В, хотя фактическая разница 10мВ.Gudd-Head писал(а):800, если в десятичной системе, будет 800/1024*Vref = 2 В при Vref = 2,56 В.
При значении АЦП 410 протеус показывает ток 40 А. Может это както взаимосвязано, а при значении АЦП 250 протеус показывает ток 20 А. Может это както взаимосвязано, т.к. при изменении напряжения всей цепи ток на амперметре и значение АЦП меняются пропорционально с небольшой погрешностью?
вот Вам и нелинейность. ток изменился в 2 раза, а напряжение на шунте меньше, чем в 2 раза.
либо как-то Вы криво читаете АЦП.
либо как-то Вы криво читаете АЦП.
Ставим плюсы: )
Конечно. В диф включении результат будет в пределах ±511.prv1984 писал(а):Ваш расчёт актуален для определения напряжения при одиночном включении входа.
Ну, во-первых, 2.56-2.46 = 0.1 В = 100 мВ. А с учётом умножителя на 10 как раз будет около 1 В.prv1984 писал(а):Например у маня на одном из входов 2,56 в на другом 2,46. Результат АЦП-410. По приведённой Вами формуле 410 в десятичной системе это 410/1024*2,56 = 1,025В, хотя фактическая разница 10мВ.
Какте ещё амперы? Давайте оперировать с напряжениями на входах МК.prv1984 писал(а):При значении АЦП 410 протеус показывает ток 40 А. Может это както взаимосвязано, а при значении АЦП 250 протеус показывает ток 20 А. Может это както взаимосвязано, т.к. при изменении напряжения всей цепи ток на амперметре и значение АЦП меняются пропорционально с небольшой погрешностью?
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Спасибо, что поправили. Действительно этот расчёт актуален и с помощью него можно определить разность напряжений. Остаётся теперь вычислить ток. Как правильнее это сделать зная разность напряжений, т.е. падение на шунте?
Через закон дедушки Ома: I = U / R.prv1984 писал(а):Остаётся теперь вычислить ток. Как правильнее это сделать зная разность напряжений, т.е. падение на шунте?
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Вы имеете ввиду так:Gudd-Head писал(а):Через закон дедушки Ома: I = U / R.prv1984 писал(а):Остаётся теперь вычислить ток. Как правильнее это сделать зная разность напряжений, т.е. падение на шунте?
I=Uпадения на шунте/Rшунта ?


