Привет.
Нашел схемку в интернете http://articles.greenchip.com.ua/3-0-24-0.html
Есть пара вопросов.
1. Что нужно сделать чтобы поменять шунт с 0,1 Ома на стандартный Шунт – 10А, 75mV.
Достаточно ли только изменить КУ операционника или нужно править программу МК?
Как это скажется на точности измерения?
2. Хотелось бы питать ОУ 5 -5,5 вольтами, можно ли это сделать?
3. На сколько нужен кварц?
1 Увеличить КУ, и сменить ОУ на какой нибудь дорогой прецизионный...
Менять программу МК ненужно.
Как скажется. Плохо.
2 Поставьте стабилизатор, например КРЕНку.
Тогда ОУ будет верхушку сигнала срезать и он не будет подниматься выше 3.6В примерно. А АЦП МК при этом измеряет от нуля до 5. Со всеми вытекающими.
3 Кварц вообще нужен, без него работать не будет (1МГц)
1.В общем понятно. Оставлю все как есть, только шунт сделаю 0,05ом и резисторы для ку пересчитаю.
2. Вопрос тоже отпадает.
3 Подкололи)
Действительно 1Мгц? В продаже чтото не вижу
На будующее, для общего развития.
Со скольки милливольт можно подавать на ОУ(понимаю, разные бывают, например среднего класса какие нибудь) чтобы на выходе не получать большие искажения, допустим 1%.
;CodeVisionAVR C Compiler V2.04.4a Advanced
;(C) Copyright 1998-2009 Pavel Haiduc, HP InfoTech s.r.l.
;http://www.hpinfotech.com
;Chip type : ATmega8
;Program type : Application
;Clock frequency : 1,000000 MHz
;Memory model : Small
;Optimize for : Size
;(s)printf features : long, width, precision
;(s)scanf features : int, width
;External RAM size : 0
;Data Stack size : 256 byte(s)
;Heap size : 0 byte(s)
;Promote 'char' to 'int' : Yes
;'char' is unsigned : Yes
;8 bit enums : Yes
;global 'const' stored in FLASH: No
;Enhanced core instructions : On
;Smart register allocation : On
;Automatic register allocation : On
Думаю, что кварц 1 МГц.
Насчет искажений незнаю, не сильный спец по ОУ. Но LM358 работает от 10мв, напряжение смещения. Есть AD822 у него напряжение смещения несколько милливольт.
Так же нужно смотреть насколько ОУ рейл то рейл и какой диапазон выходного напряжения. LM358 работает от -0.3В до Vcc-1.5В это пишут в даташите.
В принципе можно и его заточить под шунт 75мВ. Если питать от нуля тогда нижняя граница измерения будет не от нуля а от некоторого значения. Можно организовать отрицательное питание, чтобы опустить нижний предел измерения.
Чтобы точность и стабильность поднять нужно и напряжение падения на шунте поднять.
Про шумы и искажения более неразумею, может другие коты ответят.
Кстати, если очень хочется питание 5В, то можно перейти на внутренний ИОН 2.5В, тогда ОУ будет попадать в диапазон АЦП.
Но говорят точность и стабильность ИОНов atmel оставляет желать лучшего.
По питанию вопрос решил - 9В есть.
Шунт будет 0,015Ом (четыре стандартных шунта 75мВ последовательно). Максимальный ток через него - 20А. Следовательно сигнал на вход ОУ 300мВ - думаю теперь хватит.
У автора схемы при максимальном входе на мк 5В дисплей отображает 10А. То есть в прошивке нужно гдето править коэффициенты. Нужно поправить до 25А.
В прошивке (обвел красным квадратом) в строке где вычисляется ток стоит коэффициент 10 - это он?
Во второй строке где вычисляется напряжение прибавляют 400 - зачем мне не понятно.
Попробую еще с автором связатся.
Что то мне кажется у него все неправильно.
Нафига вычислять реальное напряжение на шунте
Операционником мы должны настроить так, чтобы при максимальном токе он выдал бы ровно 5В и АЦП преобразовал бы это в значение 1024. Не отупляю такой огород. u=55*u+400 это явно не напряжение получается а некий коэффициент напряжения.
Тоже самое и ток. a=a*10 если я так умножу, то получу кривое подобие.
Весь мой опыт программирования это бейсик в 10классе. Но и без опыта программирования я смотрю что у автора фигня какато.
Ну чтож, давно хотел научится программировать мк, наверное время настало
вот верная формула:
Напряжение на ноге МК = значение регистра ADC * 5В / 1024
Соответственно нужно это значение промасштабировать к значению шунта или делителя. В зависимости что измеряем. И это значение уже будет реальное напряжение и ток.
Если мы просто значение регистра умножим на 10, то получим ошибку. Видимо автор округляет значение регистра с 1024 до 1000. Тогда и расчет упрощается.
А +400 честно говоря вообще не догоняю что это.
Видимо 0.005 это грубое округление 5/1024
Ставьте CVAVR там есть генератор кода. Я им пользуюсь из за недостатка времени на изучение даташитов.
Правда это создает свои грабли, но это проще.
Всем спасибо. Устройство собрал, прошивку поправил, остался последний штрих - сбрасываются настройки при снятии питания. Достаточно ли для этого включить нужный фьюз или нужно править программу?
не понимаю, можно чуть-чуть поподробней - или пример, т.к. у меня знаний - только подправить циферки в CodeVisionAVR и скомпилировать прошивку.
Настроек всего две строчки - заданные напряжения и ток заряда.
as9 писал(а):не понимаю, можно чуть-чуть поподробней - или пример, т.к. у меня знаний - только подправить циферки в CodeVisionAVR и скомпилировать прошивку...
Пишите в еепром МК, после отключения все будет помнить.
Например:
eeprom unsigned int eep_I = 400; //определили переменную в еепром и задали ее начальное значение
eeprom unsigned int eep_V = 400; //то же самое для напряжения
//где то далее :
I = eep_I; // чтение из еепром значения тока
.......
eep_I = I; //запись значения в еепром
Попробовал пару раз вставить код в программу - высыпаются ошибки при компилировании. Почитал гугл.
По пути возникло несколько вопросов:
1. Нужно ли в CVAVR при использовании функции еепром подключать библиотеку еепром (думаю если есть, то она так и называется, и наверное по этому у меня не заработало)
2. Нужно ли код (запись в еепром) ставить (понимаю что нужно кое что дописать и это лучший вариант) после опроса кнопок, чтобы фактически запись в еепром производилась только при нажатии кнопок или достаточно (мне так проще, т.к. придется делать меньше изменений) использовать такую функцию записи в еепром, когда значение еепром проверяется в каждом цикле, но перезапись идет только если значение еепром изменилось.
3. Сильно ли это скажется на скорость работы
А то начиталься страшилок про ограниченый ресурс перезаписи, про потерю данных и замедление скорости работы контроллера.
Извеняюсь что сумбурно написал - своими словами так получилось.
Спасибо
Инклюд да нужно прописать.
Каждую секунду не пишите данные туда и все будет пучком. Можно копировать в ROM и там работать. Когда надо сохранить, опять кидаем в EEPROM.
Скорость да ниже.
Короче говоря используйте эту память как "винчестер". Нужно что то сохранить пользуйтесь. Все манипуляции предпочтительно делать в ОЗУ.
as9 писал(а):1. Нужно ли в CVAVR при использовании функции еепром подключать библиотеку еепром
Нет
as9 писал(а):2.....но перезапись идет только если значение еепром изменилось.
Так будет лучше всего, для этого добавьте пару переменных для хранения
значений тока и напряжения и сравнивайте с "новыми" значениями, если изменились, то запоминаем в еепром.
По сути будет как предлагал Gisteresis:
используйте эту память как "винчестер"
Кроме этого почитайте даташит на предмет установки фьюзов запрещающих запись в еепром при снижении питания.
as9 писал(а):3. Сильно ли это скажется на скорость работы
А то начиталься страшилок про ограниченый ресурс перезаписи, про потерю данных и замедление скорости работы контроллера.
В этой программе не критично по скорости. Ресурса Вам хватит, вручную же значения менять будете...
Чегото туплю я, не работает.
Вот код, жирным выделил что вставил:
Спойлер#include <mega8.h>
#include <delay.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>
#include <stdio.h> //библиотека в которой лежыт функция sprintf eeprom unsigned int eeAf=4000;
eeprom unsigned int eeUf=14200;
Af=eeAf;
Uf=eeUf;
//int Af=4000,Uf=14200;//отключил
unsigned long int u; //переменная для хранения напряжения в миливольтах
unsigned long int a; //переменная для хранения тока
unsigned long int w; //переменная для хранения значений потребляемой мощности
void incSkvag()
{
if (OCR1AL!=0) OCR1AL--;
}
void decSkvag()
{
if (OCR1AL!=255) OCR1AL++;
}
#define ADC_VREF_TYPE 0x00
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x64;
a=read_adc(3); // читаем значения ацп с порта 0
u=read_adc(5); // читаем значения ацп с порта 1
/*
Измеряем ток Ток протекающий через шунт вичесляется по закону Ома I=U/R R=0,1 ом, a U(падения напряжения на шунте) мы будем измерять. Так как АЦП у нас 10 битный то максимальное число которое вернет функция read_adc() будет равно 1024, ето число будет еквивалентом напряжения на входе adc0. Например если read_adc() вернул 512 то ето значит што на вход adc0 ми подали половину опорного напряжения Штобы вычеслить реальное напряжения нам нужно сложыть пропорцию опорное напряжения - 1024 искомое напряжения - a В нас опорное напряжения=5.12 Искомое напряжения = 5.12*a/1024 или Искомое напряжения = 0,005*a для простоты переведьом вольти в миливольты домножыв на 1000 Искомое напряжения = 0,005*a*1000 Здесь всьо хорошо но мы не учли коефициент усиления ОУ разщитывается по формуле Кус=1+R1/R2 подставив получим Кус=(1+4)=5 Реальное напряжения = 0,005*a*1000/5 получаем просто a
Измеряем напряжение Дальше измеряем напряжение на резисторном делителе Сложым пропорцию как описано выше и получим Искомое напряжения = 0,005*u*1000 Надо еще учесть коефициент резисторного делителя напряжения в нас он равен Кдел=(R1+R2)/R2 подставив получим Кдел=(10+1)/1=11 Рельное напряжения = 0,005*u*1000*11 */
u=37.5*u; //вычисляем значения напряжения в миливольтах
a=a*1000/40.96; // вычесляем значения тока по закону ома I=U/R=a/100*1000=a*10, в милиамперах
w=a*u; //вычесляем потребляемую мощность
//регулировка напряжения и тока
if ( (a>Af) || (a>23000) )//регулировка по току
{
incSkvag();
}
else
{
if (u>Uf)//регулировка по напряжению
{
incSkvag();
}
else
{
decSkvag();
}
}
}
while (1)
{
sprintf( k[2],"I=%u,%uA U=%u,%uV\nW=%u,%lu K=%i",
a/1000, //Целая честь тока
(a%1000)/100, //Дробная часть тока
u/1000, // Целая часть напряжения
(u%1000)/100, //Дробная часть напряжения
w/1000000, // Целая часть мощности
(w%1000000)/100000, //Дробная часть мощности
OCR1AL
); //формируем строку для вывода
//---------------------------------------------------------------
//работа с кнопками
if (PINB.2==0)
{
//переключаем меню
if (++i>2) i=0;
}
if (PINB.3==0) //проверяем нажата ли кнопка плюс
{
if (i==0) {Af=Af+100; sprintf( k,"Setup A=%i ma",Af); }
if (i==1) {Uf=Uf+100; sprintf( k,"Setup U=%i mv",Uf); }
}
if (PINB.4==0) //проверяем нажата ли кнопка минус
{
if (i==0) { Af=Af-100; sprintf( k,"Setup A=%i ma",Af);}
if (i==1) { Uf=Uf-100; sprintf( k,"Setup U=%i mv",Uf);}
} eeAf=Af;
eeUf=Uf;
lcd_clear(); //чистим дисплей перед выводом
lcd_puts(k); //выводим сформированую строку на дисплей
delay_ms(100); //делаем задержку
};
}
Потом конечно привяжу запись в еером к кнопкам.
В таком виде CVAVR не хочет читать из еепром значение - пишет: