Добро пожаловать мир робототехники чтобы сконструировать небольшого двуногого робота, способного ходить и танцевать. Познакомьтесь с Кэтботом (Catbot), нашим харизматичным двуногим роботом, и присоединяйтесь к нам в этом инновационном эксперименте, сочетающем в себе 3D-печать, технологию Arduino и серводвигатели .
Наша основная цель — предоставить вам практический опыт создания небольших роботов с использованием платы Arduino и овладения искусством программирования серводвигателей для множества приложений. К концу этого проекта у вас будут знания и навыки, необходимые для того, чтобы воплотить в жизнь Catbot'а, позволяя ему выполнять заданные процедуры ходьбы и танцев.

Более того, мы предоставим вам универсальную программу, представленную в конце данной статьи, которая позволит вам легко настроить действия вашего робота под свои желания. Вы можете управлять положением серводвигателей робота через монитор последовательной связи.
Чтобы наш робот выглядел по-настоящему круто и необычно, мы используем акриловые детали, вырезанные лазером. Эти детали не только повышают визуальную привлекательность проекта, но и придают стильный вид нашему роботу. Однако, если у вас нет доступа к этим материалам, не волнуйтесь! Вы можете воспользоваться онлайн-услугами или даже использовать картон, чтобы добиться того же результата.
Catbot, звезда нашего проекта, — замечательный двуногий робот, построенный на базе Arduino Nano. Он использует пять серводвигателей, два из которых предназначены для каждой ноги, а один управляет движениями головы. Кроме того, он использует ультразвуковой датчик для обнаружения препятствий и их обхода.
Теперь давайте окунемся в увлекательный мир создания и программирования Catbot, вашего собственного двуногого робота. А если это не тот робот, который вы ищете, то у нас на сайте есть целый раздел «Робототехника», где вы можете найти множество видов роботов, таких как робот, следующий вдоль линии, пожарный робот, роботизированная рука, самобалансирующийся робот и т. д.
Ранее на нашем сайте мы уже рассматривали проект шагающего и танцующего робота на Arduino, но он, конечно же, по всем параметрам уступает роботу из данной статьи.
Проектирование и сборка двуногого робота
Мы создали индивидуальный дизайн двуногого робота специально для этого проекта с помощью Onshape, его изображения в данном сервисе вы можете увидеть ниже.
Если вы заинтересованы в воссоздании этого проекта или использовании нашего дизайна в своей работе, мы включили файлы CAD .dxf, которые вы можете скачать по следующей ссылке.
Для создания этого робота мы использовали акриловые детали, вырезанные лазером. Однако, если у вас есть доступ к 3D-принтеру, вы также можете использовать его. Если вы выберете путь 3D-печати, вам необходимо будет загрузить формат файла .stl по той же ссылке выше.
Вот визуальное представление того, как будет выглядеть акриловый лист, вырезанный лазером.

Двуногий котбот Arduino Nano, как и многие другие роботы, оценивается по его гибкости. Это часто измеряется так называемой «степенью свободы» или DOF (degrees of freedom). Представьте себе степень свободы как количество способов, которыми робот может сгибать и перемещать свои части. Это похоже на подсчет различных движений в танце.
Этот робот поставляется в плоской упаковке, и вам не нужно много паять (плавить металл для соединения деталей), чтобы собрать его вместе и заставить работать. У него есть 4 специальных двигателя, называемых сервоприводами SG90, которые позволяют ему передвигаться четырьмя разными способами. Он может двигаться вперед, назад, вправо и влево.
Движения каждой части:
- «Голова» может вращаться на угол до 180°, в зависимости от типа сервопривода, используемого для вращения головы.
- «Бедра» на левой и правой сторонах могут наклонять робота вертикально вправо и влево.
- «Нога» на левой и правой сторонах перемещает ступни вверх и вниз, позволяя роботу двигаться вперед.

Компоненты, необходимые для сборки робота
- Плата Arduino Nano (купить на AliExpress).
- Серводвигатели SG90 с металлической передачей (5 шт.) (купить на AliExpress).
- Ультразвуковой датчик HC-SR04 (купить на AliExpress).
- Лазерная резка акриловых деталей робота.
- Литий-ионный аккумулятор 7,4 В.
- Выключатель.
- Соединительные провода.
- Макетная или печатная плата.
- Винты, гайки, проставки
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Сборка двуногого робота
Мы использовали лазерную резку акрилового листа, чтобы создать двуногого робота для нашего проекта. Лист был точно разрезан для размещения всех необходимых фитингов и компонентов, что позволяет легко собирать его с помощью отверток.
Прежде чем приступить к сборке, нам необходимо выставить угол регулировки серводвигателей. В противном случае ваш двуногий робот не будет работать должным образом.

Для начала прикрепите рычаг сервопривода к серводвигателю, тщательно выровняв и закрепив его на месте. Мы можем вручную откалибровать и отрегулировать угол серводвигателя, но иногда ручная калибровка неточна или невозможна. Для более точной калибровки серводвигателей используйте код программы №1, приведенный в конце статьи. Код программы загружайте в плату после сборки его принципиальной схемы.

Обеспечивая правильное выравнивание и калибровку серводвигателей, вы закладываете основу для стабильного и корректного функционирования робота. После выполнения всех регулировок серводвигателей на 90° вы можете переходить к этапу сборки конструкции робота.
Схема проекта
Схема шагающего и танцующего робота на основе платы Arduino представлена на следующем рисунке.
Для этого проекта вам не понадобится сложная проводка, поскольку все двигатели используют напряжение 5 В. Управлять моторами мы будем с помощью с помощью цифровых контактов платы Arduino. Мы не использовали вывод 5 В на Arduino потому что он не давал достаточно мощности для нормальной работы всех двигателей. Вместо этого мы используем дополнительный источник питания. Таким образом, мы можем обеспечить достаточную мощность чтобы убедиться что все двигатели работают правильно.
Примечание: всегда выключайте питание Arduino при загрузке кода.
Подключение цепей:
Подключите плату Arduino Nano к макетной плате или печатной плате. Обязательно подключите контакты питания и заземления.
Подключите литий-ионную батарею 7,4 В к выводу Vin Arduino Nano через переключатель. Этот переключатель позволяет включать и выключать Arduino от внешнего источника питания.
Подключите ультразвуковой датчик к Arduino Nano:
- VCC (питание) датчика - к 5 В на Arduino.
- GND (земля) датчика - к GND на Arduino.
- Вывод TRIG (триггер) датчика - к аналоговому выводу на Arduino Nano, например, A5.
- Вывод ECHO (эхо) датчика - к другому аналоговому выводу на Arduino Nano, например, A3.
Подключите серводвигатели SG90 к плате Arduino Nano для управления движениями робота: каждый серводвигатель имеет три провода: питание (красный), заземление (коричневый) и сигнальный (оранжевый). Подключите провода питания к положительной клемме источника питания (батареи), заземляющие провода к отрицательной клемме, а сигнальные провода к определенным цифровым контактам на Arduino Nano.
- Серводвигатель 1: движение головы (например, цифровой контакт 3)
- Серводвигатель 2: левая нога (например, цифровой контакт 5)
- Серводвигатель 3: правая нога (например, цифровой контакт 9)
- Серводвигатель 4: левая нога (например, цифровой контакт 7)
- Серводвигатель 5: правая нога (например, цифровой контакт 11)
Прикрепите все компоненты к раме робота с помощью винтов, гаек и прокладок, если это необходимо. Убедитесь, что все соединения надежны и не имеют незакрепленных проводов или потенциальных коротких замыканий. Всегда дважды проверяйте соединения перед включением цепи.
Объяснение кода программы
Код нашей программы включает функции для управления различными движениями робота, такими как ходьба вперед, поворот, наклон и раскачивание. Кроме того, код использует библиотеку NewPing для взаимодействия с ультразвуковым датчиком измерения расстояний.
Важно выполнить код программы №1 перед началом этапов сборки. Этот код предназначен для калибровки и регулировки серводвигателей под правильными углами. Запустив этот код, вы можете убедиться, что серводвигатели работают правильно и точно расположены. Это поможет предотвратить любые потенциальные проблемы или осложнения на последующих этапах процесса сборки робота.
Код программы №1
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <Servo.h> // include servo library // Define 5 Servos Servo myServo1; // Head Servo Servo myServo2; // Left Hip Servo Servo myServo3; // Left foot Servo Servo myServo4; // Right Hip Servo Servo myServo5; // Right foot Servo void setup() { // Attach servos to Arduino PWM Pins myServo1.attach(3); myServo2.attach(5); myServo3.attach(7); myServo4.attach(9); myServo5.attach(11); myServo1.write(90); myServo2.write(90); myServo3.write(90); myServo4.write(90); myServo5.write(90); } void loop() { } |
А код программы №2 включает в себя все необходимые движения серводвигателей, чтобы ваш робот работал. Без этого кода вы не сможете успешно завершить проект.
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
В этой программе есть возможность контролировать действия вашего робота. Вы также можете настроить его движения, регулируя угол наклона, угол поворота и угол поворота для каждого отдельного двигателя в соответствии с вашими потребностями в калибровке.
Первым делом в коде программы подключим необходимые библиотеки. Библиотека Servo.h обеспечивает функции управления серводвигателями, а библиотека NewPing.h облегчает взаимодействие с ультразвуковым датчиком.
|
1 2 |
#include <Servo.h> #include <NewPing.h> |
Затем зададим осмысленные имена для используемых контактов. ECHO_PIN и TRIGGER_PIN назначены на эхо-контакты и триггерные контакты ультразвукового датчика соответственно. Контакты LEFTLEG, RIGHTLEG, LEFTFOOT, RIGHTFOOT и HEAD используются для серводвигателей, управляющих различными частями робота. MAX_DISTANCE устанавливается как максимальное расстояние, которое может измерить ультразвуковой датчик.
|
1 2 3 4 5 6 7 8 9 10 |
// edit the pin according to your connection #define ECHO_PIN A3 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN A5 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define LEFTLEG 5 #define RIGHTLEG 9 #define LEFTFOOT 7 #define RIGHTFOOT 11 #define HEAD 3 #define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. int Min_DISTANCE = 10; |
Далее создадим экземпляр класса NewPing с именем sonar, который используется для связи с ультразвуковым датчиком. Он инициализируется номерами триггерных и эхо-контактов, а также максимальным расстоянием.
|
1 |
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. |
Экземпляры класса Servo создаются для каждого серводвигателя, управляющего различными частями робота. Этим экземплярам дадим названия Lleg, Rleg, Lfoot, Rfoot и Head.
|
1 2 3 4 5 |
Servo Lleg; Servo Rleg; Servo Lfoot; Servo Rfoot; Servo Head; |
Следующие переменные хранят положения сервоприводов, которые соответствуют центральным положениям или положениям по умолчанию для сервоприводов, управляющих головой, правой ногой, левой ногой, правой ногой и левой ногой.
|
1 2 3 4 5 |
int Hcenter = 90; int RLcenter = 90; int RFcenter = 90; int LLcenter = 90; int LFcenter = 90; |
Следующие переменные хранят различные настройки углов и скорости, используемые для управления движениями робота. TAngle хранит угол наклона, uAngle хранит угол поворота, sAngle хранит угол качания, а Speed сохраняет задержку между движениями сервопривода.
|
1 2 3 4 |
int tAngle = 20; // tilt angle int uAngle = 25; // turn angle int sAngle = 25; // swing angle int Speed = 50; // Speed of walk |
Функция Forward предназначена для того, чтобы заставить робота идти вперед. Она принимает два аргумента: Steps (количество шагов) и Speed (задержка между движениями сервопривода). Функция использует различные подфункции для создания шаблона ходьбы: SwingRight, TiltRightUp, TiltRightDown, TiltLeftUp, SwingRcenter, SwingLeft, TiltLeftDown и TiltRightUp. Эти подфункции вызываются последовательно для создания шагающего движения.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void Forward(byte Steps, byte Speed){ Serial.println("Forward"); TiltRightUp(tAngle, Speed); for (byte j=0; j<Steps; ++j){ SwingRight(sAngle, Speed); TiltRightDown(tAngle, Speed); TiltLeftUp(tAngle, Speed); SwingRcenter(sAngle, Speed); SwingLeft(sAngle, Speed); TiltLeftDown(tAngle, Speed); TiltRightUp(tAngle, Speed); SwingLcenter(sAngle, Speed); } TiltRightDown(tAngle, Speed); } |
Функция TurnLeft предназначена для того чтобы заставить робота повернуть налево. Для выполнения поворотного движения он использует комбинацию подфункций: TiltLeftUp, LeftLegIn, TiltLeftDown, TiltRightUp, LeftLegIcenter, RightLegOut, TiltRightDown и TiltLeftUp.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void TurnLeft(byte Steps, byte Speed){ Serial.println("TurnLeft"); TiltLeftUp(uAngle, Speed); delay(20); for (byte j=0; j<Steps; ++j){ LeftLegIn(sAngle, Speed); TiltLeftDown(uAngle, Speed); TiltRightUp(uAngle, Speed); delay(20); LeftLegIcenter(sAngle, Speed); RightLegOut(sAngle, Speed); TiltRightDown(uAngle, Speed); TiltLeftUp(uAngle, Speed); delay(20); RightLegOcenter(sAngle, Speed); } TiltLeftDown(uAngle, Speed); } |
Функция TurnRight предназначена для того, чтобы заставить робота повернуть направо. Она использует подфункции в последовательности, аналогичной функции TurnLeft, но с движениями в противоположную сторону.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void TurnRight(byte Stps, byte Speed){ Serial.println("TurnRight"); TiltRightUp(uAngle, Speed); delay(20); for (byte f=0; f<=Stps; ++f){ RightLegIn(sAngle, Speed); TiltRightDown(uAngle, Speed); TiltLeftUp(uAngle, Speed); delay(20); RightLegIcenter(sAngle, Speed); LeftLegOut(sAngle, Speed); TiltLeftDown(uAngle, Speed); TiltRightUp(uAngle, Speed); delay(20); LeftLegOcenter(sAngle, Speed); } TiltRightDown(uAngle, Speed); } |
Следующие функции управляют движением головы робота. HeadRight и HeadLeft поворачивают голову вправо и влево соответственно, регулируя угол сервопривода головы. HeadCenter центрирует голову, устанавливая сервопривод головы на угол по умолчанию.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void HeadRight() { Serial.println("HeadRight"); Head.write(Hcenter - 105); delay(1000); } void HeadLeft() { Serial.println("HeadLeft"); Head.write(Hcenter + 105); delay(1000); } void HeadCenter() { Serial.println("HeadCenter"); Head.write(Hcenter); delay(1000); } |
Следующие функции управляют наклонными движениями ног и ступней робота. Функции пошагово увеличивают или уменьшают углы сервопривода для достижения наклонных движений.
|
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 |
void TiltRightUp(byte ang, byte sp){ //tilt right up for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter+i); Rfoot.write(RFcenter+i); delay(sp); } } void TiltRightDown(byte ang, byte sp){ //tilt right down for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter+i); Rfoot.write(RFcenter+i); delay(sp); } } void TiltLeftUp(byte ang, byte sp){ //tilt left up for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter-i); Rfoot.write(RFcenter-i); delay(sp); } } void TiltLeftDown(byte ang, byte sp){ //tilt left down for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter-i); Rfoot.write(RFcenter-i); delay(sp); } } |
Аналогично, следующие функции управляют подъемом и опусканием ног робота, регулируя углы сервоприводов.
|
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 |
void LeftFootUp(char ang, byte sp){ //tilt left up for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter-i); delay(sp); } } void LeftFootDown(byte ang, byte sp){ //tilt left down for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter-i); delay(sp); } } void RightFootUp(byte ang, byte sp){ //tilt right up for (int i=0; i<=ang; i+=5){ Rfoot.write(RFcenter+i); delay(sp); } } void RightFootDown(byte ang, byte sp){ //tilt right down for (int i=ang; i>0; i-=5){ Rfoot.write(RFcenter+i); delay(sp); } } |
Следующие функции управляют покачиванием ног робота. Функции SwingRight и SwingLeft перемещают ножки наружу, а SwingRcenter и SwingLcenter перемещают их обратно в центр.
|
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 |
void SwingRight(byte ang, byte sp){ //swing right for (int i=0; i<=ang; i+=5){ Lleg.write(LLcenter-i); Rleg.write(RLcenter-i); delay(sp); } } void SwingRcenter(byte ang, byte sp){ //swing r->center for (int i=ang; i>0; i-=5){ Lleg.write(LLcenter-i); Rleg.write(RLcenter-i); delay(sp); } } void SwingLeft(byte ang, byte sp){ //swing left for (byte i=0; i<=ang; i=i+5){ Lleg.write(LLcenter+i); Rleg.write(RLcenter+i); delay(sp); } } void SwingLcenter(byte ang, byte sp){ //swing l->center for (byte i=ang; i>0; i=i-5){ Lleg.write(LLcenter+i); Rleg.write(RLcenter+i); delay(sp); } } |
Следующие функции управляют движением правой ноги робота. RightLegIn и RightLegOut перемещают ногу внутрь и наружу соответственно. RightLegIcenter и RightLegOcenter перемещают ногу обратно в центральное положение из соответствующих позиций.
|
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 |
void RightLegIn(byte ang, byte sp){ //swing right for (int i=0; i<=ang; i+=5){ Rleg.write(RLcenter-i); delay(sp); } } void RightLegIcenter(byte ang, byte sp){ //swing r->center for (int i=ang; i>0; i-=5){ Rleg.write(RLcenter-i); delay(sp); } } void RightLegOut(byte ang, byte sp){ //swing right for (int i=0; i<=ang; i+=5){ Rleg.write(RLcenter+i); delay(sp); } } void RightLegOcenter(byte ang, byte sp){ //swing r->center for (int i=ang; i>0; i-=5){ Rleg.write(RLcenter+i); delay(sp); } } |
Следующие функции управляют движением левой ноги робота аналогично функциям RightLeg. Эти функции определяют подробные движения и закономерности движения двуногого робота. Они используют углы сервоприводов и время задержки для создания определенных движений, таких как ходьба, поворот и наклон. Поведения создаются путем соответствующей последовательности этих подфункций в функциях движения более высокого уровня, таких как Forward, TurnLeft и TurnRight.
|
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 |
void LeftLegIn(byte ang, byte sp){ //swing left for (byte i=0; i<=ang; i=i+5){ Lleg.write(LLcenter+i); delay(sp); } } void LeftLegIcenter(byte ang, byte sp){ //swing l->center for (byte i=ang; i>0; i=i-5){ Lleg.write(LLcenter+i); delay(sp); } } void LeftLegOut(byte ang, byte sp){ //swing left for (byte i=0; i<=ang; i=i+5){ Lleg.write(LLcenter-i); delay(sp); } } void LeftLegOcenter(byte ang, byte sp){ //swing l->center for (byte i=ang; i>0; i=i-5){ Lleg.write(LLcenter-i); delay(sp); } } |
В функции setup() мы делаем следующее. Настраиваем связь с вашим компьютером через последовательное соединение. Подключаем серводвигатели к определенным контактам на Arduino для управления ими. Поворачиваем серводвигатели в исходные точки. Откалибруем ультразвуковой датчик, проведя измерения. Укажем, что настройка завершена и робот готов к работе.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void setup() { Serial.begin(19200); Serial.println("Bipedino setup is running."); Lleg.attach(LEFTLEG); Rleg.attach(RIGHTLEG); Lfoot.attach(LEFTFOOT); Rfoot.attach(RIGHTFOOT); Head.attach(HEAD); CenterServos(); delay(500); for (int i = 0; i < 5; ++i) { GetSonar(); delay(1000); } Serial.println("Bipedino is ready."); } |
В функции void loop() мы будем неоднократно проверять расстояние перед роботом с помощью ультразвукового датчика и принимать решение о повороте или движении вперед на основе обнаруженных препятствий. Если препятствие обнаружено очень близко, робот повернется, чтобы найти свободный путь. В противном случае он сделает определенное количество шагов вперед в зависимости от обнаруженного расстояния.
|
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 |
void loop() { unsigned int cmCenter = MAX_DISTANCE; unsigned int cmLeft = MAX_DISTANCE; unsigned int cmRight = MAX_DISTANCE; HeadCenter(); cmCenter = GetSonar(); if (cmCenter < Min_DISTANCE) { HeadRight(); cmRight = GetSonar(); HeadCenter(); if (cmRight > Min_DISTANCE) { TurnRight(5, 50); } else { HeadLeft(); cmLeft = GetSonar(); HeadCenter(); if (cmLeft > Min_DISTANCE) { TurnLeft(5, 50); } } } else { int nSteps = cmCenter / 5; if (nSteps > 5) { nSteps = 5; } else { nSteps = 1; } Serial.print("Steps <"); Serial.print(nSteps); Serial.println(">"); for (int n = 0; n < nSteps; n++) { Forward(1,50); } } } |
Следующая функция использует ультразвуковой датчик (сонар) для измерения расстояний. Она отправляет пинг и вычисляет время, необходимое для восстановления сигнала. Затем она преобразует это время в расстояние в сантиметрах, печатает результат и возвращает расстояние.
|
1 2 3 4 5 6 7 |
int GetSonar() { unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS). Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance and print result (0 = outside set distance range, no ping echo) Serial.println("cm"); return uS / US_ROUNDTRIP_CM; } |
Следующая функция позиционирует серводвигатели ног, ступней и головы робота в центральное положение. Затем добавляется задержка, позволяющая сервоприводам достичь этих положений.
|
1 2 3 4 5 6 7 8 |
void CenterServos() { Lleg.write(LLcenter); // tell servo to go to position in variable 'center' Rleg.write(RLcenter); // tell servo to go to position in variable 'center' Lfoot.write(LFcenter); // tell servo to go to position in variable 'center' Rfoot.write(RFcenter); // tell servo to go to position in variable 'center' Head.write(Hcenter); // tell servo to go to position in variable 'center' delay(1000); // waits 100ms for the servos to reach the position } |
Кратко принцип работы нашего робота вы можете посмотреть в следующем видео.
Полный алгоритм установки и калибровки рычагов сервоприводов
Этот метод гарантирует, что все ноги и голова робота будут в правильном «нулевом» положении (как правило, 90°), что критически важно для устойчивости и корректных движений.
Этап 1: Подготовка (Аппаратная часть)
-
Соберите схему на макетной плате, как показано в разделе «Схема проекта». Подключите Arduino Nano, сервоприводы и внешнее питание (батарею 7,4В) через выключатель.
-
Важно: Питание на сервоприводы должно подаваться от внешнего источника, так как встроенного стабилизатора Arduino Nano может не хватить.
-
Загрузите калибровочный скетч («Код программы №1») в Arduino Nano. Внимание: Питание робота должно быть выключено во время загрузки кода.
-
Временно не крепите рычаги (качалки) к сервоприводам и не собирайте корпус. Сервоприводы должны быть свободны.
Этап 2: Программная калибровка (с помощью скетча №1)
-
Включите питание робота. Серводвигатели с установленным калибровочным скетчем должны автоматически установить вала в положение 90° (центральное положение). Это стандартное поведение для скетча, который просто пишет
myservo.write(90);вsetup(). -
Если в «Коде программы №1» используются другие углы, вам нужно открыть этот скетч в Arduino IDE и найти строки с командами
write(90);илиwrite(значение);. Убедитесь, что для всех сервоприводов установлено значение 90 или то, которое автор считает «центральным» для старта.
Этап 3: Механическая установка рычагов
-
Возьмите первый сервопривод (например, для левого бедра), его вал уже стоит в откалиброванном положении (90°).
-
Наденьте рычаг на вал таким образом, чтобы он располагался максимально перпендикулярно (прямо) относительно корпуса сервопривода, как на изображении ниже. Обычно это означает, что рычаг смотрит строго вбок или строго вверх/вниз, в зависимости от конструкции вашего напечатанного корпуса. Ориентируйтесь на 3D-модель и отверстия для крепления.
-
Закрепите рычаг прилагаемым винтом. Важно: если рычаг не встает ровно из-за шлицев, снимите его и проверните на один зубец в нужную сторону, пока не добьетесь максимально точного прямого угла.
-
Повторите эту процедуру для всех пяти сервоприводов.
Этап 4: Сборка и финальная проверка
-
Теперь, когда на всех сервоприводах рычаги стоят ровно под прямым углом, можно приступать к сборке механической конструкции робота: прикручивать сервоприводы к корпусу, а ноги и голову — к рычагам.
-
После полной сборки включите робота. Все конечности должны занять положение, близкое к вертикальному/горизонтальному в соответствии с дизайном. Робот должен стоять ровно.
-
Если после сборы вы заметили, что робот слегка заваливается или поза не совсем ровная, вы можете слегка подкорректировать это уже в основном скетче («Код программы №2»), изменив значения переменных
DefaultHead,DefaultRleg,DefaultLlegи т.д. в начале кода. Например, если левая нога чуть приподнята, немного уменьшите значениеDefaultLleg.
Таким образом, ответы на ваши вопросы:
-
Под каким углом закрепить рычаг? Под углом 90° (перпендикулярно корпусу сервопривода) после подачи питания с калибровочным скетчем.
-
Вручную обязательно его примерно выставлять? Нет, скетч выставляет точный угол в 90°. Вы лишь механически фиксируете рычаг в этом положении.
-
Как затем точно выставить с помощью кода №1? Скетч №1 выставляет угол, вы лишь надеваете рычаг. Если нужно подрегулировать позу после сборки, это делается правкой констант (например,
DefaultRleg) в основном скетче №2.
Если после сборки робот все еще неустойчив, проверьте, нет ли люфта в напечатанных деталях, и при необходимости используйте подстройку основного скетча.
Заключение
В заключение отметим, что проект Biped Catbot представляет собой увлекательное путешествие в мир робототехники и автоматизации на базе Arduino. В ходе этого проекта мы научились собирать и программировать маленького двуногого робота, способного ходить, танцевать и избегать препятствий.
Этот проект позволил вам персонализировать движения робота, регулируя углы, что способствовало творческому подходу к конструкции вашего робота. Независимо от того, используете ли вы акрил или картон, ключевым моментом является индивидуализация. Завершив этот проект, вы получили ценную информацию о робототехнике, улучшили навыки программирования и обрели уверенность в дальнейших начинаниях в области робототехники. Дайте волю своему творчеству и продолжайте создавать невероятных роботов.
Исходный код программы (скетча)
Код №1
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <Servo.h> // include servo library // Define 5 Servos Servo myServo1; // Head Servo Servo myServo2; // Left Hip Servo Servo myServo3; // Left foot Servo Servo myServo4; // Right Hip Servo Servo myServo5; // Right foot Servo void setup() { // Attach servos to Arduino PWM Pins myServo1.attach(3); myServo2.attach(5); myServo3.attach(7); myServo4.attach(9); myServo5.attach(11); myServo1.write(90); myServo2.write(90); myServo3.write(90); myServo4.write(90); myServo5.write(90); } void loop() { } |
Код №2
|
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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
#include <Servo.h> #include <NewPing.h> // edit the pin according to your connection #define ECHO_PIN A3 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN A5 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define LEFTLEG 5 // Left Up servo #define RIGHTLEG 9 // Right Up servo #define LEFTFOOT 7 // Left Down servo #define RIGHTFOOT 11 // Right Down servo #define HEAD 3 // Centor servo #define MAX_DISTANCE 400 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. int Min_DISTANCE = 10; NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. Servo Lleg; // create servo object to control a servo Servo Rleg; Servo Lfoot; Servo Rfoot; Servo Head; int Hcenter = 90; // variable to store the center servo position int RLcenter = 90; int RFcenter = 90; // variable to store the center servo position int LLcenter = 90; int LFcenter = 90; int tAngle = 20; // tilt angle int uAngle = 25; // turn angle int sAngle = 25; // swing angle int Speed = 50; // Speed of walk void Dance() { int pos = 0; // variable to store the servo position for (pos = 90; pos <= 120; pos += 1) { // goes from 0 degrees to 180 degrees // in steps of 1 degree Lfoot.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15 ms for the servo to reach the position } for (pos = 120; pos >= 90; pos -= 1) { // goes from 180 degrees to 0 degrees Lfoot.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15 ms for the servo to reach the position } } void Forward(byte Steps, byte Speed){ Serial.println("Forward"); TiltRightUp(tAngle, Speed); for (byte j=0; j<Steps; ++j){ SwingRight(sAngle, Speed); TiltRightDown(tAngle, Speed); TiltLeftUp(tAngle, Speed); SwingRcenter(sAngle, Speed); SwingLeft(sAngle, Speed); TiltLeftDown(tAngle, Speed); TiltRightUp(tAngle, Speed); SwingLcenter(sAngle, Speed); } TiltRightDown(tAngle, Speed); } void TurnLeft(byte Steps, byte Speed){ Serial.println("TurnLeft"); TiltLeftUp(uAngle, Speed); delay(20); for (byte j=0; j<Steps; ++j){ LeftLegIn(sAngle, Speed); TiltLeftDown(uAngle, Speed); TiltRightUp(uAngle, Speed); delay(20); LeftLegIcenter(sAngle, Speed); RightLegOut(sAngle, Speed); TiltRightDown(uAngle, Speed); TiltLeftUp(uAngle, Speed); delay(20); RightLegOcenter(sAngle, Speed); } TiltLeftDown(uAngle, Speed); } void TurnRight(byte Stps, byte Speed){ Serial.println("TurnRight"); TiltRightUp(uAngle, Speed); delay(20); for (byte f=0; f<=Stps; ++f){ RightLegIn(sAngle, Speed); TiltRightDown(uAngle, Speed); TiltLeftUp(uAngle, Speed); delay(20); RightLegIcenter(sAngle, Speed); LeftLegOut(sAngle, Speed); TiltLeftDown(uAngle, Speed); TiltRightUp(uAngle, Speed); delay(20); LeftLegOcenter(sAngle, Speed); } TiltRightDown(uAngle, Speed); } void HeadRight() { Serial.println("HeadRight"); Head.write(Hcenter - 105); delay(1000); } void HeadLeft() { int pos = 90; Serial.println("HeadLeft"); //Head.write(Hcenter + 105); for (pos = 90; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees Head.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15 ms for the servo to reach the position } delay(1000); } void HeadCenter() { Serial.println("HeadCenter"); Head.write(Hcenter); delay(1000); } void TiltRightUp(byte ang, byte sp){ //tilt right up for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter+i); Rfoot.write(RFcenter+i); delay(sp); } } void TiltRightDown(byte ang, byte sp){ //tilt right down for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter+i); Rfoot.write(RFcenter+i); delay(sp); } } void TiltLeftUp(byte ang, byte sp){ //tilt left up for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter-i); Rfoot.write(RFcenter-i); delay(sp); } } void TiltLeftDown(byte ang, byte sp){ //tilt left down for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter-i); Rfoot.write(RFcenter-i); delay(sp); } } void LeftFootUp(char ang, byte sp){ //tilt left up for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter-i); delay(sp); } } void LeftFootDown(byte ang, byte sp){ //tilt left down for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter-i); delay(sp); } } void RightFootUp(byte ang, byte sp){ //tilt right up for (int i=0; i<=ang; i+=5){ Rfoot.write(RFcenter+i); delay(sp); } } void RightFootDown(byte ang, byte sp){ //tilt right down for (int i=ang; i>0; i-=5){ Rfoot.write(RFcenter+i); delay(sp); } } void SwingRight(byte ang, byte sp){ //swing right for (int i=0; i<=ang; i+=5){ Lleg.write(LLcenter-i); Rleg.write(RLcenter-i); delay(sp); } } void SwingRcenter(byte ang, byte sp){ //swing r->center for (int i=ang; i>0; i-=5){ Lleg.write(LLcenter-i); Rleg.write(RLcenter-i); delay(sp); } } void SwingLeft(byte ang, byte sp){ //swing left for (byte i=0; i<=ang; i=i+5){ Lleg.write(LLcenter+i); Rleg.write(RLcenter+i); delay(sp); } } void SwingLcenter(byte ang, byte sp){ //swing l->center for (byte i=ang; i>0; i=i-5){ Lleg.write(LLcenter+i); Rleg.write(RLcenter+i); delay(sp); } } void RightLegIn(byte ang, byte sp){ //swing right for (int i=0; i<=ang; i+=5){ Rleg.write(RLcenter-i); delay(sp); } } void RightLegIcenter(byte ang, byte sp){ //swing r->center for (int i=ang; i>0; i-=5){ Rleg.write(RLcenter-i); delay(sp); } } void RightLegOut(byte ang, byte sp){ //swing right for (int i=0; i<=ang; i+=5){ Rleg.write(RLcenter+i); delay(sp); } } void RightLegOcenter(byte ang, byte sp){ //swing r->center for (int i=ang; i>0; i-=5){ Rleg.write(RLcenter+i); delay(sp); } } void LeftLegIn(byte ang, byte sp){ //swing left for (byte i=0; i<=ang; i=i+5){ Lleg.write(LLcenter+i); delay(sp); } } void LeftLegIcenter(byte ang, byte sp){ //swing l->center for (byte i=ang; i>0; i=i-5){ Lleg.write(LLcenter+i); delay(sp); } } void LeftLegOut(byte ang, byte sp){ //swing left for (byte i=0; i<=ang; i=i+5){ Lleg.write(LLcenter-i); delay(sp); } } void LeftLegOcenter(byte ang, byte sp){ //swing l->center for (byte i=ang; i>0; i=i-5){ Lleg.write(LLcenter-i); delay(sp); } } void setup() { Serial.begin(19200); Serial.println("Biped Catbot setup is running."); Lleg.attach(LEFTLEG); Rleg.attach(RIGHTLEG); Lfoot.attach(LEFTFOOT); Rfoot.attach(RIGHTFOOT); Head.attach(HEAD); CenterServos(); delay(500); for (int i = 0; i < 5; ++i) { GetSonar(); delay(1000); } Serial.println("Biped Catbot is ready."); } void loop() { unsigned int cmCenter = MAX_DISTANCE; unsigned int cmLeft = MAX_DISTANCE; unsigned int cmRight = MAX_DISTANCE; HeadCenter(); cmCenter = GetSonar(); if (cmCenter < Min_DISTANCE) { HeadRight(); cmRight = GetSonar(); HeadCenter(); if (cmRight > Min_DISTANCE) { TurnRight(5, 50); // 5 step right side } else { HeadLeft(); cmLeft = GetSonar(); HeadCenter(); if (cmLeft > Min_DISTANCE) { TurnLeft(5, 50); // 5 step left side } } } else { int nSteps = cmCenter / 5; if (nSteps > 5) { nSteps = 5; } else { nSteps = 1; } Serial.print("Steps <"); Serial.print(nSteps); Serial.println(">"); for (int n = 0; n < nSteps; n++) { Forward(1,50); } } } int GetSonar() { unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS). Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance and print result (0 = outside set distance range, no ping echo) Serial.println("cm"); return uS / US_ROUNDTRIP_CM; } void CenterServos() { Lleg.write(LLcenter); // tell servo to go to position in variable 'center' Rleg.write(RLcenter); // tell servo to go to position in variable 'center' Lfoot.write(LFcenter); // tell servo to go to position in variable 'center' Rfoot.write(RFcenter); // tell servo to go to position in variable 'center' Head.write(Hcenter); // tell servo to go to position in variable 'center' delay(1000); // waits 100ms for the servos to reach the position } |
Как заставить робота танцевать
1. Где в коде искать основу для танца?
В основном скетче (Код №2) уже есть все примитивы движений. Вам нужно создать новую функцию, например Dance(), и внутри нее в нужной последовательности вызывать существующие подфункции.
Вот какие движения уже есть в коде (вы можете их комбинировать):
-
Движения ног для ходьбы:
SwingRight(),SwingLeft(),TiltRightUp(),TiltRightDown(),TiltLeftUp(),TiltLeftDown(). -
Повороты:
TurnLeft(),TurnRight(). -
Движения «бедрами»:
RightLegIn(),RightLegOut(),LeftLegIn(),LeftLegOut(). -
Движения головой:
HeadRight(),HeadLeft(),HeadCenter(). -
Наклоны и покачивания. Они подробно описаны в разделе «Объяснение кода программы» (например, функции
SwingRight,TiltRightUpи т.д.).
2. Пример простой танцевальной функции
Откройте Код №2 в Arduino IDE. В самом низу, перед финальной скобкой }, добавьте новую функцию:
|
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 |
// СОЗДАЕМ ТАНЕЦ void Dance() { // Повторяем движения 3 раза for (int i = 0; i < 3; i++) { // Машем правой ногой RightLegOut(); delay(200); RightLegIn(); delay(200); // Машем левой ногой LeftLegOut(); delay(200); LeftLegIn(); delay(200); // Поворот головой вправо-влево HeadRight(); delay(300); HeadLeft(); delay(300); HeadCenter(); // Небольшой прыжок (рывок вверх-вниз) TiltRightUp(); TiltLeftUp(); delay(150); TiltRightDown(); TiltLeftDown(); delay(150); } // Финальное движение: поворот вокруг себя TurnLeft(); delay(500); TurnRight(); delay(500); } |
3. Как заставить робота танцевать вместо ходьбы?
Теперь нужно заменить обычное движение вперед (Forward) на вызов вашего танца.
Вариант А (временный танец):
Найдите в коде функцию void loop() и временно замените в ней все вызовы Forward и логику с датчиком на вызов Dance():
|
1 2 3 4 5 |
void loop() { Dance(); // Робот танцует один раз delay(2000); // Ждет 2 секунды // Можно добавить, чтобы после танца шел вперед: Forward(5, Speed); } |
Вариант Б (танец по команде):
Чтобы робот танцевал, когда вы даете команду с компьютера, измените loop() так:
|
1 2 3 4 5 6 7 8 9 10 11 |
void loop() { if (Serial.available() > 0) { char command = Serial.read(); if (command == 'd') { // Если прислали букву d Dance(); } if (command == 'w') { // Если прислали w - идти вперед Forward(5, Speed); } } } |
После загрузки скетча откройте Монитор порта (Инструменты → Монитор порта) и вводите буквы d или w, чтобы управлять роботом.







добрый день.
". Если хотите, я могу научить вас пользоваться искусственным интеллектом чтобы он писал вам нужные программы танцев для этого робота " - буду очень признателен. ИИ GigaChart в MAXе пойдет для этих целей?
Добрый. Возможно подойдет, но я им никогда не пробовал пользоваться. Советую chat.deepseek.com - бесплатно из России и без VPN (только нужно зарегистрироваться). Копируете ему прямо адрес этой страницы (https://microkontroller.ru/arduino-projects/biped-catbot-shagayushhij-i-tanczuyushhij-robot-na-arduino) и после этого через пробел пишите свой вопрос на русском языке, например "программа танца ламбада для робота" (без кавычек можно копировать). Я прямо сейчас задал ему такой вопрос и меня его ответ вполне удовлетворил.
Часть ответов на ваши вопросы я делал именно с помощью chat.deepseek.com. Статей на сайте уже очень много и, к сожалению, я уже не могу детально разбираться в каждой из них, поэтому приходится иногда прибегать к помощи ИИ
добрый вечер. робот движется вперед, видит препятствия близко ( сантиметров 5-10 ) затем движется немного назад и обходит препятствие. А как заставить робота танцевать ? Или для этого необходимо активизировать ( вставить ) определенные куски кода?
Добрый. Добавил краткую информацию по этому поводу в текст статьи - перед видео. Все необходимые движения робота в коде программы есть, но для танца нужна определенная программа чтобы управлять этими движениями. Если хотите, я могу научить вас пользоваться искусственным интеллектом чтобы он писал вам нужные программы танцев для этого робота - нужно будет только правильно формулировать вопросы к ИИ, а программу он напишет вам сам
добрый день. Вы как всегда правы! Порядок подфункций SwingRight на SwingLeft в функции Forward() переставил местами - движение пошло вперед. Ну остальное осталось поправить .
Добрый вечер. А разве еще что то не поправлено?
добрый вечер!прочел Ваши рекомендации и не стал копаться в схеме и выискивать какие то неполадки. Но в силу возрастного ценза ( рука не имеет необходимой твердости и точности ) и небольшого расстояния между пинами( 1/10 дюйма или 2,54 мм )подумал что недочеты в сборке схемы при пайке будут. Поэтому удалил универсальную печатную плату вместе с Arduino Nano , соединительными проводами и распаянными гребенками - штырями для подсоединения сервоприводов. Взял новую плату и ардуино, распаял все снова очень тщательно ( сделал упор для руки ) , собрал , залил код, включил и все заработало!!!! Но есть и недостаток. Я перегрузил заднюю часть ( плата заряда, печатная плата с ардуино и т.д. расположились сильно в задней части ). При включении модель через очень короткой время опрокидывается назад. но это я поправлю ( сместить центр тяжести надо к голове ). второй недостаток - модель движется назад. При искусственном создании препятствия ( для проверки ультразвукового сонара ) модель реагирует поворотом головы в противоположную сторону от препятствия, т.е. реагирует правильно. КАК СДЕЛАТЬ ДВИЖЕНИЕ ВПЕРЕД? Но Вам огромное спасибо за все подсказки. Скажу больше, в нынешнее АЛЧНОЕ время встретить такое бескорыстное участие ДОРОГОГО СТОИТ. Спасибо ВАМ. Подскажите еще как сделать движение вперед.
Добрый
Это не аппаратная неисправность, а программная особенность, связанная с тем, как в основном коде (Код №2) реализована логика движения.
Почему робот движется назад
В стандартном скетче для Catbot алгоритм движения в функции Forward() не всегда реализован как «движение вперед» в привычном смысле. Последовательность подфункций, составляющих шаг (например, SwingRight, TiltRightUp, TiltRightDown…), задает определенный цикл. Если в вашей сборке центр тяжести смещен назад (о чем вы пишете), то робот будет заваливаться при попытке сделать шаг в прямом направлении, и визуально это может выглядеть как движение назад. Также возможно, что в вашей версии скетча последовательность движений физически заставляет робота перемещаться назад из-за особенностей механики (направление поворота сервоприводов).
Однако, судя по вашим словам «модель движется назад», наиболее вероятно, что в коде, который вы загрузили, перепутаны последовательности вызовов функций для движения вперед и назад, либо сам алгоритм обхода препятствий заставляет робота пятиться.
Как заставить робота двигаться вперед
Есть два пути решения: «быстрый» (изменение логики в loop()) и «правильный» (изменение функции Forward()).
2. Измените направление в функции Forward()
Если вызов Forward присутствует, но движение все равно идет назад, значит, последовательность движений внутри самой функции Forward не соответствует вашей механике. Вам нужно изменить порядок подфункций в Forward на противоположный.
В коде №2 найдите функцию Forward. Она выглядит примерно так:
Чтобы изменить направление на противоположное, попробуйте переставить последовательность вызовов «задом наперед» или заменить SwingRight на SwingLeft и наоборот. Например, так:
Это заставит робота «шагать» в другую сторону. Возможно, потребуется поэкспериментировать с последовательностью, наблюдая за движением.
3. Временно измените логику обхода препятствий
Чтобы протестировать движение вперед без помех, можно временно закомментировать (поставить // в начале строки) код, связанный с ультразвуковым датчиком, и заставить робота просто выполнять цикл Forward:
void loop() {
Forward(5, Speed); // Делает 5 шагов
delay(1000);
}
Загрузите этот упрощенный скетч. Если робот пойдет вперед — значит, проблема была в логике loop(). Если все равно назад — меняйте последовательность в функции Forward.
Важное замечание по центровке
Вы правильно заметили, что центр тяжести смещен назад. Это критически важно. Даже если программно задано движение вперед, из-за перегруженной задней части робот может физически не мочь сделать шаг вперед и будет падать или двигаться назад. Обязательно переместите аккумулятор и плату заряда вперед, к «голове». Без правильной балансировки никакая корректировка кода не даст устойчивой ходьбы.
Резюме
Сначала исправьте балансировку робота, сместив тяжелые компоненты вперед.
Затем проверьте функцию loop(), убедитесь, что вызывается Forward.
Если движение все еще назад — измените последовательность вызовов внутри Forward на противоположную или зеркальную.
Если у вас останутся трудности с компиляцией или вы пришлете текст вашей версии функции Forward, я помогу скорректировать её точнее.
Не могу включить код в комментарий, он ломается, вам наверняка на почту приходили все изменения комментария, которые я делал, посмотрите, может быть в них коды нормально отобразились
добрый день.Собрал полностью Biped Catbot. Калибровку выполнил по рекомендации согласно кода №1. Закачал код № 2, включаю - ничего не происходит. Замерил напряжение на подаче на сервоприводы :
VCC - GND, v VCC - сигнал, v
1) голова ( D3 ) 8,13 7,09
2) нога левая ( D5 ) 8.12 7,08
3) бедро левое ( D7 ) 8,12 7,08
4) нога правая ( D9 ) 8,14 7,09
5) бедро правое ( D11) 8.14 7,09
И еще.Я в схему добавил параллельно батарее зарядную плату 2S 4A для двухсекционной Li - on 18650. Подскажите , где я делаю не так, куда копать ?
Добрый
1. Основная причина: раздельное питание
Судя по вашим замерам, сервоприводы получают питание, но не получают корректный сигнал управления. Это классическая проблема, которая возникает при нарушении правил подключения питания в этом проекте.
В описании схемы есть критически важное примечание:
«Мы не использовали вывод 5V на Arduino, потому что он не давал достаточно мощности для нормальной работы всех двигателей. Вместо этого мы используем дополнительный источник питания».
Как должно быть подключено правильно:
Питание сервоприводов (VCC — красный провод): подключается напрямую к плюсу вашей батареи 7.4В (или к выходу вашей зарядной платы 2S).
Питание Arduino (Vin): подключается к тому же плюсу батареи (через выключатель или параллельно).
Общая земля (GND): это самый важный пункт. Минус батареи должен быть ОБЩИМ для Arduino и всех сервоприводов. Все GND (Arduino, сервоприводов, ультразвукового датчика) должны быть соединены вместе.
Ваши замеры (VCC — сигнал ≈ 7.1В) указывают на то, что:
Сервоприводы видят напряжение питания.
Но сигнальный провод (который должен выдавать Arduino импульсы 5В) «висит» на потенциале, близком к питанию. Это часто происходит, если земля Arduino не соединена с землей сервоприводов. Без общего «минуса» сигнал не может быть прочитан.
2. Проблема с зарядной платой 2S
Вы добавили плату зарядки 2S 4A для двух последовательно соединенных аккумуляторов 18650.
Проверьте выходное напряжение батареи: два последовательных элемента 18650 (2S) в полностью заряженном состоянии выдают 8.4В, а в разряженном — около 6.0–6.4В. Это штатное напряжение для проекта, так как Arduino Nano и сервоприводы SG90 (рассчитаны на 4.8–6.0В) обычно нормально работают от 7.4В через стабилизатор.
Опасность для Arduino: Если вы подключили питание от 2S батареи напрямую к выводу 5V Arduino Nano (а не к Vin), то вы могли вывести из строя плату. Её встроенный стабилизатор на Vin выдерживает до 12В, а на вход 5V подавать больше 5.5В нельзя. Убедитесь, что питание на Arduino подается через пин VIN.
3. Проверка кода и калибровки
Калибровка: Вы выполнили калибровку кодом №1. После этого рычаги сервоприводов были установлены и закреплены на валу в положении 90°? Если рычаги закреплены неправильно, робот не будет стоять, но сервоприводы все равно должны издавать характерный звук удержания позиции. Если звука нет — это снова указывает на проблему с питанием/сигналом.
4. Пошаговый алгоритм проверки (что делать)
Выполните эти шаги, чтобы локализовать проблему:
Отключите ультразвуковой датчик HC-SR04 от Arduino. В некоторых случаях неисправный датчик может «сажать» линию питания или сигнала.
Временно уберите зарядную плату из схемы. Подключите аккумуляторы напрямую к Arduino (Vin) и к сервоприводам (VCC), строго соблюдая общую землю.
Загрузите в Arduino простой тестовый скетч (например, скетч калибровки №1, но модифицированный, чтобы он просто поворачивал один сервопривод туда-обратно каждые 2 секунды). Это позволит проверить, работают ли сервоприводы и Arduino вообще.
Проверьте общую землю. Возьмите мультиметр в режиме прозвонки и убедитесь, что между контактом GND на Arduino и черным проводом (GND) любого сервопривода есть электрический контакт (сопротивление близко к 0).
Проверьте питание Arduino. Подключив батарею, измерьте напряжение между Vin и GND на Arduino (должно быть 6-8.4В), а также между 5V и GND на Arduino (должно быть ровно 5В). Если на выводе 5V нет напряжения, Arduino не работает.
5. Ваши замеры
Ваши замеры показывают, что между VCC и GND сервоприводов есть 8.13В (это нормально для 2S), а между VCC и сигналом — ~7.09В. Это означает, что сигнальный провод имеет потенциал на 1В ниже питания. Для стандартной логики это ненормально:
Если бы сигнал был активным (5В), разница между VCC и сигналом составляла бы около 3В.
Если бы сигнал был неактивным (0В), разница составляла бы ~8В.
Ваши 7В указывают на «плавающий» сигнал, что подтверждает версию об отсутствии общего GND или неработающем выходе Arduino.
Краткий итог: Скорее всего, проблема в неправильном подключении земли или в том, что питание на Arduino подано не на тот пин. Проверьте соединение всех GND и убедитесь, что Arduino получает питание через Vin, а сервоприводы — напрямую от батареи, но с общей землей с Arduino.
Добрый день! Извиняюсь за непонятливость ( или дотошную в въедливость ), но еще пару вопросов.
1) в тексте , чуть ниже принципиальной схемы, "Всегда выключайте питание Arduino при загрузке кода ". Далее, в дополнительном пояснении по алгоритму и настройке в тексте ЭТАП №1 " Питание робота должно быть выключено во время загрузки кода ". т То есть речь идет о загрузке скетча, но о разных выключателях. Дайте пояснение ( а может можно обойтись одним выключателем, который полностью отключает робота при загрузке скетча ?
2) После калибровки ( мне так представляется ) рычаг бедра должен все таки выставляться вдоль корпуса сервопривода . Или я ошибаюсь?
3) Рычаг бедра ( как указано в видеоролике и на images ) должен быть не с одним плечом, а с двумя, так ? Заранее благодарю за ответ.
Добрый. Нет, из-за особенностей питания схемы лучше все таки использовать два выключателя, у них все таки разные роли в этом проекте. По остальным двум вопросам, к сожалению, уже не могу подсказать что то конкретное - так глубоко я в этот проект уже не вникал
благодарю за ответ. Буду пробовать завтра.
Ждем от вас комментарий об успехах
добрый день. Получил с Китая серводвигатели. Поясните фразу : " Для начала прикрепите рычаг сервопривода к серводвигателю, тщательно выровняв и закрепив его на месте. Мы можем вручную откалибровать и отрегулировать угол серводвигателя, но иногда ручная калибровка неточна или невозможна. Для более точной калибровки серводвигателей используйте код программы №1 ".
- Под каким углом закрепить рычаг.
- Вручную обязательно его примерно выставлять.
-как затем точно выставить с помощью кода №1?
- дайте пожалуйста полный алгоритм этого этого действия,т.е. как правильно установить и точно откалибровать рычаги сервоприводов.
Все детали я отпечатал на 3д принтере.
Добрый вечер. Я добавил эту информацию в статью, перед заключением
Благодарю за детальное пояснение.
Добрый вечер. Следующая ошибка в строке 278 :
exit status 1
'TurnRight' was not declared in this scope
Добрый. Я добавил функции TurnRight и TurnLeft в скетч, попробуйте теперь
скетч скомпилировался. Благодарю Вас . Всего Вам доброго. С наступающим НГ. Всех благ. Еще раз благодарю. К этому проекту и проекту термометра на адресной светодиодной ленте ( этот скетч скомпилировался без проблем с первого раза ) заказал на Алике комплектующие. Отличный у Вас ресурс , много очень интересных проектов.
И вас с наступающим Новым годом. Успехов вам в реализации проекта. Функция поворота головы робота влево может работать неправильно при таком ее виде сейчас в скетче. Если это будет действительно так, пишите, попробуем исправить
Добрый день! Благодарю за быстрый ответ. Но сейчас выдается ошибка, строка скетча 53 :
exit status 1
'steps' was not declared in this scope
Неверная библиотека найдена в C:\Program Files (x86)\Arduino\libraries\ChristmasLights-master: нет заголовочных файлов (.h), найденных в C:\Program Files (x86)\Arduino\libraries\ChristmasLights-master
Неверная библиотека найдена в C:\Program Files (x86)\Arduino\libraries\GyverMatrixBT-master: нет заголовочных файлов (.h), найденных в C:\Program Files (x86)\Arduino\libraries\GyverMatrixBT-master
Неверная библиотека найдена в C:\Program Files (x86)\Arduino\libraries\NewPing: нет заголовочных файлов (.h), найденных в C:\Program Files (x86)\Arduino\libraries\NewPing
Добрый вечер. Наверное тоже опечатка. Попробуйте steps в строке 53 с большой буквы написать, чтобы получилось Steps. Ведь именно с таким названием переменная передается в данную функцию
Добрый вечер. Благодарю за быстрый ответ.Steps в строке 53 прописал с большой буквы, но выдает ошибку вот такую :
exit status 1
expected primary-expression before '>=' token
О себе. мне 71,5 года.программирование не знаю, но делаю некоторые самоделки с микроконтроллером Arduino, освоил 3д печать на 3д принтeре Flyind Bear Ghost 6 , освоил создание моделей в Компасе.Трудовой стаж 43 года в сельском хозяйстве ( колхозный пенсионер ). Внуки увидели Вашего робота - кота Biped Catbot, очень просят сделать, но у меня проблема со скетчем. Помогите скомпилировать этот скетч и порадовать внуков ( да и себ я тож ).
Добрый. Я поправил в скетче весь код функции Forward, попробуйте теперь
Добрый день! Извиняюсь на назойливость , но опять ошибка в строке 268, но близко к победе ( всего строк в скетче 318 ) :
exit status 1
'HeadRight' was not declared in this scope
Я добавил функцию 'HeadRight' в скетч, попробуйте теперь
Не компилируется код 2. Выдается ошибка :
error: #include expects "FILENAME" or
exit status 1
#include expects "FILENAME" or
Помогите разобраться.
Там была опечатка в начале кода. Я исправил, попробуйте теперь