Танцевальная битва
- Платформы: Iskra JS
- Языки программирования: JavaScript
- Тэги: танцы, дуэль, прыжки, спорт, спор, Troyka модуль, кто не скачет…
Что это?
Кто быстрее? Кто сильнее? Кто круче?
Мы поможем поставить точку в подобных спорах раз и навсегда.
Вставайте на игровые площадки, жмите старт и прыгайте что есть сил. Светодиоды будут загораться от каждого прыжка, а общий уровень очков покажет количество жидкости в пивной башне. Опередивший соперника на 20 прыжков — победитель.
Покажи всем друзьям и коллегам, что ты — король вечеринки.
Что нам понадобится?
- Пивная башня (2 шт.)
- Истинная синяя изолента
- Многожильный монтажный провод с сечением 2×1 мм² (3 метра)
- Лист фанеры 50×50 мм (2 шт.)
- Поролон
- Балончик белой краски
- Крепёжные элементы: винты, саморезы, гайки
Как собрать?
- Закрепите платформу Iskra JS на панели #структора «крепление Arduino 7×8 шипов» с помощью акриловых стоек. Стойки закрепите на панели винтами, сверху установите платформу и зафиксируйте гайками.
- Установите Motor Shield на плату Iskra JS.
- Установите «лицевую панель Arduino c microUSB-интерфейсом 4×6 шипов» и через неё подключите входящие в комплектацию помп «разъёмы-переходники на 2 провода» к Motor Shield. Красный провод к плюсу, чёрный — к минусу.
- Установите Troyka Shield на бутерброд из плат Iskra JS и Motor Shield.
- Закрепите два модуля сенсора вибрации с помощью саморезов и гаек на боковых панелях #структора «7×7 шипа».
- Подключите модули сенсора вибрации к аналоговым пинам
A0
иA5
Troyka Shield и через клеммник выведите провода «папа-папа» для дальнейшего подключения пьезо-дисков. - Закрепите силовой ключ с помощью нейлоновых винтов к детали #структора (крепление Troyka 4×7 шипа), откусите бокорезами неиспользуемую часть и подключите к
6
пину Troyka Shield. - Подготовьте провода для подключения колонки к Iskra JS через силовой ключ:
- «Плюс» колонки подключите к пину
5V
- «Минус» колонки — к «плюсу» силового ключа.
- Пин
GND
— к «минусу» силового ключа.
- Прикрепите обновлённые боковые панели («пластины 7×6 шипов») и заднюю панель («пластина 6×6 шипов») к основанию корпуса устройства («крепление Arduino 7×8 шипов»).
- Закрепите клеммник с помощью двухстороннего скотча к задней панели корпуса и подключите к нему выведенные ранее провода от модулей сенсоров вибрации и силового ключа.
- Возьмите кнопку (Troyka-модуль), прикрутите её к панели для крепления Troyka-модулей. из четырёх панелей конструктора (3x2 шипов) соорудите «башенку» и закрепите на будущей верхней панели корпуса («пластина 7×8 шипов»).
- Закрепите два светодиода «Пиранья» на панелях крепления Troyka-модулей, затем закрепите их по бокам верхней панели устройства.
- Подключите два светодиода «Пиранья» к
8
и9
пину Troyka Shield, а кнопку (Troyka-модуль) — к3
пину Troyka Shield. - Закончите сборку лицевой части корпуса с помощью реек #структора и пластины (2×6 шипов). Прикрепите верхнюю панель («пластина 7×8 шипов») к передней, задней и боковым стенкам корпуса.
- Отпаяйте от пьезо-диска короткие провода и замените их на провод длинной около 1–2 метров. Повторите это для второго датчика.
- Подключите пьезо-диски к модулям сенсора вибрации через установленный ранее клеммник.
- Припаяйте многожильный монтажный провод к выводам динамика.
- Соберите корпус для динамика из четырёх «мега пластин» #Структора и подключите его к клеммнику на задней части корпуса.
- Возьмите две «пивные башни», опустите в них погружные помпы, концы выходящих трубок проведите в противоположную «башню». Помпы будут откачивать жидкость из башен соперника.В итоге должна получите схема.
- Подключите помпы к Motor Shield через «разъём-переходник на 2 провода»
- Выпилите из листа фанеры два модуля «Troyka XXL» и покрасьте их белой краской.
- На задней части модуля «Troyka XXL» закрепите несколько кусков поролона и приклейте пьезо-диск. Повторите действие со вторым «Troyka XXL» и сенсором вибрации.
- Расположите все модули на расстоянии в 15–20 см друг от друга и подключите источник питания к устройству.
Теперь осталось залить любимый «лимонад» в пивные башни и можно играть.
Алгоритм
- После подключения питания ничего не делаем пока не нажата кнопка «старт/сброс»;
- Проверяем текущее количество очков. Если значение очков дошло до левой или правой границы интервала:
- заканчиваем игру;
- показываем светодиодом победителя;
- переходим в режим ожидания нажатия кнопки «старт/сброс»;
- Считываем данные с сенсоров;
- Если значение сенсора первого игрока превысило порог:
- отнимаем от общего числа очков единицу;
- мигаем светодиодом об удачном прыжке;
- если количество очков кратно 3, включаем «помпу 1» на 3 секунды. Если помпа в данный момент работает, добавляем к времени её работы ещё 3 секунды.
- Если значение сенсора второго игрока превысило порог:
- прибавляем к общему числу очков единицу;
- мигаем светодиодом об удачном прыжке;
- если количество очков кратно 3, включаем «помпу 2» на 3 секунды. Если помпа в данный момент работает, добавляем к её времени работы ещё 3 секунды.
Исходный код
- duel.js
// подключаем библиотеку для проигрывание мелодий // в формате Nokia RTTTL var player = require('@amperka/ringtone').create(P11); // мелодия старта var melodyStart = 'smb:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p'; // мелодия окончания var melodyEnd = 'smbdeath:d=4,o=5,b=90:32c6,32c6,32c6,8p,16b,16f6,16p,'+ '16f6,16f.6,16e.6,16d6,16c6,16p,16e,16p,16c'; // подключаем библиотеку для управления кнопкой // подключенной к пину 3 var button = require('@amperka/button') .connect(P3); // подключаем библиотеку для управления моторами var Motor = require('@amperka/motor'); // присваиваем первому игроку мотор канала M2 на Motor Shield var motorPlayer1 = Motor.connect(Motor.MotorShield.M2); // присваиваем второму игроку мотор канала M1 на Motor Shield var motorPlayer2 = Motor.connect(Motor.MotorShield.M1); // подключаем библиотеку для управления светодиодами // подключенные к пинам 8 и 9 var ledPlayer1 = require('@amperka/led').connect(P8); var ledPlayer2 = require('@amperka/led').connect(P9); // время работы помп var timeWorkPump1 = 3000; var timeWorkPump2 = 3000; // новое время работы помп var newTimeWorkPump1 = 0; var newTimeWorkPump2 = 0; // текущее время начало работы помп var startTimeWorkPump1 = 0; var startTimeWorkPump2 = 0; // текущее количество очков var score = 0; // количество очков для победы var maxScore = 20; // состояние работы помп var idPumpPlayer1 = 0; var idPumpPlayer2 = 0; // состояние готовности устройства принять прыжок игрока var statePlayer1 = 0; var statePlayer2 = 0; // состояние игры var idPlayGame = 0; // состояние конца игры var idEndGame = 0; // прерывание по нажатию кнопки button.on('press', function() { ledPlayer1.turnOn(); ledPlayer2.turnOn(); // проигрываем мелодию о начале игры player.play(melodyStart).then(function() { print('Melody completed'); // сбрасываем игру resetGame(); // начинаем игру playGame(); }); }); // функция начало игры function playGame() { print('Start Game'); idPlayGame = setInterval(function() { // Не закончилась ли игра? if (score >= maxScore || score <= -maxScore) { clearInterval(idPlayGame); print('Stop Game'); // заканчиваем игру endGame(); // проигрываем мелодию об окончании игры player.play(melodyEnd).then(function() { print('End Game'); }); } // считывание значений с датчиков вибрации var sensorVal1 = analogRead(A5); var sensorVal2 = analogRead(A0); // если значение сенсора первого игрока превысило порог if (sensorVal1 > 0.03 && statePlayer1 === 0) { ledPlayer1.turnOn(); statePlayer1 = 1; // отнимаем от общего числа очков единицу score--; print(score); if (score % 3 === 0) { try { clearTimeout(idPumpPlayer1); // интервал времени, который прошёл // на данный момент работы помпы 1 var intervalTimeWorkedPump1 = (getTime()*1000-startTimeWorkPump1); // оставшиеся время работы помпы 1 var lastTimeWorkPump1 = timeWorkPump1 - intervalTimeWorkedPump1; // новое время работы помпы 1 newTimeWorkPump1 = newTimeWorkPump1 + lastTimeWorkPump1; print('Yes Timer for player 1'); print('Timer1 = ', newTimeWorkPump1); pump1Off(newTimeWorkPump1); } catch (e) { newTimeWorkPump1 = timeWorkPump1; print('No Timer for player 1'); print('Timer1 = ', newTimeWorkPump1); pump1CycleOnOff(); } } // следующий засчитанный прыжок будет доступен через 100 мс setTimeout(function() { statePlayer1 = 0; ledPlayer1.turnOff(); print('Continue read player 1'); }, 100); } // если значение сенсора второго игрока превысило порог if (sensorVal2 > 0.03 && statePlayer2 === 0) { ledPlayer2.turnOn(); statePlayer2 = 1; // прибавляем к общему числу очков единицу score++; print(score); if (score % 3 === 0) { try { clearTimeout(idPumpPlayer2); // интервал времени, который прошёл // на данный момент работы помпы 2 var intervalTimeWorkedPump2 = (getTime()*1000-startTimeWorkPump2); // оставшиеся время работы помпы 2 var lastTimeWorkPump2 = timeWorkPump2 - intervalTimeWorkedPump2; // новое время работы помпы 2 newTimeWorkPump2 = newTimeWorkPump2 + lastTimeWorkPump2; print('Yes Timer for player 2'); print('Timer2 = ', newTimeWorkPump2); pump2Off(newTimeWorkPump2); } catch (e) { newTimeWorkPump2 = timeWorkPump2; print('No Timer for player 2'); print('Timer2 = ', newTimeWorkPump2); pump2CycleOnOff(); } } // следующий засчитанный прыжок будет доступен через 100 мс setTimeout(function() { statePlayer2 = 0; ledPlayer2.turnOff(); print('Continue read player 2'); }, 100); } }, 10); } // функция включения помпы первого игрока с последующим отключением function pump1CycleOnOff() { print('Pump Player 1 On'); startTimeWorkPump1 = getTime()*1000; motorPlayer1.write(1.0); ledPlayer1.turnOn(); pump1Off(timeWorkPump1); } // функция выключения помпы первого игрока function pump1Off(time) { startTimeWorkPump1 = getTime()*1000; idPumpPlayer1 = setTimeout(function() { print('Pump Player 1 Off'); motorPlayer1.write(0); ledPlayer1.turnOff(); idPumpPlayer1 = 0; }, time); } // функция включения помпы второго игрока с последующим отключением function pump2CycleOnOff() { print('Pump Player 2 On'); startTimeWorkPump2 = getTime()*1000; motorPlayer2.write(1.0); ledPlayer2.turnOn(); pump2Off(timeWorkPump2); } // функция выключения помпы второго игрока function pump2Off(time) { startTimeWorkPump2 = getTime()*1000; idPumpPlayer2 = setTimeout(function() { print('Pump Player 2 Off'); motorPlayer2.write(0); ledPlayer2.turnOff(); idPumpPlayer2 = 0; }, time); } // выключить помпы и светодиоды function allOff() { motorPlayer1.write(0); motorPlayer2.write(0); ledPlayer1.turnOff(); ledPlayer2.turnOff(); } // сброс игры function resetGame() { score = 0; try { clearInterval(); print('Yes Interval'); } catch (e) { print('No Interval'); } try { clearTimeout(); print('Yes Timeout'); } catch (e) { print('No Timeout'); } allOff(); } // конец игры function endGame() { try { clearInterval(); print('Yes Interval'); } catch (e) { print('No Interval'); } try { clearTimeout(); print('Yes Timeout'); } catch (e) { print('No Timeout'); } if (score === -maxScore) { // если выиграл первый игрок motorPlayer1.write(1.0); motorPlayer2.write(0); ledPlayer1.turnOn(); ledPlayer2.turnOff(); print('Player 1 Win'); } else if (score === maxScore) { // если выиграл второй игрок motorPlayer1.write(0); motorPlayer2.write(1.0); ledPlayer1.turnOff(); ledPlayer2.turnOn(); print('Player 2 Win'); } else { allOff(); print('No Win'); } // после победы одного из игроков // через 10 секунд выключаем помпы и светодиоды idEndGame = setTimeout(function() { allOff(); }, 10000); }
Демонстрация работы устройства
Что дальше?
Добавьте в проект дисплей чтобы показывать точное количество очков.
Не оказалось платы Iskra JS, не беда. Любой обладатель платы Arduino может собрать подобный проект — в его основе лежит скетч из 20 эксперимента Матрёшки Z.
Используй больше датчиков вибрации и собери свой ответ Dance Dance Revolution.