Енкодери

На минулому уроці ми згадували про енкодери. Що це таке і для чого вони потрібні?

Енкодери — це датчики, які вимірюють, наскільки обернувся кожен двигун (а отже, і кожне колесо). Ми вже згадували, що наші двигуни не ідеальні, тому коли ми даємо їм команду виконати певне зусилля, ми не знаємо, з якою швидкістю вони насправді обертаються. Енкодери точно вимірюють роботу двигуна і передають цю інформацію назад до XRP.

../../_images/blog017-image001-disks-resolution.jpg

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

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

Порада

Диск і датчик в XRP приховані всередині пластикового корпусу двигуна, тому ви не зможете їх побачити.

XRP виконує всі обчислення, щоб перетворити ці перемикання в реальне вимірювання відстані для вас, тому вам не потрібно про це турбуватися. Ми можемо використовувати деякі нові drivetrain функції, щоб побачити, що вимірюють енкодери:

from XRPLib.defaults import *
from time import sleep

while True:
    print(drivetrain.get_left_encoder_position())
    sleep(1)
../../_images/encoder.png

Цей код використовує щось нове: while loop. Цикл while буде виконувати код, що знаходиться під ним, доки умова не перестане дорівнювати True. У цьому випадку умовою є ключове слово True, що означає, що цей код буде виконуватися доти, доки True не перестане дорівнювати True. Оскільки це ніколи не відбудеться, код буде виконуватися нескінченно, доки ви не зупините його вручну на своєму комп’ютері.

Порада

Більше про цикли та умови ви дізнаєтеся пізніше в цьому курсі.

Код повинен працювати безперервно, відображати положення лівого енкодера трансмісії, а потім чекати одну секунду. Потім він повторюється і робить це безперервно. Якщо ми не чекатимемо одну секунду, XRP зчитуватиме і надсилатиме положення енкодера на ваш комп’ютер так швидко, як тільки зможе (дуже швидко!), що буде занадто великим обсягом даних для вашого комп’ютера, щоб відобразити їх одночасно на екрані.

Спробуйте

Спробуйте запустити цей код, щоб побачити, що відбудеться. Поверніть ліве колесо XRP рукою і зверніть увагу, як змінюється число.

Розрахунок відстані

Давайте дізнаємося трохи про те, як XRP використовує кодер для обчислення відстані, на яку просунувся робот.

XRP знає діаметр коліс робота; всі XRP мають однакові колеса!

Якщо колесо автомобіля робить один повний оберт на землі, то на яку відстань проїде автомобіль? Автомобіль проїде на відстань, що дорівнює одному окружності кола:

../../_images/Circle-Graphic-1024x576-2.png

Порада

Нагадуємо, що довжина кола — це відстань по його периметру.

Окружність обчислюється як \(C = \pi \cdot d\), де \(d\) є діаметром кола.

Якщо колесо автомобіля (яке є колом з довжиною окружності 100 дюймів) обертається 5 разів, то яку відстань проїде автомобіль? Як це можна обчислити?

../../_images/P316_1-1.png

Ви обертаєте колесо один раз і бачите, що воно проїхало 100 дюймів, тому що колесо прокреслило свою окружність на землі. Потім ви обертаєте його вдруге і бачите, що воно проїхало ще 100 дюймів. Потім втретє, вчетверте і вп’яте, і бачите, що колесо прокреслило свою окружність на землі 5 разів.

Відстань, яку воно проїхало, в 5 разів перевищує довжину кола. Це можна використовувати для будь-якої кількості обертів. Якщо ви обернете колесо 3 рази, ви проїдете вперед в 3 рази більше довжини кола (300 дюймів), якщо ви обернете його 1,5 рази, ви проїдете вперед в 1,5 рази більше довжини кола (150 дюймів).

\[d\text{ cm} = (\text{number of rotations}) \cdot (\text{circumference})\]

XRP використовує це рівняння для автоматичного обчислення відстані, на яку перемістилися колеса, в сантиметрах за допомогою енкодерів.

Проїхати відстань (знову)

На минулому уроці ви використовували постійну швидкість і час для проходження відстані. Тепер, коли ви знаєте, що енкодери насправді вимірюють відстань, було б краще використовувати їх для вашої функції drive_distance. Ми можемо модифікувати вашу функцію, щоб використовувати While цикл:

def drive_distance(distance_to_drive):
    while drivetrain.get_left_encoder_position() < distance_to_drive:
        drivetrain.set_speed(5, 5)
        time.sleep(0.01)
    drivetrain.stop()
../../_images/drivedistanceencoder.png

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

Спробуйте

Замініть свою функцію drive_distance на цю нову. Випробуйте її біля метрової лінійки. Чи є вона більш або менш точною, ніж попередня?

Випробування

Цей код перевіряє тільки лівий енкодер. Оскільки обидва колеса рухаються з однаковою швидкістю, це повинно бути нормально, але, як ми вже говорили, двигуни не ідеальні. Чи можете ви придумати спосіб об’єднати обидва значення енкодера?

Щоб прочитати правий енкодер, використовуйте drivetrain.get_right_encoder_position()

Перехід до заголовка

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

Розрахунок необхідної відстані є складним, але ми можемо розбити цю задачу на етапи.

Спочатку давайте створимо дріб, який відображає від 0,0 до 1,0, наскільки колеса робота повинні проїхати по колу. У цьому випадку 0,0 дорівнює 0 градусам, а 1,0 дорівнює 360 градусам.

Тепер, щоб отримати відстань, яку проходить колесо, нам потрібно помножити цю частку на загальну відстань, яку колесо проходить, щоб обернутися на 360 градусів. Це число є довжиною кола з діаметром, що дорівнює діаметру робота. Ми можемо обчислити це, помноживши відстань проходження колеса на пі.

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

\[\frac{\text{target degrees} \cdot \text{robot wheel track}} {360 \cdot \text{wheel diameter}}\]

Тепер, коли ми маємо кількість обертів коліс, решта програми є простою. Просто поверніть робота в напрямку повороту і зупиніться, коли кількість обертів перевищить розраховану ціль обертання.

def turn(target):
    global rotations
    differentialDrive.reset_encoder_position()
    rotations = (target * 15.5) / (360 * 6)
    if target > 0:
        differentialDrive.set_effort((-0.3), 0.3)
    else:
        differentialDrive.set_effort(0.3, (-0.3))
    while not math.fabs(motor1.get_position()) >= math.fabs(rotations):

    differentialDrive.stop()
../../_images/encoder-turn-blockly.png