Как устроить гонки #Робоняш
Нравятся гонки роботов? И нам тоже! Построим своих #Робоняш с NFC-сканером и bluetooth-модулем, а затем устроим сражение за звание последнего героя. Интересно? Тогда приступим…
Нам потребуется
Видеообзор
Сборка
Собирём Робоняшу по инструкции из набора, а затем добавим новые модули. Сначала добавим ещё один аккумулятор — Power Shield
. Матрица, NFC-модуль и Bluetooth потребляют много энергии, поэтому один Power Bank долго не протянет.
На Power Shield
закрепим Motor Shield
.
Не забудьте добавить перемычку на MotorShield и снять джампер PWR JOIN
. Если этого не сделать, плата может выйти из строя.
Установите Troyka Shield LP
.
Подключите периферийные модули #Робоняши.
Аккуратно уберите провода и закрепите Troyka Slot Shield
.
Подключите модули NFC и Bluetooth. Антенну NFC-сканера прикрепите плашкой #Структора 2×2 к креплениям датчиков линии.
Соревнование
Каждая #Робоняша должна иметь своё имя, поэтому не забудьте изменить их в скетче. После этого загрузите программу в робота.
Для управления скачайте на смартфон приложение Arduino Bluetooth RC Car.
Цель игры — первым объехать максимальное количество наклеенных на трассу NFC-меток. Метки добавляют призовые очки только первому нашедшему её роботу. Игра заканчивается, когда все метки найдены. Кто набрал больше очков — тот и победил.
Код игры
- RoboNY.js
/*----- Подключение модулей -----*/ { Serial3.setup(9600); var bt = require('@amperka/bluetooth').connect({serial: Serial3, kPin: P5, speed: 9600}); var Motor = require('@amperka/motor'); var symbols = require('@amperka/basic-font').font; PrimaryI2C.setup({sda: SDA, scl: SCL, bitrate: 400000}); var matrix = require('@amperka/led-matrix').connect(PrimaryI2C); var nfc = require('@amperka/nfc').connect({i2c: I2C1, irqPin: P2}); var player = require('@amperka/ringtone').create(P3); var motorOne = Motor.connect({phasePin: P4, pwmPin: A3, freq: 100}); var motorTwo = Motor.connect({phasePin: P7, pwmPin: P6, freq: 100}); var resetButton = require('@amperka/button').connect(C4); } /*----- Данными по умолчанию -----*/ { // переменая для хранения значение скорости var velocity = 0; // это число мы будем использовать в логике поворотов var defaultSpeed = 0.5; // Счётчик считанных меток var counter = 0; // Номер страницы для чтения и записи var page2read = 5; // Символы, используемые для вывода на светодиодную матрицу var amperka = '0123456789'; // длина строки с символами var len = 10; // массив который ищем var bufferRead = [0, 0, 0, 0]; // массив который запишем var bufferWrite = [1, 1, 1, 1]; //мелодия воспроизводимая при считывании новой метки var melody = 'HeyBaby:d=4,o=5,b=700:8a4,16a#4,16b4,16c,16c#,16d,16d#' +',16e,16f,16f#,16g,16g#,16a,16a#,16b,16c6,8c#6,16d6,16d#6,16e6,16f6,p,p'; // Значение яркости матрицы var BRIGHTNESS_VALUE = 0.1; } //------------------------------------------------------------------------------------------ // НАЗВАНИЕ МОДУЛЯ BLUETOOTH var bt_name = 'RoboNY1'; //------------------------------------------------------------------------------------------ nfc.wakeUp(function(error) { if (error) { print('wake up error', error); } else { print('wake up OK'); // слушаем новые метки matrixWriter(); nfc.listen(); bt. disconnect(function (error) { console.log('disconnected'); }); bt.name(bt_name, function (error) { console.log('name change'); }); } }); //------------------------------------------------------------------------------------------ // ЕСЛИ ДВИГАТЕЛИ ВРАЩАЮТСЯ В РАЗНЫЕ СТОРОНЫ ПРИ ДВИЖЕНИИ ВПЕРЁД, ПОМЕНЯТЬ ЗНАКИ У АРГУМЕНТОВ var drive = function(motorOne1, motorTwo2) { motorOne.write(motorOne1); motorTwo.write(-motorTwo2); }; //------------------------------------------------------------------------------------------ bt.on('error', function (error) { console.log(error); }); bt.on('data', function (dataIn) { console.log(dataIn); if (dataIn === 'F') { // если пришла команда "F" // едем вперёд drive(velocity, velocity); } else if (dataIn === 'B') { // или если пришла команда "B" // едем назад drive(-velocity, -velocity); } else if (dataIn === 'L') { // или если пришла команда "L" // поворачиваем налево на месте drive(-velocity, velocity); } else if (dataIn === 'R') { // или если пришла команда "R" // поворачиваем направо на месте drive(velocity, -velocity); } else if (dataIn === 'I') { // или если пришла команда "I" // едем вперёд и направо drive(defaultSpeed + velocity, defaultSpeed - velocity); } else if (dataIn === 'J') { // или если пришла команда "J" // едем назад и направо drive(-defaultSpeed - velocity, -defaultSpeed + velocity); } else if (dataIn === 'G') { // или если пришла команда "G" // едем вперёд и налево drive(defaultSpeed - velocity, defaultSpeed + velocity); } else if (dataIn === 'H') { // или если пришла команда "H" // едем назад и налево drive(-defaultSpeed + velocity, -defaultSpeed - velocity); } else if (dataIn === 'S') { // или если пришла команда "S" // стоим drive(0, 0); } else if (((dataIn - '0') >= 0) && ((dataIn - '0') <= 9)) { // или если пришло значение от 0 до 9 // сохраняем новое значение скорости velocity = (dataIn - '0') * 0.1; } else if (dataIn === 'q') { // или если пришла "q" // полный газ velocity = 1; } }); nfc.on('tag', function(error, data) { if (error) { print('tag read error'); } else { // выводим в консоль полученные данные print(data); // читаем указанную страницу данных nfc.readPage(page2read, function(error, buffer) { if (error) { print('page read error'); } else { print('page read result: ', buffer); // проверяем метку, for (var i in buffer) { if (buffer[i] === bufferRead[i]) { if (i === buffer.length-1) { matrixWriter(); writeCard(); voiceOn(); } } } } }); } // каждые 150 миллисекунд слушаем новую метку setTimeout(function () { nfc.listen(); }, 150); }); // при нажатии на кнопку сбрасываем текущий счёт resetButton.on('click', function() { counter = 0; matrixWriter(); }); // вывод на матрицу символа function matrixWriter() { var char = amperka[counter]; counter += 1; if (counter === len) { counter = 0; } else { } matrix.brightness(BRIGHTNESS_VALUE); matrix.print(symbols[char]); } // запись на карту страницы function writeCard() { nfc.writePage(page2read, bufferWrite, function(error) { if (error) { print('write page ERROR'); } else { print('write page OK'); } }); } // проигрывание мелодии function voiceOn() { player.stop(); player.play(melody); }
Чтобы вернуть метки в активное состояние и повторить заезд — воспользуйтесь кодом обнуления. Вы можете прошить его в одну из #Няш, но лучше собрать отдельное устройство.
Код активации меток
- reActiveTAG.js
// настраиваем I2C1 для работы модуля I2C1.setup({sda: SDA, scl: SCL, bitrate: 400000}); // подключаем модуль к I2C1 и пину прерывания var nfc = require('@amperka/nfc').connect({i2c: I2C1, irqPin: P2}); var bufferWrite = [0, 0, 0, 0]; // активируем модуль nfc.wakeUp(function(error) { if (error) { print('wake up error', error); } else { print('wake up OK'); // слушаем новые метки nfc.listen(); } }); // указываем страницу для чтения данных var page2read = 5; nfc.on('tag', function(error, data) { if (error) { print('tag read error'); } else { // выводим в консоль полученные данные print(data); // читаем указанную страницу данных nfc.readPage(page2read, function(error, buffer) { if(error) { print('page read error'); } else { print('page read result: ', buffer); // обновляем данные для записи. Например, увеличиваем на единицу for (var i in buffer) { buffer[i] = bufferWrite[i]; } // перезаписываем метку новыми данными на ту же страницу nfc.writePage(page2read, buffer, function(error) { if (error) { print('write page ERROR'); } else { print('write page OK'); } }); } }); } // каждые 1000 миллисекунд слушаем новую метку setTimeout(function () { nfc.listen(); }, 1000); });