====== Электронный игральный кубик ====== ** [[slot-box:start#хочу_собрать|Проекты на Arduino и Slot Shield]] ** Чем ближе друзья живут, тем их сложнее собрать. В ход идёт куча предлогов — передвинуть мебель на даче, починить машину в гаражно-оздоровительном комплексе. Порубиться в тихие настольные игры — «Манчкин» или ещё какую-нибудь «Цивилизацию». И вот, момент настал, пенные напитки в холодильнике, все собрались и вдруг выясняется, кто-то потерял игральные кубики. Если кубики обычные, шестигранные, их можно поискать у младшего брата. Но как быть с четырёх-, двенадцати- или двадцатигранными? Подземелья так и останутся неисследованными, а драконы — непобеждёнными. {{ :slot-box:dice:dice.jpg?nolink|}} Наши универсальные электронные кости работают в режиме эмуляции стандартных кубиков d4, d6, d12 и d20. Режим работы задаётся [[amp>product/troyka-potentiometer?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|потенциометром]] и выводятся на левую [[amp>product/troyka-led-matrix?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki| LED-матрицу]]. Чтобы запустить генератор случайных чисел, возьмите гаджет в руки и встряхните его. [[amp>product/troyka-gyro?utm_source=proj&utm_campaign=slot-proj-16&utm_medium=wiki| Гироскоп]] запустит генератор случайных чисел и результат «броска» появится на правой матрице. Для четырёх- и шестигранных кубиков значение выводится крупными точками, как на настоящих костях, для остальных кубиков используется цифровая индикация. * Платформы: [[amp>product/arduino-uno?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|Arduino Uno]], [[amp>product/arduino-leonardo?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|Arduino Leonardo]], [[amp>product/iskra-neo?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|Iskra Neo]] * Язык программирования: Arduino (C++) ===== Что потребуется ===== [[amp>collection/dice?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki | Полный сет]] компонентов проекта. В сет входят: * [[amp>product/iskra-neo?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|Iskra Neo]] * [[amp>product/arduino-troyka-slot-shield?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|Troyka Slot Shield]] * две [[amp>product/troyka-led-matrix?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|LED матрицы 8×8]] * [[amp>product/troyka-gyro?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|гироскоп]] * [[amp>product/troyka-potentiometer?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|потенциометр]] ===== Видеоинструкция ===== {{youtube>JjeruyLHKKo?large}} ===== Как собрать ===== Установите [[amp>product/arduino-troyka-slot-shield?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|Troyka Slot Shield]] на [[amp>product/iskra-neo?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|Iskra Neo]] {{:slot-box:dice:step01.png?nolink|}} Вставьте две [[amp>product/troyka-led-matrix?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|LED матрицы 8×8]] в левый и правый слоты верхнего ряда. Чтобы у матриц были разные адреса, капните припой на любую контактную площадку правого модуля. Как это сделать — смотрите на странице [[http://wiki.amperka.ru/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:troyka-led-matrix#%D0%BF%D0%BB%D0%BE%D1%89%D0%B0%D0%B4%D0%BA%D0%B8_%D0%B2%D1%8B%D0%B1%D0%BE%D1%80%D0%B0_%D0%B0%D0%B4%D1%80%D0%B5%D1%81%D0%B0|описания матриц]]. {{:slot-box:dice:step02.png?nolink|}} Установите [[amp>product/troyka-gyro?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|гироскоп]] в оставшийся свободным слот верхнего ряда. {{:slot-box:dice:step03.png?nolink|}} Переверните [[amp>product/troyka-potentiometer?utm_source=proj&utm_campaign=slot-proj-17&utm_medium=wiki|потенциометр]] вверх ногами и вставьте в центральный слот нижнего ряда. {{:slot-box:dice:step04.png?nolink|}} ===== Скетч ===== Прошейте контроллер скетчем через [[../установка-и-настройка-arduino-ide|Arduino IDE]]. // библиотека для работы I²C #include "Wire.h" // библиотека для работы со светодиодной матрицей #include "TroykaLedMatrix.h" // библиотека для работы с модулями IMU #include // создаём объекты matrix для работы с матрицами // для каждой матрицы передаём свой адрес // подробнее читайте на: // http://wiki.amperka.ru/продукты:troyka-led-matrix TroykaLedMatrix matrix1; TroykaLedMatrix matrix2(0x61); // создаём объект для работы с гироскопом Gyroscope gyro; // порог скорости вращения гироскопа #define ROTATE_SPEED_TRESHOLD 500 enum {FOUR = 4, SIX = 6, TWELWE = 12, TWENTY = 20}; // массив закраски всей матрицы const uint8_t allPixels[] { B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111 }; // массив картнки цифры 4 const uint8_t four[] { B00000000, B00001000, B00011000, B00101000, B00111100, B00001000, B00001000, B00000000 }; // массив картнки цифры 6 const uint8_t six[] { B00000000, B00011000, B00100000, B00111000, B00100100, B00100100, B00011000, B00000000, }; // массив картнки цифры 12 const uint8_t twelwe[] { B00000000, B00100100, B01101010, B00100010, B00100100, B00101000, B00101110, B00000000 }; // массив картнки цифры 20 const uint8_t twenty[] { B00000000, B01000110, B10101001, B00101001, B01001001, B10001001, B11100110, B00000000 }; // массив значений кубика для режима 4d const uint8_t face4D[][8] { { 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, { 0x00, 0x06, 0x06, 0x00, 0x00, 0x60, 0x60, 0x00}, { 0x03, 0x03, 0x00, 0x18, 0x18, 0x00, 0xC0, 0xC0}, { 0x18, 0x18, 0x00, 0xC3, 0xC3, 0x00, 0x18, 0x18} }; // массив значений кубика для режима 6d const uint8_t face6D[][8] { { 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, { 0x00, 0x06, 0x06, 0x00, 0x00, 0x60, 0x60, 0x00}, { 0x03, 0x03, 0x00, 0x18, 0x18, 0x00, 0xC0, 0xC0}, { 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00}, { 0xC3, 0xC3, 0x00, 0x18, 0x18, 0x00, 0xC3, 0xC3}, { 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66} }; // массив значений кубика для режима 12d и 20d const uint8_t face20D[][8] { { 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x00}, // 1 { 0x00, 0x18, 0x24, 0x04, 0x08, 0x10, 0x3C, 0x00}, // 2 { 0x00, 0x38, 0x08, 0x10, 0x08, 0x08, 0x30, 0x00}, // 3 { 0x00, 0x08, 0x18, 0x28, 0x3C, 0x08, 0x08, 0x00}, // 4 { 0x00, 0x3C, 0x20, 0x38, 0x04, 0x24, 0x18, 0x00}, // 5 { 0x00, 0x18, 0x20, 0x38, 0x24, 0x24, 0x18, 0x00}, // 6 { 0x00, 0x3C, 0x04, 0x04, 0x08, 0x10, 0x10, 0x00}, // 7 { 0x00, 0x18, 0x24, 0x18, 0x24, 0x24, 0x18, 0x00}, // 8 { 0x00, 0x18, 0x24, 0x24, 0x1C, 0x04, 0x18, 0x00}, // 9 { 0x00, 0x26, 0x69, 0x29, 0x29, 0x29, 0x26, 0x00}, // 10 { 0x00, 0x22, 0x66, 0x22, 0x22, 0x22, 0x22, 0x00}, // 11 { 0x00, 0x24, 0x6A, 0x22, 0x24, 0x28, 0x2E, 0x00}, // 12 { 0x00, 0x2E, 0x62, 0x24, 0x22, 0x22, 0x2C, 0x00}, // 13 { 0x00, 0x22, 0x66, 0x2A, 0x2F, 0x22, 0x22, 0x00}, // 14 { 0x00, 0x2F, 0x68, 0x2E, 0x21, 0x29, 0x26, 0x00}, // 15 { 0x00, 0x26, 0x68, 0x2E, 0x29, 0x29, 0x26, 0x00}, // 16 { 0x00, 0x2F, 0x61, 0x21, 0x22, 0x24, 0x24, 0x00}, // 17 { 0x00, 0x26, 0x69, 0x26, 0x29, 0x29, 0x26, 0x00}, // 18 { 0x00, 0x26, 0x69, 0x29, 0x27, 0x21, 0x26, 0x00}, // 19 { 0x00, 0x46, 0xA9, 0x29, 0x49, 0x89, 0xE6, 0x00} // 20 }; void setup() { // открываем последовательный порт Serial.begin(115200); // выводим сообщение о начале инициализации Serial.println("Gyroscope init..."); // инициализация гироскопа gyro.begin(); // устанавливаем чувствительность гироскопа // 250dps — по умолчанию, 500dps, 2000dps gyro.setRange(RANGE_250DPS); // выводим сообщение об удачной инициализации Serial.println("Initialization completed"); // начало работы с матрицами matrix1.begin(); matrix2.begin(); // очищаем матрицы matrix1.clear(); matrix2.clear(); } void loop() { // считываем количесвто граней int countFace = readCountFace(); // выводим количество граней на первую матрицу switch(countFace) { case FOUR: matrix1.drawBitmap(four); break; case SIX: matrix1.drawBitmap(six); break; case TWELWE: matrix1.drawBitmap(twelwe); break; case TWENTY: matrix1.drawBitmap(twenty); break; } // считываем абсолютную скорость вращения гироскопа по трём осям float cubeRotate = abs(gyro.readDegPerSecX()) + abs(gyro.readDegPerSecY()) + abs(gyro.readDegPerSecZ()); // если скорость вращения гироскопа превысила порог if (cubeRotate > ROTATE_SPEED_TRESHOLD) { // считаем это за бросок кубика // бросаем кубик и отображаем результат dropCubeAndPrintResult(countFace); delay(1000); } } // функция считывания количество граней int readCountFace() { // считываем показания с потенциометра int sensorValue = analogRead(A1); if (sensorValue <= 255) { return TWENTY; } else if (sensorValue > 255 && sensorValue <= 512) { return TWELWE; } else if (sensorValue > 512 && sensorValue <= 767) { return SIX; } else if (sensorValue > 767 && sensorValue <= 1023) { return FOUR; } } // функция броска кубика и отображение результата void dropCubeAndPrintResult(int countFace) { int number = random(1, countFace + 1); randomPixels(); Serial.println(number); switch (countFace) { case FOUR: matrix2.drawBitmap(face4D[number - 1]); break; case SIX: matrix2.drawBitmap(face6D[number - 1]); break; case TWELWE: matrix2.drawBitmap(face20D[number - 1]); break; case TWENTY: matrix2.drawBitmap(face20D[number - 1]); break; } } void randomPixels() { matrix2.clear(); for (int i = 0; i < 20; i++) { // заполняем матрицу случайным пикселем matrix2.drawPixel(random(8),random(8)); // очищаем на матрице случайный пиксель matrix2.clearPixel(random(8),random(8)); // ждём 50 мс delay(30); } matrix2.clear(); } ====== Что дальше? ====== Хотите собрать другой девайс? Выберите своё будущее устройство из [[slot-box:start#хочу_собрать|списка проектов на Slot Shield]]. Если вы захотите изменить графику, рекомендуем воспользоваться удобным [[https://xantorohara.github.io/led-matrix-editor/|редактором для LED матриц]]. ====== Часто задаваемые вопросы ====== > Где скачать необходимые библиотеки и как их установить? * [[https://github.com/amperka/TroykaLedMatrix|библиотека для работы с LED-матрицей]] * [[https://github.com/amperka/Troyka-IMU|библиотека для работы с гироскопом]] * [[программирование:библиотеки|Как установить библиотеку]]