Стильная электронная матрица D20, сделанная своими руками

Стильная электронная матрица D20, сделанная своими руками

Хотите что-то уникальное для вашей следующей настольной ролевой игры? Как насчет электронного D20 с настраиваемой графикой для критических попаданий и промахов? Сегодня я покажу вам, как создать свой собственный с помощью Arduino и нескольких простых частей.





Не волнуйтесь, если вы никогда раньше не использовали Arduino, у нас есть руководство по началу работы .





План сборки

Это простой проект. Arduino будет управлять OLED-дисплеем, а кнопка бросит кубик. Пользовательская графика будет отображаться для бросков на критическое попадание или критический промах. Вы можете легко изменить код на D8, D10 или D12.





Что вам нужно

  • 1 х Ардуино
  • 1 х 0,96 ' I2C OLED-дисплей
  • 1 х кнопка
  • 1 х 10к? Резистор
  • 1 х макет
  • Ассорти соединительных проводов
  • Полный код здесь, если вы не хотите полностью следовать письменным инструкциям.

Это основные детали, необходимые для создания собственного D20. Вы можете установить его в корпус (обсуждается ниже) и припаять схему в более постоянное состояние. Вот дополнительные детали, которые вам понадобятся для этого:

Эти OLED-дисплеи очень классные. Обычно их можно купить белого, синего, желтого или их трех цветов. Я купил синий, чтобы он соответствовал моему случаю. Убедитесь, что вы получили I2C модель вместо SPI .



Подойдет практически любая Ардуино. Я выбрал Nano, так как они достаточно малы, чтобы поместиться в корпусе. Ознакомьтесь с нашим руководством по покупке для получения дополнительной информации о моделях Arduino.

Схема

Вот схема, которая вам нужна:





Соединять VCC а также GND на OLED-дисплее к Arduino + 5В а также земля . Соединять аналог 4 на Arduino к контакту с надписью ПДД . Соединять аналог 5 к SCL штырь. Эти контакты содержат схемы, необходимые для управления дисплеем по шине I2C. Точные контакты зависят от модели, но на Nano и Uno используются A4 и A5. Проверить Документация библиотеки проводов для вашей модели, если вы не используете Uno или Nano.

Подключите аккумулятор к земле и ВИНО штырь. Это означает входное напряжение и допускает множество различных напряжений постоянного тока, но сначала проверьте свою конкретную модель, и иногда оно может незначительно отличаться.





Подключите кнопку к цифровой контакт 2 . Заметили, как 10к? резистор подключен к земле. Это очень важно! Это известно как понижающий резистор, и он предотвращает обнаружение Arduino ложных данных или помех при нажатии кнопки. Он также служит для защиты доски. Если бы этот резистор не использовался, + 5В пошло бы прямо на землю. Это известно как мертвый короткий и это простой способ убить Arduino.

Если вы паяете эту схему, защитите свои соединения термоусадочной трубкой:

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

Тест кнопки

Теперь, когда вы построили схему, загрузите этот тестовый код (убедитесь, что выбрали правильную плату и порт из списка Инструменты> Доска а также Инструменты> Порт меню):

const int buttonPin = 2; // the number of the button pin
void setup() {
pinMode(buttonPin, INPUT); // setup button
Serial.begin(9600); // setup serial
}
void loop(){
if(digitalRead(buttonPin) == HIGH) {
Serial.print('It Works');
delay(250);
}
}

После загрузки оставьте Arduino подключенным через USB и откройте последовательный монитор ( Вверху справа> Монитор последовательного порта ). Вы должны увидеть слова Оно работает появляются каждый раз, когда вы нажимаете кнопку.

Если ничего не происходит, дважды проверьте свою схему.

Настройка OLED

Вам нужно установить две библиотеки для управления дисплеем. Загрузите Adafruit_SSD1306 и библиотеки Adafruit-GFX [больше не доступны] из Github, и сохраните их в папке своей библиотеки. Если вы не уверены, где находятся папки библиотеки, прочтите мой учебник по ретро-играм, где я более подробно настраиваю этот же дисплей.

Перезагрузите IDE Arduino и загрузите тестовый скетч из Файл> Примеры меню. Выбирать Adafruit SSD1306 а потом ssd1306_128x64_i2c . Загрузите этот код (это займет некоторое время), и вы увидите на дисплее множество форм и узоров:

Если ничего не происходит, дважды проверьте свои соединения. Если после проверки он по-прежнему не работает, вам необходимо изменить пример кода.

что такое биксби на моем телефоне самсунг

Измените эту строку (в начале настраивать функция):

display.begin(SSD1306_SWITCHCAPVCC, 0x3D);

К этому:

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

Это сообщает конкретной библиотеке подробности об используемом вами дисплее. Теперь у вас должно быть все готово для продолжения сборки.

Дело

Если вы собираете это на макетной плате или не хотите упаковывать его в коробку, вы можете пропустить этот шаг.

Я спроектировал и распечатал эту коробку на 3D-принтере. Получите файлы Thingiverse . Не волнуйтесь, если у вас нет 3D-принтера - онлайн-услуги 3D-концентраторы а также Shapeways предоставлять услуги онлайн-печати.

Вы можете легко сделать эту шкатулку из дерева или купив пластиковую коробка проекта .

Крышка имеет простую конструкцию с плотной посадкой и содержит несколько вырезов для оборудования:

Код

Теперь, когда все готово, пора писать код. Вот как это будет работать в Псевдокод :

if button is pressed
generate random number
if random number is 20
show graphic
else if random number is 1
show graphic
else
show number

Чтобы это работало правильно, необходимо сгенерировать случайное число - это бросок кубика. В Arduino есть генератор случайных чисел, который называется случайный , но не следует его использовать. Хотя он достаточно хорош для простых случайных задач, он недостаточно случайный для электронного кубика. Причины несколько сложны, но вы можете прочитать больше, если вам интересно boallen.com .

Загрузите TrueRandom библиотека сэрлич на Github. Добавьте это в папку вашей библиотеки и перезапустите IDE.

Теперь создайте новый файл и настройте исходный код (или просто возьмите готовый код с GitHub):

#include
#include
#include
#include
#include
Adafruit_SSD1306 display(4);
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // setup the OLED
pinMode(buttonPin, INPUT); // setup button
}
void loop() {

}

Этот код настраивает OLED и включает в себя все библиотеки, необходимые для связи с ним, а также вашу новую библиотеку случайных чисел. Теперь добавьте это в основной цикл:

if(digitalRead(buttonPin) == HIGH) {
delay(15);
if(digitalRead(buttonPin) == HIGH) {
display.fillScreen(BLACK); // erase the whole display
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(0, 0);
display.println(TrueRandom.random(1, 21)); // print random number
display.display(); // write to display
delay(100);
}
}

На данный момент это довольно просто, но это рабочий D20. При каждом нажатии кнопки на экране отображается случайное число от 1 до 20:

Это хорошо работает, но немного скучно. Сделаем лучше. Создайте два новых метода, drawDie а также стереть :

void drawDie() {
display.drawRect(32, 0, 64, 64, WHITE);
}

Они нарисуют кубик в центре экрана. Вы можете усложнить этот процесс, например, нарисовав D20 или D12 и так далее, но проще нарисовать базовый шестигранный кубик. Вот базовое использование:

drawDie();

Затем измените свой основной цикл, чтобы нарисовать случайное число, только больше и посередине. Измените размер текста и курсор на это:

display.setTextColor(WHITE);
display.setCursor(57, 21);

Теперь это выглядит намного лучше:

Единственная проблема - с числами больше девяти:

Исправить это просто. Любые числа меньше 10 будут иметь курсор, установленный в другую позицию, чем эти числа 10 или больше. Замените эту строку:

система, использующая 100% диска
display.setCursor(57, 21);

С этим:

int roll = TrueRandom.random(1, 21); // store the random number
if (roll <10) {
// single character number
display.setCursor(57, 21);
}
else {
// dual character number
display.setCursor(47, 21);
}

Вот как это выглядит сейчас:

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

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

Кредит изображения: publicdomainvectors.org

Любое изображение, которое вы хотите использовать, необходимо будет преобразовать в массив HEX. Это представление изображения в кодовой форме. Для этого доступно множество инструментов, некоторые из которых написаны специально для OLED-дисплеев. Самый простой способ - использовать PicturetoC_Hex онлайн-инструмент. Вот необходимые настройки:

отключить уведомления Windows 10 по электронной почте

Загрузите свое изображение и установите формат кода на HEX: 0x . Установленный Используется для к Черный / белый для всех функций рисования изображений . Оставьте все остальные параметры по умолчанию. При необходимости вы можете изменить размер изображения здесь. Нажмите Получить строку C и вы должны увидеть, как появятся данные изображения:

Эти сгенерированные данные вам понадобятся через минуту. Создайте две функции с именем drawExplosion а также drawSkull (или подходящее название для вашей версии). Вот код:

void drawExplosion() {
// store image in EEPROM
static const unsigned char PROGMEM imExp[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x78,0x7f,0xff,0xc0,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xf0,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xfb,0x00,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x07,0xff,0xff,0xf9,0xff,0xd8,0x00,0x00,0x00,0x3f,0xff,0xf0,0x0f,0x00,0x00,0x00,0x00,0x1f,0x1f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x01,0xbf,0xff,0xff,0xff,0x30,0x00,0x00,0x00,0x13,0xf7,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
display.drawBitmap(0, 0, imExp, 64, 62, 1); // draw mushroom cloud
}
void drawSkull() {
// store image in EEPROM
static const unsigned char PROGMEM imSku[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x78,0x00,0x07,0xf0,0x00,0x00,0x00,0x00,0xfc,0x00,0x07,0xf8,0x00,0x00,0x00,0x00,0xfe,0x00,0x07,0xf8,0x00,0x00,0x00,0x01,0xfe,0x00,0x07,0xfc,0x00,0x00,0x00,0x01,0xfe,0x00,0x07,0xfe,0x00,0x3f,0xc0,0x03,0xfe,0x00,0x01,0xff,0x81,0xff,0xfc,0x07,0xec,0x00,0x00,0x3f,0xc7,0xff,0xff,0x1f,0xc0,0x00,0x00,0x0f,0xcf,0xff,0xff,0xdf,0x00,0x00,0x00,0x07,0xbf,0xff,0xff,0xee,0x00,0x00,0x00,0x01,0x7f,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x1e,0x3f,0xff,0x3f,0xc7,0x80,0x00,0x00,0x1e,0x0c,0x0f,0x00,0x07,0x80,0x00,0x00,0x1e,0x00,0x0f,0x00,0x0f,0x80,0x00,0x00,0x1e,0x00,0x19,0x80,0x0f,0x00,0x00,0x00,0x0f,0x00,0x19,0x80,0x0f,0x00,0x00,0x00,0x0d,0x00,0x30,0xc0,0x1f,0x00,0x00,0x00,0x05,0x80,0x70,0xc0,0x1e,0x00,0x00,0x00,0x05,0xf0,0xe0,0xe0,0x36,0x00,0x00,0x00,0x01,0xff,0xe0,0x7f,0xf0,0x00,0x00,0x00,0x03,0xff,0xc4,0x7f,0xf0,0x00,0x00,0x00,0x03,0xff,0xcc,0x7f,0xf0,0x00,0x00,0x00,0x03,0xff,0xcc,0x7f,0xf0,0x00,0x00,0x00,0x03,0xff,0x9e,0x7f,0xf0,0x00,0x00,0x00,0x00,0xff,0xfe,0x7f,0xc0,0x00,0x00,0x00,0x00,0x01,0xff,0xf8,0x1c,0x00,0x00,0x00,0x03,0xe0,0x3f,0x01,0xbf,0x00,0x00,0x00,0x07,0xa6,0x40,0x09,0x9f,0x80,0x00,0x00,0x1f,0x27,0x5a,0x39,0x9f,0xf8,0x00,0x01,0xff,0x27,0xdb,0x39,0x0f,0xfc,0x00,0x03,0xfe,0x31,0x7f,0x39,0x07,0xfc,0x00,0x03,0xfc,0x10,0x1a,0x02,0x03,0xf8,0x00,0x03,0xf8,0x10,0x00,0x02,0x01,0xf0,0x00,0x01,0xf8,0x10,0x00,0x02,0x01,0xe0,0x00,0x00,0x78,0x10,0x00,0x02,0x00,0xe0,0x00,0x00,0x70,0x30,0x00,0x02,0x00,0x00,0x00,0x00,0x30,0x20,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0x1b,0x00,0x00,0x00,0x00,0x00,0x73,0x55,0x63,0x00,0x00,0x00,0x00,0x00,0xf9,0x55,0x4f,0x00,0x00,0x00,0x00,0x00,0x7f,0x14,0x1f,0x00,0x00,0x00,0x00,0x00,0x1f,0xe0,0xfe,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
display.drawBitmap(0, 0, imSku, 60, 64, 1); // draw skull cloud
}

Если вы хотите использовать изображения, которые использовал я, скопируйте код. Если вы хотите использовать свои собственные изображения, созданные ранее, скопируйте байт-код в имСку а также imExp массивы по мере необходимости.

Вот как эти изображения выглядят на дисплее:

Самая важная часть этого кода - это строка:

static const unsigned char PROGMEM imSku[]

Это говорит Arduino хранить ваши изображения в EEPROM ( что такое EEPROM? ) вместо ОЗУ ( краткое руководство по оперативной памяти ). Причина этого проста; Arduino имеет ограниченную оперативную память, и использование всего этого для хранения изображений может не оставлять никаких остатков для выполнения вашего кода

Измените свой основной если заявление, чтобы показать эти новые графики при выпадении единицы или 20. Обратите внимание на строки кода, чтобы показать число, которое отображается рядом с изображениями:

if(roll == 20) {
drawExplosion();
display.setCursor(80, 21);
display.println('20');
}
else if(roll == 1) {
display.setCursor(24, 21);
display.println('1');
drawSkull();
}
else if (roll <10) {
// single character number
display.setCursor(57, 21);
display.println(roll); // write the roll
drawDie(); // draw the outline
}
else {
// dual character number
display.setCursor(47, 21);
display.println(roll); // write the roll
drawDie(); // draw the outline
}

А вот как выглядят эти новые роллы:

Это все, что касается кода (возьмите код с GitHub, если вы все это пропустили). Вы можете легко изменить это на D12, D8 и так далее.

Окончательная сборка

Теперь, когда все остальное закончено, пора все упаковать. Прикрутите дисплей, стараясь не затягивать болты слишком сильно. Возможно, это самая сложная часть. При этом я разбил дисплей, так что вы можете использовать пластиковые шайбы. Я вырезал из Пластикард :

Маленькие гайки и болты сложно соединить. Кончик: Используйте небольшой кусок клейкой ленты на конце отвертки, чтобы сначала закрепить гайки:

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

Вот как это выглядит внутри:

А вот и готовый продукт:

Теперь вы должны стать счастливым обладателем электронного D20!

Какие модификации вы внесли? Вы меняли изображения? Дайте нам знать в комментариях, мы будем рады видеть, что вы сделали!

Делиться Делиться Твитнуть Эл. адрес Руководство по анимации речи для новичков

Оживить речь может быть непросто. Если вы готовы начать добавлять диалог в свой проект, мы разберем этот процесс за вас.

Читать далее
Похожие темы
  • Сделай сам
  • Ардуино
  • Настольная игра
  • Электроника
Об авторе Джо Коберн(136 опубликованных статей)

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

Ещё от Joe Coburn

Подписывайтесь на нашу новостную рассылку

Подпишитесь на нашу рассылку, чтобы получать технические советы, обзоры, бесплатные электронные книги и эксклюзивные предложения!

Нажмите здесь, чтобы подписаться