Проекты на Arduino и Slot Shield
Чем ближе друзья живут, тем их сложнее собрать. В ход идёт куча предлогов — передвинуть мебель на даче, починить машину в гаражно-оздоровительном комплексе. Порубиться в тихие настольные игры — «Манчкин» или ещё какую-нибудь «Цивилизацию». И вот, момент настал, пенные напитки в холодильнике, все собрались и вдруг выясняется, кто-то потерял игральные кубики. Если кубики обычные, шестигранные, их можно поискать у младшего брата. Но как быть с четырёх-, двенадцати- или двадцатигранными? Подземелья так и останутся неисследованными, а драконы — непобеждёнными.
Наши универсальные электронные кости работают в режиме эмуляции стандартных кубиков d4, d6, d12 и d20. Режим работы задаётся потенциометром и выводятся на левую LED-матрицу. Чтобы запустить генератор случайных чисел, возьмите гаджет в руки и встряхните его. Гироскоп запустит генератор случайных чисел и результат «броска» появится на правой матрице. Для четырёх- и шестигранных кубиков значение выводится крупными точками, как на настоящих костях, для остальных кубиков используется цифровая индикация.
Полный сет компонентов проекта. В сет входят:
Установите Troyka Slot Shield на Iskra Neo
Вставьте две LED матрицы 8×8 в левый и правый слоты верхнего ряда. Чтобы у матриц были разные адреса, капните припой на любую контактную площадку правого модуля. Как это сделать — смотрите на странице описания матриц.
Установите гироскоп в оставшийся свободным слот верхнего ряда.
Переверните потенциометр вверх ногами и вставьте в центральный слот нижнего ряда.
Прошейте контроллер скетчем через Arduino IDE.
// библиотека для работы I²C #include "Wire.h" // библиотека для работы со светодиодной матрицей #include "TroykaLedMatrix.h" // библиотека для работы с модулями IMU #include <TroykaIMU.h> // создаём объекты 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 Shield.
Если вы захотите изменить графику, рекомендуем воспользоваться удобным редактором для LED матриц.
Где скачать необходимые библиотеки и как их установить?