Увы, "чудес не бывает". В том смысле, что при увеличении частоты дискретизации АЦП блока .. нет, точность остается в пределах заданных 8 бит, как и велено по даташиту .. но эта "зараза" тупо игнорит такты своей частоты и максимально чего отдает - это около 335 кГц. По крайней мере для Мега2560. Установка делителя 1:2 на самом деле не ускоряет блок АЦП до ожидаемых 16/2/13 = 615кГц результатов. Только чуть больше 300: примерно 5,4 тиков АЦП на период таймера на предельной частоте его работы 16/256=62,5кГц. (на 100 отсчетов АЦП попадает 18.5 периода)
------
<del> Предыдущие выводы оказались неверны при "детальном осмотре".
И так работа АЦП ATmega2560-16au с кварцем 16Мгц.
1. АЦП нормально функционирует на всех режимах делителя АЦП (ADPS0..ADPS2), в т.ч. на частотах блока АЦП в 8,4,2 Мгц, кроме заявленного в даташит "max 1Mhz". В том смысле, что он пытается снимать показания, а не "вешается наглухо".
2. Съем показаний всегда 10 бит, при любой частоте тактирования АЦП. Иное дело точность этих показаний.
3. Точность АЦП сильно зависит от (в порядке убывания важности, мое ИМХО):
а) схемотехники подключения выводов - особенно разводка заземления;
б) стабильности питания блока АЦП и опорного уровня;
в) наличия сигналов на физически соседних ножках АЦП, например настроенных как "выход";
г) выходного сопротивления источника сигнала - за это есть даже указание в даташит "не более 10кОм", а лучше менее и значительно;
д) запрета этой ножки как входа в регистрах DIDRx - подавление шума входной цепи ноги - тоже есть в даташите, но у компаратора;
е) СКОРОСТИ работы АЦП;
ж) применение способов шумодава, описанные в даташите;
Некоторые пункты, наверное можно поменять местами, "д,е,ж" мало отличаются друг от друга и вместе с "г" - определяются проблемой переключения мультиплексора с одного входа на следующий и скоростью рассасывания заряда на измерительной ноге АЦП от предыдущего замера. В целом - мультиплексор блока АЦП и есть главный источник проблем быстрого съема точных показаний.
4. Время измерения. Вот тут кроется основная засада расхождения оценки скорости блока и реальности. Дело в том, что в даташит указано расплывчато и в нескольких местах: Цикл замера 13..13.5 тактов, разогрев блока 12 тактов перед первым замером после включения, фиксация результата в зависимости от режима от 0.5 до 1.5 тактов блока АЦП .. плюс(!) плывущее время задержки обнаружения программой факта завершения замера, поскольку АЦП выставляет процу состояния согласно своему тактированию, а проц тактируется своим генератором. Т.е. может пройти ещё в среднем до 1/2 такта АЦП пока до программы допрет что замер завершен. Итого имеем (0..12) + (13..13.5) + (0.5..1.5) + (0..1) = около 15 тактов АЦП на замер.
5. Замер АЦП ведет вполне стабильно, ничего не "пропускается" как писал ранее. Вполне способен вести замеры на 8Мгц тактовой АЦП и теоретически можно иметь частоту дискретизации: 16/2/15 = 533(1/3) кГц!
Но, при прямом однократном замере в это время плюсуется блок запуска АЦП на замер + блок переноса результата замера в ОЗУ. Цикл, хотя и небольшой, но тем не менее на "С" реализации занимает НЕ МЕНЕЕ 20 таков ЦПУ (на асм можно ужаться до 9-11 тактов). Итого, в прямом режиме получить такую скорость нереально и она падает до .. 15*2+20 = 50 тактов ЦПУ на цикл замера И переноса данных или частота дискретизации составит 16000/50 = 320кГц. Ровно эту частоту я и получил в своих экспериментах на делителе 1:2 (ADPS0..2 = 1)!
Вывод: получить скорость дискретизации в 533кГц можно только в аппаратной обработке прерывания ADC с тщательным прописыванием этого обработчика, чтобу его работа укладывалась в 30 тактов ЦПУ вместе со "входом/выходом" из обработчика, а для надежной работы надо ещё иметь "запас" тактов в 10-12.
6. Точность измерения на повышенном тактировании АЦП. .. измеряет он всегда по 10бит, но вот "что"?
Ответ банален - что нашел, то и измерил. Основная проблема тут - мультиплексор входов АЦП - он устанавливает измеряемый уровень небыстро, особенно при переключении с одного входа на другой И тут главную роль играет .. сопротивление источника сигнала.
Рекомендованные "менее 10кОм" нормально дают замерять на делителях 1:2, 1:4 при перекрытии этого требования .. более чем в 10 раз для последовательного съема с одной ноги.
Итого, в рамках применения "осцилограф" вполне можно получить устойчивый сигнал точностью 7-8 бит (класс прибора 0.5%!) с частотой дискретизации около 500кГц для 1-входового варианта, в т.ч. и дифференциальных режимов и 125кГц для "2-4-х лучевого" варианта, в т.ч. дифференциальных.
------
Провел наконец-то теже тесты для АЦП Мега128а с кварцем 20Мгц. Плата МУРК-128:
В общем, всё нрустно. Делитель 1:2 на сатоте 10Мгц валит АЦП напрочь. Из него ничего не вылазит вовсе, корме 255 или 1023. Так что можно перепаивать кварц обратно на 16Мгц. Повышение общей частоты сказывается больше негативно, чем полезно.
------
Перепаял кварц у Мега128а обратно на 16Мгц. В целом АЦП несколько хуже чем у Мега2560 и он явно проще: нет регистра ADCSRB и соответственно нет выбора источника автозапуска, нет регистров DIDR0,1 и соответственно, шумы несколько выше и точность на делителе 1:2 явно хуже на 1 разряд. На делителе 1:2 - в общем-то работает, но точность в районе 3-5% (6 бит в лучшем случае) и периодически проскакивают сбои в 0 или 255.
Для полноты экспериментов провел такое же исследование для Ардуино Нано на базе ATmega328p .. увы, на делителе 1:2 она не заработала ни на каком входном режиме. Только 1:4 (тактовая АЦП = 4Мгц). Точность оцифорвки также в районе 6бит. даже с включенным DIDRx.
В общем, МУРК-2560 пока показал наилучшие результаты с частотой в районе 340 килозамеров в секунду и это похоже предел.
Да, попытка использовать непрерывный режим и прерывание не увенчалась успехом. Программа обработчика прерывания укладывается с прологом и эпилогом только в 45 тактов, что хуже чем "разовый" замер в цикле: примерно 20 тактов. Если выделять жесткий буфер для обработчика, то наверное его можно незначительно ускорить, но вход в прерывание, пролог и эпилог всего на 3 регистра, все равно съедают не менее 22 такта.
-------
Да. АЦП валится на делителе 1:2, то есть работать на частоте 10Мгц он отказался напрочь. После перепайки кварца на 16Мгц этот же делитель работает, но тоже нестабильно - периодически вылетают "зубья" в 0 или 255, в режиме осцилограф, а его запуск периодически почему-то тоже дает "0" на первых 50-100 замерах. У МУРК-2560 с кварцем 16Мгц этот же делитель - на 8Мгц, работает стабильно и ровно. Самое что печально, это то что земля и питание на обоих платах у блока АЦП разведены с учетом рекомендаций даташита .. и большого смысла в разгоне заменой кварца - не наблюдается вовсе. Похоже правильнее наоборот понижать тактовую до 14Мгц.
Как понял, у всех "урезков" (младших мег) АЦП блок несколько упрощен в той или иной степени. Так что, если и превращать Мегу в осцилограф, то только 2560.
Переписав на asm блок замера можно сократить цикл замера в однократном режиме до 10 доп. тактов или суммарно с АЦП до его 16 тактов, что должно дать предельную скорость дискретизации по одному каналу около 16000/2/16= 500кГц., но это требует проверки.
У мега2560 точность оцифровки на делителе 1:2 тоже "страдает" и не превышает 6 бит (1.5%), и этого вполне достаточно для отрисовки на дисплеях.
--------
Предельная частота дискретизации на плате МУРК-128 (ATmega128a) с делителем АЦП 1:2 (частота блока АЦП=8Мгц) составила около 400кГц. Сигнал с ноги таймера в режиме Phase Correct PWM mode (01) TOP=255, prescaler = 1:8 => частота ноги таймера = 2000/2/256=3,90625кГц. Точность АЦП около +- 4/256 = +-1.5%. Это с ассемблерной подпрограммой чтения, которая к циклу АЦП добавляет всего 11 тактов. Странно, но "маловато" и больше не будет.
Сигнал интегрировался конденсатором, размер буфера 400 точек, скрин с плоттера:
Код подпрограммы чтения для ATmega128a:
void adcReadBuffer()
{
asm volatile(
" push r24 \n\t"
" push r28 \n\t"
" push r29 \n\t"
" push r30 \n\t"
" push r31 \n\t"
" lds r30,adcBuffer \n\t"
" lds r31,adcBuffer+1 \n\t"
" lds r28,adcCount \n\t" // for(Y=adcCount..
" lds r29,adcCount+1 \n\t"
".ADC_LOOP: \n\t"
" sbi 0x06,6 \n\t" //1 ADCSRA |= _BV(ADSC);
".ADC_WAIT: \n\t" // while(ADCSRA|_BV(ADSC));
" sbic 0x06,6 \n\t" //2 пропуск после замера!
" jmp .ADC_WAIT \n\t" //
" in r24,0x5 \n\t" //1 *Z++ = ADCH;
" st Z+,r24 \n\t" //3
" sbiw r28,1 \n\t" //2 Y-- ..
" brne .ADC_LOOP \n\t" //2 .. != 0?
".ADC_END2: \n\t"
" pop r31 \n\t"
" pop r30 \n\t"
" pop r29 \n\t"
" pop r28 \n\t"
" pop r24 \n\t"
::);
}
------------------
Продолжу разбор работы АЦП и возможные направления развития применения "осцилограф" для ATmega2560 (для ATmega128A - все примитивно: нет в нем нифига
, соответственно только "программно"):
1.
Вариант "программной реализации": можно следить за уровнем АЦП на входе без записи в буфер, по достижению порога с заданным направлением (синхронизация по уровню + спад/подъем), включать сохранение данных АЦП в буфер. Можно повторять эту операцию для 2,3 и т.д. буфера "со сдвигом" (вставка паузы перед стартом сохранения очередного буфера) и тем самым получить "стробирующий эффект" растянув ось "Х". Минимальная пауза = 1 такт (nop) на 16Мгц = 62.5нсек. Соответственно, в 2.5мксек умещается 20 пауз, и максимально, программно можно "улучшить" частоту дискретизации до 8Мгц при 20 последовательных съемах "фрагмента". Этот же объем буферов сохранения можно использовать и для усреднения сигнала.
Итого можно получить ряд "дискретизация - усреднение" на делителе АЦП 1:2 : "8Мгц - без усреднения" (буфера 20х1), "4Мгц - 2х" (10х2), "2Мгц - 4х" (5х4), "1.6Мгц - 5х (4х5), "800кГц - 10х" (2х10) и "400кГц - 20х" (1х20). соответственно в режиме "400-20х" можно уточнить показания на 4.5 раза или на 2-3бита. На других делителях получится несколько иначе, например на 1:4 частота дискретизации составляет уже 16000/(14.5*4+11) = 232кГц (4,3125мксек) и точность одиночного замера уже не 3%, а 1.5% .. ну и при шаге стробирования 62.5нсек потребуется иметь 69 буферов или загрублять шаг стробирования ...
2. Вариант "аппаратной реализации" (только 2560, 328p!): обработчик прерываний компаратора устанавливает буфер сохранения и время работы выхода В таймера 1, который запускает АЦП на замеры. В этом случае уровень синхронизации отрабатывается аппаратно компаратором (можно вокнуть переменник и крутить его ручку), задержка стробирования фиксируется таймером "физически" и также может настраиваться с шагом 62.5нс. Задержка по времени от срабатывания компаратора составит: 7тактов вход в прерывание + обработчик компаратора (ок.30) + 5 тактов выход + задержка таймера (мин 2 такта) = 35-50 тактов (2-3мксек) системная задержка + установка таймера для стробирующего сдвига (шаг 62.5нсек). Поскольку системная задержка влияет на все замеры одинаково, то про неё можно "забыть".. по сути получим "то же самое", но проще программно + отсутствие влияния прочих прерываний на работу осцилографа.
P.S. Многолучевая работа, работа в диф. режиме - практически не отличаются от описанных решений. При нескольких лучах согласовано (в 2, 3 и т.д. раз) тупо падает частота дискретизации по каждому лучу.
P.P.S. Автомасштабирование как и усреднение можно делать чисто программно в разумных пределах уже при выводе "итого" на экран.
Ну и ещё. Можно замутить режим внешней синхронизации (фигуры Лиссажу к примеру) программно.
Какие ещё режимы есть смысл "предусмотреть"?
------------
Частота АЦП-блока в 450 кило-замеров в секунду - достигнута, ура товарищи!
Итого, что удалось получить: Мега2560, делитель АЦП 1:2, режим "free running mode" контроль завершения замера - ручной в цикле по сигналу ADIF.
Процедура замера снимает byte::adcMaxSamples образцов, по word::adcSampleLegth показаний одновременно с byte::adcMaxChannels каналов.
Каждый канал переустанавливается записью ADMUX целиком "на лету", т.е. теоретически каждый канал допускает свой вариант опорного напряжения и типа оцифровки, но .. "даташит против" и режим съема имеет существенное ограничение: нельзя смешивать настройки для обычных и дифференциальных каналов. Ибо переключение на дифф. режим требует .. 125 микросекунд ожидания. Ровно похожая, но меньшая по времени "засада" при смене уровня опорного сигнала. И ещё: поскольку MUX5 находится в регистре ADCSRB, то он не изменяется при смене каналов, соответственно одновременно можно проводить измерения или по 0..7 или по 8..15 ногам АЦП, но не совместно, типа 1 и 10 вход.
Вариант процедуры на "С" на плате МУРК-2560 показал "де факто" скорость оцифровки 450 тысяч замеров в сек., вариант "асм-вставка" полноценно пока запустить не удалось, но похоже что скорость в 500кГц - вполне достижима в таком режиме. С-шному коду буквально не хватает оптимизации в 5-6 тактов на замер.. абидна.
Точность каждого замера в районе 4-8 LSB (оценка очень примерная). Точность оценить сложно, поскольку при быстром нарастании сигнала "шаг" получается ближе к 8 делениям, а верхние/нижние полочки показывают "наводки" глубиной 2-4LSB "только в путь" .. нипанятна как измерить точнее. Но, сигнал от сэмпла к сэмплу имеет практически одну форму, что делает "бесполезным" вариант усреднения по нескольким замерам.
Процедура замера умеет искать в исходном сигнале заданный уровень и направление его перепада, что позволяет сделать синхронизацию "по фронту", "по спаду" заданного уровня. Кроме этого, есть возможность "сдвигать" во времени каждый набор замеров для всех adcMaxChannels * adcSampleLength на величину, кратную 187,5-250нсек (3-4 такта МК). Систематическая задержка фиксирована и составляет 3.375мксек (время расчетное) от точки обнаружения уровня. Поскольку сам замер длится 15.5 тактов АЦП (13.5 + 2 .. даташит для free running mode), то возникает возможность применить стробирование при снятии нескольких сэмплов (для всех каналов одновременно) и повысить "виртуальную" частоту оцифровки примерно в 8 раз.
То есть до .. 4Мгц.
В общем, остался только один момент: победить опцию линковщика -flto, который безобразно корежит результат и приводит к проблемам сборки. Похоже недаром у ATmega128a есть опция "отключить -flto" ..
P.S. Приехали экраны, пора собирать все вместе: плата + память + экран..
-------------
В общем, частоту замеров в 592кГц получить можно. АЦП действительно отрабатывает за 13.5 тактов. Однако переключение каналов сменой ADMUX происходит не шустрее чем с частотой 1Мгц, которая и указана в даташите, что делает "многоканальный режим" в практическом плане бесполезным.
На этом изыскания с АЦП блоком можно закрыть.
------------
Ну и последний результат экспериментов со стробированием: если НЕ закрывать прерывания (от таймера в первую очередь), то стробирование не позволяет получать фикс. сдвиг на заданное количество тактов и тем самым получать "промежуточные" точки на кривой измеряемого сигнала. А ещё оно требует строгой (в количество сдвигов раз) стабильности семплов снимаемого сигнала. Или по-просту:
При сдвиге на 1/3 периода замера, к концу семплов получаем расползание измеряемых точек больше чем период замера на частотах АЦП выше 2Мгц (делитель ADPS 1:3), что на практике снижает полезность стробирования практически в ноль.
Итого, на плате МУРК-128 получена скорость замеров в 592кГц при точности АЦП около 6бит. Малейшие проблемы с землей (макетка с втыкающимися проводками) и на картинке можно наблюдать кучки "зубьев" вместо сигнала. Гонять АЦП с таким делителем можно в режиме "free running mode" с таким макросом получения результата:
#define adcReadInt(p) \
{
while( (ADCSRA & _BV(ADIF) == 0 );
ADCSRA |= (1<<ADIF);
(p) = ADCH;
}
// и в коде далее:
{
register uint8_t _adc;
adcReadInt(_adc);
*buffer++ = _adc;
}
То есть ждем сигнала прерывания, сразу же сбрасываем его, тем самым разрешаем начало след. цикла и уже потом читаем чего намеряно в предыдущем цикле и уже потом сохраняем результат куда хотелось, если хотелось. В таком режиме работа АЦП идет строго по 13.5 тактов.
Замерять в таком режиме можно только 1 канал. Никаких "переключений" ADMUX.
Если надо производить замеры больше 1 канала, то делитель АЦП требуется выставлять на тот самый 1Мгц даташита (ADPS=4, 1:16), в противном случае влияние измеренного уровня на новый канал будет превышать 5-6 бит. А точность АЦП даже с делителем 1:4 уже близка к 8 битам..
Зато, можно кратковременно отключать АЦП и быстро включать заново сигналом ADSC в режиме "free running mode" .. но, опять же "кратно скорости АЦП" (включится на ближайшем начале такта АЦП) а не F_CPU..