Математика на пальцях: ардуїнов головного мозку або лінійно-квадратичний регулятор для управлінням електродвигуном

Постановка завдання: як зі шкільними знаннями дійти до висновків університетського рівня

Ця стаття припускає, що ви прочитали мої статті (ну або і без того знаєте) про методи найменших квадратів і лінійно-квадратичний регулятор.

Як я вже говорив у попередніх статтях, мої знайомі студенти хочуть побудувати зворотний маятник, але умаялись підбирати коефіцієнти ПІД-регулятора, тому я неспішно дивлюся, що таке лінійно-квадратичний регулятор, ну а заодно і вам переказую те, що прочитав. Завдання цієї статті — показати, як втілити в залозі одновимірний приклад зі статті про лінійно-квадратичний регулятор. Грубо кажучи, я хочу написати написати управління для сервомотора: у мене є поточне положення осі приводу і поточна швидкість її обертання, я хочу її зупинити в заданому положенні. Я спробував було прочитати схожу статтю на цю тему, але, зізнатися, нічого в ній не зрозумів, тому сіл розбиратися самостійно, переважно на пальцях і без страшних слів типу диференціальних рівнянь Лагранжа-Ейлера.

Продовжуючи робочий ексгібіціонізм, знайомлю вас з Bubble Bobble, який живе у нас з колегою в кабінеті. Він рецензує статті для конференції SIGGRAPH.





Інструкція по користуванню моїми статтями або навіщо я пишу на хабрахабр


Інструкція строго одна: будемо доброзичливі один до одного.
Я нездатний написати струнку послідовність формул без помилок. Абсолютно всі мої формули невірні. Але особисто я здатний по неправильній формулою відновити правильну, так як у мене кожен символ має свою семантику. Якщо ви маніпулюєте математикою як просто набором граматичних правил над деякими алфавітом, нам з вами не по дорозі. Особисто я не можу оперувати не одним поняттям, якщо у мене немає «картинки» в голові, якоїсь інтуїції про природу даного феномена. Якщо ви бачите помилку у мене, скажіть мені про це, я буду тільки радий. Заздалегідь спасибі!



Розгорнуто про цієї інструкціїНа даний момент я написав вже півтора десятка статей на хабр, і за результатами змушений написати невеликий ліричний відступ про моїх цілях. Я цікавий і багато читаю, тобто, я постійно вчуся. Для того, щоб засвоїти нові для мене речі, я намагаюся пояснити іншим людям. Як свідчать дві класичні цитати:

Nothing clears up a case so much as stating it to another person.
*— Sherlock Holmes, Silver Blaze*


Або російський варіант:
Розмова 2-х викладачів:
— Ну і група мені в цьому році потрапила тупа!
— А що так?
— Уявляєш собі, пояснюю теорему — не розуміють! Пояснюю другий раз — не розуміють!!! В третій раз пояснюю. Сам вже зрозумів. А вони не розуміють...


На хабрахабр я прийшов за трьома речами:
1. Щоб поділитися знаннями з людьми, що знають менше мене.
2. Це вимагає структурування інформації, таким чином, я ще краще засвоюю те, що зрозумів.
3. Щоб отримати цінні коментарі від людей, які знають більше за мене (до речі, більшість знань, що я почерпнув для цієї статті, мені передав шановний Arastas).

Кожна моя стаття — це плід роздумів як мінімум кількох днів, як мінімум декількох годин написання тексту і можливо кількох годин написання вихідного коду, так як по можливості я намагаюся супроводжувати свої статті програмами. Я погано ставлюся до тих, хто з місця в кар'єр мені каже, що я ідіот. Спасибі, я це й сам знаю, нової інформації в цьому немає, а неповага до моєї роботи є. Я вкрай вітаю будь-які коментарі, що містять конструктивну критику. Якщо я сказав дурницю, то напишіть мені, де саме і чому. Це допоможе мені поправити текст, збільшивши мої знання і знання інших читачів. Я також вітаю будь-які конструктивні запитання і ніколи не ставлюся зарозуміло до людей, які знають менше мене, саме тому вимагаю симетричного відношення від тих, хто знає більше за мене.

Я хочу збільшити кількість людей з гарним настроєм і високою кармою на хабре (до того ж, як ми знаємо, її жорсткий дефіцит). Тому я щедро роздаю плюси коментарям і в карму, але при цьому не соромлюся видавати і мінуси, останнє стосується лише зарозумілих і/або нечемних людей.

Перегляньте сюди, щоб зрозуміти, чого саме я б не хотів бачити в коментарях. Мені не потрібні крики про быдлохабр і висловлювання про те, що я дебіл. Так, особисто я не вмію розрахувати токоограничительный резистор для світлодіода. Я вмію обмежити зверху його номінал. Так, я прийму опір світлодіода за нуль і отримаю безпечне значення для резистора. І так, я знаю, що світлодіод безкоштовно світитися не може. Коли буде потрібно, я розберуся в деталях, а поки груба прикидка зверху, яка гарантовано не спалить мою плату — це прекрасно. Якщо ви бачите неточність або просто помилка, виправте її, всім буде користь.



Наявні в розпорядженні залізяки

У розпорядженні є оптичний енкодер (1000 пульсів на оборот), електродвигун (750 rpm при 12В без навантаження), драйвер L6201 і atmega 328 (arduino nano).



В залежності від сигналу PWM, що я подаю на вхід L6201, він видає різну напругу на електродвигун. Тобто, мій мікроконтролер вміє керувати тільки напругою на клемах електродвигуна.

Рівняння Максвелла на пальцях або як себе веде двигун постійного струму

Зовсім недавно я вже казав про те, що з себе представляють рівняння Максвелла. Давайте повторимо: рівнянь Максвелла чотири за кількістю наступних законів:

1. Закон Гаусса, «на пальцях» це просто закон збереження: енергія нізвідки не береться і нікуди не йде.
2. Закон Гаусса для магнітного поля — те ж саме, тільки для магнітного, а не електричного поля.
3. Закон Фарадея: якщо ми рухаємо магнітами, то вони породжують електричне поле.
4. Закон Ампера: якщо ми рухаємо електричним полем, то породжує магнітне.

Векторні поля, які є вирішенням цих чотирьох рівнянь, називаються електричним і магнітним полем. У статті про магнітну левітацію я цікавився в основному законами Гаусса, у даній статті мені цікаві закони Ампера і Фарадея. Як взагалі працює електродвигун постійного струму? Ми пропускаємо через обмотки струм, що створює магнітне поле (див. закон Ампера). Це і змушує обертатися ротор нашого двигуна.

Давайте спробуємо уявити, як працює такий двигун. Нехтуємо всім чим тільки можна (індуктивність, тертя тощо) і згадуємо тільки курс сьомого-восьмого класу школи, а саме — закон Ома. Отже, закон ома свідчить, що напруга — це добуток сили струму на опір (U=IR). Опір обмоток двигуна постійно, тому, з точністю до постійного множника, напруга на обмотці і струм через неї — це одне і те ж. Далі, закон Ампера говорить, що сила, після прикладання білої тканини до ротору, пропорционалена пропускає струму, а значить, і нашому напрузі. Тобто, якщо я живу в моєму вигаданому світі, то подавши постійні 12В на обмотки двигуна, я створюю якусь постійну силу (момент).

Але наш двигун цілком підпорядковується другому закону Ньютона (F=ma). Таким чином, якщо у мене на обмотці двигуна постійна напруга, то це тягне за собою постійне прискорення вала двигуна (маса не змінюється!). А ось цей висновок починає вже зовсім погано пахнути, адже якщо у мене є постійне прискорення, то я так і швидкість світла преплюнуть можу…

Тут сама пора згадати про те, що є варіант не подавати напругу на двигун, а крутити його вал, навпаки знімаючи напругу з нього (див. велогенератор). Це наслідок закону Фарадея: якщо ми крутимо магнітами, то це породжує електромагнітну індукцію. «Напруга» (строго кажучи, ЭДС) прямо пропорційно обертам двигуна: чим швидше ми його крутимо, тим більше ЕРС (U = C * v, де U — це напруга, C — деяка константа для нашого двигуна, а v — швидкість обертання валу).

І яка заковика: якщо ми-таки подаємо напруга на двигун, то ротор обертається (закон Ампера), але при цьому сам генерує ЕРС (закон Фарадея), яка бореться з поданими напругою, зменшуючи його! Таким чином, закон Ома для двигуна буде виглядати швидше як U — I*R — C*v = 0.

Закон Ампера нам говорить про те, що струм пропорційний силі, створюваної магнітним полем. А другий закон Ньютона говорить про те, що сила пропорційна прискоренню (а прискорення — це похідна від швидкості за часом!). Таким чином, закон Ома для двигуна можна записати u(t) — const1 * v'(t) — const2 * v(t) = 0. У дискретному світі похідну v'(t) можна представити як v'(t) = v(t+1)-v(t), таким чином, закон Ома можна записати як v(t+1) = a*v(t) + b*u(t), де a і b — це константи, що залежать від фізичних параметрів двигуна і від часового кроку.

Я подав на зупинений двигун чотири різних постійних напруги (24В, 18В, 12В, 6В) і записав швидкість пересування каретки за допомогою інкрементального енкодера. Ось так виглядали випробування:



Ось ця картинка дає чотири різних графіка (некрасиві, зубчасті) для чотирьох напруг:



А також вона дає теоретичну криву (я знайшов a=0.97, b=0.218) для цих напруг. Параметри a і b знайдені за допомогою вкрай тупого коду фиттинг. Зрозуміло, в реальному світі тертя ненульове, тому моя теоретична крива не збігається зі всіма вимірами, але остільки, оскільки я припускаю, що моя каретка буде частіше рухатися з напругою в районі нуля, а не в районі максимуму, то теоретична крива краще апроксимує рух при малих напругах.

Нова формулювання лінійно-квадратичного регулятора

Увага: тут передбачається, що ви добре прочитали мою статтю про лінійно-квадратичний регулятор.

В ній наш приклад моделювався наступною системою рівнянь:



тут x_k — це положення каретки, v_k — її швидкість, а u_k — її прискорення. З попередньої секції ми знаємо, що прискорення дуже нелінійно залежить від прикладеної напруги, і мене це трохи напружує, так як мікроконтролер вміє безпосередньо керувати тільки напругою. Але при цьому ця залежність (при нульовому терті) експоненціальна, що дуже добре входить в рамки лінійної системи переходу! Таким чином, я моделюю систему наступним чином:



тут x_k — це положення каретки, v_k — її швидкість, а u_k — це вже не прискорення каретки, а напруга, яку я прикладаю до клем електромотора. Для конкретно мого двигуна я знайшов a = .97, b = .218.

Ось код, який знаходить коефіцієнти залежності змінної управління (напруга на клемах) від вектора станів (положення і швидкість каретки). У мене каретка може максимально відхилятися від нульового стану на 245мм, тому я поставив нульову початкову швидкість і положення 245мм. Завдання полягає в тому, щоб зупинити каретку в нульовому положенні (центр рейки).

Рядки 17-53 ставлять жорсткі умови нашої системи (початкові і кінцеві умови, лінійний перехід станів), а рядки 55-70 — оптимізуючу функцію. Основне завдання — збіжність положення і швидкості до нуля (рядки 56 і 61). Я поступово збільшував обмеження на управління (рядок 66), поки результат не вписався у фізичні параметри системи (при даних параметрах напруга не виходить за 24В).

Ось так виглядають теоретичні криві положення, швидкості та напруги, яке необхідно для їх досягнення:



Таким чином, вищезазначений код каже, що напруження, яке необхідно докласти, може бути розрахована як:



де x_k — це поточна позиція каретки, а v_k — її швидкість.

Повний код з боку мікроконтролера

Отже, остання формула і є наиглавнейшая для цієї статті, ось мій код для безпосередньо керування кареткою.

Давайте я його приведу її основну частину:

void loop() {
vi = xi-xi_1;
int ui = 255.*(-0.000973669*xi -0.0563218*vi)/24.;
xi_1 = xi;
set_speed(ui);
delay(2);
}


Підрахунок значень экодера (функція ISR) заслуговує окремої невеликої статті, це не суть важливо на даний момент. Що важливо — це функція loop(). Я вважаю поточну швидкість як різниця положень енкодера зараз і дві мілісекунди тому, потім поточне напруга ui підраховується по щойно наведеній формулі. Всі! Ось і весь той лінійно-квадратичний регулятор.

Непогано б порівняти те, що ми натеоретизировали, з тим, що виходить на практиці. Ось ця картинка дає порівняння:



Таким чином, реальне положення каретки злегка відрізняється від теоретичного, я вважаю, що це за неврахованого тертя: чим ближче до нуля, тим менше подається напруга, і одного разу вона вже не може боротися з тертям. Боротьба з цим феноменом буде темою однієї з наступних статей. Stay tuned!

Удачі вам і будьте цікавими!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.