Arduino, ШИМ, ПИД и Epson
- Войдите на сайт для отправки комментариев
Доброго всем времени суток!
Есть необходимость крутить в Эпсоновской лентопротяжке помпу прокачки чернил. Конструктивно помпа выглядит как пластиковый стакан-статор на стенке которого лежит виток силиконовой трубки внутри которого вращается челнок-ротор с пережимающим трубку валиком. Из-за того, что вход и выход витка в/из стакана имеют 1-2 мм перехлёста (иначе вакуум не создавался бы) каждый оборот валик "наступает" на 2 трубки и нагрузка на вал возрастает аж наблюдается девиация частоты воя шестерёнок (это если питать движок стабилизированными 8..42V - Эпсоновская же плата не иначе как через ПИД-управление на любых, задаваемых прошивкой, оборотах крутит ровно и гладко). Для этого на Али была приобретена китайская Nano и обвязана как-то так:
А скетч выглядит так:
#include <PID_v1.h> #include <TimerOne.h> #define PIN_encoder 2 #define PIN_MOTOR 9 // PWM #define Key_Plus 7 #define Key_Minus 12 volatile int encoderCnt = 0;// Счетчик импульсов с энкодера за 1 таймер //Define Variables we'll be connecting to double Setpoint, Input, Output;//volatile //Define the aggressive and conservative Tuning Parameters double consKp=0.4, consKi=0, consKd=0; //подбираем ручками //1.3023 //Specify the links and initial tuning parameters PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT); void doEncoder(void)// Обработчик прерывания для энкодера { encoderCnt++; } void timerIsr()// “Скорость” – количество импульсов, зарегистрированное за интервал { // между вызовами этой процедуры Input = double(encoderCnt); // Input = RealSpeed в импульсах с энкодера // Serial.println("encoderCnt = " + String(encoderCnt));// строго для отладки encoderCnt = 0; if (Input != Setpoint) { myPID.SetTunings(consKp, consKi, consKd); } myPID.Compute(); analogWrite(PIN_MOTOR, byte(Output)); } } void setup() { pinMode(Key_Plus, INPUT);// инкремент Setpoint'a pinMode(Key_Minus, INPUT);// декремент Setpoint'a pinMode(PIN_encoder, INPUT);// Настройка энкодера digitalWrite(PIN_encoder, HIGH); // включаем подтяжку входа к «1» Serial.begin(9600);// строго для отладки Serial.println("Initializing");// строго для отладки Setpoint = 196;//128; analogWrite(PIN_MOTOR, Setpoint); myPID.SetMode(AUTOMATIC);//turn the PID on myPID.SetControllerDirection(DIRECT);// REVERSE myPID.SetOutputLimits(0, 255); // Настройка прерываний для энкодера // Энкодер подключен к ноге №2 – прерывание №0 attachInterrupt(0, doEncoder, RISING); // Прерывания от Timer1 будут происходить каждые 6656 микросекунд //(длительность импульса с энкодера = 26 мкс * 256 импульсов) // Timer1.initialize(6650);//6656 Timer1.initialize(10000);//6656 Timer1.attachInterrupt( timerIsr ); // Настройка обработчика } void loop() { if (digitalRead(Key_Plus) == HIGH) { if (Setpoint < 255){ Setpoint++; // //250 } delay(200); Serial.println("Setpoint = " + String(Setpoint));// строго для отладки analogWrite(PIN_MOTOR, Setpoint); Serial.println("Output = " + String(byte(Output)));// строго для отладки } if (digitalRead(Key_Minus) == HIGH) { if (Setpoint > 5){ Setpoint--; // 0 } delay(100); Serial.println("Setpoint = " + String(Setpoint));// строго для отладки analogWrite(PIN_MOTOR, Setpoint); } }
И никак не могу победить возбуждение/перерегулирование.
З.Ы. Прошу палками и камнями сильно не метать - это 1-й опыт с Ардуиной, а опытный глаз сразу найдёт где собака порылась.
Первое что бросается в глаза так это насилие над транзисторами:
1. При подаче 1на базу второго С945 5 вольт через КЭ и БЭ радостно сквозит на землю. КЭ - доли вольта, БЭ 0,5 - 0,8 вольт. Не великоват ли ток коллектора?
2. Переходу БЭ КТ846 тоже не позавидуешь....
Посему есть подозрение что какой-то, а может оба транзистора насыщается. А при насыщении управляющего элемента ни о каком регулировании речи быть не может.
И ещё. Нигде не вижу борьбу с дребезгом кнопок. Вы уверены что одно нажатие приводит к одному управляющему импульсу? Я нет.
А этим мотором точно можно управлять ШИМ?
Вспомните как работал ЛПМ в кассетниках и никакой девиации, Ардуино, ПИД и ШИМ...)
Про транзисторы в правой части схемы Вам уже написали. Я бы ещё добавил, что не вижу диода параллельно двигателю.
Теперь про левую часть схемы :)
... При подаче 1цы? на базу второго С945 5 вольт через КЭ и БЭ радостно сквозит на землю.
Ну, во-первых: не на землю, а на нагрузку - эм. переход 846-го, во-вторых этот каскад и задумывался как эмиттерный повторитель дабы базовым током 846 не жогнуть выход Ардуинки и в-третьих: когда там стоял делитель - 1Ком на D9 + 1Ком на землю - движок стоя пищал какую-то модуляцию.
И вообще - к чему весь этот разбор полётов (хватит "[/quote]"): я забыл добавить к первому посту, что если заREMировать строки 57 и 58, то, управляемый кнопками, движок крутится очень даже нормально (за исключением подвываний от нагрузки на вал - так что со схемой хоть и "плюс/минус", но вродь как всё норм), а вот процедура обработки прерываний по таймеру через ПИД вносит не детские корректировки в значение Output из-за чего движок разгоняется от минимума до максимума с частотой раза полтора-два в секунду. И как бы я не экпериментировал с П, И и Д коэффициентами - эта частота ("перегазовок") не меняется.
1. Пин D2 в программе сконфигурирован, а потом не используется от слова никак. Или я то-то пропустил?
0 - диод просто забыл нарисовать (иначе транзисторы летели бы как семечми - от первого же фронта);
1 - наверное пропустили: я пометил маркером зуб шестерёнки на которой сидит энкодер и ровно за оборот encoderCnt показал 745 импульсов
2 - аппаратные передвижки в попытке через SPI передать код старта в Эпсоновский драйвер, но...
Заканчиваем разбор полётов:
UFO 007: И как бы я не экпериментировал с П, И и Д коэффициентами - эта частота ("перегазовок") не меняется.
Значит дело не в программе?
Про настройку коэффициентов ПИД тут глянте http://lazysmart.ru/osnovy-avtomatiki/nastrojka-pid-regulyatora/
А этим мотором точно можно управлять ШИМ?
Я глубоко сумлеваюсь, что теплоотвод под драйвером (QFP48) обеспечивает нормальное функционирование 3-х движков (каретка/бумага/сканер - особенно при копировании документа) в аналоговом режиме.
Вспомните как работал ЛПМ в кассетниках и никакой девиации, Ардуино, ПИД и ШИМ...)
Эт ты щас сострил или сумничал? Хорошо - спешл ту ты: БУМАГОпротяжка
...
Значит дело не в программе?
А ежелить дело в железе - почему выставленная кнопками скорость, хоть и не идеально ровно, но поддерживается?
... хоть и не идеально ровно, но поддерживается?
"Ширина" (длительность) импульса, отдаваемой в нагрузку (на ДиСи мотор), мощности не варьируется от нагрузки на вал, хотя энкодер эти отклонения "видит" - наверное именно для такой стабилизации PID и придуман.
Спс, гляну обовъязково.
Спс, гляну обовъязково.
Сорри - еррор 404
... И как бы я не экпериментировал с П, И и Д коэффициентами - эта частота ("перегазовок") не меняется.
И = Д = 0 (вродь как с этого советуют начинать), а вот П = 1, 1.1, 1.2, 1.3 = движок "мычит" а при 1.303 перегазовки... Вот, собственно, и дилемма или с майПид что-то не так или, действительно, прав ВасилийВ и транзисторы, получив квадратный импульс, умудряются работать в аналоговом режиме (это там на вход усилка может приходить 0,3 мВ (или 4..20 мА) и соотношение резисторов обратной связи - это есть коэффициент усиления/искажения/шумов и тд и тп - там есть где разгуляться фантазии...). Тут же всё просто: лог "0" - транзистор закрыт, лог "1" - открыт и если грубо утрировать, то угол поворота ротора прямопропорционален длительности "1".
А еще пляски возле трения вы забили. Оно как бывает что сдернуть предмет с места тяжелее чем когда это тело скользит. Вот когда движет "мычит", то стоит. А получив заводящий пендаль дергается до следующего мычания, если пендаль слабый.
ПС: А про схему включения некого Дарлингтона слыхали. Нет мы этого чувака в глаза не видели
эмитерный повторитель наше дело.
Вспомните как работал ЛПМ в кассетниках и никакой девиации, Ардуино, ПИД и ШИМ...)
Эт ты щас сострил или сумничал? Хорошо - спешл ту ты: БУМАГОпротяжка
Там ДПТ управлялся регулятором частоты вращения (плата РЧВ), в которой выходной каскад был охвачен ПОС и за счет этого ДПТ имел постоянные обороты при меняющей нагрузке на валу. Скорость выставлялась подстроечником.
А еще пляски возле трения вы забили. Оно как бывает что сдернуть предмет с места тяжелее чем когда это тело скользит. Вот когда движет "мычит", то стоит. А получив заводящий пендаль дергается до следующего мычания, если пендаль слабый.
ПС: А про схему включения некого Дарлингтона слыхали. Нет мы этого чувака в глаза не видели
и изобрёл этот некий Дарлингтон ни что иное, как КТ827
эмитерный повторитель наше дело.
А если вместо R эмиттерный переход КТ846?
А еще пляски возле трения вы забили....
Ну, да - если заREMировать 34-ю строку
чтобы от PID_v1 в PWM ничего не писалось, то при кнопочном управлении никакого трения... Выходит PID_v1 периодически притирает?
Там ДПТ управлялся регулятором частоты вращения (плата РЧВ на К198НТ1+КТ814), в которой выходной каскад был охвачен ПОС и за счет этого ДПТ имел постоянные обороты при меняющей нагрузке на валу. Скорость выставлялась подстроечником.
При соотношении диаметра оси (транспортировавшей МЛ) к диаметру маховика тонвала - коэффициент редукции будь здрав, как следствие: движок потребляет пол-копейки и, соответственно, аналоговый режим возможен даже без радиатора/теплоотвода, а перемотка (нагрузка-то на вал увеличивается, но) длится несколько секунд - особо не перегреешься
З.Ы. "Фамилии" радиоэлементов РЧВ помню неуверенно
Или я то-то пропустил?
строку №53 и комментарий над ней. Сейчас (начиная со строки №19) сделал так:
и более точный замер оборота шестерни показал
импульсов с энкодера за оборот - т. е. аппаратное прерывание работает тип-топ - не докопаться, а вот програмное...
Может не правильно выбран тайминг для Timer1? В исходнике было 20000 мкс = 50 Гц, но сколько тысяч импульсов за это время насчитает encoderCnt? А в PWM "помещается" значение только #00...#FF. Так вот чтобы не вводить дополнительные коэффициенты пересчёта (а как я соображаю - чем больше этот коэффициент, тем меньше точность регулирования) была замерена осциллоскопом длительность импульса с энкодера на максимальных оборотах (когда вал подаёт бумагу на печать помпа отключается и подвывания пропадают) и умножена на 256: т. е. какое значение в PWM записали - столько импульсов encoderCnt между проверками по таймеру должен накопить. Иначе говоря PID_v1 должна варьировать значение Output, запысываемое в PWM так, чтобы encoderCnt постоянно совпадал с Setpoint. Или я совсем неправильно всё понимаю?
Да, нет, я пропустил attachInterrupt. Комментарии меня не особо волнуют :)))
UFO 007. Вам бы книжечку почитать: Пол Хоровиц и Уильям Хилл. Искусство схемотехники. Том первый. Читать пару раз в год в течении 2х лет. Потом с интервалом раз в 3 года. И разобрать там примеры. Тогда поймете что переход база - эмиттер не самая тривиальная нагрузка. Далеко не сопротивление.
По теме. Замените выходной транзистор на n-канальный мосфет. С материнской платы с цепи питания процессора, неважно верхнее плечо или нижнее. Затвор притяните к земле сопротивлением 1к.
По моему место теме в аппаратной ветке.
UFO 007. Вам бы книжечку почитать: Пол Хоровиц и Уильям Хилл. Искусство схемотехники. Том первый. Читать пару раз в год в течении 2х лет. Потом с интервалом раз в 3 года. И разобрать там примеры. Тогда поймете что переход база - эмиттер не самая тривиальная нагрузка. Далеко не сопротивление.
По теме. Замените выходной транзистор на n-канальный мосфет. С материнской платы с цепи питания процессора, неважно верхнее плечо или нижнее. Затвор притяните к земле сопротивлением 1к.
По моему место теме в аппаратной ветке.
В той книжице есть раздел неправильные схемы (или что-то похожее). Схеме ТС там место.
UFO 007, какой макс. ток перистальтика потребляет при 42 В?
Э-э-эх, жестянщики... Вам бы только (хоть и схемотехническим, но) молотком (точнее - паяльником) размахивать...
А ларчик открывался просто (собака порылась всё-таки в коде):
и диагноз "перегазовки" - искоренён: смысл пытаться чё-то вычислять каждые 6,6 мС если ждём целых 200.
З.Ы. По поводу перистальтики в ветку про хирургию - однозначно, т. к. согласно ГОСТ - это недопустимое название шлангового насоса. А помпа потребляет динамически изменяющийся ток - иначе PID было бы не нужно.
З.Ы. По поводу перистальтики в ветку про хирургию - однозначно, т. к. согласно ГОСТ - это недопустимое название шлангового насоса. А помпа потребляет динамически изменяющийся ток - иначе PID было бы не нужно.
Я заметил, что поисковиком можешь пользоваться. Даже в вики заглянул...
Перистальтика и шланговый насос - синонимы.
Э-э-эх, жестянщики... Вам бы только (хоть и схемотехническим, но) молотком (точнее - паяльником) размахивать...
А ларчик открывался просто (собака порылась всё-таки в коде):
Вот за чем вы тему на форуме открыли, а потом туману напускали. Ясно же Вам надо поднять навык Программирования, который разумеется подымается индивидуально.
Вот за чем вы тему на форуме открыли...
Я же думал - помогут, а тут: умничают... А вместо того, чтобы пальцы гнуть - взяли бы да и привели идеально работающую схему коммутации/управления движком
И да ,если хотите в могилу быстро и безболезнено, то и в этом случае не занимаетесь любительством, а то срачка вас долго отпускать не будет.
Так вот и помогают...
точнее - ахинею несут... И вообще: слыш ты, великий теоретик, или нарисуй схему, или не разводи грязь в теме
точнее - ахинею несут... И вообще: слыш ты, великий теоретик, или нарисуй схему, или не разводи грязь в теме
Волшебное слово забыл добавить...
Э-э-эх... Господа Великие Семотехники... вам из-за паяльника не видно, что переменная Input, "уходящая в прерывание" имеет НЕволатильную ипостась (на её волатильность ругается компилятор) и возвращается из прерывания некий "мусор", в соответсвии с которым, движок и рычал пока я не избавился от прерывания - теперь програмным таймером жду 6,6 мс... но библиотеке PID_v1 из-за работы с дублёвым типом данных не хватило быстродействия, а вот FastPID (что на интах работает) передвигает пузырёк воздуха внутри трубки от капельницы так гладко, как будто движок (ну и помпу) вращает сам Эпсоновский Realoid. А то: "... нетривиальная нагрузка ...", "... МОСфеты ...", ... - прерывания удобней феном припаивать.
А этим мотором точно можно управлять ШИМ?
Волшебное слово забыл добавить...
Да всем просто пофиг на вашу неволатильнось, бессмысленное использование глобалов и счетчик в типе int.
счетчик в типе int.
движки работают "молча" - не пищат, не зудят
счетчик в типе int.
И зачем ему тогда быть int, если максимальное значение ШИМ 255?
И зачем ему тогда быть int, если максимальное значение ШИМ 255?
P.S. А вообще лучше пользоваться типами данных с точной шириной. Например вместо byte использовать uint8_t
UFO 007 - зачем вы эту тему снова подняли? - чтобы доказать. что форум вам не помог, а сами вы справились? - довольно смешно выглядите, с учетом того, что реванш занял у вас полгода...
...uint8_t
... полгода...
UFO 007 - зачем вы эту тему снова подняли?
а ещё в СИ меня прикалывает unsignet char - если он просто char (сигнет), то может быть и "-А"?
то может быть и "-А"?
А то!