Русский
Русский
English
Статистика
Реклама

Adc

АЦП преобразования в указанные моменты времени на STM32

22.02.2021 22:16:08 | Автор: admin

Доброго времени суток. В этом посте я расскажу, как мне удалось заставить STM32F407VET6 измерять аналоговые сигналы в указанные моменты времени с помощью DMA.

Главной моей причиной измерять сигналы в точное время была необходимость измерять токи, протекающие в шунтах контроллера трехфазного BLDC мотора.

Для упрощения и ограничения задачи условимся, что

  • мы знаем точные моменты времени, когда необходимо измерять сигнал;

  • из предыдущего пункта также ясно, сколько измерений должно быть произведено;

  • разница по времени между двумя последовательными измерениями может быть любой;

  • нам необходим только один канал для измерения в точные промежутки времени.

Учтем также следующие особенности STM32:

  • STM32 обладает DMA(DMA1) контроллером, который может избавить MCU от перекладывания данных из регистра ADC в RAM память по окончанию преобразования;

  • ADC преобразование может быть вызвано по некоторым событиям в том числе: TIMx_UP, TIMx_CCRy.

Таким образом каждое последующее преобразование может быть вызвано когда у таймера, который может триггерить ADC, срабатывает Capture/Compare или Update события . После окончания преобразования в работу вступает DMA1 и перекладывает измеренное значение в память MCU.

Конечно, можно на Capture/Compare событие активировать прерывание и в этом прерывании записывать новое значение в этот же CCR. Минусом этого подхода являются затраты микроконтроллера на обслуживание каждого прерывания (сохранение и восстановление стека для работы прерывания) а также сопутствующее ему отклонение времени измерения. И чем больше измерений должно быть сделано, тем больше будет отклонение. Конечно, можно учесть время входа и выход из прерывания, но это слишком сложно да и не нужно, если есть способ проще и лучше.

Обоснование использования CCR

Далее буду рассказывать про работу с Capture/Compare Register. С Update событием тоже можно сделать, принцип останется такой же, но регистры будут другие. Плюс использования CCR я вижу в том, что таймер всегда переполняется с одной и той же частотой.

С другой стороны ту же самую работу по обновлению значения в TIMx->CCRy может взять на себя ещё один DMA(DMA2), если настроить его таким образом, что каждое событие по CCRy помимо запуска ADC также бы вызывало и обновление этого CCRy с помощью DMA2. Такой подход полностью освобождает нас от использования прерываний (всю работу берут на себя DMA2, ADC и DMA1) необходим лишь только массив значений CCR, который будет предоставлен DMA2 для отправки их в TIMx->CCRy. Поэтому же и все измерения произойдут в точно указанные промежутки времени.

Получается для работы алгоритма, должны соблюдаться следующие пункты:

  • ADC должен быть настроен на преобразование по внешнему событию от CCRy, каждое последующее преобразование должно ждать соответствующего ему CCR события;

  • После окончания преобразования DMA1 должен перекладывать преобразованное значение из регистра ADC в память MCU;

  • DMA2 должен срабатывать по тому же событию от CCR что и ADC. По каждому событию DMA2 должен записывать последующее значение в TIMx->CCRy регистр из массива чисел заданного при его настройке.

  • Первый момент времени должен быть записан в CCR с помощью MCU, а не DMA.

Графически это будет выглядеть так:

Настройка периферии

Чтобы не описывать каждый пункт по отдельности, на рисунках укажу, какие параметры периферии должны быть установлены. Также скажу, что вся работа над проектом велась в STM32CubeIDE.

1. Для ADC должен быть установлен Scan Conversion Mode, выбран канал(IN1), настроен триггер и DMA1, который будет перекладывать готовые измерения в память.

2. Настройка таймера. Установку значений предделителя и AutoReload Register я опущу, т.к. они будут зависеть от вашего проекта. Для данного примера я экспериментально подобрал такие значения, которые бы позволили мне провести наглядный эксперимент, который я опишу ниже. Также для TIM3 необходимо добавить DMA, и указать его направление - из памяти в периферию, а также поставить галочку в пункте Increment Address для Memory. Прерывания для TIM3 устанавливались опционально для того, чтобы проверить, что в CCR каждый раз записываются новое значение с помощью DMA. Также в настройках конфигурации Output Compare CH1 может быть заменен на Output Compare No Output если нет необходимости отображать состояние сравнение CCR регистра с CNT на пине MCU.

Установка режима Toogle on match в TIM3 Output Compare Channel 1 позволяет отрабатывать каждое событие по CCR в ADC. Только в таком режиме со связкой в ADC : Trigger detection on both the rising and failling edges мне удалось заставить ADC запускать каждое преобразование.

3. На этом настройка периферии закончена, но для экспериментальной проверки включим DAC, который будет генерировать значения для оцифровывания, а пины микроконтроллера DAC и ADC IN1 соединим друг с другом, а также с каналом осциллографа.

С настройкой периферии разобрались, теперь необходимо написать код и провести эксперимент.

Код

Запишем нулевое значение в DAC и включим его. Далее в тестовом примере будет написана функция, которая постепенно увеличивает выходное значение DAC до достижения им потолка (4095).

HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0u);__HAL_DAC_ENABLE(&hdac, DAC_CHANNEL_1);

Создадим массив для CCR значений и запишем в него случайные возрастающие значения, которые меньше чем значение, хранящееся в ARR, чтобы провести все измерения за один цикл таймера. Случайные значения взяты для того, чтобы глазами можно было убедиться в том, что сигнал действительно измеряется в разные не периодические моменты времени.

Инициализация значений CCR
uint16_t ccValues[MEASUREMENT_COUNT];ccValues[0] = 115;ccValues[1] = 252;ccValues[2] = 388;ccValues[3] = 475;ccValues[4] = 582;ccValues[5] = 646;ccValues[6] = 727;ccValues[7] = 871;ccValues[8] = 993;ccValues[9] = 1062;ccValues[10] = 1211;ccValues[11] = 1339;ccValues[12] = 1425;ccValues[13] = 1466;ccValues[14] = 1541;ccValues[15] = 1669;ccValues[16] = 1818;ccValues[17] = 1872;ccValues[18] = 1963;ccValues[19] = 2000;

Далее необходимо положить первое значение из массива в регистр CCR1, а также на всякий случай остановим таймер и сбросим его счетчик. Опционально включаются прерывания таймера по CC1 и заморозка счетчика в режиме отладки.

htim3.Instance->CCR1 = ccValues[0];HAL_TIM_Base_Stop(&htim3);htim3.Instance->CNT = 0;__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_CC1);__HAL_DBGMCU_FREEZE_TIM3();

После этого запускаем преобразования ADC с DMA. ADC теперь будет ждать события от таймера.

HAL_ADC_Start_DMA(&hadc3, measuredAdcValues, MEASUREMENT_COUNT);

И следом запускается таймер с DMA2, при этом количество транзакций должно быть на единицу меньше, т.к. первое число уже находится в регистре CCR1.

HAL_TIM_OC_Start_DMA(&htim3, TIM_CHANNEL_1, &ccValues[1], MEASUREMENT_COUNT - 1u);

Осталось запустить на железке и проверить.

Проверка на железе

Подключив два щупа осциллографа к MCU (один к пину DAC/ADC IN1, другой к выходу TIM3_CH1) Можем наблюдать следующее изображение:

Желтый - сигнал с DAC, зеленый - выход TIM3_CH1Желтый - сигнал с DAC, зеленый - выход TIM3_CH1

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

Теперь перенесем измеренные значения ADC на график и посмотрим, что получилось:

Результат измерения, по горизонтальной оси значения CCR, по вертикальной оцифрованные значения DACРезультат измерения, по горизонтальной оси значения CCR, по вертикальной оцифрованные значения DAC

Как видим, измеренные значения расположенные по времени измерения сигнала образуют прямую линию, доказывая то, что сигнал был оцифрован и измерен корректно, и данный метод работает.

Я попытался повторить тот же самый трюк на STM32F103C8T6, но к сожалению мне не удалось добиться такого же эффекта. Как только происходит первое событие по сравнению с CCR, MCU тот час же пытается оцифровать сразу все запрошенное количество, не дожидаясь следующих событий. Если у кого-то получится это реализовать, я с радостью добавлю в статью.

Выводы

Используя АЦП настроенный на преобразование по запросу от таймера, DMA1, который перекладывает оцифрованные значения в память, а также DMA2 для настройки следующего момента измерения удалось реализовать механизм, который позволяет измерять сигнал в произвольно заданные моменты времени не расходуя вычислительных ресурсов микроконтроллера. Если таймер синхронизировать с таймером ШИМ, или использовать этот же таймер, который генерирует ШИМ, то можем легко измерять сигнал точно в нужный момент.

Update 1:
Ссылка на тестовый пример на github.

Подробнее..

Разнообразие аналогово-цифровых преобразователей вырождается?

18.06.2020 21:44:10 | Автор: admin


Окружающий нас мир с нашей точки зрения является аналоговым, то есть большинство измеряемых нами величин является множеством вещественных чисел в определенном диапазоне значений. В то же время методы обработки таких величин при помощи аналоговых операций оказывается сильно ограничен по функциональности и сложности, а разработанная цифровая обработка сигналов оказывается на много порядков функциональнее, надежнее, компактнее, но оперирует только с цифровыми данными, то есть с данными, дискретными по времени и по мгновенным значениям сигнала. Для преобразования из непрерывного аналогового сигнала в дискретный цифровой используется аналогово-цифровой преобразователь (АЦП).

Первый АЦП


Самым первым упоминанием АЦП в истории является патент США 1 608 527 под названием Facsimile Telegraph System, который был подан 20 июля 1921 года Полом М. Рейни, работником компании Western Electric. Патент был получен спустя 6 лет, 30 ноября 1926 года.



Рисунок 1 Патент Facsimile Telegraph System

Изображенное в патенте устройство фактически является 5-битным АЦП прямого преобразования (flash ADC, direct-conversion ADC). Принцип действия полностью параллельного АЦП прямого преобразования заключается в том, что все параллельные компараторы с напряжением сравнения меньшим, чем уровень входного сигнала переключаются в 1, а все параллельные компараторы с напряжением сравнения большим, чем уровень входного сигнала остаются в состоянии 0. Шифратор перекодирует полученный двоично кодированный унарный код (Binary Coded Unary, BCU) в код для передачи дальнейшим устройствам.

Типы существующих АЦП


  1. АЦП параллельного (прямого) преобразования (flash ADC, DC ADC).
  2. АЦП последовательного приближения (SAR ADC).
  3. Интегрирующие АЦП (integrating ADC).
  4. Сигма-дельта АЦП (sigma delta ADC, -ADC).

Существуют и другие типы АЦП, например, конвейерные и комбинированные, но они узкоспециализированные и широкого распространения не получили.

АЦП имеет множество характеристик, которые условно можно
разделить на статические:
  1. разрешающая способность;
  2. погрешность полной шкалы;
  3. температурную нестабильность;
  4. нелинейность;

и динамические:
  1. максимальная частота дискретизации;
  2. время преобразования.

Основными можно назвать частоту преобразования и разрядность. Частота преобразования обычно выражается в отсчетах в секунду (SPS), разрядность в битах. Современные АЦП могут иметь разрядность до 24 бит и скорость преобразования до единиц GSPS, конечно, не одновременно. Чем выше скорость и разрядность, тем труднее получить требуемые характеристики, тем дороже и сложнее преобразователь.
Скорость преобразования и разрядность связаны друг с другом определенным образом, и мы можем повысить эффективную разрядность преобразования, пожертвовав скоростью.
На рисунке 2 показан график зависимости разрядности различных типов АЦП от частота преобразования.



Рисунок 2 График зависимости разрядности различных типов АЦП от частоты преобразования

Наибольшим быстродействием и самой низкой разрядностью обладают АЦП прямого (параллельного) преобразования. Например, АЦП параллельного преобразования TLC5540 фирмы Texas Instruments обладает быстродействием 40 MSPS при разрядности всего 8 бит. АЦП данного типа могут иметь скорость преобразования до 1 GSPS. Среднюю нишу в ряду разрядность-скорость занимают АЦП последовательного приближения. Типичными значениями является разрядность 12-18 бит при частоте преобразования 100 kSPS 1 MSPS. Наибольшей точности достигают сигма-дельта АЦП, имеющие разрядность до 24 бит включительно и скорость от единиц SPS до десятков kSPS. Интегрирующие АЦП в настоящее время практически полностью вытеснены другими типами АЦП, но могут встретиться в измерительных приборах.

Сигма-дельта АЦП


На хабре была статья 2011 года, где упоминались разные типы АЦП, но в данной статье смысл совсем другой.
Структура любого сигма-дельта АЦП содержит сигма-дельта модулятор, который преобразует входной аналоговый сигнал в последовательность нулей и единиц, и цифровой фильтр-дециматор. Эта последовательность нулей и единиц в иностранной литературе называется PDM (pulse density modulation), что принципиально отличает ее от ШИМ (широтно импульсной модуляции).



Рисунок 3 структура сигма-дельта АЦП

Входной сигнал поступает на блок вычитания полученного битового кода, далее на интегратор, компаратор и триггер (элемент задержки по времени), выход триггера последовательность битового кода PDM. Данная последовательность поступает на усредняющий ФНЧ, дециматор, и на выходе получается оцифрованный сигнал высокой разрядности (разрядность повышается внутри фильтра). Надо заметить, что частота следования нулей и единиц в потоке PDM должна быть существенно выше, чем частота построения выходного кода высокой разрядности. В простейшем случае для получения 8-битного АЦП необходимо повышение частоты PDM в 256 раз. Это неудобно и нерационально.
Поэтому сигма-дельта модуляторы собирают последовательно в количестве 2..3..7 штук, возникает эффект модуляции шума, перенос энергии шума на высокие частоты, и как следствие в рабочей низкочастотной области шумов оказывается меньше. Это позволяет получить эффективную разрядность существенно выше, что у PDM первого порядка, как показано на рисунке 4.



Рисунок 4 Формирование спектра шума сигма-дельта модуляторов разного порядка

Таким образом, при повышении частоты дискретизации в 64 раза и использовании сигма-дельта модулятора 4 порядка можно получить разрядность 12 бит вместо 6. При повышении порядка до 7 и той же частоте дискретизации разрядность можно поднять уже до 16. Таким образом, оказывается возможным создавать сигма-дельта АЦП не только до единиц-десятков kSPS, но и существенно больше. Например, если производить цифровую фильтрацию PDM в ПЛИС Xilinx на частоте 400 МГц (что вполне реализуемо с использованием аппаратных умножителей и дифференциальных входов), коэффициенте передискретизации 64 можно получить 16-битный АЦП на частоте 6.250 MSPS. При меньшей разрядности можно увеличить частоту дискретизации. Данный тип АЦП можно использовать для синхронной обработки большого числа АЦП, особенно если всю цифровую обработку всех потоков PDM поместить внутри одной ПЛИС.
Классический рисунок областей применения различных АЦП можно изменить так:


Рисунок 5 Современное состояние различных типов АЦП

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

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru