上海极制信息科技有限公司

 找回密码
 立即注册
搜索
热搜: 活动 培训 资料
查看: 3438|回复: 1

Arduino电子密码锁

[复制链接]

40

主题

65

帖子

1418

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1418
发表于 2016-8-16 12:06:04 | 显示全部楼层 |阅读模式
本帖最后由 jizhi01 于 2016-8-16 12:07 编辑


制作了一个基于Arduino微控制器的密码锁,为了方便初学者学习与操作,这里提供了两个版本的电子密码锁源码。

    1、电子密码锁1(没有时间显示)

    2、电子密码锁2(集成了时间显示)


本制作将会应用到如下技术技巧:
1、EEPROM字串存取
2、运用#include文件,把谋些函数(function)调去外部文件
3、简单的旋律处理
4、日期与时间处理
5、如何形成Press and hold
6、矩阵键盘应用与空闲(idle)侦察
7、密码处理与验证
8、i2c LCD应用
9、非阻塞编程(Non blocking programming)

零件与材料
    Arduino UNO
    4x4(或3x4)矩阵键盘
    用于释放门锁的按键(Door button exit switch)
    1K电阻器
    NPN 晶体管
    12V继电器
    电磁锁
    I2C 16X2 LCD(如果不需要显示,可以省略)
    电脑主板扬声器(如果不需要声音提醒,可以省略)
    100 ohm电阻器(随意,连接扬声器与Arduino之间)
    扬声器,最好有低功率扩音器(如果不需要按铃通知,可以省略)
    门铃按键(如果没有使用按铃通告,可以省略)


功能
    LCD显示
    时间显示
    键盘密码输入与验证
    3次密码重试,之后键盘将会禁用一分鈡
    紧急门锁释放
    电源故障,门锁自动释放
    按键声响与声音提醒
    门铃按键与旋律
    通过串口与电脑连接,以便显示密码锁状况


操作与使用

此密码锁预设了两个不同级的密码,称之为USER密码和ADMIN密码。USER密码用于开锁,ADMIN密码则用于设定与更换所有密码。第一次使用密码锁时,EEPROM是空的,因此必须做一次设定重置以便把USER密码和ADMIN密码写入EEPROM。
设定重置
按着RESET键开电,维持按键五秒。听到Do Re Mi声响表示完成重置。
开锁与上锁
输入正确的USER密码(预设是1234)开锁。如果用户是在屋内,可以按下紧急按键来开锁。五秒后,门锁将会自动上锁。
更换密码
    按#进入菜单
    输入ADMIN密码(预设是1234)
    想要更改USER密码,请按1。按2则是更改ADMIN密码
    输入新密码。如不想换密码,隨时按下星(*)键退出
    输入确认密码,(同样新密码)
    听到Do Re Mi声响表示完成更换密码
更换日期与时间
    按#进入菜单
    输入ADMIN密码 (预设是1234)
    按3进入日期与时间设定。如不想更换改日期,隨时按下*键退出
    输入日期,格式为DDMMYYYY,年份必须是四位数。例:三十一曰,十二月,二零一三年,则是输入31122013,年份必须是四位数
    输入时间,格式为HHMMSS,小时(HH)为二十四小时。例:下午五时,四十三分,二十一秒,则是输入174321
    听到Do Re Mi声响表示完成更换日期与时间


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

40

主题

65

帖子

1418

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1418
 楼主| 发表于 2016-8-16 12:08:01 | 显示全部楼层
本帖最后由 jizhi01 于 2016-8-16 12:15 编辑

代码分析
从Arduino IDE里打开CodeLock_with_Time.ino主文件时,在同一文件夹里的所有xxx.h文件会隨之打开,这是由于动用了#include。#include文件的目的是把多个编译单元(也就是c或者cpp文件)公用的内容,单独放在一个文件里减少整体代码尺寸,或者提供跨工程公共代码。


Arduino libraries
eeprom_string.h文件里只有两个函数定义(function header),分别为eeprom_read_string()和eeprom_write_string(),功能如其名,eeprom_read_string()用以读取EEPROM谋地址的字串,eeprom_write_string()则是写入字串至谋EEPROM地址。eeprom_string.h打开后,eeprom_string.ino也隨之打开。
eeprom_string.ino是我更改于Arduino官方网站的EepromUtil例子,由于EepromUtil例子里包含了多个没有使用到的函数,所以我把它简化了以方便编写及容易明白。
Arduino软件已经包含了EEPROM程序库,为何还要编写多一个eeprom程序呢?理由很简单,因为Arduino软件里的EEPROM程序库不支持存取字串(String)。
接下来是matrixKeypad.h文件,这是矩阵键盘的设定。之前是编写在CodeLock_with_Time.ino主文件里,为了更容易处理代码,所以又将之分开了。
最后的是pitches.h文件,用来定义音调。运用了#define谋个常数(constant value)为谋个音调,编写旋律变得很容易了。

#include文件运行完后,接下来是变量与常量设置,可以根据自己的要求而设定。
void setup()
setup创建函数一般用来作初始化,开机后,setup只运行一次。setup里有几行比较特别的代码必须交代一下。
sw_state = digitalRead(RESET_SETTINGS_PIN );
if (sw_state==LOW) reset_settings();
开机时,检查sw_state状态,如果是LOW的话将会执行reset_settings()程序。在什么状况下sw_state才会LOW呢?那就是按着RESET_SETTINGS按钮开机,检验到sw_state是低平后,reset_settings() 程序会运行。以下是reset_settings() 程序的代码
第五行代码while (sw_state == LOW)是用来侦察RESET_SETTINGS按钮,如果是LOW的话将会继续运行第七行代码if ((millis() - start_hold) >= HOLD_DELAY),否则将会回返原来的呼叫位置。维持按着RESET_SETTINGS按钮五秒 ,initializeEEPROM()程序将会运行。这就是所谓的Press and Hold了。
USER_PASSWORD和ADMIN_PASSWORD同时设定为1234,然後写入EEPROM里。完EEPROM写入后,将会听到Do-Re-Mi音调,表示成功EEPROM初始化。
上面程序完成后,接下来是loadConfiguration()程序
loadConfiguration()程序里暂时没有太多的设定,只是把USER_PASSWORD和ADMIN_PASSWORD从EEPROM里读取,然後分别分配给userPassword和adminPassword。当然你也可以把更多的设定值如LOCK_HOLD_TIME,KEYBOARD_EVENT_TIMEOUT,maxPasswordLength等存入EEPROM,隋后读取。
setup创建函数里的最後一行就是welcome()程序了。此时LCD将出现Enter Password字符


void loop()
顾名思义,所有的代码将会在这里不停的运行。

runEventAnyTime()是在loop里的第一个程序。凡事需要不间断处里的事件都可以编写在runEventAnyTime()程序里。
上面的代码用来释放门锁,门铃以及RFID(这功能暂时还没实现),将来还可以置入别的事件,但不允许有delay代码。为何不采用定时器中断(timer interrupt)方式来解决delay问题呢?这是由于ATMega328的所有三个timer(8 bit timer0, 16 bit timer1, 8 bit timer2)都被占用了,逼不得已之下,只好使用polling方式了。
print_date_time()程序是用来显示日期与时间。当然你也可以将之编写在runEventAnyTime()程序里,不过你会遇到一个小问题,我忘记了是什么。
此电子密码锁设计並没有使用RTC(Real Time Clock)IC,当电源中断后,日期与时间会隋之重置,因此必须从新设置日期与时间。不过这并不重要,因为使用这类密码锁通常都设有后备电源以防止电磁锁自动释放。
每次输入错误的密码时,retryCount的值会增一。如果输入三次错误的密码,键盘将会禁用,所以必须有一程序来恢复启动键盘。
当下面代码侦察到retryCount大于零(用户输入了错误的密码)时,将会比较当前的时间和之前的时间加一分钟(AUTO_RESET_RETRY_COUNT * 60000)。AUTO_RESET_RETRY_COUNT预设为一,60000则表示一分钟(1000 millisecond x 60 ),如果超过了一分钟,resetRetryCount()程序将会运行。
resetRetryCount()运行后,键盘又重新启动了。
下面代码用于键盘输入,keypad.getKey()是一个非阻塞矩阵键盘输入,keypad.getKey()是没有等待输入的,它下面的程序会继续运行的。毎一次按键都会产生一beep声响,用来提醒,各自的按键值将会赋予key。输入#号时,就会进入 enterPasswordForMenu()菜单,否则会执行enterPasswordToRelease_DoorLock(key)以便让用户输入密码来打开门锁。当输入了三次(reached_maximum_retries=3)错误的密码 ,键盘输入将会禁用一分钟。

这里有一段很好玩的代码,那就是boolean isTimeout()程序。
每次用户按键时,此程序会不停的运行直至timeout。isTimeout()程序会侦察键盘输入,当用户在谋一段时间内没有按键输入时,我们称之idle(空闲)。空闲10秒后(KEYBOARD_EVENT_TIMEOUT预设为10),程序将会自动退出。
CodeLock_with_Time.ino文件里共有746行代码,似乎很长及复杂,其实不然,这是因为运用了许多print指令丶空白行以及置入了许多注解,另外音调程序方面也占用了不少空间。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|上海极制信息科技有限公司 ( 沪ICP备14016067号

GMT+8, 2018-11-21 13:34 , Processed in 0.127029 second(s), 25 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表