Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
03.08.2012, 12:33
|
#21
|
Почётный гражданин KAZUS.RU
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 6,916
Сказал спасибо: 2,980
Сказали Спасибо 3,161 раз(а) в 2,146 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от _Артём_
|
Не понял причём тут BOD?
|
При том, что источник опорноно напряжения дла аналоговых узлов (BOD, компаратор и АЦП) - один. Если включен BOD или компаратор, то опорный источник уже вышел на режим и задержка не нужна.
|
|
|
|
03.08.2012, 14:46
|
#22
|
Супер-модератор
Регистрация: 03.05.2007
Сообщений: 2,695
Сказал спасибо: 28
Сказали Спасибо 4,509 раз(а) в 956 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от Dimitrij
|
Мне посоветовали: для того, чтобы показания не так прыгали, пропустить первый замер
|
Сообщение от _Артём_
|
Вроде правильно.
Можно еще несколько раз мерять с накоплением результата в сумму. И с ней работать.
|
Сообщение от ut1wpr
|
Подобное может иметь место только после переключения канала. В таком случае достаточно просто отработать преобразование не вычитывая результата.
|
Подытожу три цитаты.
1. Совет полезный, но реализация... именно "вроде". ut1wpr уже Вам указал - не надо читать первый результат, а значит и преобразование должно быть не одиночным, как в той портянке с первой страницы. Тогда контролируется флаг окончания преобразования, первый пропускается, а по второму считывается значение ADCW. Обычно это делается в обработчике прерываний от ADC. У вас каждый раз при входе в п/пр read_adc инициируется единичное преобразование и по его окончании (как только встал флаг: ADCSRA & 0x10) считывается ADCW. Где второй замер то? Он будет только в следующем заходе в п/пр, т.е. опять выбор канала, старт преобразования и т.д. "Пони бегают по кругу..."
2. Про прыжки показаний. Вам наверное подразумевали младшие разряды значения, которые будут перемаргивать при частом чтении ADC. Ну так тогда усреднять надо в разумных временных пределах, а не как Вы делаете с влажностью. Ну усреднили за несколько десятков микросекунд 6 показаний и что? За это время влажность воздуха в квартире изменилась? Позвольте заметить, что все физические величины, измеряемые в данном случае имеют относительно медленные изменения во времени. Представьте себе - как возможно изменить ту же влажность за несколько десятков микросекунд. Даже плюхнутый в ведро воды датчик не мгновенно отреагирует - нужно время на намокание. Так какой смысл в усреднении 6 значений влажности за сотые доли секунды? Чёто с DS-кой вы такие финты не проводите, - обновляете раз в секунду. Хотите усреднить, - заводите отдельные переменные или обновляемые массивы из N последних считанных значений на основе их и усредняйте, например, раз в 2, 3, 10, 20 сек или как заблагорассудится.
3. Ну и еще по поводу "в Протеусе все идет". Вы пользовали старую версию с библиотекой AVR.DLL для Меги 8, для новых с AVR2.DLL, которые имеют намного меньше глюков тут же начинает бомбиться многократное предупреждение "горчичник" касательно вывода на LCD, что и не мудрено при вашем построении программы - прерывания почти все время в разрешении и запущенный таймер ими благополучно рвет процесс обмена с LCD, который в п/пр lcd_output растянут аж на 4 стадии. В ОЗУ Меги 8 вполне достаточно места, чтобы сформировать два массива строк по 16 символов, а потом быстро "выплюнуть" их в LCD, не смакуя этот процесс, как гаванскую сигару.
Ну, в общем продолжать про то, что "причесывать в коде" можно до бесконечности... решайте сами с чего начнете путь праведный.
ЗЫ Еще насчет LCD, уже схемотехнически, - а не проще его унести на порт D, чтобы не иметь проблем с часто обновляемым PWM.
Последний раз редактировалось Halex07; 03.08.2012 в 15:03.
|
|
|
|
03.08.2012, 15:19
|
#23
|
Гражданин KAZUS.RU
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от ForcePoint
|
При том, что источник опорноно напряжения дла аналоговых узлов (BOD, компаратор и АЦП) - один. Если включен BOD или компаратор, то опорный источник уже вышел на режим и задержка не нужна.
|
Простите, а с чего вы взяли (применительно к BOD). Просмотрел даташит, такого не нашёл. Можно ссылку в этой части? Например для работы АЦП с внутренним опорником требуется внешняя ёмкость. Для BOD такого абсолютно не требуется. Да и вообще требования по точности к BOD +/- лапоть, так что я не вижу смысла увязывать эти узлы вместе. В некоторых MCU используются оконные BOD, что тоже как-то не очень вяжется. В ARM вообще BOD постоянно включен, а опорника часто нет и питание на все аналоговые узлы подаётся строго раздельно, то есть там 100% такое невозможно. Короче, у меня сомнения ... Развейте.
|
|
|
|
03.08.2012, 16:01
|
#24
|
Почётный гражданин KAZUS.RU
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 6,916
Сказал спасибо: 2,980
Сказали Спасибо 3,161 раз(а) в 2,146 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от SasaVitebsk
|
Простите, а с чего вы взяли (применительно к BOD). Просмотрел даташит, такого не нашёл.
|
Опорник один, разные (если надо) выходные - формируются буферными усилителями. Конкретно, например - для ATmega8A, в разделе 10.3 (DS от 2009 года):
Сообщение от ATmega8A
|
Internal Voltage Reference
ATmega8A features an internal bandgap reference. This reference is used for Brown-out Detection, and it can be used as an input to the Analog Comparator or the ADC. The 2.56V reference to the ADC is generated from the internal bandgap reference.
|
|
|
|
|
03.08.2012, 18:24
|
#25
|
Почётный гражданин KAZUS.RU
Регистрация: 07.05.2008
Адрес: Мурманск
Сообщений: 1,300
Сказал спасибо: 461
Сказали Спасибо 526 раз(а) в 273 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Я фильтрацию делал так:
Цитата:
|
#define SWAP(A, B) {int t = A; A = B; B = t;}
// 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;
}
unsigned int real_data(unsigned char data) //усредняем по 16-ти измерениям
{
unsigned char i,j;
unsigned int summ;
unsigned int mass[16];
unsigned int tmp;
for (i=0; i‹16; i++) // делаем 16 измерений подряд
{
tmp = read_adc(data);
delay_us(100); //через 100 мkсек
mass[i]= tmp;
};
for (i = 15; i › 0; i--) //сортируем замеры пузырьковым методом
{
for (j = 0; j ‹ i; j++)
{
if (mass[j] › mass[j + 1])
SWAP( mass[j], mass[j + 1] );
}
}
summ = 0;
for (i=5; i‹13; i++) summ = summ + mass[i]; //откидываем 4 наименьших значения и 4 наибольших значения и складываем 8 средних сначений
return summ››3;//делим на 8
}
|
Последний раз редактировалось IOPA4; 03.08.2012 в 18:28.
|
|
|
|
03.08.2012, 19:41
|
#26
|
Почётный гражданин KAZUS.RU
Регистрация: 19.08.2006
Адрес: Львов
Сообщений: 1,616
Сказал спасибо: 65
Сказали Спасибо 315 раз(а) в 264 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от IOPA4
|
Я фильтрацию делал так:
|
В принципе можно и так. Стартеру ветки нужно уяснить, что это будет как бы один замер, усредненный по N одиночным, следующим один за другим. Чтобы получить усредненный результат для вывода нужно прежде всего задатся временнЫм окном, внутри которого и будет производится усреднение. Скажем, раз 10-20-30 секунд. В нем тоже можно применить фильтрации, как простые, так и сложные. Зависит от типа датчика, характера среды и черт знает от чего. Весьма субъективный фактор.
Мне кажется, что мы ушли далеко в сторону. Автору надо сначала разобраться с элементарными функциями, а мы в метрологию поперли..
__________________
С уважением,
Vic / ut1wpr
|
|
|
|
03.08.2012, 20:19
|
#27
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от Halex07
|
контролируется флаг окончания преобразования, первый пропускается, а по второму считывается значение ADCW. Обычно это делается в обработчике прерываний от ADC.
|
и
Сообщение от Halex07
|
В ОЗУ Меги 8 вполне достаточно места, чтобы сформировать два массива строк по 16 символов, а потом быстро "выплюнуть" их в LCD, не смакуя этот процесс, как гаванскую сигару.
|
А как это делается на практике? На просторах интернет конкретных примеров что-то не нашел, а в теории ничего не понял!
|
|
|
|
06.08.2012, 10:13
|
#28
|
Супер-модератор
Регистрация: 03.05.2007
Сообщений: 2,695
Сказал спасибо: 28
Сказали Спасибо 4,509 раз(а) в 956 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от Dimitrij
|
А как это делается на практике? На просторах интернет конкретных примеров что-то не нашел, а в теории ничего не понял!
|
Че-то потерял эту тему... потому не ответил сразу. А оно Вам надо? Вы и так наслушались дурных советов, которым не всегда нужно следовать. Хотя бы с той же задержкой. Загляните в книжку Трамперта "Измерение, управление и регулирование с помощью AVR-микроконтроллеров" - вот Вам скриншот, нужное выделено желтым. Вот и решите для себя, надо подождать зарядки кондера, али и так сойдет... А то пока в вашей теме больше BOD-аются, чем дельных советов дают. Для однократного преобразования код, который сформировал кадаАВР вполне работоспособный и второе преобразование подряд на том же канале по большому счету ни к чему, вот к чему я Вас подводил. Ну а если уж очень хочется, то используйте бит ADFR регистра ADCSRA для запуска непрерывного преобразования и читайте по второму флагу ADIF.
А что каcается LCD, то у Вас объявлен один массив: char lcd_text[33]; Так вот на фига Вам резервировать 34 ячейки памяти, если Вы не пользуютесь скроллингом? Сделайте два по 16 для двух строк, например lcd_str1[15] и lcd_str2[15]. Потом printf-м отформатировали каждую строку полностью с нужными значениями через lcd_puts за два приема выплюнули в нужные места LCD, а на время вывода можно еще и прерывания запретить, чтоб уж совсем гарантированно вывод прошел. А то Вы то и дело рюхаетесь с LCD, то один кусочек, то перевод в другую строку, то еще кусочек строки. Тут не мудрено словить кучу прерываний в процессе, а у HD44780 свои времянки есть и их тоже желательно соблюдать, а то он Вас не поймет.
ЗЫ ну а по обработке результатов, то бишь усреднению, читайте вумные книжки по цифровой обработке сигналов. Там все приемы описаны, один Вам уже предложили, хотя и не самый производительный, можно воспользоваться, например, скользящим средним, - примеров в сети туча, или вообще экспоненциальным скользящим средним, чтобы не забивать ОЗУ лишними значениями, тут уже Вам самому решать.
Ну и напоследок я, честно говоря, таки не понял в чем фишка использования LM35 - это от большой бедности или как? При REFе 5V точности не будет никакой, если не усилить сигнал. Гораздо логичнее довесить еще один DS18B20, тем более что стоят они ну чуть подороже LM, а гемора с обработкой результата меньше на порядок. Про автоматическую регулировку яркости подсетки LCD, я уж вообще не буду распространяться, но честно говоря, она нужна там "как рыбе зонтик", это все таки не LED, хотя может и ошибаюсь, и у ТС вооще OLED, а вот там да, с яркостью перебор.
Последний раз редактировалось Halex07; 06.08.2012 в 10:43.
|
|
|
|
06.08.2012, 17:38
|
#29
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от Halex07
|
Для однократного преобразования код, который сформировал кадаАВР вполне работоспособный и второе преобразование подряд на том же канале по большому счету ни к чему, вот к чему я Вас подводил.
|
В принципе, я так и сделал, на показаниях это не отразилось.
Сообщение от Halex07
|
Сделайте два по 16 для двух строк, например lcd_str1[15] и lcd_str2[15]. Потом printf-м отформатировали каждую строку полностью с нужными значениями через lcd_puts за два приема выплюнули в нужные места LCD, а на время вывода можно еще и прерывания запретить
|
Не уверен, правильно ли я сделал, но только с sprintf
Код:
|
void lcd_output(void) // функция вывода на индикатор
{
sprintf(lcd_str1,"%+.1fC"" ""%.1f""%%"" ",temp, vlazhnost);
sprintf(lcd_str2,"%+.1fC"" ""%.0fmm",temp1, davlenie);
#asm("cli")
lcd_gotoxy(0,0);
lcd_puts(lcd_str1);
lcd_gotoxy(0,1);
lcd_puts(lcd_str2);
#asm("sei")
} |
Не нравится только, что в зависимости от показаний температуры, изменяются знакоместа влажности и давления (при меньшем числе знаков смещаются влево). Можно ли это как-то исправить? А с printf у меня не получилось, компилятор требует на выходе flash unsigned char, а lcd_puts- unsigned char.
А датчик температуры LM35 заменю на DS18B20, просто я не знал, что при выводе в sprintf можно корректировать его показания. Можно ведь к примеру так temp1+4?
|
|
|
|
06.08.2012, 17:48
|
#30
|
Почётный гражданин KAZUS.RU
Регистрация: 19.08.2006
Адрес: Львов
Сообщений: 1,616
Сказал спасибо: 65
Сказали Спасибо 315 раз(а) в 264 сообщении(ях)
|
Re: Помогите разобраться с кодом на СИ для ATmega8
Сообщение от Dimitrij
|
Не нравится только, что в зависимости от показаний температуры, изменяются знакоместа влажности и давления (при меньшем числе знаков смещаются влево). Можно ли это как-то исправить?
|
У вас в руках есть устройство, собранное вами же. Используйте его для изучения форматов мощной функции printf. Почитайте хотя бы здесь http://ru.wikipedia.org/wiki/Printf, внимательно почитайте, напишите простенькую программу вывода и погоняйте по всем возможным вариантам. Сами поймете, и других потом учить будете. ![Улыбка](images/smilies/icon_smile.gif) Это лучший способ научиться, гораздо лучше, чем спрашивать и ждать ответа.
__________________
С уважением,
Vic / ut1wpr
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 01:48.
|
|