我们将继续系列文章,介绍如何使用Arduino 数字实验室套件NR05的功能来研究微控制器的编程,并以Arduino为例并设计有用的电子设备。
我们的材料不会假装成最终设计,但是,正如您将看到的那样,它完全可以实现代码锁的所有基本功能,并且可以很好地说明微控制器的功能和使用外部插件。您可以自行决定重做微控制器的程序,添加或更改锁的功能,同时提高您的编程知识水平。首先,我们将使用扩展板(该套件的一部分)具有两行液晶显示器和5个按钮的事实。我们使用这些元素来构建密码锁。让我们提出以下要求:1.有5个按钮用于输入打开锁的密码;2.最左边的按钮对应于代码1,然后从左到右分别为2,3,4,5;3.输入代码的位数可以是任何数字(在合理范围内),并且可以简单地安装在程序中;4.所拨打的代码以星号显示;5.如果输入的代码与示例代码一致,则将程序中指定的持续时间的正脉冲提供给执行器;6.如果密码输入错误,则会显示一条错误消息。7.如果您部分键入代码,则过一会儿将重置拨号值。8.我们使用套件中随附的显示屏,RGB LED和声音发射器来显示用户友好信息。9.我们将打开一个真正的由12伏电压供电的机电锁。现在,我们拿起将对锁施加打开电压的设备。根据我们将要打开的电动机械锁的密码,该电压为12伏,电流约为1安培。 NR05套件扩展板无法在这样的电压和电流下工作,因此需要一个附加的开关模块。此类模块可以是Master Kit提供的MP515继电器,也可以是MP2211,MP4411继电器单元取决于我们是否不仅要控制锁,还要控制其他设备,例如,在门打开时打开灯。所有这些设备都与Arduino控制信号电平兼容。在我们的特殊情况下,我们使用MP2211-具有两个继电器的模块。鉴于以上所述,我们将绘制所用设备的连接图:
如果您仔细观察扩展板的标记,我们将看到GREEN RGB LED的绿色通道和CH3继电器的输出连接到D9 Arduino Nano的一个引脚。在这种情况下,这是允许的,因为继电器控制电路的输入具有足够高的输入电阻,并且引脚D9仅用作数字输出。通常,您应该检查所用电路板的引脚是否连接到相同的Arduino引脚,并避免这种情况。锁在工作期间会消耗大量电流,因此我们分别为锁和控制电路供电。这是在扰流板Arduino中工作的草图// RGB-
// NR05
//-------------------------------------------------------------------
// LiquidCrystalRus
#include <LiquidCrystalRus.h>
#include <LineDriver.h>
#include <LiquidCrystalExt.h>
// RGB-
#define red 5
#define blue 6
#define green 9
#define beep 12
// ,
#define NUM_KEYS 5
// ( )
int adcKeyVal[NUM_KEYS] = {30, 150, 360, 535, 760};
///////////////////////////////////////////////////////////
// ,
#define codeLength 6
// , , . codeLength
const int codeOrigin[codeLength] = {1, 2, 3, 4, 5, 3};
// ,
const int unlockTime = 400;
///////////////////////////////////////////////////////////
//
int codePressed[codeLength];
// ( )
int pressCount;
//
unsigned long oldTime;
unsigned long currentTime;
const int timeout = 5; // , .
//-----------------------------------------------------------------------
// , RS,EN,DB4,DB5,DB6,DB7
LiquidCrystalRus lcd(A1, A2, A3, 2, 4, 7);
//-----------------------------------------------------------------------
// 1 Arduino
void setup()
{
// LCD: 16 2
lcd.begin(16, 2);
// ()
// « »
lcd.print(« »);
//
lcd.setCursor(0,1);
lcd.print(«t.: „);
lcd.print(unlockTime);
lcd.print(“ »);
// 2000 = 2
delay(2000);
//
lcd.clear();
//
pressCount = 0;
// « » RGB-
pinMode(red, OUTPUT);
pinMode(blue, OUTPUT);
pinMode(green, OUTPUT);
pinMode(beep, OUTPUT);
}
//-----------------------------------------------------------------------
// setup .
void loop() {
// ( ),
currentTime = millis();
// ,
if (currentTime — oldTime <= timeout*1000){
// key
int key;
// , get_key
key = get_key();
lcd.setCursor(0, 0);
lcd.print(« :»);
//
digitalWrite(blue, HIGH);
if (key > 0){ //
codePressed[pressCount] = key; //
// (50 )
digitalWrite(beep, HIGH);
delay(50);
digitalWrite(beep, LOW);
// ,
lcd.setCursor(pressCount, 1);
lcd.print('*');
digitalWrite(blue, LOW);
delay(200);
digitalWrite(blue, HIGH);
pressCount++; //
//
oldTime = currentTime;
}
}
// ,
else{
pressCount = 0;
lcd.clear();
oldTime = currentTime;
}
// , : codeOrigin codePressed
if (pressCount == codeLength){
int compareResult = 1;
for (int i = 0; i < codeLength; i++)
if (codeOrigin[i] != codePressed[i])
compareResult = 0; //
//
if (compareResult == 1){ //
digitalWrite(blue, LOW);
digitalWrite(green, HIGH);
lcd.setCursor(0, 0);
lcd.print(« „);
delay(unlockTime);
digitalWrite(green, LOW);
pressCount = 0;
delay(1000);
lcd.clear();
digitalWrite(blue, HIGH);
}
//
else {
lcd.setCursor(0, 1);
lcd.print(“ »);
digitalWrite(blue, LOW);
digitalWrite(red, HIGH);
digitalWrite(beep, HIGH);
delay(2000);
pressCount = 0;
lcd.clear();
digitalWrite(beep, LOW);
digitalWrite(blue, HIGH);
digitalWrite(red, LOW);
}
}
}
//-----------------------------------------------------------------------
//
// ,
// ,
int get_key()
{
int input = analogRead(A6);
int k;
for(k = 0; k < NUM_KEYS; k++)
if(input < adcKeyVal[k])
return k + 1;
return 0;
}
//
草图清单提供了详细的注释,以帮助您理解该程序。不过,我们提醒您注意其某些功能。正如我们已经写的,在扩展板上使用了仅使用一个Arduino引脚的按钮连接方案。这样的方案节省了微处理器的输出,但是不允许同时处理几个按钮的同时按下,但是在我们的情况下,这是不必要的。注意草图末尾的get_key函数。如果未按下任何按钮,则函数返回0;如果按下,则返回按下的按钮的编号。还要看一下比较两个数组的实现:引用和键入的代码:int compareResult = 1;对于(int i = 0; i <codeLength; i ++)如果(codeOrigin [i]!= codePressed [i])compareResult = 0; //如果至少一对元素不相等,那么这种比较算法的问题经常在编程论坛上讨论,但是每次都归结为元素比较,在我们的案例中就使用了这种方法。如果具有相同索引的数组的元素相等,则compareResult变量将保持等于1;如果至少一对元素不匹配,则compareResult变量将变为等于0。为了显示西里尔字母,使用了由Ilya Danilov开发的LiquidCrystalRus库。为了使库正常工作,草图标题中必须包含三行:#include <LiquidCrystalRus.h>#include <LineDriver.h>#include <LiquidCrystalExt.h>并且显示初始化应如下所示:LiquidCrystalRus lcd(A1,A2,A3、2、4、7);输入代码的长度由预定义的codeLength常量指定,例如,对于六单击代码#define codeLength 6下一行指定了六单击代码的参考值数组:const int codeOrigin [codeLength] = {1、2、3、4、5、3} ;花括号中的值的数量必须等于codeLength。如果有更多的值,则编译器将引发错误;如果有更少的值,则将没有错误,但是随机值将用作缺少的元素,这将使键入将打开锁的代码成为可能。程序每5秒钟重置一次键入的代码元素。如果按下了按钮,则将记住按下的时间,并且五秒钟间隔的倒计时再次开始。这是使用内置函数millis()实现的,该函数返回自草图开始以来经过的毫秒数以及变量oldTime和currentTime。这是一个简短的视频,演示了代码锁的操作:对于好奇和好奇的电子程序员,您可以提出一些其他想法,以使草图自动完成,并在电路中包含一些模块,以扩展城堡的功能。例如,在程序中输入主代码,借助该主代码,锁将进入编程模式,并记住按下的按钮作为参考代码,以免在草图中更改此代码。如果两次点击之间的间隔超过一定的时间,则结束对新代码的编程。或依赖材料与Arduino的通过蓝牙智能手机的交互,使打开的这个最智能手机发送代码锁。您也可以直接在我们的设备中输入无线控制频道。为此,只需使用两个模块:发送器MP910和具有继电器输出MP911的单通道接收器,其工作频率为433 MHz。MP2211模块的继电器触点与遥控器上的按钮并联连接,接收器模块的继电器与锁具连接。控制距离可达100 m。学习Arduino,学习微控制器及其编程-您可以创建许多智能且有用的电子设备!