Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Xmega ADC

Сообщений 1 страница 19 из 19

1

Это точно требует отдельной темы, в Xmega с ADC не всё так просто.
Первое, что оказалось проблемой - максимум опорное напряжение 1,6в., даже если использовать AREF и подать на него 3,3в., всё равно ничего не получится.
Чистого нуля по АЦП тоже нет.
Аналог инициализации Atmega в Xmega будет примерно такой:

Код:
Config Adca = Single , Convmode = Unsigned , Resolution = 12bit , Dma = Off , Reference = Intvcc , Event_mode = None , Prescaler = 512 , Ch0_gain = 1 , Ch0_inp = Single_ended , Mux0 = &B0_0000_000


Для получения данных:
W = Getadc(adca , 0 , &B0_0000_000 )

Где:
adca - входы порта А, входы порта B - типа того
0 - Номер используемого канала
&B0_0000_000 - а это понимать вот так:

0000 Pin0 ADC0
0001 Pin1
0010 Pin2
0011 Pin3
0100 Pin4
0101 Pin5
0110 Pin6
0111 Pin7
1000 Pin8
1001 Pin9
1010 Pin10
1011 Pin11
1100 Pin12
1101 Pin13
1110 Pin14
1111 Pin15 ADC15

Для получения данных с АЦП можно и так:
ADC0 = Getadc(adca , 0 , &B0_0000_000 )
ADC1 = Getadc(adca , 0 , &B0_0001_000 )
ADC2 = Getadc(adca , 0 , &B0_0010_000 )

Но вот не задача, начальное значение 9-11.
Тут то и беда, к Xmega чего-то замутили с DAC и какой-то калибровкой чего-то.
Есть у кого информация, как можно просто оцифровать аналоговый сигнал?

Отредактировано Ev3658 (2017-12-24 15:06:37)

0

2

Есть ещё один не понятный случай.
У меня срабатывает прерывание по INT0 порта С по смене значения любого ADC, не могу понять причину, условие прерывания не выполняется точно, а вот само прерывание срабатывает.

Код:
$regfile = "xm256a3def.dat"
$crystal = 33177600
$hwstack = 225
$swstack = 225
$framesize = 225

$lib "xmega.lib" : $external _xmegafix_clear : $external _xmegafix_rol_r1014


Config Osc = Enabled , Extosc = Enabled , Pllosc = Enabled , _
Range = 2mhz_9mhz , Startup = Xtal_1kclk , Pllsource = Extclock , Pllmul = 9 , Plldiv2 = Disabled , 32khzosc = Disabled       ', 32khzpowermode = Normal
Config Sysclock = Pll , Prescalea = 1 , Prescalebc = 1_1
Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled , Hi = Enabled

'============== АЦП
Config Adca = Single , Convmode = Unsigned , Resolution = 8bit , Dma = Off , Reference = Intvcc , Event_mode = None , Prescaler = 512 , _
Ch0_gain = 4 , Ch0_inp = Single_ended , Mux0 = &B0_0011_000
Config Pina.3 = Input
Config Pina.4 = Input
Config Pina.5 = Input

'Порт матрицы клавиатуры (перебор)
Portkn Alias Portd
Config Portkn = Output
Config Xpin = Portd , Slewrate = Enabled , Outpull = Pulldown      ' (по порядку: , ограничение скорости порта, порт подтянуть к минусу)

'Порт проверка срабатывания кнопок матрицы
Pinkn Alias Pinc
Config Portc = Input 
Config Xpin = Pinc , Outpull = Pulldown , Slewrate = Enabled , Sense = Rising '(по порядку: Подтянуть к минусу, ограничить скорость порта, вызывать событие по подъёму фронта)
Portc_int0mask = &B0111_1111 'Маска прерывания порта C (7 бит это выход)

'Порт свечения светодиодов, чтоб ноги лишние не тратить, светодиоды сидят на матрице клавиатуры.

Ledkn Alias Portc.7
Config Ledkn = Output
Config Xpin = Portc.7 , Invertio = Enabled 'Аппаратная инверсия пина

'==========Переменные
Dim Knl As Byte
Dim Knh As Byte
Dim Led As Byte
Dim Ledtm As Byte

Dim Spr As Byte
Dim Fpr As Byte
Dim Rfpr As Byte

Portkn = 1 'для сдвига бита

'====== Прерывания 
Config Tcf0 = Normal , Prescale = 256 'Запуская таймер
Tcf0_per = 300 'Ограничиваю счёт

On Tcf0_ovf Knopkitm  'Прерывание по переполнению таймера
Enable Tcf0_ovf
 
On Portc_int0 Knopki 'Прерывание по маске INT0 порта С
Enable Portc_int0 , Lo   'Включаю прерывание с приоритетом выше.

Enable Interrupts


Do
!Nop
Loop

Knopki:
     Knl = Pinkn And &B0111_1111
     Knh = Portkn
     Portc_intflags.0 = 1 'Убираем флаг прерывания, который мог остаться от дребезга
Return

Knopkitm:
        Rotate Portkn , Left   'Сдвигаем бит матрицы клавиатуры
        Ledkn = Led.ledtm 'Зажигаем светодиод если он совпадает с битами матрицы
        If Ledtm < 7 Then 'Ограничиваем счёт битов и одновременно 1 раз за 8 циклов опрашиваем АЦП
          Incr Ledtm
          Else
          Ledtm = 0
          Spr = Getadc(adca , 0 , &B0_0011_000 )
          Fpr = Getadc(adca , 0 , &B0_0100_000 )
          Rfpr = Getadc(adca , 0 , &B0_0101_000 )
        End If
Return


Так вот, прерывание INT0 срабатывает не по условию, так как Knl = Pinkn And &B0111_1111 - равно нулю в момент ложного прерывания.

Либо каким-то образом АЦП влияет на маску прерывания порта, либо чего-то не то.

Отредактировано Ev3658 (2017-12-24 15:06:00)

0

3

Буду рад любой информации по ADC Xmega, мне до лета надо провести ряд удачных экспериментов и создать кисть руки, которая будет сжиматься от импульсов нервных окончаний, а тут без АЦП и производительности Xmega вообще никак.

0

4

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

0

5

Это точно, не пойму вот одно, есть процесс калибровки АЦП или ЦАП - он обязателен или нет, ведь в контроллере записано изготовителем какое-то эталонное значение и типа его надо загружать куда-то.

0

6

Насколько я помню, вроде бы надо прочитать эту таблицу и от туда, записать значения в АЦП/ЦАП.

https://www.mcselec.com/index2.php?opti … +calibrate

0

7

И точно, оказывается калибровочное значение не только в Xmega но и в Mega328p! Не знал даже.

Код:
var = READSIG(offset)

Но это не дало эталонный нуль:

Код:
Adca_call = Readsig(&H20 )
Adca_calh = Readsig(&H21 )

Отредактировано Ev3658 (2017-12-25 18:45:27)

0

8

Ну, тогда надо читать про калибровку, а вообще проверь питание на предмет помехов и входящий сигнал.

0

9

Ev3658 написал(а):

Опорное напряжение как не старался, но больше 1,6 вольта не получается и это в режиме обычного замера. Хуже того, абсолютный ноль получить не получается.
Вот, горячая тема про ADC, сам скоро буду родственнице протез руки пытаться сделать, хотелось бы на Xmega - Xmega ADC

На самом деле, можно всё сделать на хмеге, но АЦП взять внешний и повесить расширитель аналоговый. Я на хмегу вешал 16-бит АЦП по SPI и без проблем читал всё от туда, звук эффекты делал/игрался (затем это всё превратил в АРУ, но нормально не хватало производительности на два канала).

На счет калибровки: брать заводские настройки необязательно, можно поиграться и попробовать их самому подобрать.

На счет INT0: на сколько я помню, там система прерываний делиться по портам (целиком), т.е. инициализируешь прерывание скажем по порту А, когда он срабатывает, начинаешь разбирать причину его срабатывания (какая ножка). Возможно: либо неправильно настроил срабатывание, либо конфликт событий и на одном порте не может висеть АЦП+INT. Тут мне трудно сказать, ибо с прерываниями я работал (цифровыми), а вот в перемешку с АЦП - нет.

0

10

RDW написал(а):

.... с АЦП - нет.

В Xmega есть прерывания по значениям ADC, там всё хорошо сделано кроме самого АЦП. Так-же есть и умножитель АЦП значения, хорошая такая база для исследования. Можно опорное с ЦАП брать, ещё температуру кристалла и чего-то ещё.
На калибровочные значения реакции не получил.

Отредактировано Ev3658 (2018-02-28 23:50:48)

0

11

В общем промежуточный итог (ещё не всё пока потыкал):

- на прескейлере 512 получил 0 на gnd, но вычислениями, без них никак, ибо даже в датащите написано, что нижняя граница АЦП земли может достигать до 200 значения. По факту получил от 0 до 3919 значений, но тут пришлось среднее арифметическое вычисление делать по 256 выборкам, зато значение стоит как вкопанное (уменьшать ещё не пробовал, но при прескейлере 512 оно ну оч точно считает (тот самый шум) и скорость падает измерений 8000000/512=15625 выборок).
- если поставить прескейлер 4, то считает грубо, но тогда стоит как вкопаное без средней арифметического вычисления и следовательно ещё снижает динамический диапазон (верхнее значение).
- калибровку загружаю, всё по феншую как описано в датащите, но да, толку мало, можно даже не грузить. Вручную значения менять не пробовал, надо будет поиграться.

Вообще вспоминая как я в своё время возился с операциониками, там не всё так просто, как раз картина работы АЦП сильно напоминает как раз работу с ними, ибо куча настроек по режимам работы (семеричный/несимметричный, коэффициент усиления), в общем от сюда вся эта свястопляска с не нулями и не полным размахом, надо как-то по хорошему делать внутреннюю автоблокировку. Вчера попытался на скорою руку это сделать - не получилось (вначале переключить настройками на анализ земли (которой там кстати аж два типа) и всё осложняет перевод систем измерения (ибо надо переходить в режим "differential input without gain", чтобы был доступен этот функционал).
В общем у ХМеги настоящая аналоговая схема на входе, не просто игрушка как во всех остальных АВРках.

0

12

Забыл ещё сказать, не измерял какое напряжение было при 3919, но резистор тупо выкручивал на макс до 3.3В, не на долго, канал АЦП оставался целым.

0

13

3919 значение (с учетом вычетом до нуля) - это 1.960В (не 2 скорее всего потому, что у меня в схеме на AVcc дроссель стоит).
Поигрался калибровкой, эта штука меняет значения АЦП в очень мелких (микро) масштабах. Причем сам АЦП шумит и можно подобрать такие значения, при которых шум чуть уменьшится/изменится (характер его).
Вообще вся схема очень критична к внешним помехам, только сделав 3-й фильтр (фильтр на фильтр, фильтр на логике) с небольшой усреднённкой, удалось получить стабильные значения, но скорость маленькая. Оцифровка одного канала при прескейлере 128, идёт на скорости 102 Гц.  :confused:
Делал без всяких событий и DMA, смысла не вижу (всё равно фильтры всё сжирают).
Без фильтров или на легких можно делать осцилл, как раз напоминает его работу.  :rofl:

Играюсь дальше.

ps: интересная тема http://www.forum.easyelectronics.ru/vie … amp;t=2316

Отредактировано RDW (2018-03-03 15:48:22)

0

14

Замечена некая закономерность, если измерение ближе к земле, то дрожание младших разрядов выше.
Если использовать фильтр кальмана, то результат значительно лучше, но есть некая инерционность (которая в принципе настраивается), работает в разы шустрее чем предыдущие варианты.

15,06КГц, Prescaler = 128, Kalman, GND (12-bit, без оптимизации):

Код:
Ch0: 2
Ch0: 3
Ch0: 3
Ch0: 3
Ch0: 4
Ch0: 4
Ch0: 4
Ch0: 6
Ch0: 5
Ch0: 5
Ch0: 4
Ch0: 3
Ch0: 4
Ch0: 4
Ch0: 5
Ch0: 5
Ch0: 5
Ch0: 5
Ch0: 4
Ch0: 4
Ch0: 5
Ch0: 6
Ch0: 4


15,06КГц, Prescaler = 128, Kalman, статическое значение где-то середина (12-bit, без оптимизации):

Код:
Ch0: 1187
Ch0: 1780
Ch0: 2077
Ch0: 2225
Ch0: 2301
Ch0: 2337
Ch0: 2356
Ch0: 2364
Ch0: 2369
Ch0: 2371
Ch0: 2373
Ch0: 2374
Ch0: 2373
Ch0: 2373
Ch0: 2375
Ch0: 2375
Ch0: 2375
Ch0: 2375
Ch0: 2374
Ch0: 2373
Ch0: 2373
Ch0: 2374
Ch0: 2374
Ch0: 2374
Ch0: 2374
Ch0: 2374
Ch0: 2374
Ch0: 2373
Ch0: 2374
Ch0: 2375
Ch0: 2374

Дрожание можно задавить при желании обычной делением (как нормальным делением, так и сдвигом).

А вообще, если все результаты конвертировать в 8-бит, то вообще результат на выходе отличный и никакие там фильтры не нужны.  :crazyfun:

16,02КГц, Prescaler = 128, GND (8-bit, без оптимизации):

Код:
Ch0: 0
Ch0: 0
Ch0: 0


16,02КГц, Prescaler = 128, статическое значение где-то середина (8-bit, без оптимизации):

Код:
Ch0: 154
Ch0: 154
Ch0: 154


16,02КГц, Prescaler = 128, максимальное значение (8-bit, без оптимизации):

Код:
Ch0: 255
Ch0: 255
Ch0: 255

8-бит деление на коэффициент 15.380, т.к. мой макс размах 3922 (теперь понятно почему у большинства осциллов 8-бит, они стабильнее в разы, а АЦП на большую разрядность требуют запас битности).

Для моего проекта большая разрядность не нужна, думаю остановлюсь на последнем варианте.

0

15

Пользоваться штатным переключением "Resolution = 8bit" нет никакого смысла, оно криво работает, т.к. есть так же нижняя граница обрезания (у меня в районе значения 10). Т.е. теряем весь динамический диапазон.
Т.ч. ставим 12-бит и дальше тупо преобразуем:

Код:
Const Adc_a_offset = 172

Dim W As Word
Dim Calc As Single

   W = Getadc(adca , 0 , 0)
   If W >= Adc_a_offset Then                                'We don't want to subtract more than the OFFSET
       W = W - Adc_a_offset
   End If
   Calc = W / 15.380                                        ' 8-bit convert
   W = Int(calc)

   Print "Ch0: " ; W

0

16

Как оказалось, мне для моей идеи четкие 8-бит не подходят, нужна чувствительность (большая разрядность АЦП), в итоге решил не использовать никакие фильтры и брать как есть 12-бит. Т.к. особенность моей идеи не требуют четкой фильтрации, применил обычный калибратор. Т.е. при включении, система калибруется сама (64 датчика) от минимального значения помехи до максимального. Дальше эти параметры применяются. Эффект мне пока нравится. Но чувствую надо брать АЦП вообще на 16+ бит.

http://s3.uploads.ru/t/Uhvz3.jpg

Может потом заморочиюсь и сделаю уникальную калибровку для каждого датчика (а не на всё разом).

Т.ч. проблема в шумности АЦП не актуальна от типа задач.

0

17

Ого, вот это заморочки )))
А ноль получается нулём сделать? У меня почему-то при 8 битном стабильно значение 11 - даже на GND если подтянуть.

0

18

Ev3658 написал(а):

А ноль получается нулём сделать? У меня почему-то при 8 битном стабильно значение 11

Ты невнимательно читал всё то, что выше старался писать. :) Там даже код есть.
Пост номер 15.

зы: стоит всё как вкопанное!  :cool:

0

19

Если всё ещё бегаешь в догадках, то настройка АЦП выглядит так (у меня):

Код:
Config Adca = Single , Convmode = Unsigned , Resolution = 12bit , Dma = Off , Reference = Intvcc , _
Event_mode = None , Prescaler = 128 , Sweep = Ch0 , _
Ch0_gain = 1 , Ch0_inp = Single_ended , Mux0 = &B0_0000_000

0