ARDUINO Робот LAHU гоняется за лазером (Ардуино НАНО с камерой 7670)

Хочу такого робота

  • Куплю набор.

    Голосов: 1 100.0%
  • Соберу сам.

    Голосов: 0 0.0%
  • Не понравился.

    Голосов: 0 0.0%

  • Всего проголосовало
    1
  • Опрос закрыт .

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
Небольшой робот гоняется за лазерным зайчиком аки кот…
DIY проект.
Шустренький, веселый робот сделан из Ардуино НАНО и камеры OV 7670.
Камера в режиме VGA 640*480. 10 кадров в секунду. Скетч -1 кб.
Если скучно на локдауне, можете сами построить.
Деталюшек на 20-30$.
Собрать не сложно, но для настройки требуются некоторые познания… ;-)

Вот фотки робота.

Вариант 1. В виде неведомой зверушки.

MEX_STOL.png

Вариант 2. Роботенок LAHU (Laser Hanter)

LAHU_1.png LAHU_2.JPGLAHU_KOMP.pngLAHU_VERX.pngLAHU_NIZ.png


Видео ролик, как они бегают.




Зверушка - шустрая и бюджетная.
Основа-шасси и движок с колесами от игрушки «Бешеный гонщик» из Fix Price за 3$
Ардуино НАНО.
Камера OV7670.
Серво типа MG995.
Серво типа MG90S-1шт. (Синенькие крайне не рекомендую.)
Драйвер для мотора.
Макетная плата 50*70мм.
Любимый регистр сдвига 74НС595.
М/с КР1533ЛИ6 (2*4И) (10руб.)
Маленький выключатель.
Немножко резисторов.
Проводочки, винтики. Термоклей. Батарейки ААА.
Шуба норковая. (Можно немного б\у.)

Роботенок LAHU – подороже.
Шасси- акрил (фанерка)2,5-3 мм . Чертеж – ниже.
Мотор редуктор Ардуино, с креплением.
Драйвер для мотора.
Колеса диаметром 3-5 см (4-8 шт) (Стандартные Ардуино слишком большие и тяжелые.)
Оси нержавеющие 2,5мм L=90мм 1 шт. 40 мм-2 шт.
Ардуино НАНО.
Камера OV7670 с креплением.
Разъемы 2,54.
Серво типа MG995-1шт.
Серво типа MG90S-1шт. (Синенькие крайне не рекомендую.)
Макетная плата 50*70мм.
М/с КР1533ЛИ6 и 74НС595.
Маленький выключатель.
Провод силикон AWG 30 или аналог. 2м
Отсек и аккум. 2шт. 18650(14500).
Винтики, стойки. Двухсторонний толстый скотч.

Заранее смотрим внимательно на фотки, может что забыл…

XIKS.jpg

Чертеж шасси. Печатаем в размер на бумаге, приклеиваем на акрил и вырезаем сами. Или заказываем гравировщиков.

шасси.gif

Базовая схема робота. Паяем на макетке.

shem_LAHU.gif

Как это работает.

Алгоритм простой:

На самом деле, цвет зайчика для камеры – белый, так как очень яркий.
Включаем формат вывода данных с камеры YCbCr 4:2:2 YUYV.
Получаем каждый второй байт – яркость. Белый цвет – последовательность FF(hex) через байт.
Зайчик- последовательность из 4х таких байт.
Берем четыре старших бита данных с камеры + операция 4И.
Получили последовательность бит. Для зайчика будет 1x1x1x1x .
Загоняем ее в регистр сдвига. На выходах регистра ставим опять элемент 4И(Через бит).
Зайчик даст 1 на выходе.
Это - прерывание для НАНО.

Нано ведет подсчет числа строк с начала кадра. В какой строке прерывание- там и зайчик.
Поэтому скетч маленький. Пофигу, какой видеопоток с камеры. Для нано – это всего 1 бит.
Режим - 10 кадров в секунду определяется быстродействием сервомашинок и скоростью робота.
Дергать машинки быстрее не получиться. Да и реакция человека такая -же. При мощном приводе
робот кидался на зайчика и я не успевал отвести лазер.
Можно замерять и время от начала строки – будет расстояние.


Камера установлена так, что строки идут по вертикали. По центру 240 строка. Угол обзора камеры 30 градусов.
Сервой вертим камеру +-30 градусов. Всего обзор будет 3*30 =90. Поворачиваем передние колеса пропорционально номеру строки.
Ловим зайку и включаем движок на всю.
Можно еще приделать УЗ(ИФ) дальномер(чтоб не биться о табуретки) и звуки с карточки.
Места для установки – рядом с большой сервой.
Как, что собрано – смотрим на фото.
Если собираете из игрушки: Выкидываете мотор переднего привода и крепите большую серву на небольшой пластиковой панельке.
Термоклей в помощь. К серве прикрутим передний мост игрушки. Потребуется ловкость рук.
Впереди обязательно нужен выступ, чтоб не биться камерой о препятствия.

Для увеличения угла обзора пробовал объектив «рыбий глаз» - не получается. Он сжимает зайчика меньше чем 4 пикселя.
Объектив на 60 градусов работает. (Объективы для смартфонов за копейки). Только крепить сложно.

Конец первой части.


Во второй части будет про скетч.



P.S.
Этот пост и робот DIY - для тех, кто хочет сам повозиться и поглубже разобраться с электроникой.

Я не торгую набором и запчастями робота.
Пока пишу вторую часть спрашиваем, голосуем.
 
Изменено:

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
Механический кот)
Камера справляется при дневном/ярком свете?
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Кто будет смотреть видео - берегите уши. Лучше заранее приглушить звук :)
в голосовалке нет моего варианта - робот понравился, но собирать и покупать не буду :)
 

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
@IamNikolay, Увы. Если лазерная указка для игр с животными, не справляется. :(
Рекомендуется гиперболоид Гарина.
Re//..берегите уши.. Пардон. Не расчитал..:eek:
 

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
640*480. Для такой схемы, чем больше, тем лучше. Дальше видит.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
Маловат обзор камеры, поэтому так плохо реагирует, нужно широкоугольную линзу ставить.
И скорость движения не сразу на полную давать, а постепенно разгоняться.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
Тогда получается , что камера будет реагировать на первый такой блик. причем высота его не будет играть роли. Или я не прав ?
 

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
@Геннадий П, Рыбий глаз не хочет работать. Далекий зайчик сжимается в один пиксель.
ШИМ тоже пробовал. Без него веселее. Тут важнее соотношение диаметра колес, оборотов и веса робота для динамики.
Мохнатый пошустрее был. У него более оборотистый редуктор и колеса больше. Иногда смешно буксовал, как кот при заносе.

@Старик Похабыч, Да. Но ширина блика только 3-4 строки. Это не важно.
В сумерках и на фонарик работает. Едет в сторону пятна. У меня указка с фонариком. Она круглое пятно в 10-20 см. дает.
 

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
Вероятно, случилось взаимонедопонимание.
:rolleyes:
Сектор обзора -360 гр. Поворачивайте серву на любой угол. Я крутил +-30.

Дальность обнаружения – это вертикальный угол установки камеры и размер зайчика от лазера.(Размер регулируется насадками.)
Робот смотрит с высоты в 10 см. Вы –со 150 см. Поставьте смартфон на пол и посмотрите картинку.
Скорость робота– обороты редукторадиаметр колеспи. Если слишком большая – включайте ШИМ.
Частота кадров для ловли зайки от 0 до 25. Я использовал 10 к/сек.
Что в скетче напишите, так и будет.
 

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
Часть 2.

С учетом Ваших добрых комментариев к части 1 - публикую алгоритм, полный скетч и библиотеку.(рабочие)

Алгоритм, для представления структуры скетча.
Подключаем библиотеки.
Устанавливаем пины.
Включаем генератор на 16 Мгц.
Переключаем в камеру OV7670 в нужный режим.
Ставим сервы в нулевое положение.

Ловим зайчика:
Ждем кадрового синхроимпульса.
Включаем прерывания по строкам и по зайке.
Считаем строки.

По ситуации

Не поймали зайку
Выключаем привод.
Сброс счетчика строк.
Поворачиваем камеру.
Запоминаем угол. Выставляем флаг поворота.
Идем ловить белочку.


Поймали зайку
Запомнили номер строки
Выключаем прерывания.
Считаем угол на зайку с учетом флагов.
Поворачиваем серво передних колес.
Включаем газ. Включаем свет и музыку. Передаем в порт .
Опять идем ловить зайку.
Скетч. Старался с комментариям.
LAHU_1.2 zip

Код:
*  LAHU_V1.2
*  Режим  VGA 640 х 480 // 15 кадров/сек // 8 мгц
Для  робота LAHU 2021г.
*/
// ------- БИБЛИОТЕКИ -------

#include <Servo.h>
#include <avr/io.h>
#include <util/delay.h>
#include <Wire.h>
#include <Lahu.h>

// ------- ПЕРЕМЕННЫЕ -------

Servo servoM; // для рулевого колеса
Servo servoK; // для камеры

  volatile unsigned long  tLp;    //  Время лазерной точки в прерывании
    volatile boolean        flSi;     //  Флаг строки
      volatile boolean        fLp;       //  Флаг точки
      

  unsigned long tK;                 //  Время начала кадра
    unsigned int KDR=0;                 // Номер кадра
      unsigned int Si;                  // Номер строки
        byte alfa;                        // Угол поворота колес
          byte fl_beta=1;                     // Флаг поворота камеры     
           unsigned int i=0;                  //Счетчик кадров
             byte n = 0;                        //Счетчик кадров на поворот камеры       

// --------- SETUP ----------

void setup() {
   Wire.begin();                   // I2C
   Serial.begin(2000000);           // Скорость порта
    setPIN();                         // Установка пинов
    setFr();                          // Включение генератора на 8  МГц на пин D11
    setCamera::startCAM();            // Установка камеры 15 кадров/сек при 8 мгц
}

// ---------- LOOP ----------
void loop() {
 // Serial.println("Вошли в луп");
  tK=0;
    tLp=0;
  // Обнаружение начала кадра по заднему фронту

while (digitalRead(8));          // Ждем низкого уровня  кадра
   while (!digitalRead(8));      // Ждем ВЫСОКОГО уровня  кадра
    i++;
      while (digitalRead(8));    // Ждем низкого уровня  кадра
 // Сброс флагов
    fLp=true;
      flSi=true;
        Si=1;
          tK=0;
            tK=micros();

  attachInterrupt(0, intSi,FALLING);    // Включаем прерывание подсчет строк - функция intSi
    attachInterrupt(1, intLp,RISING);    // Включаем прерывание с анализатора - функция intLp
      delayMicroseconds(4); // Очень важно !
   tLp=0;

for (;;) {
  if (flSi==false){
    Si++;
      flSi=true;
         }

  if (tLp >1) {
        KDR=i;
     //      Serial.println("К_№_ "+String(KDR)+" Л! " + String(Si));
      break;     
  }

if (Si >480) {
    //        Serial.println("Нет лазера!");
      break;
}
} // Конец ФОР

detachInterrupt(1);       //отключили прерывание  анализатора
    detachInterrupt(0);   //отключили прерывание  счета строк
if (Si<480) {
                alfa =(170 - (((Si+(480*fl_beta))/23)+54)); // Считаем угол. Серво перевернута, поэтому угол наоборот!
                    servoM.write(alfa);
                  Serial.println("Угол "+String(alfa)+" fl_B " + String(fl_beta)+" Si " + String(Si));
                        analogWrite(5,180);
                         n = 0;      // Сброс счетчика кадров на поворот камеры   
                   //       servoK.write(85);    // Поворот камеры прямо
                  
}else{         // Если нет зайчика в кадре крутим головой
        alfa =85;
          servoM.write(alfa);   
            analogWrite(5,0);
            
 if (n>4){     // Случайный поворот камеры       
              fl_beta=random(0, 3);
               servoK.write(60+(30*fl_beta));    // Поворот камеры случайно 90+-30
                n = 0;
 }else{
  n++;
  }
}
}
// --------- ФУНКЦИИ --------


void setPIN() {

  pinMode(2, INPUT);       // D2  Вход Прерывания cтроковые INT 0
    pinMode(3, INPUT);      // D3  Вход Прерывания с анализатора INT 1
      pinMode(8, INPUT);     // D8  Вход Кадровые синхроимпульсы
        pinMode(11, OUTPUT);    // D11  Выход генератора 8 МГц
 // Моторы
         pinMode(5, OUTPUT);     // D5 Ведущий мотор
            servoM.attach(6);        // D6 Сервопривод передних колес
              servoM.write(85);        // Прямое направление.Устанавливается при калибровке.
                delay(500);
                  servoK.attach(9);        // D9 Сервопривод камеры
                    servoK.write(90);        // Прямое направление.Устанавливается при калибровке.
                      delay(500);   
  Serial.println("Пины и выходы установлены!");
}
void setFr() { //  Устанавливает  8 MHz  на выходе  D 11
  TCCR2A = bit(COM2A0)| bit(WGM21) | bit(WGM20);
  TCCR2B = bit(WGM22) | bit(CS20);
  OCR2A =0;
  OCR2B =1;
  delay(3000);
}

void intSi() // Флаг начала строки
        {
 flSi=false;
}
void intLp() // Время лазерной точки
        {
  if (fLp) tLp = micros();
}

Библиотека с настройками камеры.
LAHU.zip
По скетчу.
Здесь робот крутит головой на случайный угол.
Забавно, но он при этом почему-то всегда умудряется отвернуться от куда Вы светите.
Через некоторое время рука сама тянется к тапку…


Закомментированные Serial.println полезны при отладке.
Про перевернутую серву –для камеры ось вверх, для колес -вниз. Еще они бывают правые и левые.(Угол отсчитывается по разному).
Генератор 8 Мгц. – читаем про регистры таймеров. Я лучше не объясню.


Про камеру OV 7670. Аж 200 настроечных регистров. Просто волшебна.
У нее даже адрес волшебный.
Покупаем, подключаем.
Открываем datashit “The device slave addresses are 42 for write and 43 for read”
Радостно пишем
Wire.beginTransmission(43) –увы, не работает.
Пишем 0х43 – то-же не работает. Понятно… «Хогвартс-экспресс» отправление с платформы 9 3/4 .

Интересно, а 43 с китайского на английском арабскими цифрами , по нашему по бразильски, это сколько?
Спрашиваю Алису – 0х21. Получатся из 67 вот так >>1. Ура - работает. И причем тут 43 ? ;)


И всего таких регистров 200. К счастью, при включении камера имеет стандартные настройки. Ничего не трогаем, изменяем только десяток нужных. (Настройки камеры - в библиотеке. )

cat.jpg

Если что-то непонятно - отвечу с удовольствием.
 

Вложения

_Valkiria_

✩✩✩✩✩✩✩
28 Июл 2023
1
0
Доброго времени суток!
Очень прикольный проект! Удивила его реализация)
А Вы пробовали считать пиксели в строке? Если да, то как Вы это реализовали? Очень уж интересно) 🤔
 

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
Считать пиксели Ардуино не успевает. Пробовал измерять время от начала строки до прерывания. Получается.+/_ 4 mks. Можно пересчитать в пиксели и вычислить расстояние до зайчика и регулировать скорость броска робота. Вообще Важно подобрать скорость робота. Если большая скорость, не успеваешь плавно вести лазер. Получаются резкие броски с проскоком зайчика. Приходиться стабилизировать напряжение на мотор колёс. Иначе все плывёт при разряде батареи.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
133
Считать пиксели Ардуино не успевает. Получается.+/_ 4 mks
То что написано ниже, просто размышления (я не работал с камерой 7670), как можно поднять точность определения в строке (надо это или нет - другой вопрос).

Можно попробовать захват значения таймера 1. (В даташите читать - Input Capture)

Настроить тактирование таймера 1 от внешнего сигнала = логическое И строчных и байтовых синхроимпульсов (насколько я понял - байтовые с/и идут постоянно). Сброс таймера 1 по прерыванию от кадрового синхроимпульса. Т.к. после этого импульса гарантированно очень большая пауза.
Может можно успеть сбросить и по прерыванию от заднего фронта строчного импульса тогда сразу получим номер в строке, без доп вычислений. Пауза после заднего фронта строчного импульса равна 144 Tp - вроде должно хватить, если я правильно понял значение Tp

Захват значения таймера делать по сигналу выхода анализатора яркой точки (в вашем примере подключенном к INT1). По номеру строки и захваченному значению таймера можно определить импульс в строке (если сбрасывали по кадровому с/и).

Но.
Для внешних тактовых импульсов, по даташиту требуется, чтобы их частота была < Fкварц/2 т.е. < 8 МГц.
А здесь тактовая частота камеры равна 8 МГц. Поэтому может будет работать, а может потребуется поделить ее на 2 внешней микросхемой.
Все, что написано выше - в предположении, что частота байтовых синхроимпульсов = XCLK = 8 МГц. И требует изучения работы с прерываниями.

(может быть можно перевести формирование тактов для XCLK на таймер 1 и не использовать внешнее тактирование таймера 1, но это видится более головоломным решением)
 

Sergikjet

✩✩✩✩✩✩✩
20 Ноя 2023
3
0
Доброго времени суток есть вопрос :
Компилятор ругается на этот блок:

void setFr() { // Устанавливает 8 MHz на выходе D 11

TCCR2A = bit(COM2A0)| bit(WGM21) | bit(WGM20);
TCCR2B = bit(WGM22) | bit(CS20);
OCR2A =0;
OCR2B =1;
delay(3000);
}
выдает : Compilation error: 'TCCR2A' was not declared in this scope
ну и соответственно далее по всему блоку
ошибки связаны с отсутствием объявления переменных, таких как TCCR2A, COM2A0, WGM21, WGM20, TCCR2B, WGM22, CS20, OCR2A и OCR2B.
Может Вы что то упустили в самом скетче?
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
133
@Sergikjet,
У Леонардо нет второго таймера. Нужно переделывать скетч. (Или купить нано).
Скетч написан для Нано (или UNO т.е ATmega328).
 

Sergikjet

✩✩✩✩✩✩✩
20 Ноя 2023
3
0
Действительно....чего то я и не подумал на плату.... скомпилировал для Нано -все эти ошибки ушли....
Ладно , купим теперь Нано - как раз на алике "черная пятница" ))). Скетч конечно тоже можно переписать , Leonardo у меня для экспериментов )))
Одним слово спасибо за ответы!!!! Вопрос закрыт.
 

Andre_L

✩✩✩✩✩✩✩
22 Окт 2021
9
8
Раз пошла такая пьянка....
Краткая история робота.

Изначально я хотел собрать из Ардуино и камеры спектрометр.
Спектрометр работать не хотел категорически. Я психанул и скрестил его с останками р/у самолетика и колесиками от тумбочки.
Оно сильно жужжало, еле ползало и пыль гоняло. Спектр снимать не хотело. Саморазобралось.
Скрещивание спектрометра с игрушкой "Бешенный гонщик" и звуковым модулем прошло успешнее.
Спектрометр носился по квартире за лазером. Лаял, мяукал, дико хохотал. Спектр снимать не хотел. Пугал жену.
Был убит шваброй.

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

В пандемию было скучно. Робот разваливался при встречах с табуреткой и сильно глючил.
Пришла идея сделать набор для сборки под отвертку.
Заказал 5 спаянных плат на pcbway. Нужно все скрутить и вставить в разъем НАНО и м/с 1533.
Аналог 1533 сильно смущал по быстродействию. К тому -же планарный. Заменить было -бы нельзя.
Красиво выпилить из акрила лобзиком шасси не получалось.
Заказал 5 у гравировщика. Остальное пришло в разных количествах под минимум затрат на транспорт.
На плате есть штырьки для подключения всяких датчиков и модулей к выводам ардуино.

Один робот убился при съемках ролика. Один был подарен.
Все заброшено.
Осталось три комплекта (почти полные), пылятся в ящике.
Отдам в добрые, нежные руки. По цене деталей.
Есть даже инструкция по сборке в pdf, с картинками.
 
  • Лойс +1
Реакции: Sergikjet