这款DIY电子D20模具卷成一卷

您的下一个桌面角色扮演游戏是否想要一些独特的东西?带有自定义图形的D20电子D20怎么样?今天,我将向您展示如何使用Arduino和一些简单的零件来构建自己的产品。

如果您以前从未使用过Arduino,请不要担心,我们有一个入门指南。

构建计划

这是一个简单的项目。 Arduino将驱动OLED显示屏,并且一个按钮将使模具死掉。自定义图形将显示关键命中或关键错位。您可以轻松地将代码修改为D8,D10或D12。

您需要的东西

  • 1 x Arduino
  • 1 x 0.96“ I2C OLED显示
  • 1 x按钮
  • 1 x 10k?电阻器
  • 1 x面包板
  • 各种连接线
  • 此处完整代码,如果您不想完全按照书面说明进行操作。
  • 这些是构建自己的D20所需的核心部分。您可能希望将其安装在外壳中(如下所述),并将电路焊接到更永久的状态。以下是您需要执行此操作的其他零件:

  • 4 x M2 x 10mm(0.4英寸)螺栓
  • 4 x M2螺母
  • 4 x 7mm (0.28英寸)垫圈
  • 9V电池卡扣(或合适的替代品)
  • 各种热缩管
  • 这些OLED显示屏非常酷。通常可以购买白色,蓝色,黄色或这三种的混合物。我购买了蓝色的,以匹配我的情况。确保您获得的是 I2C 模型而不是 SPI

    几乎所有Arduino都适用。我选择了Nano,因为它们足够小,可以放入箱子中。查看我们的购买指南以获取有关Arduino型号的更多信息。

    电路

    这是您需要的电路:

    连接 VCC >和 GND 在OLED显示屏上连接到Arduino + 5V 。将Arduino上的模拟4 连接到标有 SDA 的引脚。将模拟5 连接到 SCL 引脚。这些引脚包含使用I2C总线驱动显示器所需的电路。确切的引脚会因型号而异,但是Nano和Uno会使用A4和A5。如果您未使用Uno或Nano,请查看模型的线库文档。

    将电池接地并使用 VIN 引脚。这表示输入电压,可以接受各种不同的DC电压-但请先检查您的特定型号,有时可能会略有不同。

    将按钮连接到数字引脚2 。注意10k如何?电阻接地。这个非常重要!这称为下拉电阻,它可以防止Arduino在按下按钮时检测到虚假数据或干扰。它还可以保护电路板。如果不使用该电阻,则+ 5V会直接接地。这被称为短短路,是杀死Arduino的简便方法。

    如果要焊接此电路,请使用热缩管保护连接:

    确保不要将其加热过多,只有在确定电路能够正常工作后才进行加热。您可能还希望将电缆成对绞合。这样可以使它们保持整洁并有助于保护它们免受不必要的压力:

    按钮测试

    现在,您已经建立了电路,请上传此测试代码(确保选择正确的电路板并 Tools> Board Tools> Port 菜单中的端口):

    const int buttonPin = 2;     // the number of the button pinvoid 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设置< /

    You need to install two libraries to drive the display. Download the Adafruit_SSD1306 and Adafruit-GFX [No Longer Available] libraries from Github, and save them into your library folder. If you are not sure where you library folders are, go read my retro gaming tutorial , where I configure this same display in more detail.

    重新启动Arduino IDE并从文件>示例菜单上传测试草图。选择 Adafruit SSD1306 ,然后选择 ssd1306_128x64_i2c 。上载此代码(需要一段时间),然后您应该会在显示器上看到很多形状和图案:

    如果什么都没发生,请仔细检查您的连接。如果在检查后仍然无法使用,则需要修改示例代码。

    更改此行(在 setup 函数的开头):

    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有一个称为 random 的随机数生成器,但不应使用它。虽然对于基本的随机任务已经足够好了,但对于电子芯片来说,随机性还不够。原因有些复杂,但是如果您对boallen.com感兴趣,可以阅读更多内容。

    通过sirleech在Github上下载TrueRandom库。将此添加到您的库文件夹中,然后重新启动IDE。

    现在创建一个新文件并设置您的初始代码(或只是从GitHub上获取完成的代码):

    #include <SPI.h>#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafruit_SSD1306.h>#include <TrueRandom.h> Adafruit_SSD1306 display(4);void setup() {    display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // setup the OLED    pinMode(buttonPin, INPUT); // setup button  }void loop() { }

    This code configures the OLED, and includes all the libraries you need to communicate with it, along with your new random number library. Now add this to the main loop:

    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 eraseDie

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

    这些方法将在屏幕中间绘制一个模具。您可能希望通过绘制D20或D12等使事情变得更复杂,但是绘制基本的六面模具更简单。基本用法如下:

    drawDie();

    接下来,修改您的主循环以绘制随机数,该随机数仅在中间较大。将文本大小和光标更改为:

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

    现在看起来好多了:

    唯一的问题是数字大于9:

    解决这个问题很简单。小于10的任何数字都将光标设置在与10或更大的数字不同的位置。替换此行:

    display.setCursor(57, 21);

    与此:

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

    这是现在的样子:

    当您滚动一个严重击中或错过。涉及几个步骤,但这是一个足够简单的过程。

    找到您要使用的合适图像(越简单越好,因为显示仅是单色的)。这是我使用的图像:

    您要使用的任何图像都需要转换为十六进制数组。这是代码形式的图像表示。有许多工具可以执行此操作,其中一些是专门为OLED显示器编写的。最简单的方法是使用PicturetoC_Hex在线工具。以下是所需的设置:

    上传图片,并将代码格式设置为 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}

    如果您想使用我使用过的图像,请继续并复制代码。如果要使用自己生成的图像,请根据需要将字节码复制到 imSku imExp 数组中。

    以下是这些图像在显示屏上看起来像:

    该代码最重要的部分是这一行:

    static const unsigned char PROGMEM imSku[]

    这告诉Arduino将图像存储在EEPROM中(什么是EEPROM?) 。这样做的原因是简单的; Arduino的内存有限,并且全部用于存储图像可能不会留下任何剩余代码供您执行

    修改主 if 语句以在出现以下情况时显示这些新图形:一卷或二十卷。请注意代码行,以显示与图像一起滚动的数字:

    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的骄傲拥有者!

    您进行了哪些修改?您更改图像了吗?在评论中让我们知道,我们很想看看您的工作!

    标签: Arduino 棋盘游戏 电子产品