КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Сборка HEXAPOD. Электроника + Калибровка

Введение:

Установка и подключение электроники HEXAPOD, является заключительным этапом сборки.

Видео:

Нам понадобится:

  • Arduino UNO х 1шт.
  • Trema Power Shield х 1шт.
  • Крепежи.
    • Стойка x 4шт.
    • Винт x 4шт.
    • Гайка x 4шт.
  • Источник питания. (подробнее в разделе питание)

Для реализации проекта нам потребуется библиотека Servo, которая входит в стандартный набор библиотек Arduino IDE (её не требуется скачивать).

Схема подключения:

Сначала нужно закрепить Arduino Uno, при помощи крепежей, на Hexapod. Далее на Arduino Uno устанавливается Trema Power Shield, к которому подключаются выводы сервоприводов в соответствии с таблицей:

Сервоприводы Trema Power Shield
1 конечность Горизонтальный сустав (№ 0) вывод 2 (можно изменить)
Вертикальный сустав (№ 1) вывод A0 (можно изменить)
2 конечность Горизонтальный сустав (№ 2) вывод 3 (можно изменить)
Вертикальный сустав (№ 3) вывод A1 (можно изменить)
3 конечность Горизонтальный сустав (№ 4) вывод 4 (можно изменить)
Вертикальный сустав (№ 5) вывод A2 (можно изменить)
4 конечность Горизонтальный сустав (№ 6) вывод 5 (можно изменить)
Вертикальный сустав (№ 7) вывод A3 (можно изменить)
5 конечность Горизонтальный сустав (№ 8) вывод 6 (можно изменить)
Вертикальный сустав (№ 9) вывод A4 (можно изменить)
6 конечность Горизонтальный сустав (№ 10) вывод 7 (можно изменить)
Вертикальный сустав (№ 11) вывод A5 (можно изменить)
  • Если Вы подключите сервоприводы к другим выводам Arduino Uno, то их нужно изменить в строке скетча где определяется массив pinServo. Номер элемента массива соответствует номеру сустава, а значение элемента массива соответствует номеру вывода Arduino Uno к которому подключён сервопривод этого сустава:
const uint8_t pinServo[12] = {2, A0, 3, A1, 4, A2, 5, A3, 6, A4, 7, A5};
Схема паука на Arduino Uno - Hexapod

Питание:

12 сервоприводов потребляют значительный ток, который не сможет выдать USB порт компьютера. Питание от внешнего источника через Arduino UNO приведёт к значительной нагрузке на её стабилизатор. Вот почему мы предлагаем воспользоваться Trema Power Shield, который снабжен мощным стабилизатором и позволяет выбирать различные схемы питания. Источник питания на 7-12 В постоянного тока подключается к коннектору «VinS» Trema Power Shield (не перепутайте полярность), а джампер (перемычка) устанавливается в положение «Общ. Vin». В качестве источников питания могут быть использованы адаптеры на 7-12 В с током не менее 1 А, а так же батарейные или аккумуляторные отсеки.

Пример кода программы:

#include <Servo.h>          /*   Г    В    Г    В    Г    В    Г    В    Г    В    Г    В  */  // Подключаем библиотеку Servo. Буквы в комментарии указывают на плоскость вращения сервопривода (Горизонтальная / Вертикальная)
Servo         objServo[12]; /*   0    1    2    3    4    5    6    7    8    9   10   11  */  // Создаём массив, каждый элемент которого является объектом библиотеки Servo. Цифры в комментарии указывают на № сервопривода
const uint8_t pinServo[12]  ={   2,  A0,   3,  A1,   4,  A2,   5,  A3,   6,  A4,   7,  A5  };  // Определяем массив хранящий номера выводов к которым подключены сервоприводы (можно менять)
const int     cenAngle[12]  ={  90,  90,  90,  90,  90,  90,  90,  90,  90,  90,  90,  90  };  // Определяем массив хранящий углы в градусах, при которых сервоприводы находятся в центральном положении (КОРРЕКТИРУЕТСЯ В КАЛИБРОВОЧНОМ СКЕТЧЕ)
const int     minAngle[12]  ={  30,  30,  30,  30,  30,  30,  30,  30,  30,  30,  30,  30  };  // Определяем массив хранящий углы в градусах, на которые отклоняются сервоприводы от центрального положения назад или вниз
const int     maxAngle[12]  ={  30,  30,  30,  30,  30,  30,  30,  30,  30,  30,  30,  30  };  // Определяем массив хранящий углы в градусах, на которые отклоняются сервоприводы от центрального положения вверх или вперёд
void          funLimbMove    ( uint8_t, bool, int8_t );                                        // Объявляем Функцию установки суства конечности в значение от -100 до 100 (конечность 1-6, сустав 0/1, положение -100...+100)
void          funLimbStep    ( uint8_t, uint8_t );                                             // Объявляем Функцию установки всей конечности в положение от 0 до 255     (конечность 1-6, положение 0...255)
void          funLimbFree    ( void );                                                         // Объявляем Функцию ослабления всех суставов                              (без параметров)
void          funLimbGait    ( uint8_t, uint8_t );                                             // Объявляем Функцию выбора походки                                        (тип походки 0-4, положение 0...255)
int           limWidth      = 0;                                                               // Определяем переменную для выбора направления движения                   (-100 влево, +100 вправо, 0 прямо)
uint8_t       limHeight     = 100;                                                             // Определяем переменную для ограничения высоты хексапода                  (0 ползком, 100 на высоте)
uint8_t       a             = 1;                                                               // Скорость и направление (чем быстрее меняется значение тем выше скорость, если значение увеличивается - значит вперёд, если значение уменьшается - значит назад)
uint8_t       b             = 1;                                                               // Варианты движений
                                                                                               //
void setup(){                                                                                  //
     for(uint8_t i=1; i<=6; i++){                                                              // Устанавливаем 6 конечностей в центральные положения
         funLimbMove(i, 0, 0);                                                                 // Для конечности (i) устанавливаем горизонтальный (0) сустав в центральное положение (0)
         funLimbMove(i, 1, 0);                                                                 // Для конечности (i) устанавливаем вертикальный   (1) сустав в центральное положение (0)
}    }                                                                                         //
                                                                                               //
void loop(){                                                                                   //
     if(millis() %    5 == 0){a++;}                                                            // Увеличиваем значение переменной (a) на 1 за каждые 5 мс  (т.к. переменная типа uint8_t то она сама сбросится в 0 после значения 255)
     if(millis() % 5000 == 0){b++;} if(b>17){b=1;}                                             // Увеличиваем значение переменной (b) на 1 за каждые 5 сек ()
     if(b==1 ){limWidth=0;    limHeight=100; funLimbGait(0,     a);}                           // Поворачиваемся на месте влево
     if(b==2 ){limWidth=0;    limHeight=100; funLimbGait(0, 255-a);}                           // Поворачиваемся на месте вправо
     if(b==3 ){limWidth=0;    limHeight=100; funLimbGait(1,     a);}                           // Идём вперёд походкой 1
     if(b==4 ){limWidth=0;    limHeight=100; funLimbGait(2,     a);}                           // Идём вперёд походкой 2
     if(b==5 ){limWidth=0;    limHeight=100; funLimbGait(3,     a);}                           // Идём вперёд походкой 3
     if(b==6 ){limWidth=0;    limHeight=100; funLimbGait(4,     a);}                           // Идём вперёд походкой 4
     if(b==7 ){limWidth=0;    limHeight=100; funLimbGait(1, 255-a);}                           // Идём назад походкой 1
     if(b==8 ){limWidth=0;    limHeight=100; funLimbGait(2, 255-a);}                           // Идём назад походкой 2
     if(b==9 ){limWidth=0;    limHeight=100; funLimbGait(3, 255-a);}                           // Идём назад походкой 3
     if(b==10){limWidth=0;    limHeight=100; funLimbGait(4, 255-a);}                           // Идём назад походкой 4
     if(b==11){limWidth=0;    limHeight=50;  funLimbGait(2,     a);}                           // Идём вперёд походкой 2 с высотой 50% (пригнувшись)
     if(b==12){limWidth=0;    limHeight=10;  funLimbGait(2,     a);}                           // Идём вперёд походкой 2 с высотой 10% (ползём)
     if(b==13){limWidth=-100; limHeight=100; funLimbGait(2,     a);}                           // Идём вперёд походкой 2 сильно поворачивая влево
     if(b==14){limWidth=-50;  limHeight=100; funLimbGait(2,     a);}                           // Идём вперёд походкой 2 поворачивая влево
     if(b==15){limWidth=50;   limHeight=100; funLimbGait(2,     a);}                           // Идём вперёд походкой 2 поворачивая вправо
     if(b==16){limWidth=100;  limHeight=100; funLimbGait(2,     a);}                           // Идём вперёд походкой 2 сильно поворачивая вправо
     if(b==17){funLimbFree();}                                                                 // Отдыхаем
}                                                                                              //
                                                                                               //
// =========================================================================================== //
                                                                                               //
//   Функция выполнения походки по одному из возможных вариантов i                             //
void funLimbGait(uint8_t i, uint8_t j){                                                        //
     switch(i){                                                                                //
//       Разворот на месте:                                                                    // j= 0         42        85       127       170       212       255
         case 0:                                                                               //    |         |         |         |         |         |         |
             funLimbStep(1,     j);                                                            //  R | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(2, 85 -j);                                                            //  L | < < < < | < < < < | >>>>>>> | < < < < | < < < < | < < < < |
             funLimbStep(3, 170+j);                                                            //  R | > > > > | > > > > | > > > > | <<<<<<< | > > > > | > > > > |
             funLimbStep(4, 170-j);                                                            //  L | >>>>>>> | < < < < | < < < < | < < < < | < < < < | < < < < |
             funLimbStep(5, 85 +j);                                                            //  R | > > > > | <<<<<<< | > > > > | > > > > | > > > > | > > > > |
             funLimbStep(6, 255-j);                                                            //  L | > > > > | > > > > | > > > > | > > > > | >>>>>>> | < < < < |
         break;                                                                                //  R |         |         |         |         |         |         |
//       Походка №1 вперёд или назад:                                                         // j= 0         42        85       127       170       212       255
         case 1:                                                                               //    |         |         |         |         |         |         |
             funLimbStep(1,     j);                                                            //  R | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(2, 42 +j);                                                            //  L | <<<<<<< | > > > > | > > > > | > > > > | > > > > | > > > > |
             funLimbStep(3, 85 +j);                                                            //  R |         | <<<<<<< | > > > > | > > > > | > > > > | > > > > |
             funLimbStep(4, 127+j);                                                            //  L |         |         | <<<<<<< | > > > > | > > > > | > > > > |
             funLimbStep(5, 170+j);                                                            //  R |         |         |         | <<<<<<< | > > > > | > > > > |
             funLimbStep(6, 212+j);                                                            //  L |         |         |         |         | <<<<<<< | > > > > |
         break;                                                                                //    |         |         |         |         |         |         |
//       Походка №2 вперёд или назад:                                                         // j= 0         42        85       127       170       212       255
         case 2:                                                                               //    |         |         |         |         |         |         |
             funLimbStep(1,     j);                                                            //  R | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(2, 127+j);                                                            //  L | > > > > | > > > > | <<<<<<< | > > > > | > > > > | > > > > |
             funLimbStep(3, 42 +j);                                                            //  R | <<<<<<< | > > > > | > > > > | > > > > | > > > > | > > > > |
             funLimbStep(4, 170+j);                                                            //  L | > > > > | > > > > | > > > > | <<<<<<< | > > > > | > > > > |
             funLimbStep(5, 85 +j);                                                            //  R | > > > > | <<<<<<< | > > > > | > > > > | > > > > | > > > > |
             funLimbStep(6, 212+j);                                                            //  L | > > > > | > > > > | > > > > | > > > > | <<<<<<< | > > > > |
         break;                                                                                //    |         |         |         |         |         |         |
//       Походка №3 вперёд или назад:                                                         // j= 0         42        85       127       170       212       255
         case 3:                                                                               //    |         |         |         |         |         |         |
             funLimbStep(1,     j);                                                            //  R | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(2, 127+j);                                                            //  L | > > > > | > > > > | <<<<<<< | > > > > | > > > > | > > > > |
             funLimbStep(3, 170+j);                                                            //  R | > > > > | > > > > | > > > > | <<<<<<< | > > > > | > > > > |
             funLimbStep(4, 42 +j);                                                            //  L | <<<<<<< | > > > > | > > > > | > > > > | > > > > | > > > > |
             funLimbStep(5, 85 +j);                                                            //  R | > > > > | <<<<<<< | > > > > | > > > > | > > > > | > > > > |
             funLimbStep(6, 212+j);                                                            //  L | > > > > | > > > > | > > > > | > > > > | <<<<<<< | > > > > |
         break;                                                                                //    |         |         |         |         |         |         |
//       Походка №4 плывёт вперёд или назад:                                                  // j= 0         42        85       127       170       212       255
         case 4:                                                                               //    |         |         |         |         |         |         |
             funLimbStep(1,     j);                                                            //  R | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(2,     j);                                                            //  L | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(3,     j);                                                            //  R | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(4,     j);                                                            //  L | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(5,     j);                                                            //  R | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
             funLimbStep(6,     j);                                                            //  L | > > > > | > > > > | > > > > | > > > > | > > > > | <<<<<<< |
         break;                                                                                //    |         |         |         |         |         |         |
     }                                                                                         //
}                                                                                              //
//   Функция установки всей конечности в положение от 0 до 255:                                //
void funLimbStep(uint8_t num, uint8_t pos){                                                    // Аргументы функции: (num) - номер конечности от 1 до 6 , (pos) - позиция от 0 до 255
     int i, j;                                                                                 // Объявляем переменные (i) - для
     if(pos < 213){i = map(pos,   0, 212, +100, -100); }else                                   // Сустав конечности поворачивается назад                            (+100 >>> -100)
                  {i = map(pos, 213, 255, -100, +100); }                                       // Сустав конечности поворачивается вперёд                           (-100 >>> +100)
     if(pos < 213){j =                    -100;        }else                                   // Сустав конечности опущен                                          (-100)
     if(pos < 224){j = map(pos, 213, 223, -100, +100); }else                                   // Сустав конечности поднимается вверх                               (-100 >>> +100)
     if(pos < 246){j =                    +100;        }else                                   // Сустав конечности поднят                                          (+100)
     if(pos < 256){j = map(pos, 246, 255, +100, -100); }                                       // Сустав конечности опускается вниз                                 (+100 >>> -100)
     if(limWidth<0 && num%2==0){ i = map(i, -100, +100, -(100+limWidth)   , 100+limWidth);}    // Ограничиваем  угол (i) горизонтального сустава левых  конечностей (поворот влево)
     if(limWidth>0 && num%2==1){ i = map(i, -100, +100, -(100-limWidth)   , 100-limWidth);}    // Ограничиваем  угол (i) горизонтального сустава правых конечностей (поворот вправо)
                                 j = map(j, -100, +100, limHeight*(-2)+100, 100         );     // Ограничиваем  угол (j) вертикального   сустава любых  конечностей (высота хексапода)
     funLimbMove(num, 0, i);                                                                   // Устанавливаем угол (i) для горизонтального (0) сустава конечности (num)
     funLimbMove(num, 1, j);                                                                   // Устанавливаем угол (j) для вертикального   (1) сустава конечности (num)
}                                                                                              //
//   Функция установки одного суства конечности в значение от -100 до 100:                     //
void funLimbMove(uint8_t num, bool joint, int8_t pos){                                         // Аргументы функции: (num) - номер конечности от 1 до 6 , (joint) - тип сустава 0 (горизонтальный) или 1 (вертикальный) , (pos) - положение сустава от -100 (внизу-сзади) до +100 (вверху-спереди)
     uint8_t   i = (num-1) * 2 + joint;                                                        // Определяем № сервопривода (i) по № конечности (num) и типу сустава (joint)
     int       k = 0, j = pos? cenAngle[i]:0;                                                  // Определяем переменные (j) и (k) для хранения экстремумов
     if(pos>0){k = +100; if(num%2==1){j-=maxAngle[i];}else{j+=maxAngle[i];}}                   // Находим (k) - максимально допустимое значение для аргумента (pos). Находим (j) - максимально допустимый угол в градусах.
     if(pos<0){k = -100; if(num%2==0){j-=minAngle[i];}else{j+=minAngle[i];}}                   // Находим (k) - минимально  допустимое значение для аргумента (pos). Находим (j) - минимально  допустимый угол в градусах.
     if(!objServo[i].attached()){objServo[i].attach(pinServo[i]);}                             // Подключаем объект (objServo) работающий с сервоприводом (i) к выводу (pinServo[i])
         objServo[i].write(map(pos, 0, k, cenAngle[i], j));                                    // Устанавливаем сервопривод (i) в угол находящийся между центром (cenAngle[i]) и экстремумом (j)
}                                                                                              //
//   Функция освобождения конечностей:                                                         //
void funLimbFree(void){                                                                        // Аргументы функции: отсутствуют
     for(uint8_t i=0; i<12; i++){                                                              // Проходим по 12 суставам 6 конечностей
         objServo[i].detach();                                                                 // Отключаем объект (objServo) работающий с сервоприводом (i) от вывода к которому он был подключён
         digitalWrite(pinServo[i],LOW);                                                        // Устанавливаем на отключённом выводе (pinServo[i]) низкий (LOW) логический уровень (в целях безопасности)
}    }                                                                                         //

Управление:

Если воспользоваться предложенным кодом, то управление хексаподом сводится к тому, что в коде loop должна постоянно вызываться функция funLimbGait, которая принимает два параметра: тип походки (значение от 0 до 4) и позиция (значение от 0 до 255). Если значение позиции меняется - хексапод идёт, если не меняется - стоит. Функция содержит 5 типов походки (от 0 до 4) смысл которых заключается в том, что у каждой походки своя последовательность движений конечностями. Каждая походка состоит 256 позиций (от 0 до 255), перебирая всю последовательность позиций, мы заставляем идти хексапода (как перебирая номера кадров, создаём анимацию), чем быстрее меняется значение позиции - тем быстрее идёт хексапод. Если значение позиции увеличивать, то хексапод пойдёт вперёд, а если уменьшать, то назад.

Например:

if(millis() % 5 == 0){i++;} // Увеличиваем i на 1 за каждые 5 мс (это позиция походки)
if(i>255){i=0;}             // Сбрасываем i в 0, т.к. позиция может принимать значение от 0 до 255
funLimbGait(3, i);          // Идём вперёд походкой № 3 (все конечности совершат полный цикл своего хода за время пока i увеличивается от 0 до 255, далее i сбросится в 0 и цикл повторится)
if(millis() % 9 == 0){i++;} // Увеличиваем i на 1 за каждые 9 мс (в этом примере значение переменной i увеличивается медленнее)
if(i>255){i=0;}             // Сбрасываем i в 0, т.к. позиция может принимать значение от 0 до 255
funLimbGait(3, i);          // Идём вперёд походкой № 3 (теперь хексапод будет идти медленнее чем в предыдущем примере)
if(millis() % 5 == 0){i--;} // Уменьшаем i на 1 за каждые 5 мс (в этом примере i не увеличивается, а уменьшается)
if(i<0){i=255;}             // Устанавливаем i в 255, т.к. позиция может принимать значение от 0 до 255
funLimbGait(3, i);          // Идём назад походкой № 3 (хексапод пойдёт назад, т.к. все суставы будут совершать свои движения в обратном порядке, как при перемотке анимации назад)

Еще есть две переменные: limWidth (принимает значения от -100 до +100) и limHeight (принимает значения от 0 до 100) которые позволяют хексаподу не просто идти при помощи функции funLimbGait, а еще пригибаться и поворачивать. Переменная limWidth отвечает за повороты при ходьбе (-100 - влево, ... , 0 - прямо, ... , +100 - вправо), а переменная limHeight отвечает за высоту хексапода при ходьбе (0 - ползёт ... 100 - приподнят). В коде loop приведены 17 примеров с использованием некоторых значений переменных limWidth и limHeight, а так же аргументов функции funLimbGait.

Калибровка:

Калибровка выполняется только 1 раз, после сборки хексапода.

При сборке хексапода невозможно установить качалки всех сервоприводов с точностью до градуса, вот почему в предложенном скетче имеется массив cenAngle. Номера элементов массива соответствуют номерам суставов, а значения элементов массива являются углами сервоприводов при которых суставы конечностей находятся в центральном положении. Калибровка заключается в том, что бы заменить углы по умолчанию 90°, на те которые действительно соответствуют центральным положениям суставов.

const int cenAngle[12] = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; // Определяем массив хранящий углы в градусах, при которых сервоприводы находятся в центральном положении (КОРРЕКТИРУЕТСЯ В КАЛИБРОВОЧНОМ СКЕТЧЕ)

Можно последовательно менять значения каждого элемента массива и загружать скетч с пустым кодом loop, повторяя эту процедуру по несколько раз для каждого сервопривода Вы найдёте значения для всех суставов и заполните массив действительными значениями. Но есть способ проще - воспользоваться калибровочным скетчем, который выдаёт значения всех элементов массива в монитор последовательного порта после каждого сдвига конечности. Загрузите калибровочный скетч и откройте монитор последовательного порта. Вводя числа от 0 до 11 Вы выбираете сустав, а вводя символы + или - Вы сдвигаете выбранный сустав. После каждого сдвига сустава, в мониторе высвечивается строка с указанием текущего угла выбранного сустава и результатом в виде всего массива cenAngle. После установки всех суставов в центральные положения, скопируйте результат, заменив им строку определяющую массив cenAngle основного скетча (представлена выше), сохраните этот (основной) скетч и загрузите его, на этом калибровка будет завершена и калибровочный скетч больше не понадобится.

Код калибровочного скетча:

#include <Servo.h>
Servo objServo[12];
const uint8_t pinServo[12]={2, A0, 3, A1, 4, A2, 5, A3, 6, A4, 7, A5}; int cenAngle[12]={90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90}; uint8_t i, f, numServo=0;
void setup(){ Serial.begin(9600); Serial.println(F("ВВЕДИТЕ:\r\n0...11 - выбор номера сустава\r\n+      - сдвиг сустава вверх или вперёд на 1°\r\n-      - сдвиг сустава вниз  или назад  на 1°\r\n*      - освободить все суставы (выключить сервоприводы)\r\n?      - подсказка\r\n========================================================"));}
void loop(){
  if(Serial.available()>0){
    i=f=0; while(Serial.available()){switch(Serial.read()){case '+': if(objServo[numServo].attached() && cenAngle[numServo]<255){if(numServo/2%2){cenAngle[numServo]++;}else{cenAngle[numServo]--;}} f=1; break; case '-': if(objServo[numServo].attached() && cenAngle[numServo]>0  ){if(numServo/2%2){cenAngle[numServo]--;}else{cenAngle[numServo]++;}} f=1; break; case '0': i*=10; i+=0; f=2; break; case '1': i*=10; i+=1; f=2; break; case '2': i*=10; i+=2; f=2; break; case '3': i*=10; i+=3; f=2; break; case '4': i*=10; i+=4; f=2; break; case '5': i*=10; i+=5; f=2; break; case '6': i*=10; i+=6; f=2; break; case '7': i*=10; i+=7; f=2; break; case '8': i*=10; i+=8; f=2; break; case '9': i*=10; i+=9; f=2; break; case '*': f=3; break; case '?': f=4; break;} delay(10);}
    if(f==1){objServo[numServo].write(cenAngle[numServo]); Serial.print((String) "Сустав N "+numServo+", угол = "+cenAngle[numServo]+"°"); if(cenAngle[numServo]<10){Serial.print("  ");}else if(cenAngle[numServo]<100){Serial.print(" ");} Serial.print(F(" РЕЗУЛЬТАТ: const int cenAngle[12]={")); for(f=0; f<12; f++){Serial.print(cenAngle[f]); if(f<11){Serial.print(",");}} Serial.println("};");}
    if(f==2){if(i<12){numServo=i; f=i%2; if(!objServo[numServo].attached()){objServo[numServo].attach(pinServo[numServo]);} objServo[numServo].write(cenAngle[numServo]); Serial.println(F("===========================================================")); Serial.println((String) "УСТАНОВКА СУСТАВА № "+numServo+": ("+(f?"вертикальный":"горизонтальный")+" сустав "+(numServo/2+1)+" конечности)"); Serial.println(F("==========================================================="));}}
    if(f==3){for(f=0; f<12; f++){objServo[f].detach(); digitalWrite(pinServo[f],LOW);} Serial.println(F("===========================================================\r\nВСЕ СУСТАВЫ ОСВОБОЖДЕНЫ!\r\n==========================================================="));}
    if(f==4){Serial.println(F("===========================================================\r\nВведите № сустава от 0 до 11 включительно (заработает его сервопривод)\r\nВводя знаки + или - установите сустав в центральное положение\r\nКаждый знак + или - соответствует сдвигу сустава на 1°\r\nНапример, если ввести ++++++ то сустав сдвинется на 6°\r\nПосле каждого сдвига высвечивается угол сустава и общий результат\r\nКогда Вы отцентруете положение всех суставов, вставьте последний\r\nполученный общий результат вместо 4 строки основного скетча\r\n==========================================================="));}
  }
}

Примечание:

Калибровочный скетч выводит информацию на Русском языке, что доступно только в версиях Arduino IDE 1.8.2 и выше!

Управление сервоприводами происходит с использованием библиотеки Servo, которая работает с ограниченным количеством сервоприводов (по 12 на каждый шестнадцатиразрядный таймер). В Arduino UNO имеется всего 1 такой таймер, и логично предположить, что библиотека Servo не сможет работать с дополнительными сервоприводами (управляющими различными манипуляторами, захватами и т.д.) так как 12 уже используются для управления конечностями хексапода, но это можно исправить:

Откройте файл «Servo.h» из папки «папка_программы_arduino \ libraries \ Servo \ src» в любом текстовом редакторе, найдите в нём строку «#define SERVOS_PER_TIMER 12» и замените цифру 12 на количество сервоприводов которое Вы желаете использовать, сохраните файл «Servo.h». Теперь библиотека Servo будет работать с указанным Вами количеством сервоприводов.

Ссылки:




Обсуждение

Гарантии и возврат Используя сайт Вы соглашаетесь с условями