手把手教你做一个非常酷的PoV显示器(附源码)

关注+星标公众,不错过精彩内容

来源 | DF创客社区

作者 | Amal Shajan

今天为大家分享一个DIY产品,如下:


前两天天我在浏览购物网站的时候,被一个购物清单吸引住了,

5个ATtiny13单片机售价1.5美元。

你敢相信,一个可编程的微控制器,只要0.3美元!于是我打算捡个便宜,买几个回来玩玩。

为了让买回来的ATtiny13不落在角落里吃灰,我上网搜索了 "ATtiny13 Arduino"的关键词,发现Arduino支持ATtiny13,所以我准备拿他搞些事情。

ATtiny13对库的支持有限,所以除了让它点亮几个LED之外,我暂时没有想到其他玩法。

正当我苦苦思索还能做什么时,突然想到了一个很久以前的项目。

那是一个使用ATtiny85的PoV显示器。

(拍出来的效果会闪烁,眼睛看就不会)

PoV显示器基本上是一堆闪烁的LED,并有一些精心安排的延迟。而我发现ATtiny13和ATtiny85都有相同的引脚布局。

那么…… 嘿嘿,我也来做一个!

材料准备

  • 1 x ATtiny13

  • 5个3毫米的LED(也可以用5毫米的LED,3毫米的看起来更好,因为可以更靠近PCB)

  • 1个CR2032电池

  • 1个CR2032电池座

  • 1个滑动开关

  • 原型PCB或定制PCB

  • 电烙铁

什么是PoV显示器,它们是如何工作的?

人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间(1/16秒),光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”。

比如你看一个正常的显示器,像素是以矩阵方式排列的,但在PoV显示器中,像素或者LED则是排列成一个阵列的。就像是你快速翻动小人书那边,由于视觉暂留效应,小人书的人会动起来,这边我们看到的,也不会是一排LED,而是一串字母或者是一幅图像。

Arduino IDE相关设置

你可能正盯着ATtiny13,想知道 "我到底该怎样为这个东西编程,它又没有像Arduino那样的USB接口"。

好吧,要为这个微控制器编程,你需要另一个Arduino,Arduino Nano或Arduino Uno都可以。

下载并安装Arduino IDE。

用USB线将你的Arduino Nano / Uno连接到电脑上。

打开 工具->开发板,选择你的主控板(注意选Uno/Nano而不是ATtiny13)。

现在我们需要将我们的Arduino转换成一个编程器。

在Arduino IDE中,打开文件 -> 示例 -> 11.ArduinoISP -> ArduinoISP

并点击上传按钮。

如果上传成功,就可以用我们的Arduino为其他微控制器编程了。

现在我们还需要在Arduino IDE上安装ATtiny13的硬件包,因为IDE默认不支持ATtiny13。

打开文件 -> 首选项 -> 附加开发版管理器网址

然后粘贴上下面的链接:

https://mcudude.github.io/MicroCore/package_MCUdude_MicroCore_index.json

然后打开工具 -> 开发板 -> 开发板管理器

从列表中找到MicroCore并点击安装。

ok,现在你就可以从Arduino IDE中选择到ATtiny13了。

选择工具 -> 开发板 -> MicroCore -> ATtiny13

我们需要在Arduino IDE中再改变一些选项,

打开工具,并设置以下值:

OptionValue
BoardATtiny13
BOD2.7v
Clock9.6Mhz internal Osc.
Timing"Micors Disabled"
PortSelect Serial Port in which your Arduino is connected
ProgrammerArduino as ISP (MicroCore)

对ATtiny13进行编程

现在可以把ATtiny连接到我们的Arduino了。

把ATtiny连接到Arduino,如下所示(在ATtiny中,针脚1将用一个点. 标记。)

ATtiny13 PinArduino Pin
110
511
612
713
85v
4Ground (GND)

烧录引导程序到ATtiny13

这是一个一次性的设置,不用在每次上传代码到ATtiny时都重复这个设置。

点击 工具->烧录引导程序

这将把引导程序烧到ATtiny上,现在我们就可以用Arduino IDE把程序上传到ATtiny了。

上传PoV程序到ATtiny

在Arduino中新建一个程序。

复制代码并将其粘贴到新创建的程序中。

// https://github.com/B45i/Tiny-PoV
// App to calculate array values: https://pov-display-calc.vercel.app/
// Preact app source: https://github.com/B45i/pov-display-calc

#include <avr/pgmspace.h>

#define DELAY_TIME 1
#define CHAR_BREAK 2

uint8_t leds[] = { 0, 1, 2, 3, 4 };
uint8_t keys[] = { 1, 2, 4, 8, 16 };

void setup() {
  for (uint8_t i = 0; i < 5; i++) {
    pinMode(leds[i], OUTPUT);
  }
}

const PROGMEM uint8_t alphabets[][5] = {
  { 0, 0, 0, 0, 0 },       // Space
  { 30, 5, 5, 30, 0 },     // A
  { 31, 21, 21, 10, 0 },   // B
  { 14, 17, 17, 10, 0 },   // C
  { 31, 17, 17, 14, 0 },   // D
  { 31, 21, 21, 17, 0 },   // E
  { 31, 20, 20, 16, 0 },   // F
  { 14, 17, 19, 10, 0 },   // G
  { 31, 4, 4, 4, 31 },     // H
  { 0, 17, 31, 17, 0 },    // I
  { 0, 17, 30, 16, 0 },    // J
  { 31, 4, 10, 17, 0 },    // K
  { 31, 1, 1, 1, 0 },      // L
  { 31, 12, 3, 12, 31 },   // M
  { 31, 12, 3, 31, 0 },    // N
  { 14, 17, 17, 14, 0 },   // O
  { 31, 20, 20, 8, 0 },    // P
  { 14, 17, 19, 14, 2 },   // Q
  { 31, 20, 22, 9, 0 },    // R
  { 8, 21, 21, 2, 0 },     // S
  { 16, 16, 31, 16, 16 },  // T
  { 30, 1, 1, 30, 0 },     // U
  { 24, 6, 1, 6, 24 },     // V
  { 28, 3, 12, 3, 28 },    // W
  { 17, 10, 4, 10, 17 },   // X
  { 17, 10, 4, 8, 16 },    // Y
  { 19, 21, 21, 25, 0 },   // Z
  { 31, 17, 31, 0, 0 },    // 0
  { 18, 31, 16, 0, 0 },    // 1
  { 29, 21, 23, 0, 0 },    // 2
  { 21, 21, 31, 0, 0 },    // 3
  { 7, 4, 31, 4, 0 },      // 4
  { 23, 21, 29, 0, 0 },    // 5
  { 31, 21, 29, 0, 0 },    // 6
  { 1, 1, 31, 0, 0 },      // 7
  { 31, 21, 31, 0, 0 },    // 8
  { 23, 21, 31, 0, 0 },    // 9
};

void displayLine(uint8_t line) {
  for (uint8_t i = 0; i < 5; i++) {
    digitalWrite(leds[i], (line & keys[i]) == keys[i]);
  }
}

void displayLetter(uint8_t n) {
  for (uint8_t i = 0; i < 5; i++) {
    displayLine(pgm_read_word_near(alphabets[n] + i));
    delay(DELAY_TIME);
  }
  displayLine(0);
}

void displayString(char *s) {
  for (uint8_t i = 0; i < strlen(s); i++) {
    uint8_t index;

    if (s[i] == ' ') {
      index = 0;
    } else if (isalpha(s[i])) {
      index = (uint8_t)toupper(s[i]) - 64;
    } else if (isdigit(s[i])) {
      index = (uint8_t)(s[i]) - 21;
    }

    displayLetter(index);
    delay(CHAR_BREAK);
  }
}

void loop() {
  displayString("HELLO 123 ");
}

如果你想改变显示的文本,可以修改最后一行。

displayString("HELLO 123 "); // 替换成你想要显示的文本

根据你要使用的电机的速度,你可能还需要调整代码,更新变量DELAY_TIMECHAR_BREAK

代码解释

你可能会盯着这段代码思考,一些随机数怎么样能代表一个字符,我们如何用它们来正确地闪烁LED?

我们可能对使用数组来表示字符和图像比较熟悉,像类似这样:

  int a[][5] = {
    {0, 1, 1, 0, 0},
    {1, 0, 0, 1, 0},
    {1, 1, 1, 1, 0},
    {1, 0, 0, 1, 0},
    {1, 0, 0, 1, 0},
  };

  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
      digitalWrite(LEDs[j], a[j][i]);
    }
  }

但是,这种方法会占用大量的内存,而且我们还必须使用多个循环来迭代它们。

现在,对于没有多少处理能力的ATtiny13来说,这并不是一个好方法。

标记的枚举法

我们不使用矩阵来表示一个字符,而是使用一个数组来表示它。

PoV显示器有5行和5列,所以我们可以使用一个长度为5的数组。

该数组中的每个元素将告诉我们是否需要打开某个特定的LED。

我们给每个LED分配一个数字(枚举),这些数字都是2的幂级数。

LEDEnum
LED 12^0= 1
LED 22^1= 2
LED 32^2= 4
LED 42^3= 8
LED 52^4= 16

这些数字有一个特点,用他们组合,所产生的每一个数字的方式是唯一的。

比如:如果我们把2、4和8相加,就会得到14,而这些数字的其他组合不会产生14。

如果一个LED是关闭的,我们用0来表示它。

让我们来看看我们如何表示字母 "A"。

在第一列中,我们必须关闭LED1并打开所有其他的LED。因此,我们可以用0(LED1关闭)+2+4+8+16=30表示。

数组中的其他元素将是:

第1列0 + 2 + 4 + 8 + 16 = 30
第2列1 + 0 + 4 + 0 + 0 = 5
第3列1 + 0 + 4 + 0 + 0 = 5
第4列0 + 2 + 4 + 8 + 16 = 30
第5列0 + 0 + 0 + 0 + 0 = 0 (所有LED全不亮)

我们如何根据这些数字来开启和关闭LED?

很简单,你对数字和LED的枚举进行按位与运算(只有对应的两个二进位都为1时,结果位才为1),如果结果是枚举,我们就需要打开相应的LED。

拿数字30来举个例子:

运算结果LED状态
30 & 1 == 1false关闭LED1
30 & 2 == 2true点亮LED2
30 & 4 == 4true点亮LED3
30 & 4 == 8true点亮LED4
30 & 16 == 16true点亮LED5

30二进制是11110

这个概念通常被称为标记的枚举。

你可以添加更多的字母和数字。

手动生成这些数组是很难的,所以我做了两个应用程序方便大家更好更快地生成数组。

第一个是用Preact编写的,它是专门为这个项目制作的,最多支持5个LED。

地址:https://pov-display-calc.vercel.app/

第二个是用Angular编写的,它可以支持n个LED。

地址:https://po-v-display-calculator.vercel.app/

你也可以用这俩个网页来为其他PoV项目生成代码。

只要使用这些应用程序生成数组,并将代码添加到程序中的数组即可。

建立PoV显示电路

PoV显示电路是相当简单的,可以用下面的电路图来连接电路。

你可以使用原型电路板来焊接电路。

我已经为这个电路设计了一块PCB。如果你使用的是PCB,那么你就不用做任何布线,只需焊接元件就好了。

PCB文件可以在文末下载。

焊接好所有部件,加入电池,打开开关,把它连接到可以旋转的东西上,比如一个微型电机甚至风扇(别忘了根据角速度调整代码中的延迟,这一块儿可能需要一些试验)。

好了,现在你就有一个元件总成本不到1美元的PoV显示器了,试试效果怎么样吧!

祝你玩得开心!

原文链接:

https://www.hackster.io/B45i/make-a-pov-display-with-attiny13-for-1-e94b25

免责声明:本文素材来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。

------------ END ------------

后台回复『硬件DIY』阅读更多相关文章。

欢迎关注我的公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

欢迎关注我的视频号:

点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于MSP430的POV LED显示屏设计WORD论文文档+AD设计硬件原理图PCB+软件源码: 1. 引言 静态LED显示屏如果要加大显示点数,需要增加较多数量的LED,如要将29×10的屏幕行列各加1,变成30×11的屏幕,则需要增加30×11-29×10=40只LED,同时需要再占用2个控制器的IO引脚。另一方面,屏幕在不使用时,仍要占用大量空间,有可能造成空间浪费。 而POV LED屏能克服上述问题,每多增加一行,只要增加一个LED和再占用一个控制器IO引脚,屏幕不使用时,只占用一列LED的空间。这样,大大的节省了资源。 如果利用视觉暂留现象和POV LED技术,用单片机控制旋转中的LED发光时序,使之和电动机的转速匹配,在旋转面形成动态的文字或者图案效果。如替代灯笼,使用简单,更安全更环保。可用于广告宣传、指示、展会等众多领域。其中我们设想将其应用于本身可以提供旋转的车轮上,达到宣传与装饰作用。 美国和欧洲同类研究较多,已有可以在汽车轮毂上运行的彩色POV LED屏研制成功。 在同样亮度下,LED耗电仅为普通白炽灯的1/10、荧光灯的1/3,而寿命却可以延长100倍,发光寿命可达到10万小时以上(可连续使用11年)。静态LED显示屏如果要加大显示点数,需要增加较多数量的LED,占用控制器的IO引脚多。该设计围绕LED线阵上的某个点,或者其延长线上的某个点旋转,成像仅需控制整排LED。改变以往LED点阵方式显示形式,大大减少LED数量,可视角度大大扩展,几乎能360°观看。可以在自行车等轮式交通工具车轮上安装,使信息表现方式更加多样。在倡导低碳的现代社会,节约空间与能源达到同样的效果。制作成本低,显示方式新颖,发展潜力大,应用领域广。 该设计主要难点线路器件阵型的排列,线阵LED在变化的转速下的精准控制得以显示图像,以及图像信息的编码问题。 2. 系统方案 图1 系统设计框图 系统组成: 整个系统分成三个部分:LED显示模块、无线控制模块和电机模块。如图1所示。 电机模块主要是电动机。在具体应用中可以是车轮、风扇等旋转物体。 显示模块安装在电机模块上,由单片机、电机转速检测、LED及显示控制、无线收发等4个子模块组成。显示模块主要完成图像或者文字的显示功能,同时根据无线控制模块传来的控制信号改变显示内容。 无线控制模块由单片机、无线收发和键盘等3个子模块组成。 系统工作原理: 电机模块提供旋转动力。显示模块安装在电机模块之上。由单片机控制32只LED的亮灭时间。当电机旋转的时候,显示模块随电机同步旋转。利用流水灯原理和人眼视觉暂留效应,就能看到一幅具有悬浮效果的文字或者图案。 系统设计

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值