电子说
步骤1:4位7段显示
明显的出发点是熟悉4位7段显示器。这些单元来自我们为教室使用而购买的一些Elegoo stater套件,但最有可能与您在上图中看到的部件一起购买。除了上面的物理设备图像,您还可以看到该设备的引脚和原理图。将Arduino编程为单独的显示字符非常简单,但是要同时显示整个单词或数字是有趣的。与任何7段显示一样,可以通过打开字母段的不同组合来显示数字和一些字符;使用4位7段单元的扭曲是每个数字的所有单个段都连接在一起,每个数字只有它自己的共用阴极或阳极单独控制。实际上,使这些单元显示单词或数字的唯一方法仍然是一次一位数;然而,数字的开启和关闭速度都很快,以至于人眼看起来一直都在。
第2步:理解(和使用)Arduino端口
为了避免使用数以千计的“digitalWrite”命令打开和关闭我需要的所有组合,我决定熟悉Arduino上端口的使用平台。使用此命令(例如:PORTA = B01110101;)可以同时打开和关闭8个数字I/O引脚,其中1表示等于向该引脚写入“高电平”,0表示与写入“低电平”相同到针。每个端口对应Arduino上的8个引脚,可以用二进制(我使用的)或十六进制写入。一个简单的例子是上面的引脚输出中显示的Arduino Mega上的端口F和K,PORTF对应于模拟引脚A0-A7和PORTK,对应于模拟引脚A8-A15。非常感谢Adafruit社区在这个壮观的引脚上的工作!
第3步:全力以赴
虽然上面的图片很难看,但我决定未来编程的最合理布局是将每个4位7段分成上半部分和下半部分,然后将每一半分配给特定端口。这将允许我轻松查看我需要的数字,然后使用二进制输出打开相应的段到相关端口。使用port命令的十六进制版本会使每个命令(实际上是命令调用的2D数组)更短但在布局代码时看起来更容易看到高/低组合而不是必须以十六进制转换那些相同的组合,即使代码从长远来看会更紧凑。为了帮助完成这个过程,我创建了一个图表来显示哪些数字/段与哪个端口分配相关联。您还可以在上图中看到,通过每个数字的共阴极引脚实现限流,而不是限制每个单独的电流。
步骤4:代码 - CountUpDownTimer
在几次尝试运行一系列嵌套for循环以控制时序和显示失败后,我开始研究适用于Arduino的并行处理。最后我遇到了一个名为“CountUpDownTimer”的预先存在的库,可以在这里找到Arduino Playgound。该库在后台为您执行计时,允许您在需要时拨打小时,分钟和秒。然后将这些值作为参数传递给一个数组,该数组打开适当的段以显示相应的数字。唯一的复杂因素(除了创建数组 - 下一步更多)是我必须修改库以添加“ShowDays”方法,该方法不是原始代码的一部分。
#include
CountUpDownTimer T(DOWN, HIGH); //Create the timer object void setup(){
//Setting all digital pins as outputs
for (int i=3; i《=53; i++)
pinMode(i, OUTPUT);
//Setting all analog pins as outputs
for (int a=A0; a《=A15; a++)
pinMode(a, OUTPUT);
T.SetTimer(52,07,17,00); // (days, hours, minutes, seconds)
T.StartTimer();
} void loop() {
T.Timer();
int stepDelay = 50;
long sm = T.ShowMinutes();
long sh = T.ShowHours();
long sd = T.ShowDays();
for(int c = 0; c 《 4; c++){
PORTB = upperArray[sm][c];
PORTL = lowerArray[sm][c];
PORTA = upperArray[sh][c];
PORTC = lowerArray[sh][c];
PORTF = upperArray[sd][c];
PORTK = lowerArray[sd][c];
delayMicroseconds(stepDelay);
}
}
步骤5:代码 - 2D数组
驱动端口的值被放置在一个单独的2D阵列中,该阵列分成两半,一个用于显示器的上半部分,另一个用于下半部分。部分。端口分配基于显示器的引脚,每列代表相应的数字。这里的关键是将高点和低点的适当组合应用于每个连续数字的各个段和适当的共阴极。 2D阵列长270行,占整个学年,四列宽,每个显示四位数。尽管小时和分钟从不调用阵列的大多数,但使用相同的结构来驱动这些显示器而不是每个部分的自定义阵列似乎更容易。上半部分和下半部分的前几行如下所示。我还创建了您在上面看到的图表,显示哪些端口输出与哪些段相对应,以最大限度地减少错误并保持理智。
byte upperArray[270][4]
{B00011111,B00111011,B00111101,B00111111}, //00u
{B00011111,B00111011,B00111101,B00100111}, //01u
{B00011111,B00111011,B00111101,B00110111}, //02u
{B00011111,B00111011,B00111101,B00110111}, //03u
{B00011111,B00111011,B00111101,B00101111}, //04u
{B00011111,B00111011,B00111101,B00111110}, //05u
{B00011111,B00111011,B00111101,B00111110}, //06u
{B00011111,B00111011,B00111101,B00110111}, //07u
{B00011111,B00111011,B00111101,B00111111}, //08u
{B00011111,B00111011,B00111101,B00111111}, //09u
{B00011111,B00111011,B00100101,B00111111}, //10u byte lowerArray[270][4]{
{B00110101,B00110101,B00110101,B00110100}, //00
{B00110101,B00110101,B00110101,B00000100}, //01
{B00110101,B00110101,B00110101,B00110010}, //02
{B00110101,B00110101,B00110101,B00010110}, //03
{B00110101,B00110101,B00110101,B00000110}, //04
{B00110101,B00110101,B00110101,B00010110}, //05
{B00110101,B00110101,B00110101,B00110110}, //06
{B00110101,B00110101,B00110101,B00000100}, //07
{B00110101,B00110101,B00110101,B00110110}, //08
{B00110101,B00110101,B00110101,B00010110}, //09
{B00110101,B00110101,B00000101,B00110100}, //10
步骤6:LCD屏幕 - 后想法
我最初并不想包括静态显示倒计时的日期/时间结束的LCD屏幕;然而,当我为该项目购买BASE时,有一个大小与小面包板大小相当的开放空间,因此它似乎是该项目的合理添加。该显示器是标准的16x2单色白色蓝色显示屏,也来自Elegoo套件。除了数据和控制线的附加布线外,代码修改也很简单;我添加了预处理器功能,包括库和定义用于每个所需连接的引脚,以及在void设置中显示静态消息的代码,这样只运行一次而不影响时序计数器。两种修改如下所示:
#include
const int rs = 17, en = 16, d4 = 21, d5 = 20, d6 = 19, d7 = 18;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print(“Countdown Ends:”);
lcd.setCursor(0, 1);
lcd.print(“5/30/19 @ 3:10pm”);
第7步:结论 - 问题和教训
这个项目中有问题的部分是迄今为止繁琐的部分。首先,在硬件方面,使得所需的40多条数据线的布线看起来很整洁;接下来是2D阵列的创建,它包含显示正确数字所需的高低组合。我必须做的一个小的硬件修改是调整我在每个显示器的第四个数字上使用的限流电阻的大小;由于时间(并假设视觉的持续性),数字总是比其他数字亮一点,所以我增加该值,直到所有四位数的外观看起来均匀。我确信通过某种时间共享或多路复用可能有一种更优雅的方式来实现这一目标,但我从经验中学到了很多东西,并意识到我刚刚开始划清我们所说的这个神奇工具的表面“ Arduino“能够完成。
全部0条评论
快来发表一下你的评论吧 !