Рисующий плоттер своими руками (drawing robot).
Балансирующий робот своими руками на ардуино и шаговых двигателях
Балансирующий робот своими руками на ардуино и шаговых двигателях
Drawing Robot. Робот — Художник на 3D принтере
Drawing Robot. Робот — Художник на 3D принтере
Приводится описание упрощенной (из линеек) сборки балансирующего робота.
Это первая часть трилогии про балансирующего робота.
Вторая часть будет посвящена его программированию.
Желаете собрать такого же? Заходите ко мне в лабораторию роботов http://zizibot.ru/ — в ближайшее время я выложу набор.
The description of assembly of the balancing robot is provided.
It is the first part of the trilogy about the balancing robot.
The second part will be devoted to its programming.
You wish to assemble same? You come to me into laboratory of robots (http://zizibot.ru/) — in the nearest future I will lay out set.
Видео Как сделать балансирующего робота/How to make the balancing robot (Arduino) канала Mikhail Momot
Показать
Информация о видео
21 мая 2017 г. 20:53:25
00:15:43
Рассказываем о том как можно использовать Ардуино для создания самобалансирующего робота, который балансирует как Сигвей.
Как работает балансировка?
Сигвей от англ. Segway – двухколесное средство передвижения стоя, оснащенное электроприводом. Еще их называют гироскутерами или электрическими самокатами.
Вы когда-нибудь задумывались, как работает Сигвей? В этом уроке мы постараемся показать вам, как сделать робота Ардуино, который уравновешивает себя точно так же, как Segway.
Чтобы сбалансировать робота, двигатели должны противодействовать падению робота. Это действие требует обратной связи и корректирующих элементов.
Элемент обратной связи — гироскоп-акселерометр MPU6050, который обеспечивает как ускорение, так и вращение во всех трех осях (основы MP26050 I2C). Ардуино использует это, чтобы знать текущую ориентацию робота. Корректирующим элементом является комбинация двигателя и колеса.
В итоге должен получиться примерно такой друг:
Схема робота
Сначала подключите MPU6050 к Ардуино и проверьте соединение, используя коды в этом учебном руководстве по интерфейсу IMU. Если данные теперь отображаются на последовательном мониторе, вы молодец!
Продолжайте подключать остальные компоненты, как показано выше. Модуль L298N может обеспечить +5В, необходимый для Ардуино, если его входное напряжение составляет +7В или выше. Тем не менее, мы выбрали отдельные источники питания для двигателя и схемы.
Внимание! Если вы планируете использовать напряжение питания более 12 В для модуля L298N, вам необходимо удалить перемычку чуть выше входа +12 В.
Создание робота
Корпус робота изготовлен в основном из акрилового пластика с двумя редукторными двигателями постоянного тока:
Основная печатная плата, состоящая из Arduino Nano и MPU6050:
Модуль драйвера двигателя L298N:
Мотор редуктора постоянного тока с колесом:
Самобалансирующийся робот по существу является перевернутым маятником. Он может быть лучше сбалансирован, если центр массы выше относительно колесных осей. Высший центр масс означает более высокий момент инерции массы, что соответствует более низкому угловому ускорению (более медленное падение). Вот почему мы положили батарейный блок на верх. Однако высота робота была выбрана исходя из наличия материалов ?
Завершенный вариант самостоятельно балансирующего робота можно посмотреть на рисунке выше. В верхней части находятся шесть Ni-Cd-батарей для питания печатной платы. В промежутках между моторами используется 9-вольтовая батарея для драйвера двигателя.
Теория
В теории управления, удерживая некоторую переменную (в данном случае позицию робота), требуется специальный контроллер, называемый ПИД (пропорциональная интегральная производная). Каждый из этих параметров имеет «прирост», обычно называемый Kp, Ki и Kd. PID обеспечивает коррекцию между желаемым значением (или входом) и фактическим значением (или выходом). Разница между входом и выходом называется «ошибкой».
ПИД-регулятор уменьшает погрешность до наименьшего возможного значения, постоянно регулируя выход. В нашем самобалансирующем роботе Arduino вход (который является желаемым наклоном в градусах) устанавливается программным обеспечением. MPU6050 считывает текущий наклон робота и подает его на алгоритм PID, который выполняет вычисления для управления двигателем и удерживает робота в вертикальном положении.
PID требует, чтобы значения Kp, Ki и Kd были настроены на оптимальные значения. Инженеры используют программное обеспечение, такое как MATLAB, для автоматического вычисления этих значений. К сожалению, мы не можем использовать MATLAB в нашем случае, потому что это еще больше усложнит проект. Вместо этого мы будем настраивать значения PID. Вот как это сделать:
- Сделайте Kp, Ki и Kd равными нулю.
- Отрегулируйте Kp. Слишком маленький Kp заставит робота упасть, потому что исправления недостаточно. Слишком много Kp заставляет робота идти дико вперед и назад. Хороший Kp сделает так, что робот будет совсем немного отклоняться назад и вперед (или немного осциллирует).
- Как только Kp установлен, отрегулируйте Kd. Хорошее значение Kd уменьшит колебания, пока робот не станет почти устойчивым. Кроме того, правильное Kd будет удерживать робота, даже если его толькать.
- Наконец, установите Ki. При включении робот будет колебаться, даже если Kp и Kd установлены, но будет стабилизироваться во времени. Правильное значение Ki сократит время, необходимое для стабилизации робота.
Поведение робота можно посмотреть ниже на видео:
Код Ардуино самобалансирующего робота
Нам понадобилось четыре внешних библиотеки, для создания нашего робота. Библиотека PID упрощает вычисление значений P, I и D. Библиотека LMotorController используется для управления двумя двигателями с модулем L298N. Библиотека I2Cdev и библиотека MPU6050_6_Axis_MotionApps20 предназначены для чтения данных с MPU6050. Вы можете загрузить код, включая библиотеки в этом репозитории.
#include <PID_v1.h>
#include <LMotorController.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
#define MIN_ABS_SPEED 20
MPU6050 mpu;
// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
//PID
double originalSetpoint = 173;
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;
//adjust these values to fit your own design
double Kp = 50;
double Kd = 1.4;
double Ki = 60;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
double motorSpeedFactorLeft = 0.6;
double motorSpeedFactorRight = 0.5;
//MOTOR CONTROLLER
int ENA = 5;
int IN1 = 6;
int IN2 = 7;
int IN3 = 8;
int IN4 = 9;
int ENB = 10;
LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft, motorSpeedFactorRight);
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady()
{
mpuInterrupt = true;
}
void setup()
{
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
mpu.initialize();
devStatus = mpu.dmpInitialize();
// supply your own gyro offsets here, scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
// make sure it worked (returns 0 if so)
if (devStatus == 0)
{
// turn on the DMP, now that it's ready
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// set our DMP Ready flag so the main loop() function knows it's okay to use it
dmpReady = true;
// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
//setup PID
pid.SetMode(AUTOMATIC);
pid.SetSampleTime(10);
pid.SetOutputLimits(-255, 255);
}
else
{
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
}
void loop()
{
// if programming failed, don't try to do anything
if (!dmpReady) return;
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize)
{
//no mpu data - performing PID calculations and output to motors
pid.Compute();
motorController.move(output, MIN_ABS_SPEED);
}
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024)
{
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
}
else if (mpuIntStatus & 0x02)
{
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
input = ypr[1] * 180/M_PI + 180;
}
} Значения Kp, Ki, Kd могут работать или не работать. Если они этого не делают, выполните шаги, описанные выше. Обратите внимание, что наклона в коде установлен на 173 градуса.
Вы можете изменить это значение, если хотите, но обратите внимание, что это угол наклона, которым должен поддерживаться роботом. Кроме того, если ваши двигатели слишком быстры, вы можете отрегулировать значения:
- motorSpeedFactorLeft
- motorSpeedFactorRight
Loading…
Робот – машинка на Ардуино становятся одним из самым популярных инженерных проектов в школьной робототехнике. Именно с таких устройств, автономных или управляемых со смартфона и bluetooth, начинается путь в робототехнику “после Lego”. К счастью, сегодня можно без труда купить все необходимые компоненты и достаточно быстро создать своего первого робота для езды по линии или объезда препятствий. В этой статье вы найдете подробную видео инструкцию как сделать продвинутый автомобиль Arduino Car своими руками, с питанием, датчиками линии, расстояния и управлении через bluetooth.
Робот на ардуино своими руками
В отличие от других проектов, создание робота – автомобиля (Arduino Car) требует понимания и навыков работы сразу с несколькими важными компонентами, поэтому не стоит приступать к созданию машинок без получения базовых навыков работы с платформой Arduino. В любом случае, вам нужно будет но только подключить готовые модули, но и собрать конструкцию, шасси с двигателями, обеспечить правильное питание и управление. Все это потребует определенного терпения.

Вот список ключевых компонентов, которые обязательно встретятся в проекте.
Контроллер Ардуино
Куда уж без него, если мы говорим о проектах на этой платформе. Как правило, роботы машины делают на базе плат Arduino Uno и Nano. Mega будут слишком большие, Pro Mini сложнее подключать к компьютеру и соединять с остальными компонентами, а Leonardo требуют дополнительных навыков в программировании, они дороже и их основное преимущество (тесная интеграция с компьютером в качестве периферийного устройства) в данном случае не слишком востребована.
Есть еще вариант использования плат ESP8266 или ESP32, тогда в проекте появляется возможность управления машиной через WiFi. Но и сами платы и их программирование требует определенных навыков, в этой статье мы будем говорить преимущественно об Uno или Nano.
Конструкция, шасси и двигатели робота на Ардуино
Для того, чтобы что-то поехало или стало перемещаться, надо снабдить “это” колесами, гусеницами или манипуляторами-ногами. Вот тут выбор совершенно не ограничен, можно использовать совершенно любые комбинации и сочетания платформ. Как правило, в качестве начального варианта берутся уже готовые наборы платформ с Алиэкспресс.

Если работать со стандартными наборами вам не интересно, можно создать платформу своими руками. Например, разобрать игрушечные радиоуправляемые машинки или любые двигатели на 5-12 вольт, с редукторами или без. Колеса можно создать и самим, что тоже является интересной задачей.
Драйвер двигателей
Ардуино – достаточно ранимое устройство, не терпящее больших нагрузок по току. Соединяя его с “брутальными” мощными двигателями, не избежать беды. Поэтому для нормальной совместной работы нам нужно будет включить в схему робота компонент, отвечающий за управление двигателями – подающий и отключающий ток на их обмотки. Речь идет о микросхеме или готовом модуле, которые называют драйвером двигателя. На нашем сайте есть статьи, посвященные драйверам, построенным на схеме H-моста. Если вы покупаете готовые шасси, то обязательно предусмотрите возможность размещения на них подходящего драйвера.
Красивый корпус
Как правило, вся конструкция автомобиля строится вокруг его шасси. Если посмотреть примеры готовых проектов, то они часто выглядят как “провода на колесиках” – внешний вид их изобилует пучками соединительных проводов, ведущих от восседающего на троне контроллера Ардуино к драйверам, моторам и датчикам. Между тем, красивый и функциональный корпус не только вызывает правильные эстетические чувства и помогает выделить вашу модель от остальных. Хороший корпус может превратить игрушку в реальное устройство, помогает привить навыки конструирования и промышленного дизайна, что важно для инженеров любого возраста.
Питание робота
Обеспечение правильной схемы питания – это то, что очень часто оказывается на последнем месте в списке приоритетов начинающих ардуинщиков. Между тем, именно ошибки в схеме электропитания становятся основными причинами проблем, возникающих в процессе работы умных устройств на Ардуино. Создавая ардуино-машинку нужно предусмотреть питание контроллера, двигателей, драйвера и датчиков. У всех них есть свои ограничения и особенности работы, требуется создать оптимальное по весу и сложности решение, позволяющее учесть все эти ограничения.

Создавая по-настоящему автономное устройство робота, нужно побеспокоиться и о времени его работы, и о возможности быстрой подзарядки или смены батареек. Как правило, выбираются решения из следующих вариантов:
- Обычные батарейки AA. Тут нужно понимать, что платы Arduino Uno, Nano и большинство двигателей, используемых в Ардуино-робототехнике, требуют напряжения в диапазоне 6-9 вольт. Поэтому придется собрать вместе последовательно не менее 4 батареек на 1,5 В, причем сами батарейки должны быть хорошего качества и обеспечивать работу с достаточно большим током. Например, большинство солевых батареек этим критериям не удовлетворяют. Батарейки AAA при создании ардуино-машинок практически не используются из-за своей пониженной емкости (хотя могут использоваться в миниатюрных моделях, где размер имеет первостепенное значение).
- Аккумулятор AA. Здесь возникает еще большее ограничение по напряжению и току. Большинство аккумуляторов выдают напряжение 1,2 вольт, поэтому их требуется больше для “собирания” нужных нам 6-9 вольт. Несомненным плюсом является возможность перезарядки.
- Литиевые аккумуляторы 18650. Это уже “серьезная артиллерия”, позволяющая получить большое время автономной работы, возможность подзарядки и приемлемые характеристики по току и напряжению. Рабочее напряжение для таких элементов питания – 3,7 В, что позволяет собирать готовую схему питания всего из двух элементов.
- Другие источники питания. Сюда можно включить как более мощные и габаритные никель-металлгидридные, кадмиевые аккумуляторы, так и многочисленные литий-ионные “плоские” варианты, используемые в дронах, смартфонах или другой портативной цифровой технике.
Каким бы ни был источник питания, нужно обеспечить его надежное крепление, удобное расположение, защиту от воздействия недружелюбной окружающей среды. Если вы подключаете к одному источнику и контролер, и двигатели, и датчики, то нужно позаботиться о правильной схеме, включающей, например, надежную связь “по земле” всех устройств.
Где купить платформу и запчасти
Все, о чем говорится в этой статье, можно без проблем купить на всем известном сайте. К сожалению, подавляющее большинство предложений основываются на стандартной платформе 4WD автомобиля с двумя несущими планками, не очень надежными двигателями и колесами, любящими ездить в “развалочку”. Но эти варианты относительно не дороги и вполне подойдут для начала работы.
(учимся пользоваться одним прерыванием для управления несколькими шаговыми моторами)
От старых экспериментов с балансировкой для роботов у меня остался вот такой экспонат
Робот ездил не очень хорошо, и я решил, что будет удобнее применить более скоростной контроллер ESP32 и возможно более дорогой гироприбор BNO055, так появился проект робота на ногах с колесами:
Selfbalancing bot (esp32) – part 2
В этом роботе мне удалось победить практическую сторону балансировки и добиться качественной работы алгоритмов.
Затем поступило достаточное количество вопросов о возможности реализации балансировки на роботе без подвижных ног, и как только появилось свободное время, я это реализовал (обязательно почитайте статью, там описана и теория и практика балансировки):
Все это время робот на шаговых моторах с Arduino Nano пылился в чулане, а алгоритмы совершенствовались и ускорялись. Пришло его время. Для него был адаптирован стандартный на начало лето 2019 года алгоритм балансировки. И. его производительности вполне хватило.
Модуль selfbalNANOmpu6050.ino
Основной запускающий программный модуль. В функции loop() производится расчет балансировки. Расчет аналогичен http://zizibot.ru/articles/programming/selfbalance-robot-esp32-bno055-mpu6050/ , добавлен блок обработки максимального наклона, после которого робот уже не сможет сбалансировать.
Модуль defin.h
Содержит описание переменных используемых для расчета балансировки, может содержать рудименты и атавизмы.
Модуль gyro_acsel.h
Инициализация гироприбора, чтения данных из гироприбора, устранение дрейфа нуля гироскопа.
Модуль step_motor.h
Обслуживает шаговые моторы. Включает в себя функцию void i_stepcoder(), которая вызывается по прерыванию 16-разрядного таймера (1 раз в 20микросекунд), и генерирует шаги, согласно условий, которые задаются в void SetSpeed(), которая в свою очередь принимает данные из расчета скорости по показаниям гироприбора.
Для генерации прерываний используется библиотека TimerOne.h, которая позволяет использовать 16разрядный таймер для генерации прерывания, которые нужны для обработки событий, которые невозможно отложить.
Также в модуле используется прямой доступ к порту PORTB , что позволило укорить функцию обработки прерывания и генерации шагов.
Давайте поговорим о том как можно использовать Ардуино для создания робота, который балансирует как Сигвей.
Сигвей от англ. Segway – двухколесное средство передвижения стоя, оснащенное электроприводом. Еще их называют гироскутерами или электрическими самокатами.
Вы когда-нибудь задумывались, как работает Сигвей? В этом уроке мы постараемся показать вам, как сделать робота Ардуино, который уравновешивает себя точно так же, как Segway.
Как работает балансировка?
Чтобы сбалансировать робота, двигатели должны противодействовать падению робота. Это действие требует обратной связи и корректирующих элементов. Элемент обратной связи – гироскоп-акселерометр MPU6050, который обеспечивает как ускорение, так и вращение во всех трех осях (основы MP26050 I2C). Ардуино использует это, чтобы знать текущую ориентацию робота. Корректирующим элементом является комбинация двигателя и колеса.
В итоге должен получиться примерно такой друг:
Схема робота
Сначала подключите MPU6050 к Ардуино и проверьте соединение, используя коды в этом учебном руководстве по интерфейсу IMU. Если данные теперь отображаются на последовательном мониторе, вы молодец!
Продолжайте подключать остальные компоненты, как показано выше. Модуль L298N может обеспечить +5В, необходимый для Ардуино, если его входное напряжение составляет +7В или выше. Тем не менее, мы выбрали отдельные источники питания для двигателя и схемы.
Создание робота
Корпус робота изготовлен в основном из акрилового пластика с двумя редукторными двигателями постоянного тока:
Основная печатная плата, состоящая из Arduino Nano и MPU6050:
Модуль драйвера двигателя L298N:
Мотор редуктора постоянного тока с колесом:
Самобалансирующийся робот по существу является перевернутым маятником. Он может быть лучше сбалансирован, если центр массы выше относительно колесных осей. Высший центр масс означает более высокий момент инерции массы, что соответствует более низкому угловому ускорению (более медленное падение). Вот почему мы положили батарейный блок на верх. Однако высота робота была выбрана исходя из наличия материалов 🙂
Завершенный вариант самостоятельно балансирующего робота можно посмотреть на рисунке выше. В верхней части находятся шесть Ni-Cd-батарей для питания печатной платы. В промежутках между моторами используется 9-вольтовая батарея для драйвера двигателя.
Теория
В теории управления, удерживая некоторую переменную (в данном случае позицию робота), требуется специальный контроллер, называемый ПИД (пропорциональная интегральная производная). Каждый из этих параметров имеет «прирост», обычно называемый Kp, Ki и Kd. PID обеспечивает коррекцию между желаемым значением (или входом) и фактическим значением (или выходом). Разница между входом и выходом называется «ошибкой».
ПИД-регулятор уменьшает погрешность до наименьшего возможного значения, постоянно регулируя выход. В нашем самобалансирующем роботе Arduino вход (который является желаемым наклоном в градусах) устанавливается программным обеспечением. MPU6050 считывает текущий наклон робота и подает его на алгоритм PID, который выполняет вычисления для управления двигателем и удерживает робота в вертикальном положении.
PID требует, чтобы значения Kp, Ki и Kd были настроены на оптимальные значения. Инженеры используют программное обеспечение, такое как MATLAB, для автоматического вычисления этих значений. К сожалению, мы не можем использовать MATLAB в нашем случае, потому что это еще больше усложнит проект. Вместо этого мы будем настраивать значения PID. Вот как это сделать:
- Сделайте Kp, Ki и Kd равными нулю.
- Отрегулируйте Kp. Слишком маленький Kp заставит робота упасть, потому что исправления недостаточно. Слишком много Kp заставляет робота идти дико вперед и назад. Хороший Kp сделает так, что робот будет совсем немного отклоняться назад и вперед (или немного осциллирует).
- Как только Kp установлен, отрегулируйте Kd. Хорошее значение Kd уменьшит колебания, пока робот не станет почти устойчивым. Кроме того, правильное Kd будет удерживать робота, даже если его толькать.
- Наконец, установите Ki. При включении робот будет колебаться, даже если Kp и Kd установлены, но будет стабилизироваться во времени. Правильное значение Ki сократит время, необходимое для стабилизации робота.
Поведение робота можно посмотреть ниже на видео:
Код Ардуино самобалансирующего робота
Нам понадобилось четыре внешних библиотеки, для создания нашего робота. Библиотека PID упрощает вычисление значений P, I и D. Библиотека LMotorController используется для управления двумя двигателями с модулем L298N. Библиотека I2Cdev и библиотека MPU6050_6_Axis_MotionApps20 предназначены для чтения данных с MPU6050. Вы можете загрузить код, включая библиотеки в этом репозитории.
Значения Kp, Ki, Kd могут работать или не работать. Если они этого не делают, выполните шаги, описанные выше. Обратите внимание, что наклона в коде установлен на 173 градуса. Вы можете изменить это значение, если хотите, но обратите внимание, что это угол наклона, которым должен поддерживаться роботом. Кроме того, если ваши двигатели слишком быстры, вы можете отрегулировать значения motorSpeedFactorLeft и motorSpeedFactorRight.
На этом пока всё. До встречи.
Опубликовал: Константин Александров / 17.04.2018
Нам кажется что многие из вас находятся под сильным впечатлением от быстро развивающихся технологий современного мира, одними из впечатляющих технологий современности являются двигатели от RYNO и самобалансирующиеся скутеры от Segway. Мы думаем, что многих из вас посещала мысль создать что либо подобное. Поэтому в данной статье мы рассмотрим создание DIY (самодельного, своими руками) самобалансирующегося робота на основе платы Arduino. Во многом принципы работы данного робота будут основаны на алгоритмах PID (PID — proportional, integral, derivative — пропорционально-интегрально-дифференцирующий (ПИД) регулятор), используемых для построения самобалансирующихся скутеров.
Оказалось, что создание подобного робота является задачей не из легких и дело здесь не ограничивается правильным выбором двигателей для робота и ввода необходимых значений в алгоритм PID. Оказалось, что для создания подобного рода необходимо учитывать и много других вещей, например, тип батареи, позиция батареи, захват колеса, тип драйвера мотора, поддержание центра тяжести и многое другое. Но мы все таки попробуем создать такого робота. Итак, начнем.
Необходимые компоненты
- Плата Arduino Uno (купить на AliExpress).
- Приводной двигатель постоянного тока желтого цвета (Geared DC motor (Yellow coloured) ) – 2 шт.
- Модуль драйвера мотора L298N (L298N Motor Driver Module) (купить на AliExpress).
- Гироскоп MPU6050 (купить на AliExpress).
- Два колеса.
- 7.4V Li-ion Battery (литий-ионная батарея или литий-полимерная батарея) (купить на AliExpress).
- Соединительные провода.
- Напечатанный на 3D принтере скелет (остов) робота.
Микроконтроллер: в качестве управляющего микроконтроллера в данном проекте мы выбрали плату Arduino UNO потому что с ней просто работать. Вы можете также использовать платы Arduino Nano или Arduino mini, но мы все таки рекомендовали использовать бы Arduino UNO потому что ее можно программировать без использования внешнего аппаратного обеспечения.
Двигатели: конечно, лучшим выбором для построения самобалансирующегося робота были бы шаговые двигатели, но в целях упрощения проекта мы использовали приводные двигатели (gear motor) постоянного тока желтого цвета – они значительно проще и дешевле чем шаговые.
Драйвер мотора (Motor Driver): если вы, как и мы, выбрали приводные двигатели постоянного тока, то вы можете использовать модуль драйвера мотора L298N или даже L293D (с ним проект будет также работать отлично). Более подробно об управлении электродвигателем постоянного тока с помощью платы Arduino и драйвера мотора L293D можно прочитать в этой статье.
Колеса: не стоит недооценивать эти элементы конструкции робота. У нас достаточно долго не получалось настроить баланс робота пока мы не поняли что проблема состоит в колесах. Колеса для построения самобалансирующегося робота должны иметь очень хорошее сцепление с полом и ни в коем случае они не должны проскальзывать при движении по полу.
Акселерометр и гироскоп: наилучшим выбором в качестве акселерометра и гироскопа для нашего проекта будет модуль MPU6050 – на нашем сайте вы можете прочитать статью о его подключении к плате Arduino. Ни в коем случае не пытайтесь создать подобного робота с использованием обычного акселерометра, например, ADXL345 или подобного ему – это не будет работать. Более подробно объяснение этого фактора будет приведено в конце статьи.
Батарея: для проекта необходима батарея, которая по возможности будет максимально легкой и ее напряжение должно быть больше 5V чтобы мы могли запитать от нее плату Arduino непосредственно, без использования повышающего напряжения модуля. Идеальным выбором в данном случае будет 7.4V Li-polymer (литий-полимерная) батарея. Но в нашем распоряжении была только 7.4V литий-ионная батарея, поэтому мы ее и использовали при создании робота. Но помните о том, что литий-полимерная батарея в данном случае будет все таки лучше чем литий-ионная.
Шасси робота: еще один элемент робота, при создании которого неуместны компромиссы. Для изготовления шасси робота вы можете использовать листы картона, дерево, пластик и т.п. Но помните о том, что шасси должно быть достаточно прочным и не изгибаться когда робот пытается балансировать. Мы для изготовления шасси робота использовали 3D принтер, ссылки на необходимые файлы для него будут приведены далее в статье.
3D печать и сборка шасси робота
Если вы хотите использовать (напечатать) то же самое шасси, которое использовали и мы, то вы можете скачать необходимые для его печати STL файлы с сервиса thingiverse. Мы также добавили туда файлы дизайна чтобы вы могли изменить внешний вид компонентов шасси по своему желанию.
Компоненты данного шасси робота не имею нависающих структур, поэтому вы без особых проблем можете напечатать их на практически любом 3D принтере. Мы для этой цели использовали программное обеспечение Cura и 3D принтер Tevo Tarantula, установки для печати компонентов показаны на следующем рисунке.
Вам необходимо напечатать скелет робота и 4 компонента для крепления двигателей. Для сборки робота можно использовать 3 мм болты (шурупы). После сборки у вас должна получиться конструкция примерно следующего вида:
Изначально дизайн робота предусматривал размещение модуля драйвера мотора L298N в нижнем отсеке робота и батарею на его верху как показано на приведенном выше рисунке. Этот дизайн робота также является рабочим и вы можете его использовать, в этом случае вы можете непосредственно скрепить части робота, используя специально выделенные для этого отверстия.
Но мы в дальнейшем решили немного изменить дизайн робота и поменяли место расположения батареи и платы Arduino UNO для упрощения ее программирования. Для обеспечения соединений в схеме мы использовали перфорированную плату. Внешний вид самобалансирующегося робота для данного расположения элементов показан на следующем рисунке.
Работа схемы
Схема самобалансирующегося робота на основе платы Arduino UNO представлена на следующем рисунке.
Как видите, схема достаточно проста и в ней вам всего лишь необходимо подключить гироскоп MPU6050 и драйвер мотора к плате Arduino, а также соединить двигатели с драйвером мотора. Схема запитывается от литий-ионной батареи на 7.4V.
Плата Arduino и модуль драйвер мотора L298N непосредственно запитываются через контакты Vin и 12V соответственно. Встроенный в плату Arduino регулятор напряжения преобразует входное напряжение 7.4V в напряжение 5V, с помощью которого и запитывается микроконтроллер ATmega на плате и гироскоп MPU6050. Электродвигатели постоянного тока могут запитываться от напряжения от 5V до 12V, в нашем случае они будут работать от напряжения 7.4V.
Распиновка подключения контактов гироскопа MPU6050 представлена в следующей таблице.
| MPU6050 | контакт Arduino |
| Vcc | +5V |
| Ground | Gnd |
| SCL | A5 |
| SDA | A4 |
| INT | D2 |
Распиновка подключения контактов драйвера мотора L298N представлена в следующей таблице.
| L298N | контакт Arduino |
| IN1 | D6 |
| IN2 | D9 |
| IN3 | D10 |
| IN4 | D11 |
Гироскоп MPU6050 взаимодействует с платой Arduino через интерфейс I2C, поэтому для его подключения мы использовали SPI контакты A4 и A5 платы Arduino. Двигатели постоянного тока управляются с помощью ШИМ (широтно-импульсная модуляция) контактов D6, D9, D10 и D11. ШИМ сигнал в данном случае необходим для управления скоростью вращения двигателей.
Программирование самобалансирующегося робота
Как мы уже видели, схема нашего проекта достаточно проста, но вся «магия» нашего проекта будет как раз заключаться в его программе для платы Arduino UNO. В программе мы с помощью гироскопа MPU6050 будем проверять наклоняется ли робот вперед или назад. Если робот будет наклоняться вперед, то нам необходимо вращать колеса в прямом направлении (прямо) для удержания баланса, а если он будет наклоняться назад, то нам необходимо будет вращать колеса в обратном направлении.
В это же самое время мы должны будем управлять скоростью вращения колес – если робот будет слегка дезориентирован от центрального положения колеса будут вращаться немного медленнее и скорость будет увеличиваться по мере удаления от центрального положения. Для управления подобной логикой робота мы использовали PID алгоритм, в котором центральное положение рассматривается как исходная точка, а уровень дезориентации является выходом.
Для определения текущего положения робота в нашем проекте мы используем модуль MPU6050, который является 6-осевым акселерометром и гироскопом одновременно. Для того чтобы получить надежное значение позиции робота нам необходимо получать значения одновременно и от акселерометра, и от гироскопа поскольку значения от акселерометра обычно зашумлены, а значения от гироскопа имеют тенденцию смещаться (дрифтовать) с течением времени. То есть в программе мы будем комбинировать значения с контактов yaw, pitch и roll гироскопа, а использовать будем только значение с выхода yaw.
На первый взгляд задача создания подобного робота в домашних условиях звучит как невозможная, неправда ли? Но благодаря сообществу Arduino у нас в распоряжении уже есть готовая библиотека, способная выполнять вычисления по алгоритму PID, а также библиотека для работы с гироскопом MPU6050. Эти библиотеки разработаны авторами br3ttb и jrowberg соответственно. Перед началом написания программы вам необходимо их скачать по ниже приведенным ссылкам и добавить в папку с библиотеками Arduino на вашем компьютере.
https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h
https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050
После того, как эти библиотеки добавлены в соответствующую папку, приступим к написанию программы для нашего самобалансирующегося робота. Полный код программы для этого робота приведен в конце данной статьи, здесь же сначала рассмотрим наиболее важные фрагменты этого кода.
Первым делом в программе мы должны подключить используемые библиотеки — I2C library, PID Library и MPU6050 Library (последние две мы как раз скачали).
| #include «I2Cdev.h» #include <PID_v1.h> //From https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h #include «MPU6050_6Axis_MotionApps20.h» //https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050 |
Затем мы объявим переменные, которые будут нам необходимы для получения данных с датчика MPU6050. Мы будем считывать и вектор гравитации, и значения кватерниона, и затем вычислять значения yaw (отклонение от курса), pitch (угол наклона) и roll (вращение) для нашего робота. Наглядная картинка про все эти параметры, чтобы вам было лучше понятно, есть в статье про подключение гироскопа MPU6050 к плате Arduino. Эти три параметра будут записываться в результирующий массив вещественного типа float ypr[3].
| //переменные для управления/статуса bool dmpReady = false; // установим в true если инициализация процессора DMP была успешной uint8_t mpuIntStatus; // статус прерывания от процессора MPU uint8_t devStatus; // возвращаем статус после каждой операции с устройством (0 = success (успех), !0 = error (ошибка)) uint16_t packetSize; // ожидаемый размер пакета процессора DMP (по умолчанию 42 байта) uint16_t fifoCount; // текущее число байт в буфере FIFO uint8_t fifoBuffer[64]; // буфер для хранения FIFO // переменные для определения ориентации/направления движения Quaternion q; // [w, x, y, z] quaternion container VectorFloat gravity; // [x, y, z] вектор гравитации float ypr[3]; // [yaw, pitch, roll] контейнер (массив) для хранения значений yaw/pitch/roll |
Далее необходимо настроить параметры, которые позволят роботу балансировать – на это может уйти достаточно продолжительное время. Если ваш робот создан с «идеальным» центром тяжести и все его компоненты симметрично расположены на нем (хотя в большинстве случаев это не будет выполняться), тогда исходной точке setpoint можно установить значение 180. Если это не так, то подсоедините вашего робота кабелем к компьютеру, наклоняйте его постоянно из стороны в сторону до тех пор пока не добьетесь состояния идеального баланса – все это контролируйте с помощью монитора последовательной связи (serial monitor) и когда добьетесь состояния баланса, это и будет ваше значения setpoint. Также во время этих манипуляций необходимо определить и значения параметров Kp, Kd и Ki для вашего робота. Даже для двух одинаковых с виду роботов эти значения будут отличаться. Более подробно весь процесс определения данных параметров показан на видео, приведенном в конце статьи.
| /*********эти 4 значения необходимо настроить для вашего робота*********/ double setpoint= 176; //установите это значение с помощью монитора последовательной связи когда робот находится перпендикулярно земле //Read the project documentation on circuitdigest.com to learn how to set these values double Kp = 21; //устанавливаем это значение первым double Kd = 0.8; //устанавливаем это значение вторым double Ki = 140; //наконец устанавливаем это значение /******End of values setting*********/ |
В следующей команде мы инициализируем вызов алгоритма PID, передав ему в качестве входных переменных input, output, set point, Kp, Ki и Kd. Значения параметров set-point Kp, Ki и Kd мы уже установили выше в программе. Значение параметра input будет текущим значением yaw (отклонение от курса), которое считывается с гироскопа MPU6050. А значение параметра output будет рассчитываться с помощью PID алгоритма. Этот параметр output будет рассчитываться PID алгоритмом чтобы потом на его основе скорректировать значение параметра input чтобы оно было как можно ближе к исходной точке (set point).
| PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT); |
Внутри функции void setup мы инициализируем датчик MPU6050 при помощи конфигурации DMP (Digital Motion Processor – процессор цифрового движения). Это поможет нам в объединении данных акселерометра и гироскопа и обеспечить надежные (стабильные) значения Yaw, Pitch и Roll. Мы не будем слишком глубоко погружаться в эту проблему из-за ограниченности объема статьи. Еще в функции void setup необходимо установить значения сдвига для гироскопа. Каждый датчик MPU6050 имеет свои значения сдвига, для определения которых можно использовать соответствующий скетч для Arduino, после их определения необходимо внести соответствующие изменения в программу.
| // впишите сюда значения сдвига для вашего гироскопа, отмасштабированные для минимальной чувствительности mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(—85); mpu.setZAccelOffset(1688); |
Также мы должны инициализировать контакты ШИМ, которые используются нами для подключения двигателей. В нашем случае это контакты D6, D9, D10 и D11. Мы зададим для этих контактов режим работы на вывод данных и запишем в них по умолчанию значения напряжений низкого уровня (LOW).
| //установка режимов работы для ШИМ контактов, с которых осуществляется управление двигателями pinMode (6, OUTPUT); pinMode (9, OUTPUT); pinMode (10, OUTPUT); pinMode (11, OUTPUT); //по умолчанию оба двигателя выключены, поэтому записываем в эти контакты LOW analogWrite(6,LOW); analogWrite(9,LOW); analogWrite(10,LOW); analogWrite(11,LOW); |
Внутри основной функции loop мы будем проверять готовы ли к считыванию данные из датчика MPU6050. Если готовы, то мы будем использовать их для вычисления значения PID и отображать значения input и output из алгоритма PID в окне монитора последовательной связи для целей отладки проекта. Затем, основываясь на значении output мы будем решать необходимо ли роботу двигаться вперед или назад или оставаться на месте.
Мы будем предполагать что датчик MPU6050 будет возвращать значение 180 когда робот находится в строго вертикальном положении. Мы будем получать положительные корректировочные значения когда робот будет падать (заваливаться) вперед и отрицательные корректировочные значения когда робот будет падать (заваливаться) назад. Мы будем проверять эти значения и вызывать соответствующие функции чтобы робот начал движение вперед или назад.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | while (!mpuInterrupt && fifoCount < packetSize) { //пока нет данных от процессора mpu data – выполняем вычисления по алгоритму PID и управляем двигателями pid.Compute(); //печатаем значения Input и Output в окне монитора последовательной связи (serial monitor) чтобы проверить работу программы Serial.print(input); Serial.print(» =>»); Serial.println(output); if (input>150 && input<200){//если робот падает (заваливается) if (output>0) //падает вперед Forward(); //вращаем колеса вперед else if (output<0) //падает назад Reverse(); //вращаем колеса назад } else //If Bot not falling Stop(); //Hold the wheels still } |
Переменная output с выхода PID алгоритма также определяет как быстро двигатель должен вращаться. Если робот только начала падать мы осуществляем незначительную коррекцию медленно вращая колеса. Если эта незначительная коррекция не помогла и робот продолжает падать мы увеличиваем скорость вращения двигателя. Значение скорости, с которой должны вращаться колеса, определяется PID алгоритмом. При этом в функции вращения колес в обратную сторону (назад) мы просто умножаем значение переменной output на -1 чтобы преобразовать отрицательные значения в положительные.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | void Forward() //функция для вращения колеса вперед { analogWrite(6,output); analogWrite(9,0); analogWrite(10,output); analogWrite(11,0); Serial.print(«F»); //для целей отладки } void Reverse() //функция для вращения колеса назад { analogWrite(6,0); analogWrite(9,output*—1); analogWrite(10,0); analogWrite(11,output*—1); Serial.print(«R»); } void Stop() //функция чтобы остановить оба колеса { analogWrite(6,0); analogWrite(9,0); analogWrite(10,0); analogWrite(11,0); Serial.print(«S»); } |
Тестирование работы самобалансирующегося робота
После того как вы соберете всю конструкцию загрузите код программы в плату Arduino. Проверьте надежность всех соединений и после этого можете подавать питание на схему. Также откройте окно монитора последовательной связи (serial monitor). Если плата Arduino успешно взаимодействует с датчиком MPU6050 и все работает так, как это и задумывалось, вы должны увидеть на экране монитора примерно следующую картину:
На экране мы видим входные и выходные значения PID алгоритма в формате input => output. Если у робота отличный (совершенный) баланс, то значение переменной output будет равно 0. Входное значение (input) – это текущее значение с датчика MPU6050. Буква “F” на экране монитора будет обозначать что робот движется вперед, а “R” – назад.
Во время первоначальных этапов работы PID алгоритма мы рекомендуем оставить подключенным кабель к плате Arduino чтобы вам было просто контролировать значения переменных input и output, а также скорректировать значения параметров Kp, Ki и Kd чтобы потом загрузить их уточненные значения с программой в плату Arduino. Более подробно все эти процессы показаны на видео, приведенном в конце статьи.
Надеемся, что приведенная статья поможет вам в конструировании собственного самобалансирующегося робота.
Исходный код программы (скетча)
Комментарии к коду программы переведены выше в статье чтобы вы могли сравнить оригинал и мой перевод. Буду признателен если вы напишите в комментариях об ошибках/опечатках в переводе. Проект достаточно сложный, поэтому тяжело досконально разобраться в нем просто переведя его с сайта-источника, но не собирая его. И удачи вам в сборке этого непростого проекта, может быть и у меня когда-нибудь дойдут руки попробовать его реально собрать.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | /*Arduino Self Balancing Robot * Code by: B.Aswinth Raj * Build on top of Lib: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050 * Website: circuitdigest.com */ #include «I2Cdev.h» #include <PID_v1.h> //From https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h #include «MPU6050_6Axis_MotionApps20.h» //https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050 MPU6050 mpu; // MPU control/status vars bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer // orientation/motion vars Quaternion q; // [w, x, y, z] quaternion container VectorFloat gravity; // [x, y, z] gravity vector float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector /*********Tune these 4 values for your BOT*********/ double setpoint= 176; //set the value when the bot is perpendicular to ground using serial monitor. //Read the project documentation on circuitdigest.com to learn how to set these values double Kp = 21; //Set this first double Kd = 0.8; //Set this secound double Ki = 140; //Finally set this /******End of values setting*********/ double input, output; PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT); volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high void dmpDataReady() { mpuInterrupt = true; } void setup() { Serial.begin(115200); // initialize device Serial.println(F(«Initializing I2C devices…»)); mpu.initialize(); // verify connection Serial.println(F(«Testing device connections…»)); Serial.println(mpu.testConnection() ? F(«MPU6050 connection successful») : F(«MPU6050 connection failed»)); // load and configure the DMP devStatus = mpu.dmpInitialize(); // supply your own gyro offsets here, scaled for min sensitivity mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(—85); mpu.setZAccelOffset(1688); // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it’s ready Serial.println(F(«Enabling DMP…»)); mpu.setDMPEnabled(true); // enable Arduino interrupt detection Serial.println(F(«Enabling interrupt detection (Arduino external interrupt 0)…»)); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it’s okay to use it Serial.println(F(«DMP ready! Waiting for first interrupt…»)); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); //setup PID pid.SetMode(AUTOMATIC); pid.SetSampleTime(10); pid.SetOutputLimits(—255, 255); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it’s going to break, usually the code will be 1) Serial.print(F(«DMP Initialization failed (code «)); Serial.print(devStatus); Serial.println(F(«)»)); } //Initialise the Motor outpu pins pinMode (6, OUTPUT); pinMode (9, OUTPUT); pinMode (10, OUTPUT); pinMode (11, OUTPUT); //By default turn off both the motors analogWrite(6,LOW); analogWrite(9,LOW); analogWrite(10,LOW); analogWrite(11,LOW); } void loop() { // if programming failed, don’t try to do anything if (!dmpReady) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { //no mpu data — performing PID calculations and output to motors pid.Compute(); //Print the value of Input and Output on serial monitor to check how it is working. Serial.print(input); Serial.print(» =>»); Serial.println(output); if (input>150 && input<200){//If the Bot is falling if (output>0) //Falling towards front Forward(); //Rotate the wheels forward else if (output<0) //Falling towards back Reverse(); //Rotate the wheels backward } else //If Bot not falling Stop(); //Hold the wheels still } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); Serial.println(F(«FIFO overflow!»)); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; mpu.dmpGetQuaternion(&q, fifoBuffer); //get value for q mpu.dmpGetGravity(&gravity, &q); //get value for gravity mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //get value for ypr input = ypr[1] * 180/M_PI + 180; } } void Forward() //Code to rotate the wheel forward { analogWrite(6,output); analogWrite(9,0); analogWrite(10,output); analogWrite(11,0); Serial.print(«F»); //Debugging information } void Reverse() //Code to rotate the wheel Backward { analogWrite(6,0); analogWrite(9,output*—1); analogWrite(10,0); analogWrite(11,output*—1); Serial.print(«R»); } void Stop() //Code to stop both the wheels { analogWrite(6,0); analogWrite(9,0); analogWrite(10,0); analogWrite(11,0); Serial.print(«S»); } |
Видео, демонстрирующее работу робота
Видео как правильно настраивать значения для PID алгоритма
Источник статьи
Загрузка…
3 368 просмотров
Октябрь 14, 2017
Нам понадобится:
Для изготовления корпуса для балансира я взял картон. Картон был довольно тонкий и я склеивал несколько листов, для увеличения прочности конструкции.
Размер боковин балансира указан на фото:
Таких деталей должно быть две, но с учетом того что картон тонкий, я их сделал 4 и склеил между собой термопистолетом.
С вертикальными частями разобрались, теперь нужно сделать 3 горизонтальных. Я их склеивал тоже между собой, поэтому сделал вот таких частей 6 шт.:
После склейки должна получиться лесенка. Все детали я склеивал между собой термоклеем, картон он очень хорошо склеивает.
Моторредукторы я крепил на стяжки к боковинам получившейся “лесенки”
Драйвер двигателей, я разместил на самую нижнюю полку получившейся конструкции.
При подключении самих моторов к драйверу, важно подобрать правильную полярность, чтоб моторы крутились именно в ту сторону, в которую нужно чтоб они крутились для удерживания ровновесия.
Наши “мозги” Ардуино и гироском Mpu 6050 я установил на среднюю полку, чтоб было не сложно дотянуться и до драйвера двигателей и до аккумуляторов.
ВАЖНО: Гироскоп нужно расположить ровно в плоскости, иначе роботу будет тяжело держать равновесие.
Ну и сами аккумуляторы прикрепил на стяжки в самом верху конструкции.
После размещения всех элементов и подключения их друг с другом проводами, Робот выглядит вот таким вот образом.
После того как мы разобрались с конструкцией робота, давайте перейдем к электронной части, а именно к схеме подключения элементов.
Ну и собственно сам скетч:
Для корректной работы скетча нам еще понадобятся две библиотеки kalman и PID_v1
Ну и собственно демонстрация работы:
Давайте поговорим о том как можно использовать Ардуино для создания робота, который балансирует как Сигвей.
Сигвей от англ. Segway – двухколесное средство передвижения стоя, оснащенное электроприводом. Еще их называют гироскутерами или электрическими самокатами.
Вы когда-нибудь задумывались, как работает Сигвей? В этом уроке мы постараемся показать вам, как сделать робота Ардуино, который уравновешивает себя точно так же, как Segway.
Как работает балансировка?
Чтобы сбалансировать робота, двигатели должны противодействовать падению робота. Это действие требует обратной связи и корректирующих элементов. Элемент обратной связи – гироскоп-акселерометр MPU6050, который обеспечивает как ускорение, так и вращение во всех трех осях (основы MP26050 I2C). Ардуино использует это, чтобы знать текущую ориентацию робота. Корректирующим элементом является комбинация двигателя и колеса.
В итоге должен получиться примерно такой друг:
Схема робота
Сначала подключите MPU6050 к Ардуино и проверьте соединение, используя коды в этом учебном руководстве по интерфейсу IMU. Если данные теперь отображаются на последовательном мониторе, вы молодец!
Продолжайте подключать остальные компоненты, как показано выше. Модуль L298N может обеспечить +5В, необходимый для Ардуино, если его входное напряжение составляет +7В или выше. Тем не менее, мы выбрали отдельные источники питания для двигателя и схемы.
Создание робота
Корпус робота изготовлен в основном из акрилового пластика с двумя редукторными двигателями постоянного тока:
Основная печатная плата, состоящая из Arduino Nano и MPU6050:
Модуль драйвера двигателя L298N:
Мотор редуктора постоянного тока с колесом:
Самобалансирующийся робот по существу является перевернутым маятником. Он может быть лучше сбалансирован, если центр массы выше относительно колесных осей. Высший центр масс означает более высокий момент инерции массы, что соответствует более низкому угловому ускорению (более медленное падение). Вот почему мы положили батарейный блок на верх. Однако высота робота была выбрана исходя из наличия материалов 🙂
Завершенный вариант самостоятельно балансирующего робота можно посмотреть на рисунке выше. В верхней части находятся шесть Ni-Cd-батарей для питания печатной платы. В промежутках между моторами используется 9-вольтовая батарея для драйвера двигателя.
Теория
В теории управления, удерживая некоторую переменную (в данном случае позицию робота), требуется специальный контроллер, называемый ПИД (пропорциональная интегральная производная). Каждый из этих параметров имеет «прирост», обычно называемый Kp, Ki и Kd. PID обеспечивает коррекцию между желаемым значением (или входом) и фактическим значением (или выходом). Разница между входом и выходом называется «ошибкой».
ПИД-регулятор уменьшает погрешность до наименьшего возможного значения, постоянно регулируя выход. В нашем самобалансирующем роботе Arduino вход (который является желаемым наклоном в градусах) устанавливается программным обеспечением. MPU6050 считывает текущий наклон робота и подает его на алгоритм PID, который выполняет вычисления для управления двигателем и удерживает робота в вертикальном положении.
PID требует, чтобы значения Kp, Ki и Kd были настроены на оптимальные значения. Инженеры используют программное обеспечение, такое как MATLAB, для автоматического вычисления этих значений. К сожалению, мы не можем использовать MATLAB в нашем случае, потому что это еще больше усложнит проект. Вместо этого мы будем настраивать значения PID. Вот как это сделать:
- Сделайте Kp, Ki и Kd равными нулю.
- Отрегулируйте Kp. Слишком маленький Kp заставит робота упасть, потому что исправления недостаточно. Слишком много Kp заставляет робота идти дико вперед и назад. Хороший Kp сделает так, что робот будет совсем немного отклоняться назад и вперед (или немного осциллирует).
- Как только Kp установлен, отрегулируйте Kd. Хорошее значение Kd уменьшит колебания, пока робот не станет почти устойчивым. Кроме того, правильное Kd будет удерживать робота, даже если его толькать.
- Наконец, установите Ki. При включении робот будет колебаться, даже если Kp и Kd установлены, но будет стабилизироваться во времени. Правильное значение Ki сократит время, необходимое для стабилизации робота.
Поведение робота можно посмотреть ниже на видео:
Код Ардуино самобалансирующего робота
Нам понадобилось четыре внешних библиотеки, для создания нашего робота. Библиотека PID упрощает вычисление значений P, I и D. Библиотека LMotorController используется для управления двумя двигателями с модулем L298N. Библиотека I2Cdev и библиотека MPU6050_6_Axis_MotionApps20 предназначены для чтения данных с MPU6050. Вы можете загрузить код, включая библиотеки в этом репозитории.
Значения Kp, Ki, Kd могут работать или не работать. Если они этого не делают, выполните шаги, описанные выше. Обратите внимание, что наклона в коде установлен на 173 градуса. Вы можете изменить это значение, если хотите, но обратите внимание, что это угол наклона, которым должен поддерживаться роботом. Кроме того, если ваши двигатели слишком быстры, вы можете отрегулировать значения motorSpeedFactorLeft и motorSpeedFactorRight.
На этом пока всё. До встречи.
Опубликовал: Константин Александров / 17.04.2018
Давайте поговорим о том как можно использовать Ардуино для создания робота, который балансирует как Сигвей.
Сигвей от англ. Segway – двухколесное средство передвижения стоя, оснащенное электроприводом. Еще их называют гироскутерами или электрическими самокатами.
Вы когда-нибудь задумывались, как работает Сигвей? В этом уроке мы постараемся показать вам, как сделать робота Ардуино, который уравновешивает себя точно так же, как Segway.
Как работает балансировка?
Чтобы сбалансировать робота, двигатели должны противодействовать падению робота. Это действие требует обратной связи и корректирующих элементов. Элемент обратной связи – гироскоп-акселерометр MPU6050, который обеспечивает как ускорение, так и вращение во всех трех осях (основы MP26050 I2C). Ардуино использует это, чтобы знать текущую ориентацию робота. Корректирующим элементом является комбинация двигателя и колеса.
В итоге должен получиться примерно такой друг:
Схема робота
Сначала подключите MPU6050 к Ардуино и проверьте соединение, используя коды в этом учебном руководстве по интерфейсу IMU. Если данные теперь отображаются на последовательном мониторе, вы молодец!
Продолжайте подключать остальные компоненты, как показано выше. Модуль L298N может обеспечить +5В, необходимый для Ардуино, если его входное напряжение составляет +7В или выше. Тем не менее, мы выбрали отдельные источники питания для двигателя и схемы.
Создание робота
Корпус робота изготовлен в основном из акрилового пластика с двумя редукторными двигателями постоянного тока:
Основная печатная плата, состоящая из Arduino Nano и MPU6050:
Модуль драйвера двигателя L298N:
Мотор редуктора постоянного тока с колесом:
Самобалансирующийся робот по существу является перевернутым маятником. Он может быть лучше сбалансирован, если центр массы выше относительно колесных осей. Высший центр масс означает более высокий момент инерции массы, что соответствует более низкому угловому ускорению (более медленное падение). Вот почему мы положили батарейный блок на верх. Однако высота робота была выбрана исходя из наличия материалов 🙂
Завершенный вариант самостоятельно балансирующего робота можно посмотреть на рисунке выше. В верхней части находятся шесть Ni-Cd-батарей для питания печатной платы. В промежутках между моторами используется 9-вольтовая батарея для драйвера двигателя.
Теория
В теории управления, удерживая некоторую переменную (в данном случае позицию робота), требуется специальный контроллер, называемый ПИД (пропорциональная интегральная производная). Каждый из этих параметров имеет «прирост», обычно называемый Kp, Ki и Kd. PID обеспечивает коррекцию между желаемым значением (или входом) и фактическим значением (или выходом). Разница между входом и выходом называется «ошибкой».
ПИД-регулятор уменьшает погрешность до наименьшего возможного значения, постоянно регулируя выход. В нашем самобалансирующем роботе Arduino вход (который является желаемым наклоном в градусах) устанавливается программным обеспечением. MPU6050 считывает текущий наклон робота и подает его на алгоритм PID, который выполняет вычисления для управления двигателем и удерживает робота в вертикальном положении.
PID требует, чтобы значения Kp, Ki и Kd были настроены на оптимальные значения. Инженеры используют программное обеспечение, такое как MATLAB, для автоматического вычисления этих значений. К сожалению, мы не можем использовать MATLAB в нашем случае, потому что это еще больше усложнит проект. Вместо этого мы будем настраивать значения PID. Вот как это сделать:
- Сделайте Kp, Ki и Kd равными нулю.
- Отрегулируйте Kp. Слишком маленький Kp заставит робота упасть, потому что исправления недостаточно. Слишком много Kp заставляет робота идти дико вперед и назад. Хороший Kp сделает так, что робот будет совсем немного отклоняться назад и вперед (или немного осциллирует).
- Как только Kp установлен, отрегулируйте Kd. Хорошее значение Kd уменьшит колебания, пока робот не станет почти устойчивым. Кроме того, правильное Kd будет удерживать робота, даже если его толькать.
- Наконец, установите Ki. При включении робот будет колебаться, даже если Kp и Kd установлены, но будет стабилизироваться во времени. Правильное значение Ki сократит время, необходимое для стабилизации робота.
Поведение робота можно посмотреть ниже на видео:
Код Ардуино самобалансирующего робота
Нам понадобилось четыре внешних библиотеки, для создания нашего робота. Библиотека PID упрощает вычисление значений P, I и D. Библиотека LMotorController используется для управления двумя двигателями с модулем L298N. Библиотека I2Cdev и библиотека MPU6050_6_Axis_MotionApps20 предназначены для чтения данных с MPU6050. Вы можете загрузить код, включая библиотеки в этом репозитории.
Значения Kp, Ki, Kd могут работать или не работать. Если они этого не делают, выполните шаги, описанные выше. Обратите внимание, что наклона в коде установлен на 173 градуса. Вы можете изменить это значение, если хотите, но обратите внимание, что это угол наклона, которым должен поддерживаться роботом. Кроме того, если ваши двигатели слишком быстры, вы можете отрегулировать значения motorSpeedFactorLeft и motorSpeedFactorRight.
На этом пока всё. До встречи.
Опубликовал: Константин Александров / 17.04.2018















