суббота, 30 января 2016 г.

EV3 НУ ПОГОДИ

Появление EV3 Basic пришлось для нас весьма кстати, наши последние EV3-проекты  стали слишком сложными для того, чтобы получать удовольствие от программирования в EV3-G. И, раз уж мы взялись за текстовое программирование, мы решили сделать что-нибудь стоящее, показывающее явные преимущества данной среды программирования. На глаза попалась электронная игра "Ну, погоди!", в которой волк ловит яйца и мы подумали - почему нет?

Для справки: «Ну, погоди!» («Электроника ИМ-02») —электронная игра, самая известная и популярная из серии первых советских портативных электронных игр с жидкокристаллическим экраном, производимых под торговой маркой «Электроника». Является неофициальным клоном Nintendo EG-26 Egg из серии Nintendo Game & Watch. Производилась с 1984 года





Инструкцию по сборке в двух форматах (LDD и PDF) можно скачать по ссылке. Для работы игры нужен только блок EV3, ИК-датчик и ИК-маяк - все остальное - не обязательные детали корпуса, который Вы можете собрать по своему вкусу.

Все файлы игры нужно скопировать с помощью EV3 Explorer (который входит в состав среды EV3 Basic) в память блока, в предварительно созданную папку volk.

Мы реализовали две версии игры, оригинальную "Волк яйца ловит" (запускать файл volk):



И версию с переработанной графикой, где Самоделкин ловит шестеренки:(запускать файл ks):


На видео ниже можно посмотреть, как работает наша игра:



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

player = 1
trigger = "True"
last = 0
Speed = 350  
score = 0
game_over = "False"
over = "True"
life = 3
level = 0
LCD.Clear()

Sensor.SetMode(4,2)

Speaker.Play(100,"/home/root/lms2012/prjs/volk/0")
LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/1")
Speaker.Wait()

' заполняем массивы нужными значениями
For i = 0 To 4
  m1[i] = 0
  m2[i] = 0
  m3[i] = 0
  m4[i] = 0
EndFor

x1[0] = 26
y1[0] = 44
x1[1] = 34
y1[1] = 49
x1[2] = 42
y1[2] = 54
x1[3] = 52
y1[3] = 61
x1[4] = 52
y1[4] = 120

x2[0] = 26
y2[0] = 72
x2[1] = 34
y2[1] = 77
x2[2] = 42
y2[2] = 82
x2[3] = 52
y2[3] = 89
x2[4] = 52
y2[4] = 120

x3[0] = 151
y3[0] = 44
x3[1] = 143
y3[1] = 49
x3[2] = 135
y3[2] = 54
x3[3] = 126
y3[3] = 61
x3[4] = 126
y3[4] = 120

x4[0] = 150
y4[0] = 73
x4[1] = 143
y4[1] = 77
x4[2] = 136
y4[2] = 82
x4[3] = 126
y4[3] = 89
x4[4] = 126
y4[4] = 120

' Запускаем подпроцесы
Thread.Run = logic
Thread.Run = screen
' отрисовка экрана
Sub screen
  While over
    If trigger = "True" Then    
      If player = 1 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl1")
      EndIf
      
      If player = 2 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl2")
      EndIf
      
      If player = 3 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl3")
      EndIf
      
      If player = 4 Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/vl4")
      EndIf
      
      
      For i = 0 To 4
        If m1[i] > 0 Then
          LCD.FillCircle(1,x1[i],y1[i],3)
        EndIf
        
        If m2[i] > 0 Then
          LCD.FillCircle(1,x2[i],y2[i],3)
        EndIf
        
        If m3[i] > 0 Then
          LCD.FillCircle(1,x3[i],y3[i],3)
        EndIf
        
        If m4[i] > 0 Then
          LCD.FillCircle(1,x4[i],y4[i],3)
        EndIf  
      EndFor
      
      LCD.Text(1,40,34,1,"Life-" + life + "   " + score)
      
      If game_over = "True" Then
        LCD.BmpFile(1,0,0,"/home/root/lms2012/prjs/volk/GO")
        Speaker.Note(100,"E4",3000)
        Speaker.Wait()
        Speaker.Note(100,"D4",3000)
        Speaker.Wait()
        Speaker.Note(100,"C4",3000)
        Speaker.Wait()
        Program.End()
      EndIf
      
      trigger = "False"
    EndIf
    
  EndWhile
EndSub
' процедура обработки яйца
Sub logic
  While over
    ' процедура увеличивания сложности игры
    Speed = 1000 / (0.03*score+1)
    
    ' процедура рождения яйца
    If EV3.Time > (last + (Speed*2)) Then
      If m1[0] = 0 And m1[1] = 0 And Math.Round(Math.GetRandomNumber(100)) = 10 Then
        m1[0] = EV3.Time
        last = m1[0]
        trigger = "True"
      EndIf
    EndIf
    
    If EV3.Time > (last + (Speed*2)) Then
      If m2[0] = 0 And m2[1] = 0  And Math.Round(Math.GetRandomNumber(100)) = 20 Then
        m2[0] = EV3.Time
        last = m2[0]
        trigger = "True"
      EndIf 
    EndIf
    
    If EV3.Time > (last + (Speed*2)) Then    
      If m3[0] = 0 And m3[1] = 0  And Math.Round(Math.GetRandomNumber(100)) = 30 Then
        m3[0] = EV3.Time
        last = m3[0]
        trigger = "True"
      EndIf 
    EndIf
    
    If EV3.Time > (last + (Speed*2)) Then      
      If m4[0] = 0 And m4[1] = 0  And Math.Round(Math.GetRandomNumber(100)) = 40 Then
        m4[0] = EV3.Time
        last = m4[0]
        trigger = "True"
      EndIf  
    EndIf
    
    ' цикл для перемещения яйца
    For i = 0 To 4
      If m1[i]  <> 0 And m1[i] + (Speed*(i+1)) < EV3.Time Then
        m1[i+1] = m1[i]
        m1[i] = 0 
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
      
      If m2[i]  <> 0 And m2[i] + (Speed*(i+1)) < EV3.Time Then
        m2[i+1] = m2[i]
        m2[i] = 0
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
      
      If m3[i]  <> 0 And m3[i] + (Speed*(i+1)) < EV3.Time Then
        m3[i+1] = m3[i]
        m3[i] = 0
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
      
      If m4[i]  <> 0 And m4[i] + (Speed*(i+1)) < EV3.Time Then
        m4[i+1] = m4[i]
        m4[i] = 0
        trigger = "True"
        Speaker.Note(100,"C4",150)
      EndIf
    EndFor
    ' Проверка на забирание яйца
    
    If m1[3] > 0 And player = 1 And m1[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m1[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    
    If m2[3] > 0 And player = 2 And m2[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m2[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    
    If m3[3] > 0 And player = 3 And m3[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m3[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    
    If m4[3] > 0 And player = 4 And m4[3] + (Speed*3.5) < EV3.Time Then
      score = score+1
      m4[3] = 0
      trigger = "True"
      Speaker.Note(100,"C5",250)
    EndIf
    ' Проверяем не упалоли яйцо
    
    If m1[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m1[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
    
    If m2[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m2[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
    
    If m3[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m3[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
    
    If m4[4] > 0 Then
      Program.Delay(1500)
      Speaker.Note(100,"E4",500)
      Speaker.Wait()
      Speaker.Note(100,"D4",250)
      Speaker.Wait()
      Speaker.Note(100,"C4",250)
      Speaker.Wait()
      
      life = life - 1
      If life = 0 Then
        game_over = "True"
      EndIf
      m4[4] = 0
      trigger = "True"
      Program.Delay(1500)
    EndIf
  EndWhile
EndSub
' процедура считывания покозаний ИК-датчика

Speaker.Note(100,"E4",1000)
Speaker.Wait()
Speaker.Note(100,"D4",1000)
Speaker.Wait()        

While over
  If Sensor.ReadRawValue(4,0) = 1 Then
    If player <> 1 Then
      player = 1
      trigger = "True"
    EndIf
  EndIf
  
  If Sensor.ReadRawValue(4,0) = 2 Then
    If player <> 2 Then
      player = 2
      trigger = "True"
    EndIf
  EndIf
  
  If Sensor.ReadRawValue(4,0) = 3 Then
    If player <> 3 Then
      player = 3
      trigger = "True"
    EndIf
  EndIf
  
  If Sensor.ReadRawValue(4,0) = 4 Then
    If player <> 4 Then
      player = 4
      trigger = "True"
    EndIf
  EndIf

EndWhile

суббота, 23 января 2016 г.

Большой железный робот. Часть 1. Колесные узлы

Как же в LEGO все просто - воткнул в мотор ось, на нее - колесо и колесный узел готов. С готовыми китайскими шасси чуть посложнее - нужна отвертка, которой нужно закрутить пару-тройку винтов.




Покрутив в руках купленные мотор-редукторы стеклоподъемников ВАЗ 2110 и колеса "от тележки" PR1804 сразу пришло понимание того, что тут все просто и быстро не получится. В первой части статьи мы озвучили нашу концепцию сборки - не использовать эксклюзивных деталей и технологий, недоступных в домашних условиях, поэтому пришлось поломать голову как же просто и надежно прикрепить мотор-редуктор к колесу с использованием доступных материалов и инструментов.

Ниже на схеме показан принцип передачи вращения вала мотор-редуктора на колесо.

\


"Корпус" колесного узла собирается из стальной трубы профильной 40x20x2, он состоит из трех частей. На фото показаны размеры элементов и необходимые монтажные отверстия. В отверстие 20 мм вставлена неподвижная ось из трубы стальной 20x1.5.








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


Мотор-редуктор крепится к "корпусу" колесного узла болтами М6 (30 и 50 мм). На концы профилей можно установить пластиковые заглушки:

Внутри неподвижной оси располагаем подвижную из трубы 12x1.5. Вал мотор-редуктора квадратный, поэтому необходимо придумать - как крутить им ось-трубку. Мы предлагаем такой способ (см. фото). Его преимущество - возможность сборки-разборки, настройки усилия сопряжения и использование кусочка все той же трубы 20x1.5 в качестве внешнего упорного элемента.







Винты используем М4 длиной 10 мм (из детского железного конструктора подходят отлично), гайки немного стачиваем (либо можно использовать винты и гайки М3).

Для того, чтобы центрировать подвижную ось относительно неподвижной и придать бОльшую жесткость конструкции между осями поставим подшипник 941/12, его внутренний диаметр 12 мм, внешний - 17 мм. Другая его маркировка - HK121712.



Два из четырех противоположных колесных болта М8 следует удлинить и поставить на них "поводок", который будет передавать вращение от оси на колесо. Поводок делаем из U-образного алюминиевого профиля 20x10x20x2.





В качестве шайбы между колесом и профильной трубой использовали кусочек полипропиленовой трубы на 3/4.



В качестве стопорной шайбы использовали еще один такой же кусочек, разрезанный поперек и сантехнический хомут.


В итоге колесный узел получается разборным и ремонтопригодным. Чтобы винты на подвижной оси и поводке не раскручивались в процессе работы, в качестве фиксатора резьбы можно применить специальный фиксатор или лак для ногтей.



Из инструментов для работы в итоге понадобится:

- ножовка по металлу
- напильники и/или надфили
- набор гаечных ключей
- дрель со сверлами по металлу на 4, 6 и 20 мм. При отсутствии сверла на 20 мм можно просверлить меньшим сверлом и расточить, например, "шарашкой":


Для колесных узлов понадобятся:
- мотор-редуктор стеклоподъемника ВАЗ 2110 (2 шт. левый+правый)
- колеса PR1804  2 шт.
- подшипники 941/12 12x17x12 мм 2 шт.
- труба стальная 12x1,5 1м
- труба стальная 20x1,5 1м
- труба профильная 40x20x2 1м
- профиль аллюм. U-обр. 20x10x20x2 1м
- винты М4
- гайки М4
- болты М6
- гайки М6
- болты М8
- гайки М8
- хомуты сантех. 2 шт.
- клей "Эпоксилин" 150 руб
- заглушки пластиковые для профильной трубы 40 x 20 12 шт.


четверг, 21 января 2016 г.

Пара новых задачек (№17-18)

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

В первой задаче ваш робот должен сдвинуть банки в центр круга, это похоже на кегельринг, но наоборот. Банки 4, робот стартует из центра.

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


воскресенье, 10 января 2016 г.

Большой железный робот. Часть 0. Задумка

В последнее время "из пол пера" нашей команды выходит много проектов с использованием платформы LEGO Mindstorms, а в рубрике "Строим из микроконтроллеров" свежих разработок у нас не наблюдается. Мы решили исправить эту несправедливость и задумали построить нового, "большого" робота. Небольших роботов, например "из коробки от тормозов" мы уже строили, но вот получится ли у нас собрать что-то побольше?
Проект нами планируется как "долгоиграющий", не нацеленный на быстрый результат любой ценой. Для начала начинаем потихоньку искать детали для нового робота и прикидывать что и как. Начнем мы с колесной платформы,  добавим датчики и навигацию. В планах поставить на робота манипулятор и заставить ориентироваться в пространстве с использованием машинного зрения. Данный робот не предназначен для решения какой-то определенной задачи, это учебная модель.
Мы принципиально постараемся не использовать никаких не доступных в домашних условиях технологий, таких как сварка и не применять эксклюзивных деталей, поэтому наш робот будет полностью повторяем любым желающим.



Итак, что мы уже раздобыли из комплектующих и материалов:

1. Колеса пневматические для тележки RP1804, диаметром 250 мм, под ось 20 мм, 2 штуки. Имеют встроенные подшипники. Диски разборные, собраны с использованием болтов М8.

2. Приводы стеклоподъемников от ВАЗ 2110, 2 штуки. Имеют встроенные редукторы 66:1. Питаются от 12 В. Судя по характеристикам и тестам в Интернете имеют ток холостого хода в 1,5А, в нагруженном состоянии - до 15-30А.


3. Труба квадратная стальная 40x20x2 мм. Планируем использовать для колесного узла, для крепления моторов. Болты и гайки М6 - для крепления моторов к колесным узлам.

4. Труба стальная круглая 20x1,5 - для осей колес. Труба стальная 3/4 - для шайб на осях колес. Труба стальная 12x2 - для осей, передающих вращение от моторов колесам.
5. Arduino Mega 2560. Решили использовать в качестве управляющего контроллера для двигателей и сбора показаний с датчиков.


Что еще может понадобится, что не раздобыли, но уже присматриваем:

Для питания планируем использовать аккумулятор от ИБП 12В 9Ач
В качестве "мозга" робота, для анализа видеопотока с камеры - Raspberry Pi Zero
Для управления двигателями - китайский драйвер на 30А

В данный момент начаты работы над колесными узлами, сейчас они выглядят вот так


Схема колесного узла:



Дальше в планах рама и корпус - в ожидании электроники от Почты России.




Самое популярное