Pull to refresh

Comments 135

Да там ничего не помогало, с теми двумя импульсными источниками питания, их иголками и персональными шумами. Только жёсткая алгоритмическая фильтрация всё спасла.

Добавить "Переключаемые конденсаторы" при резком изменении входной величины. Фильтры 2-6 порядка. Дельта-триггеры с гистерезисом, что если после фиксации величины играют 1-2 бита, то не дергаться.

А ваш велосипед - это балансный вход на коленке. Возможно, балансник можно было сделать попроще. Но, если по другому никак, то и ок.

Велосипед, конечно, велосипед, но не от хорошей жизни он изобретён. Как я и отмечал во вступлении, всё уже наверняка 100500 раз написано, но намного меньше раз опубликовано. Я же постарался опубликовать не просто красивые названия, но ещё и готовое решение. Для вполне себе типовой задачи, которая наверняка встретится ещё многим.

Возможно, балансник можно было сделать попроще. 

А что может быть проще одного экрана кода на усреднение и одного экрана на гистерезис?

не от хорошей жизни он изобретён. Как я и отмечал во вступлении, всё уже наверняка 100500 раз написано, но намного меньше раз опубликовано.

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

Настолько общности нет, что усреднители даже в аппаратуру современную добавлены. Только не все ими пользуются (мне же пришлось за ребятами добавлять, но в старую аппаратуру - программно). Настолько нет общности, что даже в этой ветке комментариев говорится про гистерезис... И в ряде других веток - тоже. Собственно, моё решение - один из методов его реализации.

Я не критикую ваш метод, работает и слава богу, просто указал почему такие вопросы редко затрагивают в литературе.

А Вы не пробовали питание датчиков отдельным проводом ? Как во всех нормальных схеммах , просто слаботочку отдельно ?

Этому посвящены целых два больших раздела статьи. Схема не наша. И похоже, Заказчик к её разработке отношения тоже не имеет. Все попытки обсудить улучшение схемы, наткнулись на полное непонимание. Но без устранения дёрганий, программную часть Заказчик принимать отказывался. Хорошо быть Заказчиком!

Ещё можно дополнить алгоритм с окошками привязкой к реальности - крутануть потенциометр как можно быстрее и определить максимально возможную скорость изменения параметра. В случае, если параметр на входе меняется быстрее возможного - это повод для фильтрации или даже для алярмы (может, коротнуло или провод оторвался?) ;)

если вы делаете прошивку - вы к ней имеете доступ, что мешало програмно убрать из значений дребезжащий хвост?

ну то есть: у вас потенциометр 0-10 кОм(надеюсь 10 оборотный, а не фигня "попробуй попади в значение")

итого значения от 0 до 10000 +-99, обычно там дребезжание доли Ома, но хз как у вас там, пусть до 100 Ом, да и сами говорите, что запас по точности там есть

Value = датчик (0-10000)

Value = Value/100 (при условии, что это инт без дробной части)

Value=Value*100

Rezult = Value

Вот ваши 100% переменного значения, без дребезга... хоть в мониторинг на телефон выводи хоть в скаду.

Или я что-то не понимаю?

ИМХО: усреднять нужно приходящие переменные значения, в которых есть полезный сигнал(тот самый всплеск), когда переменная часть - ненужный мусор - его можно просто вынести....

итого значения от 0 до 10000 +-99

В текста сказано, что значения были от 93 до 930 (вообще, у Меги АЦП 10 битный, выше, чем 1023 не может быть в принципе, но в конкретной схеме не приходило более, чем 930, проверено опытным путём, схему менять нельзя, это тоже указано в тексте). И что не хотелось терять точность. Поэтому среднее значение мы искали очень точное, просто вокруг него не давали прыгать, если было видно, что ручка не пришла в движение. Пришла - снова ищем точное среднее.

Ну хорошо, убираем "хвосты" с крайних положений потенциометра, итого значения от 100 до 900. На какие величины был дребезг? больше 8 единиц? И с какой точностью в этих же единицах пользователь выставляет значение?

Нет, не больше. Ну вот, у нас показания равны, скажем, 567, дрожат на плюс-минус 8. Я очень боюсь переврать Ваш алгоритм, но мне кажется, что Вы просто предлагаете округлять. То есть, терять точность.

именно, терять точность, которая никому не нужна....

Шпиндель достаточно инертен. Все эти дрожания на плюс-минус несколько оборотов в минуту, ему не сделают никакой погоды. Мало того, измерение этих оборотов имеет намного большую погрешность, чем та самая ошибка считанных с потенциометра данных. Вроде, и ненужная работа намечалась, если бы не одно «но»: эти требуемые обороты также отображаются всё в том же мобильном приложении.

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

Пусть шпиндель вращается на 3000 оборотов, шаг задания скорости вращения в 50 оборотов за шаг - более чем достаточно, скорее там и 100 на шаг - всех устроит.

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

Ну поделим мы на 10. У нас останется 90 измеряемых положений потенциометра... Это даже не по 2 градуса на шаг. Может даже по 3.

Единицы измерения реального шпинделя сейчас обсуждать не будем. Тем более, что они там меняются от модели к модели. Просто обсудим именно положения ручки, которые можно задать. 900 положений и 90.

В найденном алгоритме, вся точность сохранена, просто добавлен, как верно отметили в комментариях ниже, гистерезис. Поймали среднее положение и замерли в нём. Крутанули туда-сюда - за несколько итераций (незаметных глазу человека) найдём новое среднее положение с максимально возможной точностью. И снова замрём.

Ну если задача была - найти значение максимально точно - тогда без вопросов.

А что мешает отбрасывать отсчёты АЦП, изменяющиеся на 8 единиц?

Цель же - зафиксировать статическое положение потенциометра как я понимаю?

Зачем тогда усреднять всплески?

Они же не несут полезной информации.

1.Фиксируем в регистре текущее значение.

2.Заполняем массив очередными отсчетами АЦП.

3.Вычисляем среднее значение и отклонение от среднего в массиве.

4. Если отклонение от среднего выше заданной величины (5 единиц к примеру) - бракуем замер и оставляем сохранённое в регистре значение.

5.Если отклонение от среднего ниже заданной планки - сохраняем среднее в регистре как текущее.

"Выбор метода усреднения шумов" - так себе технология ;)

Лучше подождать пока вал потенциометра перестанут вертеть, а потом уж мерить...

3.Вычисляем среднее значение и отклонение от среднего в массиве.

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

Лучше подождать пока вал потенциометра перестанут вертеть, а потом уж мерить...

Была такая претензия: "Если сдвинуть потенциометр, то потом всё замирает". Это у основного разработчика (меня привлекали только помочь устранить проблему) раз в секунду всё опрашивалось. При этом задержку на начало вращения Заказчик, как оказалось, не замечал, а вот что потом нет реакции - замечал. Так что как минимум, при приёмке, вал крутили нещадно, и были недовольны, что это не отражается на лету. Уже поэтому так не получилось бы.

Желание потрафить заказчику в ущерб функционалу - такой себе пример для подражания... Все мы колхозим иногда, но зачем писать статью об этом?

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

Им ясно, но не опубликовано... Поэтому ясно ограниченному кругу лиц. Теперь - опубликовано...

Типовые шаги - их же нужно по назначению применять. Усреднение сигнала - одно, а усреднение дребезга контактов - другое.

Если польза от первой операции очевидна, то поиски смысла второй операции - нетривиальная философская задача ;)

Что касается нехватки памяти и регистров, то потенциометры любили читать как раз в 80-90-е на разных Atmel-ах MC51. Тогда к энкодерам не было привычки.

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

Правда для этого нужно влиять на код модуля индикации и донести до заказчика эту фичу...

Усреднение сигнала - одно, а усреднение дребезга контактов - другое.

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

Если что, дребезг контактов во время отладки на моей стороне был равен нулю. Так получилось, что на плате был программируемый источник аналогового сигнала, который с одной стороны, избавил меня от необходимости крутить ручку, а с другой - позволил контролировать, что точность считывания значений приемлема. Вот я с его помощью всё и проверял.

Все дребезги контактов если и возникали, то на стороне Заказчика. И как видим, они были такими, что полученный результат всё равно был принят. А все проблемы на моей стороне прекрасно воспроизводились без них.

Да - ясно в общем...

"Качество" - это же "степень удовлетворенности заказчика" ;)

А всякие там программные реализации пик- лимитеров - это дурацкие упражнения из учебника.

Листал статью, ожидая увидеть слово "гистерезис". Не увидел, озадачился.

Если вам надо, чтобы пока ручку потенциометра не крутят, показания стояли, как вкопанные – это и надо было делать. Обнаружили по сигналу, что ручку никто не крутит – зафиксировали значение.

Так а у меня что сделано? Тут главное - не забыть, что ручка - вообще несерьёзная мелочь в рамках проекта. Что не стоит класть все силы разработчиков, всё ОЗУ, всё ПЗУ и все такты процессора на её обработку.

Результирующий алгоритм получился в экран размером. И по сути, это как раз он, гистерезис. Просто на фоне битвы, я про это слово забыл. Спасибо за напоминание!

"Заказчик крутит ручку а реакции никакой..."

А вот такой вопрос, частота опроса АЦП (семплирования) какая? Для вялотекущего процесса чем реже опрос - тем лучше, это уже будет ФНЧ, дальше в скользящее среднее, а для редкого опроса хватит уже и 5...10 точек ( и ведь тоже ФНЧ!) и еще улучшили характеристики.

Ну, я в тексте показал, что 250 чтений происходят за 100 мс. То есть, чтения идут с частотой 2.5 КГц. Там на одно измерение тратится 13 тактов. Значит, тактовая у АЦП 35.5 КГц. У меня выбрана самая большая константа деления, какую только можно поставить в Меге - 128.

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

Не надо так часто опрашивать АЦП! Допустим, нам достаточно, чтобы показания менялись раз в 0.5 секунды (можно в 1 сек, но уже заказчик может занервничать), и делаем скользящее среднее из 5 значений - тогда опрашиваем АЦП раз в 0.1 секунду = 10 Гц. А у Вас в 250 раз чаще - но задача не требует такой высокой частоты оцифровки.

При тех шумах и иголках, получим такое дёрганье, что ууууууу! Я начинал с малого числа опросов. Частоту АЦП ещё сильнее уменьшить нельзя. Коэффициент деления - максимальный.

А ещё меня смущает то, что в блок-схеме АЦП значение на входе компаратора отмечено, как фиксирующееся, а вот опорное AREF - нет. Считается, что его-то должны идеально застабилизировать и так. Но в нашем конкретном случае, не факт, что это было сделано идеально у разработчиков схемы. Поэтому если ещё уменьшить частоту, там уже ошибки оцифровки могут полезть.

Частота преобразования АЦП != частоте опроса АЦП. Опрашивается в цикле по таймеру, хоть раз в сутки.

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

Частота опроса - это как часто мы хотим снимать с АЦП семплы (отсчеты и т.д.), например мы звук цифруем - 22 кГц частоту семплирования берем. Температуру в комнате - 1 Гц, нам чаще меняющиеся данные неинтересны. Так и с резистором, юзер его крутит и ждет что за 1 секунду он изменит свое значение. И мы получим это значение раз в секунду. И не надо усреднять 250 отсчетов,это избыточно.

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

Не поможет. Попали у вас в одном цикле 3 опроса из 5 на верхние иголки, а в другом на нижние - и здравствуй скачок показаний.

У вас очевидно косяки в схемотехнике и разводке платы. Я понимаю когда дрожит 16-24 битный АЦП, но с 10 битным, даже в AVR нет никаких проблем при правильной разводке правильной схемы. Ну может на +/- 1-2 из 1024 дрожит. Для считывания потенциометра вообще не мешает. Работает без всяких фильтраций и усреднений.

Ну там по условиям задачи разводка = дано, ее низзя крутить, так же как и рихтовать значения в мобильном приложении(тут тоже вопрос, но пусть)

Там ещё есть возможность чтения этого параметра через ModBus, так что всё-таки надёжнее в прошивке. Вдруг при приёмке начнут проверять через неё. Задавить оптом, чтобы точно везде не дёргалось. Мы из этого исходили. Но я решил, что если перечислять все пути, то статья ещё сильнее перегрузится. Её и так многие явно по диагонали читают.

Я ее явно по диагонали читал, не спорю =) Но тут у меня есть оправдание - совсем не интересно было как выводили среднее из значений, был интересен вопрос - а нужна ли была вся эта работа, с разбором схемотехники платы/осцилографом и явно потраченным временем в попытке сохранить незначащие доли показаний. Но если задача была: максимально точное значение от показаний - значит проделанная работа была нужна, вопрос снимается.

Однозначно косяк, и это отмечено в целых двух разделах статьи. Но не у нас. Как отмечено, мы не имеем отношения к разработке схемы и не имеем возможности влиять на её доработки. Но при этом, нашу (программную) часть проекта бы без стабилизации не приняли.

Что то похожее делал в свое время, но со считываем температуры паяльника с термопары, где милливольты сначала усиливаются, потом на АЦП подаются, тоже помех со всех сторон много.
Раньше понимали проблему и решали чисто аппартно, в статье понимая проблему решили алгоритмом, через пару лет эту задачу будут решать с помощью ИИ, загрузят ЦОД на 50Мвт на пару дней и он им такой-же алгоритм по итогу выдаст.

ЗЫ: И кстати в одном кабеле где силовые и сигнальные линии помех больше за счет магнитной индукции а не за счет конденсаторного эффекта.

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

Тезисно:

  1. шорох резистора убираем аппаратно

  2. шум АЦП и питания убираем усреднителем наименее ресурсоёмким алгоритмом.

  3. накладываем гистерезис для стабилизации

Далее подробнее.

Это аппаратная часть, но это будет актуально большинству.

  1. конденсатор стоит не так дорого. RC фильтр НЧ наше всё. Для механической крутилки Тау подбираем порядка 0,1-1 сек. В качестве резистора для фильтра можно ограничиться самой крутилкой.

  2. резистор включаем по схеме делителя. Чтобы сопротивление контакта движка не оказывало существенного влияния.

  3. чтобы убрать шум питания и перетоков можно задействовать Vref+ и Vref- слегка отодвинув их от питания.

Теперь про софт.

Удивился числу 250 в накопителе усреднения. Проще использовать 256 и потом откинуть младший байт. Особенно на чахлых 8-битниках, но не только.

Для более плавной регулировки лучше использовать скользящее среднее.

Если жалко ресурсов на честное скользящее среднее, есть лайвхак.:

  1. При старте после стабилизации входного сигнала считываем значение умножаем на глубину усреднения и записываем в переменную-накопитель. Можно этого не делать, но увеличится время начальной стабилизации показаний.

  2. Далее каждую итерацию к накопителю прибавляем текущее значение АЦП и вычитаем предыдущий результат усреднения. Переменную делим на глубину фильтра и получаем новое значение. Если глубину фильтра выбирать кратной степени 2, то операция деления меняется на сдвиг и можно уложиться в пару десятков тактов на итерацию независимо от глубины фильтра.

Результат работы этого фильтра похож на RC ФНЧ. И никаких массивов с историей. Ресурсоемкость практически не зависит от глубины усреднения, потянет любой контроллер любую глубину и частоту. Актуально не только на древних 8-битниках, но и на устройствах с батарейным питанием, большой загрузкой, когда требуется очень малый отклик и т.п.

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

Так-то можно навернуть всякого, например отфильтровать по первой производной (вместо медианы) и т.п. но для механической крутилки этого совершенно точно не требуется (если не надо диагностировать саму крутилку).

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

Вообще я в своих поделках давно от переменных резисторов ушел к энкодерам.

Удивился числу 250 в накопителе усреднения. Проще использовать 256 и потом откинуть младший байт. Особенно на чахлых 8-битниках, но не только.

Вы не поверите, но как я ждал этого комментария! Потому что это очевидно, поэтому я думал об этом, и осмысленно отбросил такой вариант. 250 - это "близко к максимальному значению uint8_t". При выходе на 256, пришлось бы или менять счётчик на uint16_t с усложнением операции "+- 1" на каждом шаге, или сравнивать его с нулём, что могло бы ввести в ступор тех, кто потом будет сопровождать код. У нас же восьмибитная архитектура AVR!

Поэтому я предпочёл совместить классический, понятный даже школьнику, код с какой-никакой, а оптимизацией. Одно деление выполнится быстрее, чем загрузка-сложение с переносом-выгрузка, проведённые 256 раз...

достаточно из накопителя вычесть самое старое значение и записать на его место и прибавить текущее.

То есть, хранить весь этот массив в хилой памяти Меги.

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

Вот как раз гистерезис и достигается в финальном разделе. Да, я забыл это слово в пылу битвы (были там и другие баталии, не описанные в статье), но мне его уже напомнили в комментариях.

Вообще я в своих поделках давно от переменных резисторов ушел к энкодерам.

Золотые слова! Но мы не могли влиять на схему, что отмечено в тексте.

При выходе на 256, пришлось бы или менять счётчик на uint16_t с усложнением операции "+- 1" на каждом шаге, или сравнивать его с нулём, что могло бы ввести в ступор тех, кто потом будет сопровождать код.

Можно вместо cnt++ проверять бит переноса, например, с инкрементом через интрисик __builtin_add_overflow.

Вот я и говорю. Кто потом полезет код сопровождать - много интересных слов в мой адрес скажет.

Взяв константу 250, я выжал не полную, но хоть какую-то оптимизацию, но оставил код универсальным. Если вдруг завтра его будет кто-то читать, ему не понадобится вникать в странные операторы. Мало того, если его соберут под ARM или ещё какой RISCV - он тоже заработает (хоть там все эти переменные, отличные от 32 битных, начнут замедлять процесс - там будет вставляться код, зануляющий лишние биты, есть у меня опыт изучения работы компиляторов под 32 битные архитектуры, когда используются такие укороченные переменные)..

Одно деление выполнится быстрее, чем загрузка-сложение с переносом-выгрузка, проведённые 256 раз...

У вас же АТмега а не ПИК, зачем загрузка и выгрузка? У АТмеги 32 регистра, поэтому накапливать результат можно прямо в регистрах. Всего лишь 2 команды и вроде 2 машинных цикла на всё.

250 - это "близко к максимальному значению uint8_t"

Тут не понял. При сложении от 2 до 255 1-байтных чисел результат всегда 2-байтный если вам не нужны переполнения.

У вас же АТмега а не ПИК, зачем загрузка и выгрузка? У АТмеги 32 регистра, поэтому накапливать результат можно прямо в регистрах. Всего лишь 2 команды и вроде 2 машинных цикла на всё.

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

Тут не понял. При сложении от 2 до 255 1-байтных чисел результат всегда 2-байтный если вам не нужны переполнения.

Делить надо, когда счётчик достиг 256. Хотя, да, не подумал, что можно проверять до увеличения счётчика. Тут уже у меня инертность мышления сработала.

При сложении 256 чисел, равных 255 - получается 255 255 т.е. всё те же 16 бит.

Вот как раз в прерывании и есть смысл выделить 2 персональных регистра, чтобы сэкономить на стёке и времени обработки прерывания. А у меня во времена АВР вообще вся программа крутилась на регистрах и ОЗУ использовалось в основном только под массивы.

Вот как раз в прерывании и есть смысл выделить 2 персональных регистра, чтобы сэкономить на стёке и времени обработки прерывания. А у меня во времена АВР вообще вся программа крутилась на регистрах и ОЗУ использовалось в основном только под массивы.

Там в основном алгоритме такие вычисления, что ему регистры не помешают. А стабилизация потенциометра - даже не вторичная задача. При основной работе обороты задаются в цифровом виде через мобильное приложение. И не такие они частые, прерывания от АЦП. А вот данные от сопроцессора и ModBus стекаются всё время, и должны вовремя обсчитываться.

Я же говорю... Главное - не увлечься, и не положить все силы и средства на задачу третьего приоритета... Но без которой проект не приняли бы. Но силы надо рассчитывать.

Вообще я в своих поделках давно от переменных резисторов ушел к энкодерам.

Вот вот, не понимаю как это в 21-м веке еще резюки ставят в качестве регуляторов... :)

Ну, у в ту железку, про которую статья, его поставили те, кто в двадцатые годы 21 века делает схемы на Мегах. Вот в нулевые я лично на них поделки делал, но прогресс не стоит на месте. Схемотехник целевой железки явно так привык с более древних времён. И к тем процессорам, и к той обвязке. И этот схемотехник работает не у нас (и даже не у нас в стране).

Зря вы на мегу наезжаете. Нормальные контроллеры. В своё время очень хорошие. Да и сейчас вполне годные для любых проектов. Если бы не неадекватные цены на них и невозможность найти оригинальный, а не китайскую подделку. Я считаю это всё из-за ардуино. Оно же наплодило "разработчиков" способных накидать скетч из готовых библиотек, но не способных правильно подключить резистор к АЦП.

неадекватные цены на них и невозможность найти оригинальный

Посмотрел на маузере оригинал (понятно) стоит 2 евро за 328 и около 6 за 2560. Обычные вроде цены?

Ф030 на 64 кБ - это по ПЗУ аналог 328-й в пересчёте на 32-битность - стоит $0,4 и в нём ещё есть часы, DMA и вытесняющие прерывания. А 8-битные аналоги младших АТтини начинаются от 9 центов.

Зря вы на мегу наезжаете. Нормальные контроллеры. В своё время очень хорошие. Да и сейчас вполне годные для любых проектов. 

Только очень бедные по ресурсам и очень дорогие. Какой смысл-то за х5 цены получать в десять раз меньше памяти и частоты?

Там есть нормальный EEPROM. Это иногда гораздо дороже.

С обьемом флеша в мегабайт можно прекрасно в 95% случаев использовать эмуляцию

Я не разработчик аппаратуры, но когда-то сталкивался с Мегами, поэтому из чистого любопытства и интереса: а на чем сейчас собирают и какие преимущества/недостатки имеются по сравнению с Мегами?

Ядра Cortex-M весьма хороши. Cortex M0+ - минимум, Cortex M3 - часто достаточно. Cortext M4 - это уже совсем круто (особенно Cortex M4F), но через это не всегда нужно. Более крутые - дорого, если они нужны - они точно не на замену Меге будут поставлены. Цена M0+ и даже M3 - почти как у Мег, но 32 битная архитектура. Контроллер прерываний покруче.

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

Но лично мне они нравятся именно за 32 битную архитектуру. Потому что расчёты обычно идут в таких разрядностях. А у Cortex M4 ещё и поддержка типа float может быть встроенная, что на ряде задач полезно.

Конкретные процессоры не называю, они бывают разные. Та же Atmel делала AT-SAM (сейчас MicroChip их выпускает). STM32... Ну, и куча других производителей, на выбор, включая Миландр. На многих доводилось делать проекты. Все плюс-минус одинаковы.

Ещё у Cortex M более правильное видение Гарвардской архитектуры. Если у Меги память программ и память данных имеют независимую адресацию, то у тех Cortex, которые Гарвард поддерживают, шины из процессора выходят разные, но потом они попадают на матрицу шин. И там адресация общая. Поэтому если запросы уходят на разные шины - имеем все прелести Гарварда. А вот программист всё видит по заветам Фон Неймана. Он не может различить код и данные.

Но если случайно запросы попадают на одну шину - ну просто чуть медленней всё выполнится. Код можно запускать в ОЗУ, данные грузить хоть из ОЗУ, хоть из флэша одними и теми же командами. Меня на Мегах разные адресные пространства из себя выводили!

Что касается модных RISC-V... Они однозначно круче Мег в силу 32 разрядности, но мне кажется, что слабее Кортексов. Особенно те, у которых нет Compressed- команд. Но это не точно. А то сейчас мне быстро докажут, что я не прав...

ESP32 также использует архитектуру xTensa, но её я на низком уровне не изучал. Она тоже не восьмибитная, уже этим хороша.

"У всех - свои недостатки". Вон, во вчерашней статье про ARM STM32... Переход в режим энергосбережения StandBy - [остановка тактирования периферии?] - все порты слетели на входы без подтяжек. Бр-р-р...

Нашего шефа на выставке ребята из Nordic убедили, что энергосбережение лучше организовывать на их чипах. Он приехал, попробовал... И очень много выиграл в плане экономии по сравнению с тем, чего сам же и добился на ESP32 (не помню, C или S).

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

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

Чуть не забыл. У всех современных архитектур DMA обычно является обязательным. А через это можно многие интерфейсные вещи реализовывать по принципу "Настроил и забыл". Не надо следить, пришло чего-то там или нет. Я однажды на контроллере FreeScale настроил цепочку из трёх DMA так, что данные из линейной камеры принимались вообще без участия процессора. Там просто можно было цепочки настраивать.

Сначала я программно запускал оцифровку на АЦП. Камера в той схеме выдавала всё в аналоговом виде. По факту окончания, результат записывался в буфер с инкрементом указателя, после чего автоматически запускался второй блок DMA в цепочке. Тот в GPIO отправлял два слова. По результату, камера получала импульс "точка принята". Дальше запускался третий блок DMA, который писал в порт АЦП команду приёма. Точно такую же, какую в начале процесса посылал процессор. Система была подготовлена к тому, что в конце оцифровки начнётся работа первой записи в цепочке.

Приём из АЦП был закольцован на 128 байт (камера на машинке Freescale Cup давала линию из 128 точек). По окончании, формировался запрос на прерывание, и приём автоматически переходил к началу.

Правда, это не свойство архитектуры Cortex M. DMA каждый производитель делает, как считает нужным. На том же STM32, думаю, такой чисто аппаратный трюк бы не сработал, но всё равно, часть работ тоже можно было бы автоматизировать. Не отвлекать программу на каждую мелочь. На STM32 я усреднял и фильтровал данные от термодатчика как раз при помощи DMA. Во времена, когда придумывали Меги, это ещё не было принято, поэтому там DMA нет.

Понятия не имею, я тоже не разработчик, Atmega, это целое семейство микроконтроллеров, которые ставят куда ни попадя в.т.ч. и в Arduino...

Интересная статья и много слов, проглядел бегло и то только потому что тема очень близка, как раз сейчас пишу программулину под ПР для управления частотником, который в свою очередь крутит насос, и это все должно стабилизировать скорость потока в нужных границах.
Не, я понимаю что потенциометр вещь простая как оцинкованное ведро, но не понимаю почему их до сих пор ставят скажем в те же частотники, когда уже давно существует такая вещь, как энкодер инкрементный, есть даже с кнопками, ни каких тебе шумов и колебаний, работает четко как триггер, один щелчёк, увеличил или уменьшил значение, а нужно то только и всего, простой функциональный блок или в ПЛК или в ПР, что бы обрабатывать его вращение, а еще можно визуализировать как меняешь уставку, не понимаю как в наше время нужно пускаться во все тяжкие, что бы только устаканить значения древнейшего "целеуказателя"... непонимаю! :), а тех к то в современные цифровые устройства до сих пор ставят резистивные потенциометры, поубивав бы... :)))

давно существует такая вещь, как энкодер инкрементный, есть даже с кнопками, ни каких тебе шумов и колебаний, работает четко как триггер, один щелчёк

К сожалению, не всё так здорово, ибо зависит от исполнения. С оптикой (наверное) всё отлично, но бывают контактные энкодеры, которые могут работать (и как правило, работают) отвратно, когда контакты подокислились (возможно, подвытерлись). Сейчас есть под рукой плеер, стоивший в своё время недурных денег, где производитель выпендрился, поставил утопленную крутилку на громкость. Сначала было нормально, теперь оно работает как генератор случайных чисел (хорошо хотя бы, что только когда крутишь, а не всегда). Надо вскрывать, но конструкция не очень располагает.

"Налить масла в переменник" - классическая операция. У меня валяется старый лабораторный БП, у которого настройки на месте не стоят. Сильно не стоят. Как раз резисторы надо промаслить. Они дурят.

С другой стороны, у очень дорогой мышки ребёнок уже два раза энкодер в колёсике маслил. Первый раз было забавно. Мышка дурила во время поездки в Китай. Тот, у кого мы были, спустился с нами на подземную парковку, открыл капот своего автомобиля и капнул с кончика масляного щупа.

Так что тут проблема общая. Но зато пока сам крутящийся прибор целый - показания у энкодера стабильнее. Пусть даже у контактных пропуски бывают периодически. В нашем случае, они были бы не принципиальными. А потом - ну отключить от разъёма и поставить новый.

Обиднее всего то, что крутилка в обсуждаемом проекте - штука редко используемая. При основной работе, всё в числовом виде через мобильное приложение задаётся. Там ничего не окислится.

Ну дык, контакт может и на потенциометре подокислиться, причем гораздо быстрее, тут вопрос не в том что там и тут может подокислиться, тут вопрос на чем быстрее это произойдет, если деталь качественная то и прослужит она долгие годы, опять же зависит от того с какой интенсивностью ее эксплуатируют, а так в качестве примера могу сказать, есть у нас один частотник Hitachi и там нужно менять частоту в пределах одного герца и на нем в качестве регулятора как раз и стоит потенциометр, который уже изношен дальше некуда, так вот мастера там все время плевались, когда нужно герцовку поменять на 0,3гц., стоял бы энкодер было бы гораздо проще, а так пришлось им на кнопки эту функцию переводить, щас вообще хочу сделать что бы они этот частотник не трогали от слова совсем, типа задал нужный поток, а ПР-ка сама подстроила частотник, а на ПР-ке нужный поток будет устанавливаться одним энкодером и не только поток, а еще несколько нужных настроек, в.т.ч. и для усреднения входящих в ПР-ку данных о самом потоке (допустимая дельта отклонения и кол-во усредняемых данных, в общем все то о чем здесь автор статьи нам и поведал) :) Проще говоря для настройки параметров будет использоваться одна крутилка и одна кнопка встроенная в крутилку, а в качестве индикатора настраиваемых параметров, цифровой 4-х значный индикатор работающий по RS-485, в общем любой олигофрен с настройками разберется даже без инструкции.... :)))

Не, я понимаю что потенциометр вещь простая как оцинкованное ведро, но не понимаю почему их до сих пор ставят скажем в те же частотники, когда уже давно существует такая вещь, как энкодер

Энкодер в качестве регулятора чего-то (громкости, скорости, яркости...) - это зло, чистое и незамутненное. А если самые умные программисты еще и добавляют ему переменную скорость (чем быстрее крутишь, тем больше величина инкремента/декремента) - это вообще жопа.

На частотнике нужен именно резистор. У которого каждому положению ручки соответствует одно определенное выходное значение. Независимо от скорости поворота, независимо от истории действий, независимо от включения-выключения питания.

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

На частотнике нужен именно резистор. У которого каждому положению ручки соответствует одно определенное выходное значение. Независимо от скорости поворота, независимо от истории действий, независимо от включения-выключения питания.

Притянуто за уши, ибо уже есть частотники с энкодерами, например у Toshiba или у Shnaider Electric, ну вот же:

Им же и настройки производятся и чёт я не встречал что бы кто то из за этого испытывал какие то неудобства, обратные ситуации видал постоянно, когда резистором не получается выставить точное значение... Не, это не аргумент... :)))

Кстати, если что, то при потере питания, последнее заданное значение сохраняется в энерго независимой памяти, это даже работает на частотниках с резисторами, который отключен, а энкодер дает дополнительные плюшки, например, можно записать некоторое кол-во пресетов и легко их менять...

уже есть частотники с энкодерами

Отличный пример хренового UI - частотники Шнайдер с их головоломными "мЕнЮ", в которых изменение одного пункта влияет на кучу других параметров. Энкодер в них далеко не самое худшее.

Ну для не квалифицированного персонала любой UI будет вызывать трудности, по мне так лучше "хреновый" юзер интерфейс с энкоденром, чем резистор в понятном... :))), Хотя на мой скромный взгляд у всех частотников UI, +/- одинаковый, хотя вон Owen "снизошел" до конфигуратора для ПЧВ, чего я у других не встречал, только толстенные талмуды, возможно они есть, но в наших краях почему то не распространено... :)

Хотя на мой скромный взгляд у всех частотников UI, +/- одинаковый

Да ладно.

Большинство частотников: открываешь инструкцию, находишь страницу со таблицей параметров, проходишь по списку, ставишь их в нужные значения, профит.

Шнайдер Альтивар: чтобы получить доступ к параметру X, нужно изменить параметр Y в подменю aBcDe/kLmN (см. страницу 456 инструкции), при этом автоматически изменятся параметры A, B и С...

Ну дык , так у всех что я видел, параметр не включается ибо он противоречит, тому что вы хотите включить, и выключите сначала это потом позволю включить то, и в шнайдеровских инструкциях все тоже самое и таблицы тоже есть, не понимаю, что там не так, хотя да, программирование частотников даже в 21-м веке, квест еще тот, "Ассемблер" в чистом виде :)))
По мне так на современном частотнике вообще не должно быть ни каких кнопок, крутилок и индикаторов, шучу конечно, а программироваться он должен без инструкции через WEB интерфейс, который уже научились в "прикуриватели" встраивать... :)))

Не надо мне там веб-интерфейсов. По крайней мере в качестве единственной опции. Возможность при отладке станка поменять, скажем, время раскрутки шпинделя с 10 секунд на 11 несколькими нажатиями штатных кнопок - без ноутбуков, программ, облаков, кабелей и донглов - это бесценно.

Ну дык, вот тут энкодер и бесценен, сделал несколько пресетов, какие нужны в работе, нажал на энкодер, выставил нужный пресет и все само настроилось, причем с абсолютной точностью, это не резистором ловить десятые доли герца, тут только вопрос в другом, нужен специалист, кто это сможет грамотно один раз и навсегда настроить, а я вижу что со специалистами беда, поэтому и ловят десятые доли герца, изношенным потенциометром, при этом плюясь и матерясь на чем свет стоит... :)))

поэтому и ловят десятые доли герца, изношенным потенциометром

Если в изделии приходится "ловить доли герца изношенным потенциометром", то что-то в нем сделано не так на стадии разработки. Точные пресеты в частотнике можно выставить кнопками в меню, а потом переключаться между ними через входы или по цифровой шине. Либо подключить кнопки "частота вверх/вниз", если скорость нужно точно регулировать в процессе.

Ну дык, расскажите это тетеньке мастеру, которая на пенсии подрабатывает, что можно на кнопки перепрограммировать... :))) и про цифровую шину и про входы.... :))) для нее и потенциометр, это просто крутилка, а так да, уже перенастроил на кнопки, вздохнули с облегчением... :), сл. этап вобще сделать так что бы они этот частотник не трогали и забыли про него, будет у них 1 энкодер с функцией нажатия, а частотник вобще будет в другом помещении находится... Все равно не понимаю зачем там аналоговый потенциометр нужен, не иначе ума не хватает энкодер поставить или просто инерция мышления... :)

Станок в котором нало лазить в частотник (кроме как для ремонта этого частотника) надо выкинуть на свалку истории.

в шнайдеровских инструкциях все тоже самое и таблицы тоже есть, не понимаю, что там не так

В обычных частотниках проходишь по параметрам линейно, один раз, в любом удобном порядке. Параметр B0001 - 50. Параметр B0002 - 380 вольт. Параметр B0045 - 17.

В шнайдеровских - прыгаешь по разным подменю в сложном и неочевидном порядке. И сами параметры вместо "A1234" называются "CtL-tEr" или "drC-SrF", сложным образом влияют друг на друга и дублируются в нескольких меню.

У меня как раз похожая проблема в маленьком хобби проекте. Атмега8 управляет двухступенчатым повышателем напряжения, (два шим 100khz всего по одному для каждой ступени), выходное напряжение от каждой ступени через делитель передается на аналоговые пины, атмега решает когда шим duty cycle понизить/выключить. Все питается от двух 18650, атмега через lc1805. Встроенный aref.

Я отделил плату атмега8 от платы с повышателем, шлейфами соединяются входы и выходы, но всё-равно, шумит всё, считываемые значения скачут, ещё на плате с повышателем несколько мосфетов, которые также атмегой управляются через tc4421. (Выход второй ступени открывают к светодиоду (да, 300+вольт светодиод) по сигналу от атмеги.

Помехи на всех входах и выходах, особенно когда напряжение выхода второй ступени поднимается выше 300 вольт.

Достаточно ли будет добавить rc фильтр на затвор каждого мосфета кроме шим и рядом с пинами атмеги на которые приходит аналоговый сигнал? Я разнес индукторы и мосфеты с микросхемами так далеко друг от друга как мог, но всё равно устройство маленькое, всё очень рядом.

Без схемы и компоновки плат(ы) такое трудно обсуждать. Но "разнёс индукторы и мосфеты" - намекает на необходимость полной переделки (если я правильно понял несколько объединительных союзов).

Площади контуров, ометаемых импульсными токами преобразователей - должны быть минимальны.

Мосфеты преобразователей вплотную к индукторам, имел в виду, что мосфет, который управляет диодом вместе с драйверами мосфетов подальше поставил.
Вот схема компоновка версии, которая сейчас в работе(недоделанная). В первой были ещё другие недостатки, которые после печати и тестирования выяснились, исправляю. Но шум на мосфетах q3, q1, драйверах и входах adc с делителей r9-r10 / - самый нериятный. Мосфеты должны открываться на милисекунды и только тогда, когда приходит сигнал от контроллера. А напряжение должно считываться точно, чтобы выключать шим вовремя. Я добавил 1uf конденсаторы перед затворами q3, q1 и ещё отодвинул их как можно дальше. В предыдущей версии их не было. Думаю сигнал от делителей пропустить через фильтр на операционном усилителе. Будет ли этого достаточно ?
В моей схеме ещё наверняка куча странных вещей, но я просто любитель. :-) Для меня уже успех, что даже первая версия работает примерно как надо, не сгорает, погрешность в напряжении не превышает 20 вольт (что я и хочу уменьшить).

схема
схема



Перво-наперво - не выдержано пожелание DS по выходному сопротивлению источников аналогового сигнала для АЦП ATmega - менее 10 кОм. Желательно поставить буферные ОУ на выходах делителей R7-8 и R9-10.

Во-вторых, для такого большого повышения напряжения целесообразнее использовать трансформатор, а не две ступени.

По разводке - обнять и плакать. Тонюсенькие дорожечки и вот это всё...

Контур, ометаемый током L1 при закрытом Q2.
Контур, ометаемый током L1 при закрытом Q2.

Да, думал про буферные ОУ с конденсатором для фильтрации на плате контроллера перед пином adc. Лучше же ближе к пинам?
Да, дорожки будут правильной толщины, не настроил ещё. Это плагин дорожки сделал, не я же сам вручную.
Про трансформатор думал, в следующей версии сделаю скорее всего. Не разобрался ещё как трансформатор для повышателя подбирать.
То есть конденсаторы лучше поменять местами с батарейками? Спасибо, я думал, что только индуктор с мосфетом имеют значение

буферные ОУ ..... Лучше же ближе к пинам? 

Нет, ближе к делителям. Выход ОУ имеет меньший импеданс и менее подвержен влиянию помех. Может быть - даже подобрать точку соединения R8, R10 (и вторых входов ОУ) с общим проводом. Чтобы импульсные токи не протекали между этой точкой и контактами 1 и 2 J1 (относительно которых проводит измерение АЦП).

То есть конденсаторы лучше поменять местами с батарейками? Спасибо, я думал, что только индуктор с мосфетом имеют значение.

Минимизация площади контуров импульсных токов, которые излучают магнитную компоненту помех. Для L1 - это контура входной цепи из: Параллельные C1 и батарея - L1 - Q2. И выходной из: Параллельные C1 и батарея - L1 - D4 - C6.

Кстати - да, какова цель 1 мкФ конденсаторов?

Они уронят КПД под плинтус.

Благодарю за совет! Добавлю на эту плату буферы значит.
Кондненсаторы чтобы отфильтровать наводки от индукторов, чтобы мосфеты которые управляют светодиодами не активировались сами. А что с кпд будет? Один мосфет - просто включает и выключает маленький светодиод, второй выдаёт по сигналу от контроллера милисекундные импульсы высокого напряжения на сверхмощный диод вспышки. Этот проект - это светодиодная вспышка для фотосъёмки

@RTFM13расписал всё о конденсаторах. Плавно включающийся транзистор - рассеивает энергию впустую. Хотя, включающийся слишком быстро - создаёт условия для излучения помех.

[Q1 и Q3] не активировались сами.

Скорее - дело в багах в прошивке. В крайнем случае - в плохой разводке платы и наводках на входные цепи U1.

второй выдаёт по сигналу от контроллера милисекундные импульсы высокого напряжения на сверхмощный диод вспышки

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

Ниже ответил, по какой причине думаю, что наводки.
На светодиод ток подаётся, естественно. Он через резисторы подключен и у мосфета сопротивление в полностью открытом состоянии 3.5Ом. Я не стал резисторы на плату выводить, потому что у меня много светодиодов, с разным током и напряжением от 30 (~4A) до 360v(~10A). И я экспериментирую с тем какой ток больше номинального они могут выдержать если импульсы короткие и давать им остыть. По заверению производителя (заказал печать кастомных COB в китае) x2 c милисекундными импульсами - точно ок. А выше они сами не тестировали.
CRI не важно - светодиоды и вспышка ультрафиолетовые.

Никакие наводки от индукторов у вас мосфеты не активируют.

У вас самый большой ток это зарядка ваших безумных конденсаторов в цепи затворов. Остальное крохи.

Преобразователь надо поменять например на обратноходовый на трансформаторе от первого попавшегося китайского зарядника. Вот у вас 1 транзистор освободился. Отсечку по току сделайте с гистерезисом на операционнике и заведите её на прерывание и на драйвер. Можно сразу драйвер поставить с отсечкой (а также UVLO, если найдёте на такое напряжение)

Для включения низковольтного светодиода вам драйвер не нужен, можно смело ставить мосфет с "логическим входом". Вот у вас полностью освободился 1 драйвер.

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

У вас там, что, мосфет в TO247? Серьёзно? У вас импульсная мощность больше 30 КВт? У вас тут 3 мосфета скорее всего в корпусах максимум SOT23, SOT223, SOT263. При чем на счет последнего - не уверен.

Я думаю наводки, потому что осциллограф показывает что с контроллера сигнала нет, и проблема начинается при зарядке конденсатора второй ступени выше 250v. Но это в первой версии, там дроссели ближе и другие торроидальные и припаяны через дырку, а не smd.
У меня среди валяющихся мосфетов есть куча в to-247 подходящие по напряжению/току. В прошлой версии был to-220 тоже, но у меня только один подходящий и у него сопротивление когда он полностью открыт 3.5 ом. Я думал их тоже smd сделать и при печати поставить, но в jlcpcb все подходящие в статусе preorder были. А которые через дырку я сам уже припаяю, благо у меня их много.
Там двойной драйвер, всё равно один канал пока свободный. В следующей версии ещё больше будет дополнительных низковольтных диодов, возможно заменю на логический мосфет!
Благодарю за совет по заливке земли!

Вообще ничего не говорит про наводки. Может земля плавает по тонким дорожкам.

Посмотрел разводку.

Обведено белым

  1. что там с выводами Q3-2, Q3-3? что за дорожка между ними.

  2. что с выводом U1-8

  3. что с землёй у конденсатора? Полигон висит в воздухе?

Нарисовал серым как примерно должна выглядеть разводка цепи затвора. Прямоугольник это резистор. Ширина дорожки примерно такая.

Конденсатор в цепи затвора выкинуть однозначно. Резистор увеличить в 5-10 раз. Резистор на землю выкинуть или увеличить в 10 раз. Стабилитрон выкинуть. Термобарьер лучше убрать или сделать в нём дорожки существенно шире.

Подключение земли к драйверу вообще не вижу! Он у вас что, через clamping диоды работает?

Контакт 9 (подложку) подключить к земле без термобарьера! К выводам U1 ENA/B подключить конденсотор 0,1-1 uF.

Землю прошить около драйвера в нескольких местах. Проверить что хотябы на одном из полигонов нет разрыва между Q3-S и U1-GND.

Это недоделанная вторая версия. Автороутинг пропускает дорожки, поэтому наверное нет подключения
Первая версия вот так выглядела. Драйверы другие были

почему выкинуть стабилитрон? У меня в первой версии его не было и всё работает хорошо (за исключением проблем из оригинального вопроса и пропущенной дорожки, которую я припаял проводом), но на бредборде иногда мосфеты сгорали(вообще с другим драйвером, не ic, самодельным на транзисторах, решил от него отказаться), на всякий случай решил добавить

Я добавил 1uf конденсаторы перед затворами q3, q1 и ещё отодвинул их как можно дальше.

Это вы хотели таким образом растянуть фронты открытия закрытия мосфетов?

Нет, там таким образом образуется low pass filter из резистора между драйвером и затвором и конденсатора. А разве нет?

Ну допустим, а цель то какая? Если не уменьшение dVds/dt, то что?

у мосфета проблема - он иногда активируется на микросекунды наводками от индукторов. (так я думаю). Его ожидаемый режим работы - активация на милисекунды по сигналу от контроллера

По этому вы увеличили длину "антенны" между драйвером и мосфетом которая принимает эти наводки?

Вообще при нормальной разводке это одна из последних проблем. Сам затвор имеет далеко не нулевую емкость влияние которой усиливается эффектом Миллера.

В любом случае установкой конденсатора на затвор с этим не борются. Он только вхолостую нагружает драйвер и смещает работу мосфета ближе к пороговому напряжению благодаря тому же эффекту Миллера.

За то сам драйвер без малейшей необходимости нагружается этим конденсатором. Подозреваю у вас там пиковый ток как бы не больше чем ток DS мосфета (порядка 5А).

Мосфет у вас нагружен индуктивностью, большим пикам тока взяться неоткуда. Если только диод не подтупливает. Но в этом случае конденсатор надо ставить совсем в другое место (в составе снаббера) или на худой конец увеличить сопротивление резисторов в взатворе (его в любом случае надо увеличить) или и то и другое.

Отдельным анекдотом выглядят емкости на питании драйвера меньше емкости нагрузки.

Как у вас организована отсечка по току насыщения дросселей?

Вообще не обижайтесь, но вся схема и разводка ужасны. Можно продолжить обсуждать отдельные косяки, но по факту надо перерисовывать с нуля.

Я не про два мосфета которые рядом с индуктором, а два, которые рядом с драйверами. Чем вам не нравятся емкости на питании драйвера? Вот, из даташита драйвера. И ёмкости какой нагрузки они меньше? С учетом конденсаторов на завторе? Ну в принципе логично увеличить наверное.

Обязательно переделаю после тестирования и учёта недостатков. Это уже вторая версия

Всяческие фильты типа бегущего среднего и экспенциального вносят задержки. Чем сильнее фильтрация тем сильнее задержка.
Между тем есть фильтры с меньшей задержкой - это медианный, Савицкого-Голлея, Калмана и т.д. Калман хорош тут, поскольку достаточно хорошо известно с какой скоростью может крутить человек и как быстро тормозить и ускоряться.

Но лучше всех тут бы наверняка работал фильтр на нейросетях. И сделать довольно просто на каком-нибудь https://docs.edgeimpulse.com/docs

Здесь самое главное - не забывать, что перед нами восьмибитный контроллер с малыми объёмами как памяти программ, так и памяти данных. Вдобавок - ещё и со скромной тактовой частотой... И всё это нужно не только для задачи стабилизации потенциометра, но и для выполнения основного функционала. Стабилизация потенциометра - очень второстепенная задача, на которую не стоит класть много ресурсов. Да и времени на подбор параметров фильтров - тоже. Так что все сложные фильтры лучше сразу отбросить. Только простые!

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

Но это замечательно, что под статьёй будет перечисление видов фильтров! Кто найдёт её во время поиска решения, тот и этот комментарий найдёт.

Проще? Усреднять надо хошь-не хошь, чтобы взяв основное значение получить не что-то прыгнувшее. Усреднение нужно ради точности основного функционала.

А алгоритм "крутит-не крутит" занимает экран, который не требует обучения (то есть, часов на подготовку данных). И требует одно 16 битное слово в памяти данных.

Это может быть самообманом.
Чтобы понять поддается ли ваш шум хорошему усреднению он должен быть нормальным или хотя бы с одним горбом. Для этого надо строить гистограмму шума.
Если горбов несколько, то сколько нибудь адекватное по длине усреднение работать не будет.
Несколько горбов будет если реально есть доминирующие внешние имульсные шумы или ошибка в коммутации каналов АЦП.
А гистерезис это тот же обман, что и решатель "крутят/не крутят". Но решатель точно будет держать стабильнее, гистерезис же может перестать совсем работать при изменении уровня шума.

Когда время на разработку бесконечно, а задача "крутят-не крутят" основная - может быть. Когда задача даже не второстепенная (но без неё не примут), а проект идёт по методике Fixed Price, за любой лишний час руководитель... В общем, отругает.

Поэтому самообман, не самообман... Работает, у Заказчика претензий нет - ладушки. Я не зря про часы на обучение нейросети сказал. Кто бы их оплатил,?

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

По любому шум надо было исследовать, иначе прилетит бумерангом.

В статье даже пара осциллограмм реального шума имеется. А так - ну да, он более-менее исследован, и зависимости выявлены.

Но лучше всех тут бы наверняка работал фильтр на нейросетях.

Пейн, я не чувствую тега "сарказм". Вы же не всерьез предлагаете сглаживать сигнал от ручки-крутилки нейросетью? (падмэ.жпг)

Вы находитесь где-то здесь ;) А что не так? Нейросеть это матрица-шматрица с весовыми коеффициентами, сигнал на входе - сигнал на выходе, процессоры и память всё дешевле и дешевле..

можно для таких целей использавть CIC и IIR фильтры в фиксированной точке
главное уметь их расчитывать, особенно IIR
ну а CIC фильтры - это вообще имба

CIC - это же всего лишь несколько подряд бегущих средних, памяти требуют неадекватно. Медиана в связке с несильным экспонециальным (тот самый IIR, но без умножения) гораздо лучше.

но вот нутром чую, что вот такой вариант был бы поинтереснее:

Нет, это плохой вариант. Vref используют для пропорционального источника. А вы его фильтруете раздельно. Это может быть не только бесполезно, но и вредно. При "удачном" стечении обстоятельств можно получить увеличение амплитуды шума.

Лучше как-то так
Я не помню как там у атмеги АЦП, но у большинства мелких МК Vref должен быть между GND и Vcc. Для других вариантов поменять номиналы соответственно.
Я не помню как там у атмеги АЦП, но у большинства мелких МК Vref должен быть между GND и Vcc. Для других вариантов поменять номиналы соответственно.

Если прям так надо питать переменник от 12В, то R1 увеличиваем до 15-20К в зависимости от чистоты "12В".

Если переменник на другой номинал - корректируем R1, R2 пропорционально в разумных пределах (плюс/минус порядок).

Период АЦП выбирать примерно Тау/10 (порядка 22 ms) или меньше (частоту выше).

Не совсем понял.

Сейчас два совсем независимых источника. Причём импульсных, которые как хотят, так и шумят.

Если один из них сделать основанным на втором, станет только хуже? Что не идеально - ну да, но хуже...

И откуда у Меги два входа VRef?

И откуда у Меги два входа VRef?

Это концепт. Для меги просто не подключаем Vref- и R2=0 (умозрительно соединяем Vref- и GND). Это кстати один из недостатков меги.

станет только хуже?

Да, если сигнал непропорциональный, то пиковое значение шума АЦП = сумме шумов входного сигнала и опорного напряжения. Если шум периодический (например ШИМ в БП) то можно словить полную амплитуду на протяжении приличного времени. Или получить систематическую погрешность (смещение сигнала).

И еще момент. У вас на схеме ползунок потенциомметра перманентно нагружен вторым делителем. И, соответственно, выходной сигнал будет зависеть от сопротивления ползунка. Т.е. всё искрение ползунка будет в выходном сигнале. В той схеме, что я привёл этого недостатка нет, ползунок нагружен лишь крошечным током АЦП.

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

Сейчас два совсем независимых источника. Причём импульсных, которые как хотят, так и шумят.

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

Если блоки питания разные значит между платами желательна (а иногда обязательна) гальваническая развязка. Или должен использоваться дифференциальный сигнал и вход допускающий смещения на существенную амплитуду (типа как у RS485). Особенно если у вас там силовая электроника рядом.

А если резистор и Vref запитаны от разных источников это вообще не должно нормально работать.

А если резистор и Vref запитаны от разных источников это вообще не должно нормально работать.

А в статье что сказано? Именно от разных!

И дана рекомендация: "Если есть возможность сотрудничать со схемотехниками - делать это, чтобы совместно приводить систему в нормальный вид". Жаль, что в нашем случае, мы даже не знаем, кто они, схемотехники этой платы.

Вашу ситуацию я понял. Но на месте тех кто в неё еще не попал я бы сосредоточился на том, как в такую ситуацию не попасть, а не на том, как из неё лучше менее худше выйти.

Так делать вообще нельзя. Во-первых дрейф блока питания вы простыми фильтрами не отловите. Во-вторых обрыв земли в данной ситуации чреват влетанием емкостных токов с ЭДС амплитудой вплоть до напряжения питающей электросети на вход микроконтроллера.

На Uref стабилитрон надо ставить. А потом уже делить. Да и потенциометр от стабилитрона питать.

Второй момент - с каким разрешением надо выставлять обороты? 1 об\мин, 0.1 об\мин? итд.
А в каком знаке начинает проявляться шум? Если дергается второй знак после запятой, а выставлять надо с точностью до единицы оборотов, то и черт бы с ним.

Отзываю данный этой статье плюс.

ЕМНИП, формула (алгоритм) расчёта медианы - совсем не таков.

Натянутые на глобус 250 вместо 256.

Манкирование этапом составления Т.З. Если там вращается что-то хоть немного инертное с небесконечной мощностью и механической жёсткостью привода, то вполне можно было получить от заказчика параметр "максимальная скорость изменения уставки" и, на её основе, строить фильтр (например - упомянутый @ABRogovи @RTFM13 простейший IIR) с достаточно низкой частотой среза. ЕМНИП, в частотниках Yaskawa потенциометр ручной установки выходной частоты весьма задемпфирован. Примерно на 0,1-0,2 Гц срез фильтра идёт.

Думал, было, хоть частично оправдать мучения пьезоэффектом 10 мкФ керамических(?) конденсаторов. Но, перечитав, нашёл, что это был другой случай - с 3Д-принтером.

Неплохо также - указать хотя бы сопротивления R1 и R2 в дополнение к 100 нФ С1. Чтобы соотнести выходное сопротивление делителя с рекомендованным макс. 10 кОм для АЦП (для оценки качества фазы выборки сигнала) с одной стороны и оценить ток ползунка потенциометра (не слишком ли мал) с другой.

И так далее.

С уверениями в совершеннейшем почтении за предыдущие статьи.

Вместо оконного фильтра, в котором вы ищете среднее по n последним значениям измерения, лучше использовать фильтр Калмана. Он как раз предназначен для оценки состояния системы (положение ручки резистора) по зашумленному сигналу с сенсора. В одномерном случае реализация фильтра будет очень простой. Единственное, что в окне можно считать - несмещенная дисперсия выборки для сигнала с сенсора по тем же последним n значениям, ну или подсчитать ее заранее при калибровке и зашить константой.

Но ТС его чего-то не применил. Вопрос: почему? Возможно были на то причины. Или просто в голову не пришло, - такое тоже в запарке бывает.

Не знаю. Некоторые не хотят погружаться в теорию, возможно (и даже ругаются, сам был свидетелем: "понавтыкают Калмана, а потом другие поддержать/понять не могут"). Хотя даже поиск обратной матрицы размером 1x1 для этого одномерного случая вида [a], требуемой для расчетов - это просто [1/a]. И там не надо сохранять последовательность всех предыдущих значений, достаточно хранить P и x для предыдущего измерения. Да и закон управления для обычных линейных резисторов упрощает имплементацию "по самое не могу", хотя фильтр Калмана так же отлично работает и для логарифмических резисторов, достаточно этот закон управления учесть при выведении фильтра.

Медианная фильтрация - это не

При ней мы сначала отбрасываем максимум и минимум из накопленного массива, а уже оставшиеся значения усредняем

Это "накопили массив, сделали QSORT, взяли середину массива". И она в таком виде отлично работает

Тоже удивился что автор использовал ключевое слово "Медианный фильтр" и совсем не понял о чем речь. А так для разовых выбросов истинный медианный фильтр как раз бы и помог даже в условиях "зажатого" ресурсами 8битного PIC контроллера....

Вставка и удаление в этот массив будут стоить O(n + log n) и поиск медианы за O(1). Оно надо? Проще вставлять и удалять за O(1) в кольцевом буфере, а искать медиану за O(n)

Серьёзно. Правда, мы в комментариях уже выяснили, что это у меня инертность мышления. Считать до 256 - надо было или счётчик делать 16 битным, или сравнивать с нулём, чем всех путать, кто когда-то будет этот код сопровождать. Я так рассуждал.

Уже потом я понял, что сравнивать с 255 можно было до инкремента счётчика... Это будет и восьмибитненько, и понятно всем.

Но в целом... На фоне тех вычислений, которые производятся в основном функционале, одно деление на 250 никакой погоды не сделает. Но таки да, глаз замылен. Что сравнивать можно до инкремента - вылетело из головы.

А так - можно?

if smth == (uint8_t)(0x100);

Если можно - то понятнее ли гипотетическому поддержателю?

Ну, кроме тех, которые захотят ещё сильнее увеличить. Проект сдан, но в своём хранилище оставлю Ваш вариант, а "не увеличивать свыше 256" внесу в комментарий.

Кстати, оптимизатор для нового варианта даже на уровне -O2 оставил две лишних строки. R26 и R27 зря заполняет.

		lastAvgValue = (uint16_t)(avg_buf / ADC_AVERAGE_CNT);
    1cbe:	89 2f       	mov	r24, r25
    1cc0:	9a 2f       	mov	r25, r26
    1cc2:	ab 2f       	mov	r26, r27
    1cc4:	bb 27       	eor	r27, r27
    1cc6:	90 93 1a 05 	sts	0x051A, r25	; 0x80051a <lastAvgValue+0x1>
    1cca:	80 93 19 05 	sts	0x0519, r24	; 0x800519 <lastAvgValue>

У меня (обычно) во всех устройствах у микроконтроллера есть батарейка для RTC. Соответственно, если по какому то аналоговому входу что то начинает сильно блымать, что из-за самого сигнала блымать не должно, то сравниваю то, что получается при попытке измерить напряжение на внутренней батарее микроконтроллера. Обычно показания от батарейки (при 12 битном разрешении АЦП) скачут не более, чем на 1LBS ( О чем написано в RM для STM32F429). Если это так, то цепь аналогово питания микроконтроллера и ИОН выполнены правильно. А проблема в говенной схемотехнике аналогово входа, например, аналоговый общий неправильно развязали и т. д. Еще раз повторяю, что говорил о батарейке питания RTC микроконтроллера.

Интересен выбор 250 значений. Видел Ваши ответы, но...
В виду применения 10бит ацп что мешало не 250, а 64 раза (2^6) считывать, и тогда уж сдвигать обратно на 6 бит вправо. ;) А 250 значений грозили уйти в переполнение.
Это если брать весь диапазон UINT16.
Тогда и нет переполнения с одной стороны, с другой стороны, деление, которое отсутствует в AVR заменяется сдвигом вправо. То же деление, но на 2^N.
То есть:
Имеются сумма X64, Xold (среднее с прошлого этапа), Xnew - новое значение,
Можно так ещё сделать усреднение - X64new=X64-Xold+Xnew; Xold=X64new>>6; X64=X64new.
При включении значения будут подниматься с 0 до текущего значения.
Для удобства я вам указал отдельные значения X64new, Xold.
В реальности имеется X64, X, вычитаем Х из Х64 и прибавляем значение ацп. Слвиг вправо и полученое из X64 число положить в X.
По поводу частоты опроса - действительно, проще было не постоянный счет делать, а скажем по таймеру.
Но Ваш выбор уважаю.

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

Понятно, что надо изменить аппаратную часть, но как вариант пусть будет.

Тут бы неплохо смотрелся аппаратный фильтр какой-нибудь 2-го порядка, на паре ОУ и щепотке пассивки. Есть отличная книжка авторства Бонни Бейкер - "Что нужно знать цифровому разработчику об аналоговой электронике". Там вот таких случаев рассмотрено штуки 3, и все они решены вообще без программной фильтрации. То есть, там результаты не среднего значения обсуждаются, а шум прямо в отсчетах АЦП до и после применения коррекций в схемотехнике.

А, еще опорное для АЦП лучше делать на отдельном источнике, брать для этого линию цифрового питания не очень хорошо. Оно, как правило, зашумлено, да еще и стабильность там так себе.

Понятно, что, когда усредняешь период 100 мс, в пределах периода всё будет хорошо. Но у разных периодов средние значения будут разными. Усреднять по большему промежутку? Тогда данные в мобильном приложении будут «замирать». Заказчик начинает нервничать уже не потому, что всё прыгает, а потому, что он крутит ручку, а реакции никакой.

Я уже лет 10 использую в своих проектах фильтр, описаный на easyelectrinics тов. drvlas. Суть его такова: берем разницу между предыдущим и текущим значением, и умножаем его на бэту. Поэтому крутанув условную ручку, мы сразу видим, как значения начинают "бежать" к новому установленному значению (а не ждать, пока 256 или сколько там значений сначала накопятся), и эту скорость (т.е. Тау) можно регулировать или иметь разную для разных параметров. И оно работает на 8-бит МК без всяких нейросетей.

Код примерно такой:

uint32_t filter(uint32_t x,  uint8_t Nb, uint8_t k)
{
static uint32_t y=0;
static uint32_t z=0;

    z += (x - y);

    return y = ((uint32_t) Nb * z) >> k;
}

temperature=filter(ADC_VAL[CHAN_TEMP], 1, 5);

Sign up to leave a comment.

Articles