Форум самогонщиков Сайт Барахолка Магазин Помощь солдатам

Ненавязчивая автоматизация ректификационной установки

Форум самогонщиков Автоматика
1 ... 100 101 102 103 104 105 106 ... 132 103
ruslan_ka Студент Железнодорожный 29 6
Отв.2040  24 Нояб. 20, 11:02
Макетная плата (без пайки) - это только для тестирования, а не для работы.
Я не стал заказывать изготовление печатных плат (хотя все их эскизы есть в теме), а решил использовать монтажные платы (как и многие в этой теме).
Сосчитал количество дырочек на плате и на листике в клеточку очертил соответствующее количество клеточек (получился масштаб 1:2).
Карандашиком нарисовал в этом поле все элементы схемы и соединил линиями.
Далее напаял все элементы на плату с одной стороны, перевернул и напаял дорожки из медной проволоки с другой стороны (все в строгом соответствии с рисунком).
Прошил, собрал, вроде бы, все работает пока Улыбающийся
IMG_20200904_090110.jpg
IMG_20200904_090110.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
M_PWR.jpg
M_PWR.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
Схема.gif
Схема.gif Ненавязчивая автоматизация ректификационной установки. Автоматика.
IMG_20201115_182528.jpg
IMG_20201115_182528.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
ekochnev Магистр Екатеринбург 207 54
Отв.2041  24 Нояб. 20, 11:32, через 31 мин
ruslan_ka, абсолютно с Вами согласен!
Я пошел по подобному пути, дополнительно еще совсем отказался от латунных силовых шин, а также малинку подключил сразу на крейт напрямую без каких-либо соединительных проводов. Поэтому и писал, что как именно изготавливать платы - это дело того кто их будет в конечном итоге изготаливать. Приведенный в теме вариант печатной платы можно использовать как для прямого изготовления, так и лишь для ориентира в качестве базового. Однако до сих пор настаиваю, что если делать все без пайки как просит Vittomin (видимо на беспаечных монтажных платах которые ардуинщики используют где все проводками-перемычками соединяется), то ничего пригодного для реальной эксплуатации не получится.

В любом случае, данная тема рассчитана на человека уже обладающего какими-то навыками в области радиотехники (умение читать схемы и паять), так и в области программирования. Если нет этих навыков, то лучше их сначала получить где-то в другом месте, где этому научат лучше и быстрее, а потом вернуться сюда. Нельзя построить самолет не сделав сначала бумажного змея и модель планера. Даже наборы LEGO различаются по сложности с учетом освоения необходимых навыков и ничего не получится если первокласснику первый раз увидевшему LEGO дать набор рассчитанный на 10-классника: либо он все сломает, либо запутается и потеряет интерес, либо за него в итоге все соберут родители.
8c4e24342516.jpg
8c4e24342516.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
20200304_203939.jpg
20200304_203939.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
Vittomin Доктор наук Минусинск 624 151
Отв.2042  24 Нояб. 20, 12:37
очень рекомендую не мучиться, а заплатить какому-нибудь знакомому мастеру, чтобы он сделал это для Васekochnev, 24 Нояб. 20, 10:23
Да вот захотелось было помучиться, собрать свою платку для управления нагрузкой, которой потом можно будет управлять со своей малинки. Так то можно купить РМ2 или РМВ-К - и сразу получить готовое, почти.

Добавлено через 29мин.:

все без пайки как просит Vittominekochnev, 24 Нояб. 20, 11:32
Нет, конечно, без пайки - это именно попробовать, а боевой вариант должен быть нормально собран
Давайте сначала определимся какой контроллер имеется в виду. На ветке их два варианта.OldBean, 24 Нояб. 20, 06:56
. Думаю закупиться деталями для первого варианта, а на январских каникулах попробовать собрать.
ruslan_ka Студент Железнодорожный 29 6
Отв.2043  24 Нояб. 20, 13:17, через 40 мин
Я пошел по подобному пути, дополнительно еще совсем отказался от латунных силовых шин, а также малинку подключил сразу на крейт напрямую без каких-либо соединительных проводов.ekochnev, 24 Нояб. 20, 11:32
Круто! Похоже на промышленный стандарт.
Про "кроватки" под MK я как-то не подумал сразу. С ними можно и ISP разъем не разводить на плате. Вытащил МК, прошил на макете и вернул назад!
Третий справа это PDM? Отличия только в снабберной цепи и тем что его симистор вынесен за корпус?
ekochnev Магистр Екатеринбург 207 54
Отв.2044  24 Нояб. 20, 13:21, через 5 мин
Vittomin, стремление похвальное. Тогда пожелаю Вам огромного терпения и удачи. Читайте, разбирайтесь, мы тут на 100 страницах уже много чего успели обсудить и наговорить. Думаю, все будут рады, если в итоге у Вас все получится.

Порекомендую Вам в качестве первого шага собрать контроллер ТЭНа без высоковольтной части, т.е. если смотреть на схему, то собрать все, что правее МОС3083. Контролировать его работоспособность можно будет по свечению светодиода. Если Вы это освоите, соедините с малинкой и добъетесь работоспособности при регулировании уровня мощности (яркость светодиода будет меняться), то следующим шагом доделаете к ней высоковольтную часть.
BogAD Кандидат наук Красногорск - Белово 403 184
Отв.2045  24 Нояб. 20, 13:27, через 6 мин
Всем здрасьте... Улыбающийся

OldBean, Сергей, сильно не осуждай меня, "выпал" я немного из "процесса".
Давно хотел предложить тебе всё причесать и создать своеобразный мануал реализации варианта "Lite", обобщить, описать установку ПО всех уровней, настройку и все необходимые тонкости.
Последовательно, с нуля, не вдаваясь в описании множественных вариантов реализации железа, а опираясь только на первоначальные варианты реализации.
А то суть размазана по теме, не всегда гиперссылки первой станице помогают.
Я конечно понимаю, что в ветке ты постарался описать все подробно, но всё же...
К примеру, возьмем описанную в 17.6. "Логическая схема ПО варианта LITE". Через 3 месяца от публикации логической схемы появился "17.7. Модуль lsync", который не отражен в логической схеме. Т.е. нет функционала "обобщения" реализации всего софта в целом.
Есть так же "мешанина" с прошивками на модули. Если прошивка обкатана и "выложена", то старые, думаю, надо перемещать в раздел (папку) "устаревшие". Или по крайне мере, "метить" как нибудь, а в ветке форума указывать об этом.
Я не спорю, сама ветка нужна для сохранения истории развития темы, но, чтоб добраться до последнего варианта, новичкам приходится делать пошагово, как была реализация по ветке, а это сильно путает.
Это, конечно, титанический труд, но... без этого будут однозначно возникать вопросы у новичков, у которых, всяко, будут постоянно появляться из-за "недопонимания", как это все правильно настроить.
Глядишь и время потом появится, и не только у тебя, на создание новый и интересных скриптов автоматизации.
Возможно я не прав, просто сужу по себе, как "не до-программиста", как эникейщика и предлагаю подумать с точки зрения новичков... Хотелось бы видеть отдельную папку для размещения там актуальных прошивок на все модули.
ekochnev Магистр Екатеринбург 207 54
Отв.2046  24 Нояб. 20, 13:35, через 9 мин
Третий справа это PDM? Отличия только в снабберной цепи и тем что его симистор вынесен за корпус?ruslan_ka, 24 Нояб. 20, 13:17
Да, третий справа - это PDM.
Отличие для PDM в том, что МОС3083 и все что по схеме левее собрано на отдельной маленькой плате (1.5х1.5 см) и размещено прямо на силовом симисторе на радиаторе. Это позволило пустить к ним от модуля лишь низковольтный управляющий сигнал (перекрученный черно-красный провод на фото), как следствие не нужно стало заводить на крейт латунные силовые шины заменив их на крейте слаботочными разъемами, т.к. весь ток ТЭНа теперь течет в обход крейта и модуля. Вместо петель на модули поставил разъемы задействовав по 4 контакта на каждый высоковольтный подвод. Теоретически, через каждый модуль по высоковольтной части у меня сейчас может протекать не более 4 ампер (220в), но т.к. у остальных модулей симисторы управляют лишь слаботочкой: клапана, реле, поэтому этого достаточно и к тому же нет необходимости размещать их на радиаторах - на радиаторе только силовой симистор ТЭНа. Платы силовых модулей (PDM, контакторы) сделал универсальными. Высоковольтная часть на них либо распаивается, либо не распаивается, в последнем случае через дополнительный разъем с модуля берется лишь низковольтный управляющий сигнал, а высоковольтку к модулю можно не подводить совсем.

Добавлено через 11мин.:

BogAD, согласен что в теме требуется упорядочивание. Но, боюсь, в рамках форума решить подобную задачу будет тяжело.
Я в свое время помучившись завел все варианты схем у себя в систему контроля версий SVN и поддерживаю в таком виде. Также разнес в ней по разным веткам варианты Step1 и Lite + свой собственный вариант. В них создал подветки: отдельно прошивки, отдельно схемотехника, платы, сопутствующие компоненты, картинки и документация. Времени потратил прилично, но в итоге имею под рукой на верхнем уровне SVN всегда только актуальную информацию по каждому варианту, но с возможностью просмотра всей истории изменений как до этого дошли + автоматом добавилась возможность просмотра изменений между отдельными версиями, очень удобно для анализа прошивок.
ruslan_ka Студент Железнодорожный 29 6
Отв.2047  24 Нояб. 20, 16:10
Я тоже читал тему последовательно с 1 страницы, параллельно делая заказы на ebay.
Теперь, кроме варианта Lite, есть небольшой запас компонентов (Ардуинки - 5 шт, Дисплейчики - 5 шт. Тиньки - 5 шт. Улыбающийся )
Но запас еще пригодится (датчик давления еще не сделан)!
Зато какой хороший курс "занимательной робототехники и автоматизации технологических процессов" получился на примере ректификационной колонны.
Хоть книгу издавай Улыбающийся
ps
Когда мы детектив читаем, мы же не читаем сразу финальную развязку.
OldBean Доцент Красноярск 1K 1.4K
Отв.2048  24 Нояб. 20, 16:13, через 4 мин
Думаю закупиться деталями для первого варианта, а на январских каникулах попробовать собрать.Vittomin, 24 Нояб. 20, 12:37
В этом варианте был использован прецизионный детектор нуля. Но, как показала практика, такая точность для этой задачи избыточна. Поэтому можно поставить детектор попроще и тем самым заметно упростить конструкцию. Например, такой, совсем простецкий, как на схеме в приложении к топику. Здесь, возможно, придется немного поколдовать с резистором R2 и задержками в самом скетче. Ну это как раз для того, чтобы немножко помучиться. :)
Удачи!

Давно хотел предложить тебе всё причесать и создать своеобразный мануал реализации варианта "Lite", обобщить, описать установку ПО всех уровней, настройку и все необходимые тонкости.BogAD, 24 Нояб. 20, 13:27
Да. Ветка разрослась, перепробовано много разных вариантов. Не только удачных, но и тупиковых. Причем, не только моих. Ориентироваться действительно трудно. Поэтому примерно год назад в этом топике я немного "подбил бабок" как по части железа, так и софта.

У меня железо с тех пор совсем не изменилось. Стоит и работает. Но, по железу, насколько я понимаю, у нас каких-то особых проблем вроде бы и не было. Общая схемотехника в целом устоялась. Там, конечно, есть куда развиваться. Есть и некоторые раздражающие моменты. Но и существующие релизы стоЯт и достаточно надежно (для реальных практических задач) работают. Ну и зачем их трогать? Поэтому что-то резко изменять и развивать по железу (подчеркну: в данной концепции автоматики!) особой мотивации нет. Тем более, что конкретные реализации железа каждый делает по своему, исходя из своих предпочтений, умений, опыта и возможностей. И это абсолютно правильно.

Что касается софта, то здесь изменений накопилось много. Правда, многие вещи еще не устоялись и являются экспериментальными. На уровне удобно-неудобно, нужно-не нужно и т.п. Ветку с редиской я забросил. Все-таки минусы превысили плюсы. Базовая библиотека lite более-менее "устаканивается". Она достаточно универсальна и годится как основа для разработки любых скриптов управления железом и проведения различных процессов. Сейчас заканчиваю тестирование версии 0.4.1.0 (осталось провести еще одну реальную ректификацию, бражка уже дозревает :))) Как выловлю все основные глюки - опубликую. Развитие библиотеки идет в основном за счет расширения API. Причем, в значительной степени из соображений удобства разработки клиентов. Постараюсь сделать к библиотеке как можно более подробное описание.

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

to ruslan_ka
Мы тут все немножко отвлеклись на железо. Возможно, топик в начале страницы затерялся. Если затерялся - обратите на него внимание. Там есть правильные формулы для коррекции мощности нагрева на сетевое напряжение.

teh_16.11.27_20.11.24.gif
teh_16.11.27_20.11.24.gif Ненавязчивая автоматизация ректификационной установки. Автоматика.
ruslan_ka Студент Железнодорожный 29 6
Отв.2049  24 Нояб. 20, 17:22
Мы тут все немножко отвлеклись на железо. Возможно, топик в начале страницы затерялся.OldBean, 24 Нояб. 20, 16:13
Ну как можно, еще утром поправил свой скрипт!

Добавлено через 56мин.:

Кстати...до Нового Года около месяца, пора настойки ставить
Ненавязчивая автоматизация ректификационной установки
Ненавязчивая автоматизация ректификационной установки. Автоматика.
ekochnev Магистр Екатеринбург 207 54
Отв.2050  06 Дек. 20, 23:01
Заметил тут у себя одну тревожную штуку...
Калибровки (комплект Lite ПО v.0.4.0.1) могут самопроизвольно измениться!ruslan_ka, 07 Нояб. 20, 13:45

Вчера заметил, что самопроизвольно слетела калибровка у датчика кубового давления (MPX5010). Ранее за ним такого не замечалось ни разу, работал исправно с момента изготовления больше года (может и даже два уже). До этого пользовался им две недели назад, все было нормально. Хранился на балконе в шкафу, может повлияли наступившие минусовые температуры, не знаю. Хотя пока не особо холодно: ниже -18 еще не было. Калибровку через API поправил, но осадочек в душе остался...

P.S. Текущая версия софта: 0.4.0.2, прошивка датчика от 2018-11-30
OldBean Доцент Красноярск 1K 1.4K
Отв.2051  07 Дек. 20, 04:44
Вчера заметил, что самопроизвольно слетела калибровка у датчика кубового давления (MPX5010).ekochnev, 06 Дек. 20, 23:01
Да. Известный глюк. К сожалению редко вылезает. Поэтому пока и не удается его четко зафиксировать.
ruslan_ka Студент Железнодорожный 29 6
Отв.2052  07 Дек. 20, 17:30
Я правильно понимаю, что хоть у MPX5010 два соска, измеряет он только с одного (дальний от ноги №1)?
PS
Недавно только собрал его, в деле еще не пробовал.
Еще собрал концевик на уровень воды в бочке автономного охлаждения (геркон и поплавок с магнитом в трубке) Улыбающийся
IMG_20201207_170251.jpg
IMG_20201207_170251.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
IMG_20201207_170704.jpg
IMG_20201207_170704.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
IMG_20201207_170507.jpg
IMG_20201207_170507.jpg Ненавязчивая автоматизация ректификационной установки. Автоматика.
ekochnev Магистр Екатеринбург 207 54
Отв.2053  07 Дек. 20, 18:11, через 42 мин
ruslan_ka, все верно. Этот датчик дифференциальный, т.е. измеряет разницу давлений между двумя сосками. Поэтому одна из них смотрит открытая в атмосферу, а другую соединяешь трубочкой с кубом.

Измеряет он с обеих сосок. Если подключить трубку к одной из них, то будешь получать положительное значение разницы, если к другой - отрицательное.
сообщение удалено
ruslan_ka Студент Железнодорожный 29 6
Отв.2054  08 Дек. 20, 09:33
Измеряет он с обеих сосок. Если подключить трубку к одной из них, то будешь получать положительное значение разницы, если к другой - отрицательноеekochnev, 07 Дек. 20, 18:11

А АЦП тиньки оцифровывает только положительное отклонение или отрицательное тоже?
ekochnev Магистр Екатеринбург 207 54
Отв.2055  08 Дек. 20, 09:45, через 12 мин
А АЦП тиньки оцифровывает только положительное отклонение или отрицательное тоже?ruslan_ka, 08 Дек. 20, 09:33
Любое.
OldBean Доцент Красноярск 1K 1.4K
Отв.2056  08 Дек. 20, 16:19
АЦП тиньки оцифровывает только положительные напряжения. От 0 до Vref, где Vref - опорное напряжение. Чтобы одновременно измерять и положительные и отрицательные напряжения нужно делать смещение сигнала. Так чтобы 0 был в районе Vref/2.
OldBean Доцент Красноярск 1K 1.4K
Отв.2057  24 Дек. 20, 19:23
17.3.6. Контроллер сервомашинки MG90S

Преамбула

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

Введение

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

В целом, сервопривод - штука довольно полезная в нашем деле. В частности, для реализации автоматического переключателя потока при фракционной перегонке или ректификации по нескольким приемным емкостям ("в миру" - "фракционник"). Одной из недорогих и доступных сервомашинок, вполне пригодных для изготовления переключателя фракций, является 5-вольтовая MG90S, которую легко найти и заказать на aliexpress. Она небольшая, имеет удобную конструкцию и металлический редуктор. Именно для такого устройства и был разработан описываемый здесь контроллер. Но, поскольку питание на двигатель подается от отдельного источника, то сам контроллер и софт вполне подойдет и для других машинок. Более мощных (> 1A), или с другим напряжением питания. Естественно, при соответствующей замене платы блока питания самого двигателя.

Краткий перечень характеристик сервомашинки MG90S (источник) приведен ниже.

Скрытый текст
Рабочее напряжение: 4.8-6.6 В (постоянное, DC)
Рабочий ток: 170 - 900 мА
Скорость реакции без нагрузки:
   0.1 секунды / 60° (4.8 вольт)
   0.08 секунды / 60° (6.0 вольт)
Угол поворота: до 160°
Управление: ШИМ
Контроллер: аналоговый, АА51880
Редуктор: латунь, алюминиевый сплав
Расположение редуктора и мотора: параллельные оси вращения
Тип редуктора: шестеренчатая цилиндрическая передача
Блокирующий момент:
   1.8 кг / см (4.8 вольт)
   2.2 кг / см (6.6 вольт)
Длина кабеля: 25 см
Размеры: 22.8 х 12.2 х 28.4 мм
Температура эксплуатации: 0°С...+55°С
Водонепроницаемость: нет
Вес: 13.4 гр

Так получилось, что мне удобнее (да и выгоднее) было заказать сразу 5 сервомашинок. Поэтому появилась возможность для некоторой "статистики". Меня больше интересовали углы поворота. Так вот, оказалось, что из 5 машинок 4 имели существенно больший угол поворота, чем по документации. У них он доходил до 208°. Это порадовало.

Контроллер. Схема, конструкция и прошивка

Цифровая часть любого модуля варианта LITE устроена единообразно. В ее основе лежит микроконтроллер ATMega328P, общающийся с малинкой по шине i2c. Среди режимов работы 16-разрядного счетчика (TIMER1) этого микроконтроллера есть режимы генерирования вполне подходящих для наших целей ШИМ-сигналов. Поэтому никакой дополнительной внешней "оснастки" для микроконтроллера не требуется. Таким образом, схема контроллера выглядит более чем просто и представлена на рисунке ниже слева. Справа - вариант разводки. Файл servo_19.10.05_pbc_02.lay6 для Sprint-Layout - есть в приложении к данному топику.
fig_01_servo_19.10.05._sch_pbc.gif
Fig_01_servo_19. Ненавязчивая автоматизация ректификационной установки. Автоматика.

Ненагруженная серовомашинка MG90S потребляет немного (на уровне сотни-другой мА), но, при вращении с нагрузкой, потребляемый ток может существенно возрастать и доходить аж до ампера. Поэтому для питания двигателя желательно использовать отдельный 5-вольтовый блок питания, а не линию +5В крейта, питание которой обеспечивается малинкой. Плата блока питания пришла ко мне гораздо позже и оказалась длиннее уже изготовленной платы цифровой части контроллера. Поэтому в дизайне всего контроллера появился некий диссонанс и эклектика. Но ничего - открытый стенд - он для этого и есть открытый стенд. Все работает вполне надежно. И на том спасибо... ;))) Внешний вид контроллера сервомашинки (отдельно плата и уже вставленная в крейт) показан на следующих рисунках.
fig_02_contr_servo.JPG
Fig_02_contr_servo. Ненавязчивая автоматизация ректификационной установки. Автоматика.

fig_03_contr_servo_in_crate.JPG
Fig_03_contr_servo_in_crate. Ненавязчивая автоматизация ректификационной установки. Автоматика.

Исходный код прошивки представлен в раскладушке ниже.
Скрытый текст
//------------------------------------------------------------------------------
// Прошивка для привода сервомашинок
// Код семейства - 0xA9
// Адрес на шине i2c - 0x19
// OldBean, 04.10.2019
//------------------------------------------------------------------------------
#include <avr/io.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <string.h>
//------------------------------------------------------------------------------
#define F_CPU 16000000UL // Тактовая частота МК
#include <util/delay.h>
//------------------------------------------------------------------------------
#define ADDR 0x19        // Адрес устройства на шине I2C
#define FAMILY_CODE 0xA9 // Код семейства данного устройства
#define BUF_SIZE 32      // Размер буфера обмена данными
#define EE_SIZE 6        // Размер блока идентиф. и калибр. данных
//------------------------------------------------------------------------------
// Команды:
// 0x33 Чтение кода семейства
// 0x4e Записать данные из буфера обмена в рабочую область (write scratch)
// 0xbe Считать данные из рабочей области в буфер обмена (read scratch)
// 0x48 Записать блок данных из рабочей области в EEPROM (copy scratch)
// 0xb8 Считать блок данных из EEPROM в рабочую область (recall EEPROM)
// 0x52 Запись данных в рабочие регистры (для контроллеров)
//------------------------------------------------------------------------------
#define ZERO_START 106 // Определяет задержку фронта импульса Zero
#define ZERO_WIDTH 13  // Определяет ширину импульса Zero (100 мкс)
#define T_ADC 49       // Определяет интервал между запусками АЦП (200 мкс)
#define SUM_MAX 5000   // Количество суммируемых отсчетов (5000 - это за 1 сек)
//------------------------------------------------------------------------------
static uint8_t buf[BUF_SIZE];        // Буфер обмена
static uint8_t scratch[BUF_SIZE];    // Рабочая область RAM
static volatile uint8_t *ptr;        // Указатель на байт буфера обмена
static volatile uint8_t runFlag = 1; // Рабочий режим, 0 - режим настройки
static volatile uint8_t nb = 0;      // Счетчик байтов
static volatile uint8_t prFlag = 0;  // Принят новый пакет байтов
static volatile uint8_t cmd = 0x00;  // Код команды
static volatile uint16_t pwm;        // Текущий уровень  PWM
static uint16_t pwma[] = {120, 287, 453, 620}; // Уровни PWM для разных углов поворота сервы
//------------------------------------------------------------------------------
ISR(TWI_vect) { // Обработчик событий модуля TWI
  switch(TW_STATUS) {     // Статус - в 5 старших битах регистра TWSR
    // Принимаем байты
    case TW_SR_SLA_ACK:   // Адрес для приема принят, ACK отправлен - 0x80
      ptr = buf;          // Настраиваемся на начало буфера обмена
      nb = 0;             // Сброс счетчика байтов
      break;
    case TW_SR_DATA_ACK:  // Очередной байт принят, ACK отправлен - 0x80
      *ptr++ = TWDR;
      nb++;
      break;
    case TW_SR_STOP:      // Состояние "стоп" на шине - 0xA0
      prFlag = 1;         // Новый пакет принят
      break;
    // Отправляем байты
    case TW_ST_SLA_ACK:   // Адрес для отправки принят, ACK отправлен - 0xA8
      ptr = buf;          // Настраиваемся на начало буфера обмена
      nb = 0;             // Сброс счетчика байтов
    case TW_ST_DATA_ACK:  // Очередной байт отправлен, ACK принят - 0xB8
      TWDR = *ptr++;
      nb++;
      break;
    case TW_ST_DATA_NACK: // Байт отправлен и получен NACK - 0xC0
    case TW_ST_LAST_DATA: // Отправлен последний байт, получен ACK - 0xC8
      break;
    // Ошибки старта или стопа - сброс TWI
    case TW_BUS_ERROR:
      TWCR = _BV(TWIE) | _BV(TWINT) | _BV(TWEA) | _BV(TWEN);
      break;
  }
  TWCR |= _BV(TWINT); // Очистим флаг TWINT (очищается при установке в 1)
}
//------------------------------------------------------------------------------
void delay_ms(uint8_t count) {
  while(count--) {
    _delay_ms(1);
  }
}
//------------------------------------------------------------------------------
int main(void) {
  DDRB = _BV(PB0) | _BV(PB1) | _BV(PB2); // Пины PB0 - PB2 - на вывод
  // Инициализация TWI-модуля --------------------------------------------------
  TWAR = ADDR << 1;   // Адрес устройства - в старших 7 битах
  TWCR = _BV(TWIE);   // Разрешаем прерывания от TWI
  TWCR |= _BV(TWEA);  // Разрешаем подачу импульса ACK
  TWCR |= _BV(TWINT); // Очистим флаг TWINT (очищается при установке в 1)
  TWCR |= _BV(TWEN);  // Разрешаем работу TWI и активирует TWI-интерфейс
  // Инициализация таймера 1 для PWM -------------------------------------------
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1); // None-inverted mode
  TCCR1A |= (1<<WGM11); // и ниже - Fast PWM
  TCCR1B |= (1<<WGM13) | (1<<WGM12);
  TCCR1B |= (1<<CS11)|(1<<CS10); // Делитель 64,
  ICR1 = 4999; // Частота - 50 Гц при таком ICR1

  pwm = pwma[0];
  OCR1A = pwm;
  volatile uint16_t oldpwm, i;
  volatile int8_t step; // Направление вращения
  uint8_t dt; // Пошаговая задержка в мс

  sei(); // Разрешаем глобальные прерывания
  ptr = buf;
  while(1) { // Бесконечный цикл
    if(prFlag) { // По шине i2c принят новый пакет - отрабатываем его
      TWCR &= ~_BV(TWEN); // Приостановим работу TWI
      prFlag = 0; // Сбросим флаг получения нового пакета
      cmd = buf[0]; // Код команды
      switch(cmd) { // Анализируем и выполняем команды
        case 0x33: // Чтение ROM - в первом байте - код семейства
          buf[0] = FAMILY_CODE;
          break;
        case 0x4e: // write scratch - записать данные в рабочую область
          memcpy(scratch, &buf[1], EE_SIZE);
          break;
        case 0xbe: // read scratch - считать данные из рабочей области
          memcpy(buf, scratch, EE_SIZE);
          break;
        case 0x48: // copy scratch - записать блок данных в EEPROM
          eeprom_update_block((const void *)scratch, (void *)0, EE_SIZE);
          break;
        case 0xb8: // recall EEPROM - считать блок данных в EEPROM
          eeprom_read_block((void *)scratch, (const void*)0, EE_SIZE);
          break;
        case 0x52: // Команда управления
          cli(); // Запрещаем прерывания
          oldpwm = pwm; // Сохраняем старое значение PWM
          pwm = buf[2];
          pwm = (pwm << 8) | buf[1]; // Принятое (новое) значение PWM
          if(pwm < 4) pwm = pwma[pwm]; // Для малых значений берем из массива
          dt = buf[3]; // Пошаговая задержка для более медленного вращения
          if(dt) {
            step = (pwm > oldpwm)? 1: -1; // Направление шагов
            i = oldpwm + 1;
            while(1) { // Двигаемся плавно, чтобы не выдернуть шланик
              OCR1A = i;
              if(i == pwm) break;
              i += step;
              delay_ms(dt);
            }
          } else { // Быстрое перемещение (dt == 0)
            OCR1A = pwm;
          }
          sei(); // Разрешаем прерывания
          break;
      }
      TWCR |= _BV(TWEN); // Активируем TWI
    }
  }
  return 0;
}
//------------------------------------------------------------------------------
// История и список изменений
// 1. 05.10.2019 - Отлажен весь функционал для этого типа устройств.
//------------------------------------------------------------------------------

На данный момент в контроллере реализован следующий функционал:

1. Запись в EEPROM и чтение из нее калибровочной информации, необходимой для пересчета кода в угол поворота сервы и наоборот. Как и у других модулей, калибровочные данные содержат три числа: coef - наклон калибровочной прямой "код-угол", offset - смещение кода и ui - код единицы измерения (в данном случае - градус). Т.е. угол_поворота = coef*(code + offset).
2. Чтение пакета данных с шины i2c и установка соответствующего угла поворота сервы. Пакет данных состоит из 3-х байт. Первые два байта задают уровень ШИМ, третий байт - задержка (в мс) для уменьшения скорости вращения сервы (0 - максимальная скорость). В данной версии прошивки реализован самый простой вариант (регистр OCR1A модифицируется в произвольный момент времени, без привязки к состоянию счетчика). Поэтому изредка наблюдаются небольшое "запинание" сервы в начале вращения. Но они довольно редки и, в общем-то, никак не сказываются на точности позиционирования сервы. Поэтому я пока не стал ничего менять в прошлогоднем варианте прошивки.

Исходник прошивки и соответствующий hex-файл находится в архиве firmware_servo.zip в приложении к данному топику.

Класс-обертка контроллера сервомашинки и тестирование

В полном варианте класс-обертка MG90S сервомашинки реализован в версии 0.4.1.1. библиотеки lite (архив находится в приложении к данному топику). Фрагмент кода с определением класса приведен в раскладушке ниже.

Скрытый текст
#-------------------------------------------------------------------------------
class MG90S(I2C):
  ''' Привод сервомашинки MG90S
  '''
  fc = 0xA9
  def __init__(self, addr):
    '''
    __init__(self, addr)
    Конструктор. addr - адрес на шине i2c
    '''
    I2C.__init__(self, addr) # Инициализируем i2c в родительском классе
    self._calibr = self.rc()
#    self._calibr = [0.3688, 90, 0] # Калибровочные данные
    self.coefi = 1.0/self._calibr[0] # Обратная величина от коэффициента
    self.delay = 0 # Пошаговая пауза для замедления вращения в мс
    self.val = 0.0

  def rc(self):
    '''
    rc()
    Читает с устройства калибровочные данные
    '''
    self.wd(b'\xb8') # Команда - считать блок данных из EEPROM
    self.wd(b'\xbe') # Команда - считать данные из рабочей области
    buf = self.rd(EE_SIZE) # Считаем калибровку
    return deser(buf) # Распаковка блока

  def wc(self, coef = 1.0, offset = 0, ui = 0):
    '''
    wc(self, coef = 1.0, offset = 0, ui = 0)
    Запись калибровочных данных в EEPROM
      coef - калибровочный коэффициент для получения физ. величины из кода
      offset - смещение кода АЦП
      ui - индекс единицы измерения физической величины в списке units
    '''
    buf = b'\x4e' # Команда записать данные в рабочую область
    buf += ser(coef, offset, ui)
    self.wd(buf) # Запись калибровок в рабочую память устройства
    self.wd(b'\x48') # Команда записать блок данных в EEPROM

  @property
  def calibr(self):
    '''Возвращает калибровочные данные'''
    return self._calibr

  @calibr.setter
  def calibr(self, value):
    '''Записывает калибровочные данные в устройство. Калибровочные данные
    должны быть указаны в формате [coef, offset, ui], где coef - калибровочный
    коэффициент, offset - смещение, ui - индекс единицы измерения.'''
    self.wc(*value)
    self._calibr = value # Обновим калибровку
    self.coefi = 1/self._calibr[0]
    pass

  @property
  def code(self):
    '''
    Свойство code - уровень ШИМ
    '''
    return self._code

  @code.setter
  def code(self, value):
#    if value > maximum?: value = maximum?
    if value < 0: value = 0.0
    buf = bytearray();
    buf.append(0x52)
    buf.append(value & 0xff)
    buf.append((value >> 8) & 0xff)
    buf.append(self.delay & 0xff)
    self.wd(buf)
    self._code = value
    self._val = (self._code - self._calibr[1])*self._calibr[0]

  @property
  def val(self):
    return self._val

  @val.setter
  def val(self, value):
    self.code = int(value*self.coefi + 0.5) + self._calibr[1]

  # Просто "затычки" для единообразия
  @property
  def v(self):
    return self.val

  @val.setter
  def v(self, value):
    self.val = value
#-------------------------------------------------------------------------------

Как и классы контроллеров других исполнительных устройств, класс MG90S содержит следующие свойства:
1. calibr для записи/чтения в EEPROM микроконтроллера калибровочных данных (список трех чисел [coef, offset, ui])
2. code для непосредственного управления уровнем ШИМ сигнала, идущего на управляющую линию сервомашники
3. v тоже для установки угла поворота сервомашинки, но уже в градусах

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

На рисунке ниже приведен скриншот небольшой сессии с комментариями, иллюстрирующей работу с объектами класса MG90S. Библиотека lite должна быть расположена либо в текущей директории, либо в директории "известной" интерпретатору питона.
fig_04_test_session.JPG
Fig_04_test_session. Ненавязчивая автоматизация ректификационной установки. Автоматика.

Примечание

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

Предыдущий топик Вернуться к оглавлению Следующий топик
ruslan_ka Студент Железнодорожный 29 6
Отв.2058  03 Янв. 21, 13:47
Поэтому изредка наблюдаются небольшое "запинание" сервы в начале вращения.OldBean, 24 Дек. 20, 19:23

step = (pwm > oldpwm)? 1: -1; // Направление шагов
i = oldpwm + 1;

Возможно, если написать так, то и "запинаний" не будет?
i = oldpwm + step;
OldBean Доцент Красноярск 1K 1.4K
Отв.2059  03 Янв. 21, 17:04
Возможно, если написать так, то и "запинаний" не будет?ruslan_ka, 03 Янв. 21, 13:47
Возможно. Хотя, вроде бы, запинания бывали не только на обратном ходу. Причем, довольно редко. Но в любом случае этот "косячок" нужно поправить. Поправлю. Спасибо!


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