怎样用Arduino驱动OLED显示屏

电子说

1.3w人已加入

描述

想要为您的下一个桌面角色扮演游戏带来一些独特之处吗?带有自定义图形的电子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个7毫米(0.28英寸)垫圈

9V电池卡扣(或合适的替代品)

各种热缩管

这些OLED显示器非常凉。通常可以购买白色,蓝色,黄色或这三种的混合物。我购买了蓝色的,以匹配我的情况。确保您获得的是 I2C 模型而不是 SPI 。

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

电路

这是您需要的电路:

OLED

将OLED显示屏上的 VCC 和 GND 连接到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 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设置

您需要安装两个库来驱动显示。从Github下载Adafruit_SSD1306和Adafruit-GFX [不再可用]库,并将它们保存到您的库文件夹中。如果不确定库文件夹在哪里,请阅读我的复古游戏教程,在该教程中我会更详细地配置相同的显示器。

重新启动Arduino IDE并从 File上传测试草图》示例菜单。选择 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

#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 和 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 number

if (roll 《 10) {

// single character number

display.setCursor(57, 21);

}

else {

// dual character number

display.setCursor(47, 21);

}

这是现在的样子:

现在剩下的只是当您击中关键命中或未命中时的图像。涉及几个步骤,但这是一个足够简单的过程。

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

《图id =“ attachment_617869” aria- describeby =“ caption-attachment-617869” class =“ wp-caption aligncenter”》

图片来源:publicdomainvectors.org

您要使用的任何图片都需要转换到十六进制数组。这是代码形式的图像表示。有许多工具可以执行此操作,其中一些是专门为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?)中而不是其RAM中(RAM的快速指南)。这样做的原因是简单的; 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的骄傲拥有者!

责任编辑:wv

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分