[Из песочницы] Женим Ардуино с Лего и строим первобота

Захотелось мне увлечь своего ребенка техникой и приобщить к программированию. Чтобы не только виртуальные дома в майнкрафте строил, но и ручками поработал. Просто программировать абстрактные задачи — для взрослых людей не увлекательное занятие, что уж говорить про детей. Надо чтобы для наглядности все моргало и шевелилось по нашему желанию.

Было решено взять ардуинку, а там видно будет…

В первую очередь оговорюсь, что ребенок тут чисто для присказки, самому давно Ардуинку и железки потрогать хотелось. А тут такой комфорт настал — заказывай, что пожелаешь, паять практически ничего ненадо. Только глаза разбегаются и дурные идеи спать не дают.

Для начала была куплена сама плата Arduino UNO, плюс ворох всякой рассыпухи, чтобы было под рукой. Все это, за копейки, в ожидаемые сроки, приехало от извесных китайских друзей.

Потратив вечер на объяснение основ электричества с проводами, выключателями, светодиодами и простейшими датчиками стало понятно — тупик близок. Интереса у ребенка хватило на первые 30 минут. Дальше задор таял на глазах. Надо переходить к решению более сложных вопросов.

Делаем робота! (чтобы за пивом к кладовку бегал)

Примеров в интернете куча, как-нибудь справимся. Все-таки папа — Инженер (ИТ). Была бы цель и вера в светлое роботизированное будущее.

Опять шерстим магаз — стандартные колесные платформы — «как у всех» или уже из разряда не бюджетных игрушек. Итог будет как с управляемыми машинками — несколько дней поиграть да потом еще раз от раза. Не спортивно как-то.

»Да у нас Леговских деталей — вагон» — говорит мое второе я, не желающее выходить из детского возраста.

Ок, па-проблем, вот задача минимум:


  • Будем строить робоплатформу на леговских деталях с ардуино мозгами.
  • Только стандартный наборы кубиков, да россыпь от Лего-техник, планки и соединения. (Не, майндсторма у нас нету. Жаба душит.)
  • Мотоцыклетные колеса будем крутить индивидуально, плюс третье — мелкое, для поддержки.
  • Как-то адаптируем бюджетные степ-моторы и сервы от Али под Лего.
  • Что б был автономным насколько это возможно, а не разряжался через 10 минут.
  • Во. И управлять что б с телефона.

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

1) Андроид телефон по блютуфу будет управлять роботом. Все просто.

Берем блютуф HC-06 платку с приемо-передатчиком. На телефоне запускаем приложение из маркета — «Bluetooth RC Controller».
Комманд — более чем достаточно для начала. Будем ловить нажатые на телефоне кнопки и что-нибудь программить.

2) Питание. Попробовали колодки с 6-ю АА батарейками, адаптер под Крону…

От Кроны ардуина уходила в ребут (может конечно не контакт в разъеме). Блок с батарейками как-то много места занимал, да и батареек/аккумуляторов не на пасешься. В итоге взяли блок под два Li-ion аккумулятора. Пишут 9900 mAh 3.7V. Получилось питание чуть больше 7 вольт на ардуинку с обвесом на ХЗ сколько-то Ампер-часов.

3) Были самые дешевые степ моторы 28BYJ-48 и микро серво SG90. Их то и стали адаптировать под лего.


Micro Servo 9g SG90 Lego-адаптация.

Спиливаем мушки ушки у серво. Они нам только мешают определиться с выравнием.

Строим выравнимающий стенд. Размеры бокса у серво SG90 вписываются:


  • по высоте идеально совпадает с высотой 2-х стандартных лего блоков и еще пластинка высотой ⅓ блока,
  • по ширине чуть меньше 2-х лего-клеток. Отцентровываем с помощью выступов «ракетниц» (LEGO Part 61184 — Technic Pin ½ with 2L Bar Extension).
  • по глубине чуть меньше 3-х лего-клеток. Выравниваем по лицевой рабочей части сервы.

13083570f3524536bf3244beeb2b1b48.jpg

Ось серво совпадает при этом с дырчатыми лего блоками. Значит, исходя из геометрии — совпадет и с зубчатыми передачами. Это на будущее.

Последние замеры и сажаем на клей лего крепеж:


  • вниз 2×2 гладкую пластинку (LEGO Part 3068 — Tile 2×2),
  • на верх 2×3 пластинку (LEGO Part 3021 — Plate 2×3).

2bb536f77f9c4c1f9540185f17a50c7f.jpg

Разбираем стенд до следующего раза, сохраняя предварительно инструкции.

В итоге серво может уже встать на любую площадку из лего блоков или прикрепиться к планкам лего-техникс через переходники.


4b454227699743dc971fea67f0ef18f2.jpg


Step Motor 28BYJ-48 5V Lego-адаптация

У моторчика металические крепежные ушки. Основная проблемма была найти «золотое» сечение для ушек и собрать устойчивый к стрессам каркас. Крепится без клея. «Ракетницы» вставленные в черный круглый соединитель (LEGO Part 2780 — Technic Pin) дают необходимую жесткость. По периметру обстраивается каркас из уголков лего-техникс.


edf29b6b2354431eae3ba8042c6a6ab1.jpg

Зеркально строится каркас на 2-е колесо.

4) Ось степ-мотора жестко вставляется в круглые дырки лего-техникс.

Я использовал LEGO Part 32523 — Technic Beam 1×3 Thick для передачи момента на мотоколеса. Крепим колеса на степ-моторы. Исходя из их радиуса прикидываем размеры нашего будущего робота.

5) Собираем робо-платформу.


  • Соединяем мотоколеса площадкой для батарейного отсека.
  • Платки с ULN2003 для степ-моторов встают в распор между деталями.
  • Добавляем третье колесо для опоры.
  • Делам впереди посадочное место для серво.
  • Сверху крепим на площадку Deek-Robot шилд с Arduino NANO, а UNO пока оставим про запас.

6) Разбираемся с управлением этим всем хозяйством с Ардуинки.

В основном все по примерам. Достаточно просто. Приняли комманду — выполнили действие. Колеса решено было крутить с независимыми скоростями. Этим добились эффекта что платформа может и на месте развернуться и по дуге поворачивать.

Вот неприятные мелочи, что решились параллельно со строительством Лего-платформы:


Блютуф фонит на всех GPIO портах (кроме Serial RX/TX).

Ну как фонит. Если блютуф в ожидании/поиске то все номально. При установленом соединении — серво начинает «дрожать».
Как советуют в интернете — повесить серво мотор на отдельное питание, и там что-то еще с резисторрами, мне не помогло.
Если блютуф присоединен на Serial RX/TX, то никакого побочного эффекта не наблюдается вовсе. На этом пока и остановились.


Степ-мотор 28BYJ-48 на стандартной stepper — библиотеке не работает на реверс.

Проблемма, как оказалось, известная. Надо использовать корректные последовательности для переключения шагов.
Решается без заморочек с помощью http://playground.arduino.cc/Main/CustomStepper


Степ-моторы 28BYJ-48 из разных партий или поставщиков крутятся в разные стороны.

Это из разряда мистики. Одинаковый код, одинаковое (внешне) подключение.
Один крутится по часовой стрелке, другой против часовой стрелки…

Итог:

Поигрались в Лего. Поразобрались с Ардуино и некоторой переферией. Нашли дешевую альтернативу лего-майндсторму.
Получилась вполне рабочая платформа для дальнейших игрушек с Ардуино.

Что дальше?

Прицепить на серво карандаш и научить тележку рисовать. Благо что степ моторы позволяют сориентировать платформу на местности с минимальными погрешностями.

Минутка видео с покатушками:



Небольшой скетч — покрутить ассинхронно колесами
#include 

int lSpeed = 4;
int rSpeed = 4;
int maxSpeed = 16;

const char bNone =  0;
const char bFwd  =  2;

byte tSteps[] = {8, B1000, B1100, B0100, B0110, B0010, B0011, B0001, B1001};

CustomStepper stepR(4,  5,  6,  7, (byte *)&tSteps, 4075.7728395, maxSpeed, STOP);
CustomStepper stepL(8,  9, 10, 11, (byte *)&tSteps, 4075.7728395, maxSpeed, STOP);

#define BT Serial
enum {
  jF = 'F', // Forward
  jB = 'B', // Back
  jL = 'L', // Left
  jR = 'R', // Right
};

int incSpeed(int I, int i)
{
  I = I + i;
  if (I > maxSpeed) I = maxSpeed;
  else if (I < -maxSpeed) I = -maxSpeed;
  return I;
}

// Process steppers
void stepRun()
{
  if (!stepL.isDone()) stepL.run();
  if (!stepR.isDone()) stepR.run();
}

// change steppers speeds independently
void stepRotate(char L, char R)
{ // owercode here
  if (L != bNone)
  {
    lSpeed = incSpeed(lSpeed, L);
    if (lSpeed == 0)
      stepL.setDirection(STOP);
    else
    {
      stepL.setRPM((lSpeed > 0) ? lSpeed : - lSpeed);
      stepL.setDirection((lSpeed > 0) ? CW : CCW);
      if (stepL.isDone())
        stepL.rotate();
    }
  }

  if (R != bNone)
  {
    rSpeed = incSpeed(rSpeed, R);
    if (rSpeed == 0)
      stepR.setDirection(STOP);
    else
    {
      stepR.setRPM((rSpeed > 0) ? rSpeed : - rSpeed);
      stepR.setDirection((rSpeed > 0) ? CCW : CW);
      if (stepR.isDone())
        stepR.rotate();
    }
  }
  stepRun();
}

void setup() {
  BT.end();
  BT.begin(9600);
}

void loop() {
  switch (BT.read())
  {
    case jF: stepRotate( bFwd,  bFwd);  break;
    case jB: stepRotate(-bFwd, -bFwd);  break;
    case jL: stepRotate(-bFwd,  bFwd);  break;
    case jR: stepRotate( bFwd, -bFwd);  break;
  }

  stepRun();
}

PS. Да, вижу что не идеально. Есть к чему стремиться и что переписать.

© Geektimes