Плывут показания АЦП Atmega8A - PU

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

Добрый день уважаемые! Помогите пожалуйста.
Написал программу для "термопечи", датчик температуры использую PT1000-5x25 (платиновый) купил тут: http://kosmodrom.ua/prodlist.php?page=0 ... E%E8%F1%EA

использую так же рейл ту рейл ОУ AD8552 для усиления и смещения шкалы.

Смущает меня качество датчика ... он может работать в диапазоне температур -70 ~ 500град. ? Нагрел его до 400град. керамика та что залита начала темнеть.

Но суть не в том. У меня когда на входе АЦП напряжение близко к максимальному - начинают прыгать значения с разбегом до 15 значений. Мультиметром замерял - четко напряжение.

Как бороться с этим?

Код преобразования данных такой:

Код: Выделить всё

   if(++timer_scan > 30 ) 
  {
   temp = read_adc(1);   // читаем температуру    
 
            temp /=2;
            temp = 512 - temp;
            temp -= 10; //  Формула преобразования данных     
            
         
            
       if(temp < 460) //  программная защита
       { 
            error=0;
       }
       else
       {
         error=1;
       }
    timer_scan=10; 
  }
я уже даже 9бит использую за счет деления на 2. Все равно когда код равен ближе к максимальному начинают происходить приколы.

Читал на одном форуме что это такая мега8А. Будто мега8 без индекса "А" ведет себя гораздо лучше.
Помогите советом пожалуйста. Проект надо сдавать... а я в такой прикол попал..
Последний раз редактировалось Artos Сб ноя 03, 2012 15:52:37, всего редактировалось 1 раз.
Контактная информация:
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1596
Зарегистрирован: Вс дек 14, 2008 20:36:47
Откуда: SPb

Сообщение saschai »

Смотри, что с опорным, возможно стоит за стабилизировать типа 431ой, у меня убегали показания изза протравы плюсового проводника под СМД корпусом восьмерки(опора питание), лечил сопелькой. в общем, скорее всего не код.
Реклама
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

Спасибо что ответили. Вот и я думаю что не код. У меня опорное висит на +5В пайка качественная стабилизация питания LM1117 везде стоит керамика и везде электролиты. Сигнал предварительно усиливается очень качественным ОУ на вход АЦП идет нормальный сигнал. Не знаю что делать...
Режим 10бит с отсечкой 1бита за счет деления. Получается режим 9бит.
Контактная информация:
Электрический кот
Сообщения: 1048
Зарегистрирован: Пт июл 30, 2010 11:49:03
Откуда: Украина

Сообщение vanyap1 »

У меня была та же проблема с мегой. Излечил - установкой дополнительного ИОНа в схему (ref5050).
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

1. LM1117 != ИОН. Поэтому не стоит сажать вход питания АЦП и опорный вход на цифровую шину питания. Для точных измерений используйте REFxxx или TL431 как более дешевый и более хреновый вариант.
2. Встроенный АЦП не особо славится точностью. Если возможно, используйте внешний АЦП.
3. Деление пополам не спасет от дрожания старших разрядов. Сделайте простейшую фильтрацию вычислением среднего из 10...100 последовательных выборок.
4. Используйте режим ADC Noise reduction.
5. И наконец можно уменьшить размах сигнала с ОУ чтобы он не попадал в эту нелинейную область.
Реклама
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

A скажите, как на си вычислить среднее? Я так понимаю надо создать массив из 10байт и писать туда значения ацп. Но как узнать с массива среднее?
Контактная информация:
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1596
Зарегистрирован: Вс дек 14, 2008 20:36:47
Откуда: SPb

Сообщение saschai »

Зачем так сложно, суммируй замеры, когда будет десяток или др. дели на 10 или др,
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

Брр... Не понял, можно пояснить подробнее не понимающему? :)
Контактная информация:
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

Все, догнал :) хороший метод! А главное оптимальный.
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Еще можно складывать восемь замеров, а потом сдвинуть вправо на 3 бита. Или 16 замеров - сдвиг 4 бита.
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

zero648 писал(а): Или 16 замеров - сдвиг 4 бита.
Как раз об этом подумал :) Должно быть оптимальнее чем деление. Хотя если компилятор умный он так и сделает.
Контактная информация:
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

А скажите пожалуйста, вот датчик имеет не линейную зависимость от температуры, есть ли какой нибудь простой метод решения этой проблемы?
Есть только одна мысль - завести массив и с него подставлять при определенных температурах.
Контактная информация:
orinoko

Сообщение orinoko »

Ну тут только табличный метод может решить вопрос преобразования.
И ещё хотелось бы вставить пару своих копеек по поводу среднего. Тут очень хорошо бы подошёл программный вариант подобия ФНЧ. Алгоритм очень простой (даже на асме 25 команд у меня занял)
пусть Xout - результат, для него должна быть выделена ячейка памяти, инициализируется нулём.
Xin - текущее входное значение
Xout = Xout* (K-1)/K + Xin/K
Таким образом вычисляется текущий результат. Он является предыдущим результатом для следующего расчёта. Коэффициент К - степень фильтрации, чем он больше, тем ФНЧ "более низкочастотнее".
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

orinoko писал(а):Xin - текущее входное значение
Xout = Xout* (K-1)/K + Xin/K.
Что то не врублюсь как этот метод работает.... Можете разьяснить подробнее? Имею ввиду пошагово.

Что у нас первое происходит, что второе и что третье? :) Запутался..
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Как раз об этом подумал :) Должно быть оптимальнее чем деление. Хотя если компилятор умный он так и сделает.
Для измерения медленных физических величин можно делать гораздо больше замеров - 1024, 4096 и т.д.
У меня вот датчик атмосферного давления работает, делаю 65536 замеров (в 4х-байтную переменную). Потом тупо забираю два старших байта (равносильно делению на 65536). Считается по фону, время обновления данных получается около 20 секунд, чего более, чем достаточно. И, разумеется, никакого шума (хотя на входе бардак).
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

можно пример кода?
А то сейчас ломаю голову.
Хочу 2секунды делать десяток замеров а потом вычислять результат.
Контактная информация:
orinoko

Сообщение orinoko »

Попытаюсь объяснить. Для упрощения принимаем К=4. Есть глобальная переменная Xout. Изначально в ней 0. Это результат работы "фильтра". В нашу функцию приходит текущее значение с АЦП (только что считали, тепленькое), это Xin. Что мы с ним делаем? Берём одну четвёртую от Xin, вот эта часть формулы: Xin/K, вычисляем три четвёртых от Xout (это число у нас глобальное, оно у нас имеет всегда значение, каторое посчитали при предыдущем вызове нашей ф-ии), вот эта часть формулы Xout* (K-1)/K, складываем полученные значения, и записываем обратно в переменную Xout.
Таким образом Xout - это результат ФНЧ, который вам нужен. И он же используется при следующем вызове нашей ф-ии. Ффух. надеюсь понятно объяснил. Проверьте в екселе - и сразу будет понятен этот принцип.фильтра
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт мар 04, 2011 13:06:42
Откуда: Украина, Ахтырка

Сообщение Artos »

наваял такой код, вроде должен работать.

Код: Выделить всё


   timer_scan++; 

  if(timer_scan < 40 ) 
  {  

    temp = read_adc(1);   // читаем температуру  
    temp_buff += temp;  

  } 
   else
  {
    temp = temp_buff / timer_scan; 
        
            temp /=2;
            temp = 512 - temp;
            temp -= 10; //  Формула преобразования данных     
            
         
            
       if(temp < 460) //  программная защита
       { 
            error=0;
       }
       else
       {
         error=1;
       }
       
               timer_scan=0;  
  }
сейчас буду пробовать. :)
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Хочу 2секунды делать десяток замеров а потом вычислять результат.
Две секунды складывайте, сколько влезет, кратно степени двойки. Будет что-то в районе 1024 (зависит от частоты АЦП)
можно пример кода?
Да легко (но асм):
Спойлер

Код: Выделить всё

;-------------------------------------------------------------------------------
; Вычисление среднего арифметического давления по 65536 отсчетам АЦП
;-------------------------------------------------------------------------------
run_pres_clear:

  lds r16,pres_cnt              ; Счетчик проходов
  lds r17,pres_cnt+1
  subi r16,1
  sbc r17,null
  sts pres_cnt,r16
  sts pres_cnt+1,r17
  brne rpc01                    ; Счетчик досчитал
    lds r16,pres_buf+2          ; Перебрасываем в очищенный результат
    lds r17,pres_buf+3          ; два старших байта буфера
    sts pres_clean,r16          ; Это будет равносильно делению на 65536
    sts pres_clean+1,r17
    sts pres_buf,null           ; И очистим буфер
    sts pres_buf+1,null
    sts pres_buf+2,null
    sts pres_buf+3,null
    ret

  rpc01:
  lds r16,adc                   ; В r16-r17 значение с АЦП
  lds r17,adc+1

  lds r20,pres_buf              ; r20-r23 буфер
  lds r21,pres_buf+1
  lds r22,pres_buf+2
  lds r23,pres_buf+3

  add r20,r16                   ; Складываем их.
  adc r21,r17                   ; Резульат будет в буфере
  adc r22,null
  adc r23,null

  sts pres_buf,r20              ; И сохраняем его обратно
  sts pres_buf+1,r21
  sts pres_buf+2,r22
  sts pres_buf+3,r23
ret
orinoko

Сообщение orinoko »

А вот моя версия :)

Код: Выделить всё

; Фильтр нижних частот 
FilterLowFreq:

 		lds		XH,	DataIIRVrmsBIN		; Предыдущее значение фильтра
		lds		XL,	(DataIIRVrmsBIN+1)
		; Нужно вычесть 1/4
		movw	Y,	X
		lsr		YH
		ror		YL
		lsr		YH
		ror		YL
		lsr		YH
		ror		YL
		;
		sub		XL,	YL
		sbc		XH,	YH
		;	Возьмём 1/4 часть от последнего значения, принятого с АЦП
		lds		YH,	DataAvgVrmsBIN
		lds		YL,	(DataAvgVrmsBIN+1)
		lsr		YH
		ror		YL
		lsr		YH
		ror		YL
		lsr		YH
		ror		YL
		;	Сложим с 3/4 от значения фильтра
		add		XL,	YL
		adc		XH, YH
		; Новое значение фильтра		
		sts		DataIIRVrmsBIN,	XH
		sts		(DataIIRVrmsBIN+1),	XL
		ret 
Ответить

Вернуться в «AVR»