Хотите что-то немного уникальное для своей следующей настольной ролевой игры? Как насчет электронного D20 с пользовательской графикой для критических попаданий и промахов? Сегодня я покажу вам, как создать свой собственный Arduino и несколько простых деталей.
Не беспокойтесь, если вы никогда раньше не пользовались Arduino, у нас есть руководство по началу работы
,
План строительства
Это простой проект. Arduino будет управлять OLED-дисплеем, а кнопка прокручивает матрицу. Пользовательская графика будет отображаться для критических попаданий или бросков. Вы можете легко изменить код на D8, D10 или D12.
Что вам нужно
- 1 х Arduino
- 1 x 0,96 ″ I2C OLED дисплей
- 1 х кнопка
- 1 х 10к? резистор
- 1 х макет
- Ассорти подключить провода
- Полный код здесь, если вы не хотите следовать всем письменным инструкциям.
Это основные части, которые вам нужны, чтобы создать свой собственный D20. Вы можете установить его в корпус (см. Ниже) и припаять схему в более постоянное состояние. Вот дополнительные детали, которые вам понадобятся для этого:
- 4 болта M2 x 10 мм (0,4 дюйма)
- 4 х M2 гайки
- 4 х 7 мм (0,28 дюйма) шайбы
- Оснастка батареи 9 В (или подходящая альтернатива)
- Ассорти термоусадочная трубка
Эти OLED дисплеи очень крутые. Обычно их можно приобрести в белом, синем, желтом цвете или в смеси из трех. Я купил один в синем, чтобы соответствовать моему случаю. Убедитесь, что вы получите I2C модель вместо SPI.
Подойдет практически любой Arduino. Я выбрал Nano, так как они достаточно малы, чтобы поместиться в корпусе. Ознакомьтесь с нашим руководством по покупке
для получения дополнительной информации о моделях Arduino.
Схема
Вот схема, которая вам нужна:
соединять VCC а также GND на OLED-дисплее в Arduino +5V а также земля. соединять аналог 4 на Arduino к булавке с надписью SDA. соединять аналог 5 к SCL штырь. Эти контакты содержат схему, необходимую для управления дисплеем по шине I2C. Точные контакты будут различаться в зависимости от модели, но A4 и A5 используются на Nano и Uno. Проверьте документацию библиотеки Wire для своей модели, если вы не используете Uno или Nano.
Подключите аккумулятор к земле и VIN штырь. Это обозначает напряжение на входе и принимает различные напряжения постоянного тока, но сначала проверьте вашу конкретную модель, и иногда она может немного отличаться.
Подключите кнопку к цифровой вывод 2. Обратите внимание, как 10k? резистор подключен к земле. Это очень важно! Это известно как понижающий резистор, и он предотвращает Arduino обнаружение ложных данных или помех при нажатии кнопки. Он также служит для защиты доски. Если бы этот резистор не использовался, + 5 В пошел бы прямо в землю. Это известно как очень короткий и это простой способ убить Ардуино.
Если вы паяете эту цепь, защитите свои соединения с помощью термоусадочной трубки:
Убедитесь, что вы не нагреваете его слишком сильно, и делайте это только после того, как убедитесь, что схема работает. Вы можете также захотеть скрутить ваши кабели в пары. Это сохраняет их аккуратными и помогает защитить их от чрезмерного стресса:
Тест кнопки
Теперь, когда вы построили схему, загрузите этот тестовый код (убедитесь, что вы выбрали правильную плату и порт из Инструменты> Доска а также Инструменты> Порт меню):
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 и сохраните их в папке библиотеки. Если вы не уверены, где находятся папки вашей библиотеки, прочитайте мой учебник по ретро-играм.
где я настраиваю этот же дисплей более подробно.
Перезапустите Arduino IDE и загрузите тестовый скетч из Файл> Примеры меню. Выбрать Adafruit SSD1306 а потом ssd1306_128x64_i2c. Загрузите этот код (это займет некоторое время), и вы должны увидеть множество форм и рисунков на дисплее:
Если ничего не происходит, дважды проверьте ваши соединения. Если после проверки он все равно не будет работать, вам нужно будет изменить пример кода.
Измените эту строку (в начале настроить функция):
display.begin(SSD1306_SWITCHCAPVCC, 0x3D);
К этому:
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
Это сообщает библиотеке конкретные сведения об используемом вами дисплее. Теперь вы должны быть готовы продолжить сборку.
Дело
Если вы строите это на макете или не хотите его упаковывать, вы можете пропустить этот шаг.
Я разработал и 3D напечатал эту коробку. Получить файлы на Thingiverse. Не беспокойтесь, если у вас нет 3D-принтера — онлайн-сервисы 3D Hubs и 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 от sirleech на 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. При каждом нажатии кнопки на экране отображается случайное число от одного до 20:
Это хорошо работает, но немного скучно. Давайте сделаем это лучше. Создайте два новых метода, drawDie а также eraseDie:
void drawDie() {
display.drawRect(32, 0, 64, 64, WHITE);
}
Они нарисуют кубик в середине экрана. Возможно, вы захотите сделать это более сложным, возможно, нарисовав D20 или D12 и так далее, но проще нарисовать базовый шестигранный кубик. Вот основное использование:
drawDie();
Затем измените ваш основной цикл, чтобы нарисовать случайное число, только больше и посередине. Измените размер текста и курсор на это:
display.setTextColor(WHITE);
display.setCursor(57, 21);
Теперь это выглядит намного лучше:
Единственная проблема с числами больше девяти:
Исправить это просто. Для любых чисел меньше 10 курсор будет установлен в положение, отличное от этих цифр 10 или больше. Заменить эту строку:
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. Вот необходимые настройки:
Загрузите свое изображение и установите формат кода HEX: 0x. Задавать Используется для в Черный / Белый для всех функций рисования изображения. Оставьте все остальные параметры по умолчанию. Вы можете изменить размер изображения здесь, если вам нужно. Нажмите Получить C String и вы должны увидеть данные изображения появляются:
Вам понадобятся эти сгенерированные данные через минуту. Создайте две функции под названием 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
}
Если вы хотите использовать изображения, которые я использовал, тогда скопируйте код. Если вы хотите использовать свои собственные изображения, сгенерированные ранее, скопируйте байт-код в imSku а также 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 и так далее.
Финальная сборка
Теперь, когда все остальное закончено, пришло время собрать все вместе. Прикрутите дисплей, следя за тем, чтобы не перетянуть болты. Это, пожалуй, самая сложная часть. Я взломал дисплей, поэтому вы можете использовать некоторые пластиковые шайбы. Я вырезал несколько квадратов из Plasticard:
Маленькие гайки и болты могут быть сложны для подключения. Совет: Используйте маленький кусок Blu-Tack на конце отвертки, чтобы изначально посадить гайки:
Прикрутите кнопку, подключите аккумулятор и закройте крышку. Будьте осторожны, чтобы не защемить какие-либо провода или не сжать их слишком сильно, что может вызвать короткое замыкание. В зависимости от длины ваших отводящих проводов вам может потребоваться защитить открытые соединения некоторой изоляцией (последовательный блок работает хорошо):
Вот как это выглядит внутри:
И вот готовый продукт:
Теперь вы должны быть счастливым обладателем электронного D20!
Какие модификации вы сделали? Вы меняли изображения? Дайте нам знать в комментариях, мы будем рады видеть, что вы сделали!