Malay
颜色选择
阳光橙
深夜黑
天空蓝
葡萄紫
薄荷绿
深海蓝
首页
论坛
佳礼报道
新闻
搜索
3767
查看
16
回复

[原创] Arduino电子密码锁兽

[复制链接]

楼主: 西门庆33       显示全部楼层   阅读模式

楼主
发表于 18-9-2013 12:13 AM | 显示全部楼层 |阅读模式

一个基于Arduino微控制器的密码锁,一般用于防盗门。除了没有实现RFID(RFID将在下一版本实现),功能已经非常完善了。为了方便初学者学习与操作,这里提供了两个版本的电子密码锁源码。代码比较长,直接下载好了。


读完文章与明白程序操作后,你将会如何应用:
  • EEPROM字串存取
  • 运用#include文件,把谋些函数(function)调去外部文件
  • 简单的旋律处理
  • 日期与时间处理
  • 如何形成Press and hold
  • 矩阵键盘应用与空闲(idle)侦察
  • 密码处理与验证
  • i2c LCD应用
  • 非阻塞编程(Non blocking programming)


零件与材料
  • Arduino UNO
  • 4x4(或3x4)矩阵键盘
  • 用于释放门锁的按键(Door button exit switch)
  • 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声响表示完成更换日期与时间

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

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文件运行完后 ,接下来是变数与常数设置,可以根据自己的要求而设定。

CodeLock_with_Time.ino文件里共有746行代码,似乎很长及复杂,其实不然,这是因为运用了许多print指令丶空白行以及置入许多注解,另外音调程序方面也占用了不少空间。


更详细
代码说明请浏览
http://www.ediy.com.my/index.php/2012-10-21-15-15-03/2013-04-14-05-06-50/item/79-arduino电子密码锁

此电子密码锁用来控制这类电磁锁
Electromagnetic lock.jpg



本帖最后由 西门庆33 于 18-9-2013 12:41 AM 编辑

回复

使用道具 举报

楼主
 楼主| 发表于 18-9-2013 12:22 AM | 显示全部楼层
为了方便阅读与参考,还是把主文件代码贴在这里
  1. /*
  2. * Arduino DIY Code Lock with Time
  3. * by smching www.ediy.com.my
  4. *
  5. * LiquidCrystal_I2C library
  6. * http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)
  7. *
  8. * Keypad library
  9. * http://playground.arduino.cc/code/Keypad
  10. *
  11. * keypad columns = 2,3,4,5
  12. * keypad rows = 6,7,8,9
  13. * reset settings pin = 11
  14. * lock open switch = 12
  15. * door lock relay = 13
  16. * bell switch = A0 (14)
  17. * bell = A2 (16)
  18. * mini_speaker = A3 (17)
  19. * lcd a4, a5
  20. */


  21. // http://forum.arduino.cc/index.php/topic,46900.0.html
  22. #define DEBUG //comment this line if you want to disable serial message
  23. #ifdef DEBUG
  24.   #define DEBUG_PRINT(x) Serial.print(x)
  25.   #define DEBUG_PRINTLN(x) Serial.println(x)
  26. #else
  27.   #define DEBUG_PRINT(x)
  28.   #define DEBUG_PRINTLN(x)
  29. #endif

  30. #include <eeprom_string.h>      // http://playground.arduino.cc/Code/EepromUtil
  31. #include <Wire.h>               // I2C library, allows you to communicate with I2C/TWI devices
  32. #include <LiquidCrystal_I2C.h>  // I2C LCD library
  33. #include <Keypad.h>             // library for using matrix style keypads
  34. #include "pitches.h"            // constant value for pitches
  35. #include "matrixKeypad.h"       // define 4x4 or 3x4 matrix keypad
  36. #include <Time.h>

  37. // http://www.leonardomiliani.com/2012/come-gestire-loverflow-di-millis/?lang=en
  38. // Arduino versions have a max value of 4294967295 or about 49 days and 17 hours
  39. // delay(), millis() and micros() uses timer0
  40. // millis() will overflow (go back to zero) after 49 days and 17 hours
  41. // use to reset timer0 in order to prevent timer overflow
  42. // declaring this after wiring.c
  43. // extern volatile unsigned long timer0_overflow_count;

  44. // press and hold variable
  45. int reset_settings_pin  = 11; //hold the switch in order to restore settings
  46. int sw_state = HIGH;

  47. int release_lock_switch_pin = 12;  //a switch use to release door lock without input password
  48. #define DOOR_LOCK_PIN 13           //connect relay to digital 13
  49. #define LOCK_HOLD_TIME 5        //if door lock is released, lock it after 5 seconds

  50. int bell_switch_pin = 14;          //connect bell switch to Analog 0 (digital 14)
  51. #define BELL_PIN 16                //connect BELL to Analog 2 (digital 16)
  52. boolean isPlayingMelody = false;   //indicating melody is playing or not
  53. boolean stopPlayingMelody = false; // forcing melody to stop playing if stopPlayingMelody = true

  54. #define MINI_SPEAKER_PIN 17             //connect speaker to Analog 3 (digital 17)

  55. // set the LCD address to 0x27 for a 16 chars and 2 line display
  56. // http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)
  57. // Uno, Ethernet  A4 (SDA), A5 (SCL)
  58. // Mega2560          20 (SDA), 21 (SCL)
  59. // Leonardo          2 (SDA), 3 (SCL)
  60. // Due                  20 (SDA), 21 (SCL), SDA1, SCL1
  61. LiquidCrystal_I2C lcd(0x27,16,2);  

  62. // timeout variable
  63. unsigned long previousMillis = 0;   //hold the current millis     
  64. #define KEYBOARD_EVENT_TIMEOUT 10   //timeout (in second) for keyboard input

  65. // Actions
  66. #define ADMIN 0     //use to change ADMIN password
  67. #define USER 1      //use to change USER password
  68. byte action = USER; //action is set to USER now


  69. ////////////////////////////////////////////////////////////////////////////////
  70. // password variable
  71. ////////////////////////////////////////////////////////////////////////////////
  72. String userPassword;              //variable to hold USER password
  73. String adminPassword;             //variable to hole ADMIN password
  74. const byte maxPasswordLength = 4; //length of ADMIN & USER password, not more than 10

  75. char buf[maxPasswordLength + 1];           //temporary storage for EEPROM data, hold the string read/write from EEPROM
  76. #define USER_PASSWORD_EEPROM_ADDRESS 0     //EEPROM address to store USER password
  77. #define ADMIN_PASSWORD_EEPROM_ADDRESS 10   //EEPROM address to store ADMIN password


  78. ////////////////////////////////////////////////////////////////////////////////
  79. // variable for password retry
  80. ////////////////////////////////////////////////////////////////////////////////
  81. const byte MAX_PASSWORD_RETRY = 3;        //Maximum number of retry
  82. byte retryCount = 0;                      //number of retry, start from 0
  83. boolean reached_maximum_retries = false;  //use to disable keyboard input
  84. const byte AUTO_RESET_RETRY_COUNT = 1;    //use to reset (in minute) for password retry count


  85. ////////////////////////////////////////////////////////////////////////////////
  86. // these code will be execute on each Arduino reset
  87. ////////////////////////////////////////////////////////////////////////////////
  88. void setup(){
  89.   Serial.begin(19200);
  90.   lcd.init();                        // initialize the lcd
  91.   lcd.backlight();                   // turn on LCD back light  
  92.   
  93.   pinMode(DOOR_LOCK_PIN, OUTPUT);    // set DOOR_LOCK_PIN as output
  94.   digitalWrite(DOOR_LOCK_PIN, HIGH); // lock the door
  95.   
  96.   pinMode(release_lock_switch_pin, INPUT);     // set release_lock_switch_pin as input
  97.   digitalWrite(release_lock_switch_pin, HIGH); // turn on pullup resistors & set release_lock_switch_pin HIGH

  98.   pinMode(BELL_PIN, OUTPUT);           // set BELL_PIN as output
  99.   pinMode(bell_switch_pin, INPUT);     // set bell_switch_pin as input
  100.   digitalWrite(bell_switch_pin, HIGH); // turn on pullup resistors & set bell_switch_pin HIGH
  101.   
  102.   //use to initialize EEPROM for first time use
  103.   pinMode(reset_settings_pin , INPUT);          // Set the reset_settings_pin  as input
  104.   digitalWrite(reset_settings_pin , HIGH);      // turn on pullup resistor & set reset_settings_pin  to HIGH
  105.   sw_state = digitalRead(reset_settings_pin );  // read input value from reset_settings_pin
  106.   if (sw_state==LOW) reset_settings();     // proceed write configuration routine if reset_settings_pin =high
  107.   
  108.   loadConfiguration();                         // load settings from EEPROM
  109.   Serial.println("Arduino DIY Code Lock");
  110.   Serial.println("by smching www.ediy.com.my");
  111.   welcome();                                   // show welcome message
  112. }


  113. ////////////////////////////////////////////////////////////////////////////////
  114. // main loop
  115. ////////////////////////////////////////////////////////////////////////////////
  116. void loop(){
  117.   runEventAnyTime(); // codes inside runEventAnyTime() will keep on updating
  118.   print_date_time();
  119.   // retryCount increase by one each time an incorrect password has been entered
  120.   // retryCount will reset to zero when idle for one minute (set by AUTO_RESET_RETRY_COUNT)
  121.   if (retryCount > 0) { //if someone have entered wrong password
  122.     if (millis() >= previousMillis + AUTO_RESET_RETRY_COUNT * 60000) {
  123.       resetRetryCount();
  124.     }
  125.   }

  126.   if (!reached_maximum_retries) { // if did not reach maximum number of retry
  127.     char key = keypad.getKey();   //waiting for keyboard input (non blocking)
  128.     if (key != NO_KEY){           //if press a key
  129.       beep();
  130.       delay(30);                  //debounce
  131.       if (key == '#')  enterPasswordForMenu();     //require to enter password before proceed to menu selection
  132.       else enterPasswordToRelease_DoorLock(key);   //otherwise proceed to enterPasswordToRelease_DoorLock routine
  133.      }
  134.   }
  135. }


  136. ////////////////////////////////////////////////////////////////////////////////
  137. // clear one line from lcd
  138. ////////////////////////////////////////////////////////////////////////////////
  139. void clear_lcd_line(byte y) {
  140.   y = y-1;
  141.   lcd.setCursor(0, y);
  142.   lcd.print("                ");
  143.   lcd.setCursor(0, y);
  144. }


  145. ////////////////////////////////////////////////////////////////////////////////
  146. // clear screen & show welcome message
  147. ////////////////////////////////////////////////////////////////////////////////
  148. void welcome() {
  149.   DEBUG_PRINTLN(); DEBUG_PRINT("Please enter password. ");
  150.   DEBUG_PRINTLN(retryCount);
  151.   lcd.clear(); lcd.print("Enter Password "); lcd.print(retryCount);  
  152. }


  153. ////////////////////////////////////////////////////////////////////////////////
  154. // show date and time on lcd
  155. ////////////////////////////////////////////////////////////////////////////////
  156. void print_date_time() {
  157.   lcd.setCursor(0, 1);        //second line (x=0, y=1)

  158.   if(day() < 10) lcd.print('0');
  159.   lcd.print(day());
  160.   lcd.print("-");

  161.   if(month() < 10) lcd.print('0');
  162.   lcd.print(month());
  163.   lcd.print("   ");

  164.   if(hour() < 10) lcd.print('0');
  165.   lcd.print(hour());
  166.   lcd.print(":");
  167.   
  168.   
  169.   if(minute() < 10) lcd.print('0');  
  170.   lcd.print(minute());  
  171.   lcd.print(":");
  172.   
  173.   if(second() < 10) lcd.print('0');
  174.   lcd.print(second());
  175. }


  176. ////////////////////////////////////////////////////////////////////////////////
  177. // load settings from EEPROM
  178. ////////////////////////////////////////////////////////////////////////////////
  179. void loadConfiguration() {
  180.   eeprom_read_string(USER_PASSWORD_EEPROM_ADDRESS, buf, maxPasswordLength + 1);  //read USER password from EEPROM
  181.     userPassword = buf;   //use this password to release door lock
  182.   eeprom_read_string(ADMIN_PASSWORD_EEPROM_ADDRESS, buf, maxPasswordLength + 1); //read ADMIN password from EEPROM
  183.     adminPassword = buf;  //use this password to enter menu selection
  184. }


  185. ////////////////////////////////////////////////////////////////////////////////
  186. // press a switch to release door lock
  187. ////////////////////////////////////////////////////////////////////////////////
  188. void press_release_lock_switch() {  
  189.   if (digitalRead(release_lock_switch_pin) == LOW) {
  190.     lockRelease();                    // release door lock
  191.     resetRetryCount();
  192.   }
  193. }


  194. ////////////////////////////////////////////////////////////////////////////////
  195. // press a switch to ring the bell
  196. ////////////////////////////////////////////////////////////////////////////////
  197. void press_bell_switch() {  
  198.   if (isPlayingMelody) return; // do not play melody if it is currently playing
  199.   
  200.   if (digitalRead(bell_switch_pin) == LOW) {
  201.     playMelody();       // ring the bell
  202.     //generate a short pulse (100 milli seconds) at BELL_PIN
  203.     //digitalWrite(BELL_PIN, HIGH);
  204.     //delay(100);
  205.     //digitalWrite(BELL_PIN, LOW);
  206.   }
  207. }


  208. ////////////////////////////////////////////////////////////////////////////////
  209. // read RFID tag
  210. ////////////////////////////////////////////////////////////////////////////////
  211. void read_RFID() {  
  212.   /*
  213.   rfid.seekTag(); // start seek mode
  214.   if (rfid.available()) {
  215.      DEBUG_PRINTLN(rfid.getTagString());
  216.      lockRelease();                    // release door lock
  217.      resetRetryCount();     
  218.   }
  219.   */
  220. }


  221. ////////////////////////////////////////////////////////////////////////////////
  222. // write whatever code here if require continuous updates
  223. // make sure no delay or blocking
  224. ////////////////////////////////////////////////////////////////////////////////
  225. void runEventAnyTime() {
  226.   // press a switch to release door lock without enter password
  227.   press_release_lock_switch();
  228.   // press a switch to ring the bell
  229.   press_bell_switch();
  230.   // read tag & release door lock if verified
  231.   read_RFID();
  232. }

  233.   
  234. ////////////////////////////////////////////////////////////////////////////////
  235. // reset retry count & enable keyboard input
  236. ////////////////////////////////////////////////////////////////////////////////
  237. void resetRetryCount() {
  238.     retryCount = 0;                   //reset retry count
  239.     reached_maximum_retries = false;  // enable keyboard input
  240.     welcome();
  241. }  


  242. ////////////////////////////////////////////////////////////////////////////////
  243. // input password for menu
  244. ////////////////////////////////////////////////////////////////////////////////
  245. void enterPasswordForMenu() {
  246.   String inputPassword = "";
  247.   clear_lcd_line(2); // clear second line
  248.      
  249.   // get input from keyboard
  250.   // only accept 0,1,2,3,4,5,6,7,8,9 key
  251.   // an * is print to the second line of LCD when a key is pressed  
  252.   inputPassword = getInput('1','6', maxPasswordLength, false);
  253.   if (inputPassword.length() > 0) { // if user had input the password
  254.     // compare input password with ADMIN password
  255.     // unlock the Door Lock if a correct password had been enter
  256.     // otherwise output warning alert & increase retry by one
  257.     if (isCorrectPassword(inputPassword, adminPassword)) {
  258.       playOKTone();
  259.       playWarningTone();
  260.       menuSelection();  // let user make a selection
  261.     } else {
  262.       processFailedPassword(); //something must be done when user enter wrong password
  263.       
  264.     }
  265.   }
  266.   if (retryCount < MAX_PASSWORD_RETRY) welcome();  
  267. }


  268. ////////////////////////////////////////////////////////////////////////////////
  269. // let user make a selection
  270. // valid key ranged from 1 to 6
  271. ////////////////////////////////////////////////////////////////////////////////
  272. void menuSelection() {
  273.   DEBUG_PRINTLN(); DEBUG_PRINT("Selection (1-6): ");
  274.   lcd.clear(); lcd.print("Selection (1-6)");   
  275.   
  276.   // get input from keyboard
  277.   // only accept 1,2,3,4,5 key
  278.   String selectedMenuString = getInput('1','6', 1, true);
  279.   
  280.   if (selectedMenuString.length() > 0) { // if user made an selection
  281.     if (selectedMenuString == "1") {     // user select 1
  282.       action = USER;                     // indicated user want to change USER password
  283.       changePassword();                  // proceed with change password routine
  284.     }
  285.     if (selectedMenuString == "2") {    // user select 2
  286.       action = ADMIN;                   // indicated user want to change USER password
  287.       changePassword();                 // proceed with change password routine
  288.     }
  289.     if (selectedMenuString == "3") {    // user select 3
  290.       setDateTime();
  291.     }     
  292.     if (selectedMenuString == "4") {    // user select 4
  293.       //addTag();        // add an RFID tag
  294.     }   
  295.     if (selectedMenuString == "5") {    // user select 5
  296.       //deleteTag();     // delete an RFID tag
  297.     }  
  298.     if (selectedMenuString == "6") {    // user select 6
  299.       //deleteAllTag();  // delete all RFID tag
  300.     }   
  301.    
  302.   }
  303.   welcome();
  304. }


  305. ////////////////////////////////////////////////////////////////////////////////
  306. // input password to unlock DOOR LOCK
  307. ////////////////////////////////////////////////////////////////////////////////
  308. void enterPasswordToRelease_DoorLock(char key) {
  309.   DEBUG_PRINT("*");
  310.   clear_lcd_line(2); // clear second line
  311.   lcd.print("*");     
  312.   // get input from keyboard
  313.   // only accept 0,1,2,3,4,5,6,7,8,9 key
  314.   // an * is print to the second line of LCD when a key is pressed  
  315.   String inputPassword = getInput('0','9', maxPasswordLength-1, false);
  316.   if (inputPassword.length() > 0) { // if user had input the password
  317.     inputPassword = key + inputPassword;
  318.    
  319.     // compare input password with USER password
  320.     // open the door if correct password had been enter
  321.     // otherwise output warning alert & increase retry count by one
  322.     if (isCorrectPassword(inputPassword, userPassword)) {
  323.       //DEBUG_PRINTLN("Password accepted.");
  324.       //lcd.clear();
  325.       //lcd.print("Pwd accepted.");
  326.       retryCount = 0;
  327.       lockRelease();
  328.     } else {
  329.       processFailedPassword();
  330.     }
  331.   }
  332.   if (retryCount < MAX_PASSWORD_RETRY) welcome();  
  333. }


  334. ////////////////////////////////////////////////////////////////////////////////
  335. // incorrect password had been enter
  336. ////////////////////////////////////////////////////////////////////////////////
  337. void processFailedPassword() {
  338.   playWarningTone();
  339.   retryCount = retryCount + 1;
  340.   if (retryCount == MAX_PASSWORD_RETRY) { // reached maximum retries
  341.      DEBUG_PRINTLN(); DEBUG_PRINT("Reached maximum retries, wait ");
  342.      DEBUG_PRINT(AUTO_RESET_RETRY_COUNT);
  343.      DEBUG_PRINTLN(" minute.");
  344.      lcd.clear(); lcd.print("Wait "); lcd.print(AUTO_RESET_RETRY_COUNT); lcd.print(" minute.");
  345.      reached_maximum_retries = true;     //cause main loop disable keyboard input
  346.   }  
  347. }


  348. ////////////////////////////////////////////////////////////////////////////////
  349. // a sub routine for keyboard input with timeout
  350. // timeout occured if user did not press any key within certain amount time (set by KEYBOARD_EVENT_TIMEOUT)
  351. // lowKey & highKey limit input range from lowKey to highKey
  352. // maxStringLength control how many alphanumeric will be enter
  353. // show input key when showKey=true, otherwise show "*"
  354. ////////////////////////////////////////////////////////////////////////////////
  355. String getInput(char lowKey, char highKey, byte maxStringLength, boolean showKey) {
  356.   boolean inputIsValid = false; // indicate valid password had been enter
  357.   String inputString = "";
  358.   byte inputStringLength = 0;
  359.   previousMillis = millis(); // use by timeout

  360.   while (!isTimeout()) {         // loop until timeout
  361.     char key = keypad.getKey();  // waiting for keyboard input
  362.     if (key != NO_KEY){          // if a key is pressed
  363.       previousMillis = millis(); // reset timeout so that the timeout will not occur
  364.       beep();                    
  365.       if (key == '*') break;     // exit loop if user press a * key
  366.       if (key >= lowKey && key <= highKey) { // user press a key which is acceptable
  367.         if (showKey) {
  368.           DEBUG_PRINT(key);
  369.           lcd.print(key);
  370.         } else {  
  371.           DEBUG_PRINT("*");
  372.           lcd.print("*");
  373.         }
  374.         inputStringLength++;
  375.         inputString = inputString + key;
  376.         if (inputString.length() >= maxStringLength) { // if input reach maxStringLength
  377.           inputIsValid = true;                         // indicated user had enter string (eg. password)
  378.           break;                                       // and then exit the loop
  379.         }  
  380.       } else playWarningTone();                            // alert user if unacceptable key is pressed
  381.     }
  382.   }
  383.   if (!inputIsValid) inputString = "";                 // if did not enter any input, return blank
  384.   return inputString;                                  // otherwise return inputString
  385. }


  386. ////////////////////////////////////////////////////////////////////////////////
  387. // compare input password with USER/ADMIN password
  388. ////////////////////////////////////////////////////////////////////////////////
  389. boolean isCorrectPassword(String inputPassword, String password) {
  390.   if (inputPassword == password) return true; else return false;
  391. }


  392. ////////////////////////////////////////////////////////////////////////////////
  393. // send LOW to DOOR_LOCK_PIN in order to release the Door Lock
  394. // lock the door after certain amount of time (defined by LOCK_HOLD_TIME)
  395. ////////////////////////////////////////////////////////////////////////////////
  396. void lockRelease() {
  397.   if (isPlayingMelody) stopPlayingMelody = true;

  398.   DEBUG_PRINTLN("Lock released.");
  399.   lcd.clear(); lcd.print("Lock released.");   
  400.   digitalWrite(DOOR_LOCK_PIN, LOW);  // release door lock
  401.   playOKTone();
  402.   
  403.   clear_lcd_line(2); // clear second line
  404.   previousMillis = millis();
  405.   // wait for 5 seconds (LOCK_HOLD_TIME is set to 5 by default)
  406.   while (true) {
  407.     if (millis() >= previousMillis + LOCK_HOLD_TIME *1000) break;
  408.     print_date_time();
  409.     //lcd.print(lcd.print((millis() / 1000) % 60UL));
  410.   }

  411.   // timer0_overflow_count = 0; //reset timer0 in order to prevent timer overflow after 49 days
  412.   
  413.   digitalWrite(DOOR_LOCK_PIN, HIGH); // lock the door  
  414.   playTimeOutTone();
  415. }


  416. ////////////////////////////////////////////////////////////////////////////////
  417. // change USER password or ADMIN password
  418. ////////////////////////////////////////////////////////////////////////////////
  419. void changePassword() {
  420.   if (action == ADMIN) {
  421.     DEBUG_PRINTLN(); DEBUG_PRINT("Admin Password: ");
  422.     lcd.clear(); lcd.print("Admin Password");
  423.   } else  {
  424.     DEBUG_PRINTLN(); DEBUG_PRINT("User Password: ");
  425.     lcd.clear(); lcd.print("User Password");   
  426.   }
  427.   
  428.   clear_lcd_line(2); // clear second line
  429.   String newPassword = getInput('0','9', maxPasswordLength, false); // waiting for new password
  430.   if (newPassword.length() > 0) { // if new password had been enter
  431.     DEBUG_PRINTLN(); DEBUG_PRINT("Confirm Password: ");
  432.     lcd.clear(); lcd.print("Confirm Password");
  433.     clear_lcd_line(2); // clear second line
  434.     String confirmPassword = getInput('0','9', maxPasswordLength, false); // waiting for confirm password
  435.     if (confirmPassword.length() > 0 && newPassword == confirmPassword) {
  436.         action == USER;
  437.         updatePassword(newPassword); // update old password with new password
  438.         playOKTone();
  439.     }
  440.   }
  441.   welcome();   
  442. }


  443. ////////////////////////////////////////////////////////////////////////////////
  444. // update old password with new password
  445. ////////////////////////////////////////////////////////////////////////////////
  446. void updatePassword(String newPassword){
  447.   char newPasswordChar[maxPasswordLength + 1];
  448.   newPassword.toCharArray(newPasswordChar, maxPasswordLength+1); //convert string to char array
  449.   strcpy(buf, newPasswordChar);
  450.   if (action == ADMIN) {
  451.     adminPassword = newPassword;
  452.     eeprom_write_string(ADMIN_PASSWORD_EEPROM_ADDRESS, buf);
  453.     DEBUG_PRINTLN();
  454.     DEBUG_PRINT("ADMIN password changed to ");
  455.   }  else {
  456.     userPassword = newPassword;
  457.     eeprom_write_string(USER_PASSWORD_EEPROM_ADDRESS, buf);
  458.     DEBUG_PRINTLN(); DEBUG_PRINT("USER password changed to ");   
  459.   }  
  460.   
  461.   DEBUG_PRINTLN(newPassword);
  462.   lcd.clear(); lcd.print("Password changed");
  463.   delay(1000);
  464.   //lcd.print(newPassword);
  465.   welcome();
  466. }

  467. ////////////////////////////////////////////////////////////////////////////////
  468. // set date and time
  469. ////////////////////////////////////////////////////////////////////////////////
  470. void setDateTime() {
  471.   byte hh, mm, ss, dd, mo, yy;
  472.   DEBUG_PRINTLN(); DEBUG_PRINT("Date (ddmmyyyy): "); // The full four digit year (eg. 2013)
  473.   lcd.clear(); lcd.print("Date (ddmmyyyy):");
  474.   lcd.cursor(); // show cursor
  475.   lcd.setCursor(0,1); //second line
  476.   if(day() < 10) lcd.print('0'); lcd.print(day());
  477.   if(month() < 10) lcd.print('0'); lcd.print(month());
  478.   if(year() < 10) lcd.print('0'); lcd.print(year()); // show current date
  479.   lcd.setCursor(0,1); //second line
  480.   String newDate = getInput('0','9', 8, true); // date input
  481.   dd = (newDate.substring(0, 2)).toInt(); // get frist two lettter from newDate and convert it to integer
  482.   mo = (newDate.substring(2, 4)).toInt();
  483.   yy = (newDate.substring(4, 8)).toInt();
  484.   if (isValidDate(dd, mo, yy)) { // valid date has been enter
  485.     DEBUG_PRINT("Time (hhmmss): ");
  486.     lcd.clear(); lcd.print("Time (hhmmss): ");
  487.     lcd.setCursor(0,1); //second line
  488.     if(hour() < 10) lcd.print('0'); lcd.print(hour());
  489.     if(minute() < 10) lcd.print('0'); lcd.print(minute());
  490.     if(second() < 10) lcd.print('0'); lcd.print(second()); // show current time
  491.     lcd.setCursor(0,1); //second line
  492.     String newTime = getInput('0','9', 6, true); // time input
  493.     hh = (newTime.substring(0, 2)).toInt();
  494.     mm = (newTime.substring(2, 4)).toInt();
  495.     ss = (newTime.substring(4, 6)).toInt();

  496.     if (isValidTime(hh, mm, ss)) {
  497.       setTime(hh,mm,ss,dd,mo,yy); // set date time  
  498.       playOKTone();
  499.     } else   {
  500.       DEBUG_PRINT("Invalid Time");
  501.       lcd.clear(); lcd.print("Invalid Time");
  502.       playWarningTone();      
  503.       delay(1000);
  504.     }
  505.    
  506.   } else { // invalid date
  507.     DEBUG_PRINT("Invalid Date");
  508.     lcd.clear(); lcd.print("Invalid Date");
  509.     playWarningTone();
  510.     delay(1000);
  511.   }  
  512.   
  513.   lcd.noCursor(); // hide cursor
  514. }


  515. boolean isValidDate(byte dd, byte mo, byte yy) {
  516.   boolean result = true;
  517.   if (dd <1 || dd>31) result = false;
  518.   if (mo <1 || mo>12) result = false;
  519.   //if (yy <1970 || yy>2099) result = false;
  520.   return result;
  521. }

  522. boolean isValidTime(byte hh, byte mm, byte ss) {
  523.   boolean result = true;
  524.   if (hh <1 || hh>23) result = false;
  525.   if (mm <1 || mm>59) result = false;
  526.   if (ss <1 || ss>59) result = false;
  527.   return result;
  528. }

  529. ////////////////////////////////////////////////////////////////////////////////
  530. // monitoring a key is pressed
  531. // return true when idle for 10 seconds (defined by KEYBOARD_EVENT_TIMEOUT)
  532. ////////////////////////////////////////////////////////////////////////////////
  533. boolean isTimeout() {
  534.   //user still able run the following code without blocking
  535.   //1. press a switch to release door lock
  536.   //2. press a swtich to ring the bell
  537.   //3. use RFID to release door lock
  538.   runEventAnyTime();  
  539.   
  540.   if (millis() >= previousMillis + KEYBOARD_EVENT_TIMEOUT *1000){ //convert KEYBOARD_EVENT_TIMEOUT in milli second to second
  541.     playTimeOutTone();
  542.     return true;
  543.   } else return false;
  544. }


  545. ////////////////////////////////////////////////////////////////////////////////
  546. // reset settings, write configuration to EEPROM
  547. /// press and hold button for 5 seconds (defined by HOLD_DELAY) to activate reset settings
  548. ////////////////////////////////////////////////////////////////////////////////
  549. void reset_settings() {
  550.   unsigned long start_hold = millis();                 // mark the time
  551.   int HOLD_DELAY = 5000;    // Sets the hold delay
  552.   DEBUG_PRINTLN("Please keep on pressing for 5 sconds.");
  553.   while (sw_state == LOW) {
  554.     sw_state = digitalRead(reset_settings_pin );      // read input value
  555.     if ((millis() - start_hold) >= HOLD_DELAY){      // for longer than HOLD_DELAY
  556.       //initialize_is_running = true;  // keep loop running even though reset_settings_pin  is low
  557.       initializeEEPROM();
  558.       break; //break the loop after initialized
  559.     }
  560.   }
  561. }


  562. ////////////////////////////////////////////////////////////////////////////////
  563. // initialize EEPROM (write configuration)
  564. // syntax: eeprom_write_string(int addr, const char* string)
  565. // addr: the EEPROM address of Arduino, ATMega328 = 0 to 1023 (1024 Byte), ATmega168 = 512 Bytes
  566. ////////////////////////////////////////////////////////////////////////////////
  567. void initializeEEPROM(){
  568.   strcpy(buf, "1234"); //set password to 1234
  569.   eeprom_write_string(USER_PASSWORD_EEPROM_ADDRESS, buf);  //write password to EEPROM
  570.   strcpy(buf, "1234"); //set password to 1234
  571.   eeprom_write_string(ADMIN_PASSWORD_EEPROM_ADDRESS, buf); //write password to EEPROM
  572.   DEBUG_PRINTLN("Initialize completed");
  573.   lcd.clear();
  574.   lcd.print("Initialized.");
  575.   delay(1000);
  576.   playOKTone();
  577. }
  578.   
  579.   
  580. ////////////////////////////////////////////////////////////////////////////////
  581. // making sound to speaker, tone() function uses timer2
  582. // syntax: tone(pin, frequency, duration)
  583. // pin: the pin on which to generate the tone
  584. // frequency: the frequency of the tone in hertz - unsigned int
  585. // duration: the duration of the tone in milliseconds (optional) - unsigned long
  586. ////////////////////////////////////////////////////////////////////////////////
  587. void beep(){
  588.    tone(MINI_SPEAKER_PIN,NOTE_C7,90);
  589.    delay(20);
  590.    noTone(MINI_SPEAKER_PIN);
  591. }


  592. void playTone(int note1, int note2, int note3, byte delayTime=100){
  593.    tone(MINI_SPEAKER_PIN, note1, 90);
  594.    delay(delayTime);

  595.    tone(MINI_SPEAKER_PIN, note2, 90);
  596.    delay(delayTime);

  597.    tone(MINI_SPEAKER_PIN, note3, 190);
  598.    delay(delayTime);
  599.    noTone(MINI_SPEAKER_PIN);
  600. }


  601. void playOKTone(){
  602.    playTone(NOTE_C5, NOTE_D5, NOTE_E5);     //playing Do-Re-Mi
  603. }  


  604. void playTimeOutTone(){
  605.    playTone(NOTE_E5, NOTE_D5, NOTE_C5);     //playing Mi-Re-Do
  606. }


  607. void playWarningTone(){
  608.   playTone(NOTE_E5, NOTE_E5, NOTE_E5, 150); //Plaing Mi-Mi-Mi
  609. }


  610. ////////////////////////////////////////////////////////////////////////////////
  611. // play melody
  612. // http://arduino.cc/en/Tutorial/tone
  613. ////////////////////////////////////////////////////////////////////////////////
  614. // notes in the melody: Mi-Do-Re-So So-Re-Mi-Do
  615. int melody[] = { NOTE_E5, NOTE_C5, NOTE_D5, NOTE_G4, NOTE_G4, NOTE_D5, NOTE_E5, NOTE_C5, 0};

  616. // note durations: 4 = quarter note, 8 = eighth note, etc.:
  617. int noteDurations[] = { 4, 4, 4, 2, 8, 8, 8, 4, 8 };

  618. void playMelody() {
  619.   isPlayingMelody = true; // indicating melody is playing
  620.   stopPlayingMelody = false;
  621.   
  622.   for (int thisNote = 0; thisNote < 8; thisNote++) {
  623.     runEventAnyTime(); // codes inside runEventAnyTime() will keep on updating
  624.     print_date_time();
  625.     if (stopPlayingMelody) break; //cause to exit "for loop" in order stop playing melody if lock is released
  626.    
  627.     // to calculate the note duration, take one second
  628.     // divided by the note type.
  629.     // e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
  630.     int noteDuration = 1000/noteDurations[thisNote];
  631.     tone(BELL_PIN, melody[thisNote],noteDuration);

  632.     // to distinguish the notes, set a minimum time between them.
  633.     // the note's duration + 30% seems to work well:
  634.     int pauseBetweenNotes = noteDuration * 1.30;
  635.     delay(pauseBetweenNotes);
  636.     // stop the tone playing:
  637.     noTone(BELL_PIN);
  638.   }
  639.   isPlayingMelody = false;
  640. }
复制代码
本帖最后由 西门庆33 于 18-9-2013 12:25 AM 编辑

回复

使用道具 举报

楼主
 楼主| 发表于 18-9-2013 12:26 AM | 显示全部楼层
为了增加一积份又把其余代码贴上

eeprom_string.h
  1. extern boolean eeprom_read_string(int addr, char* buffer, int bufSize);
  2. extern boolean eeprom_write_string(int addr, const char* string);
复制代码
eeprom_string.ino
  1. // http://playground.arduino.cc/Code/EepromUtil
  2. // EEPROM utility functions with usage example
  3. //
  4. // This example defines some utility functions
  5. // to write byte arrays, integers and strings
  6. // to eeprom and read them back.
  7. //
  8. // Some usage examples are provided.

  9. #include <Wire.h>
  10. #include <SL018.h>
  11. #include <EEPROM.h>


  12. //
  13. // Absolute min and max eeprom addresses.
  14. // Actual values are hardware-dependent.
  15. //
  16. // These values can be changed e.g. to protect
  17. // eeprom cells outside this range.
  18. //
  19. const int EEPROM_MIN_ADDR = 0;
  20. const int EEPROM_MAX_ADDR = 511;



  21. //
  22. // Returns true if the address is between the
  23. // minimum and maximum allowed values,
  24. // false otherwise.
  25. //
  26. // This function is used by the other, higher-level functions
  27. // to prevent bugs and runtime errors due to invalid addresses.
  28. //
  29. boolean eeprom_is_addr_ok(int addr) {
  30.   return ((addr >= EEPROM_MIN_ADDR) && (addr <= EEPROM_MAX_ADDR));
  31. }


  32. //
  33. // Writes a sequence of bytes to eeprom starting at the specified address.
  34. // Returns true if the whole array is successfully written.
  35. // Returns false if the start or end addresses aren't between
  36. // the minimum and maximum allowed values.
  37. // When returning false, nothing gets written to eeprom.
  38. //
  39. boolean eeprom_write_bytes(int startAddr, const byte* array, int numBytes) {
  40.   // counter
  41.   int i;

  42.   // both first byte and last byte addresses must fall within
  43.   // the allowed range  
  44.   if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) {
  45.     return false;
  46.   }

  47.   for (i = 0; i < numBytes; i++) {
  48.     EEPROM.write(startAddr + i, array[i]);
  49.   }

  50.   return true;
  51. }


  52. //
  53. // Reads the specified number of bytes from the specified address into the provided buffer.
  54. // Returns true if all the bytes are successfully read.
  55. // Returns false if the star or end addresses aren't between
  56. // the minimum and maximum allowed values.
  57. // When returning false, the provided array is untouched.
  58. //
  59. // Note: the caller must ensure that array[] has enough space
  60. // to store at most numBytes bytes.
  61. //
  62. boolean eeprom_read_bytes(int startAddr, byte array[], int numBytes) {
  63.   int i;

  64.   // both first byte and last byte addresses must fall within
  65.   // the allowed range  
  66.   if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) {
  67.     return false;
  68.   }

  69.   for (i = 0; i < numBytes; i++) {
  70.     array[i] = EEPROM.read(startAddr + i);
  71.   }

  72.   return true;
  73. }


  74. //
  75. // Writes an int variable at the specified address.
  76. // Returns true if the variable value is successfully written.
  77. // Returns false if the specified address is outside the
  78. // allowed range or too close to the maximum value
  79. // to store all of the bytes (an int variable requires
  80. // more than one byte).
  81. //
  82. boolean eeprom_write_int(int addr, int value) {
  83.   byte *ptr;

  84.   ptr = (byte*)&value;
  85.   return eeprom_write_bytes(addr, ptr, sizeof(value));
  86. }


  87. //
  88. // Reads an integer value at the specified address.
  89. // Returns true if the variable is successfully read.
  90. // Returns false if the specified address is outside the
  91. // allowed range or too close to the maximum vlaue
  92. // to hold all of the bytes (an int variable requires
  93. // more than one byte).
  94. //
  95. boolean eeprom_read_int(int addr, int* value) {
  96.   return eeprom_read_bytes(addr, (byte*)value, sizeof(int));
  97. }


  98. //
  99. // Writes a string starting at the specified address.
  100. // Returns true if the whole string is successfully written.
  101. // Returns false if the address of one or more bytes
  102. // fall outside the allowed range.
  103. // If false is returned, nothing gets written to the eeprom.
  104. //
  105. boolean eeprom_write_string(int addr, const char* string) {
  106.   // actual number of bytes to be written
  107.   int numBytes;

  108.   // we'll need to write the string contents
  109.   // plus the string terminator byte (0x00)
  110.   numBytes = strlen(string) + 1;

  111.   return eeprom_write_bytes(addr, (const byte*)string, numBytes);
  112. }


  113. //
  114. // Reads a string starting from the specified address.
  115. // Returns true if at least one byte (even only the
  116. // string terminator one) is read.
  117. // Returns false if the start address falls outside
  118. // or declare buffer size os zero.
  119. // the allowed range.
  120. // The reading might stop for several reasons:
  121. // - no more space in the provided buffer
  122. // - last eeprom address reached
  123. // - string terminator byte (0x00) encountered.
  124. // The last condition is what should normally occur.
  125. //
  126. boolean eeprom_read_string(int addr, char* buffer, int bufSize) {
  127.   // byte read from eeprom
  128.   byte ch;

  129.   // number of bytes read so far
  130.   int bytesRead;

  131.   // check start address
  132.   if (!eeprom_is_addr_ok(addr)) {
  133.     return false;
  134.   }

  135.   // how can we store bytes in an empty buffer ?
  136.   if (bufSize == 0) {
  137.     return false;
  138.   }

  139.   // is there is room for the string terminator only,
  140.   // no reason to go further
  141.   if (bufSize == 1) {
  142.     buffer[0] = 0;
  143.     return true;
  144.   }

  145.   // initialize byte counter
  146.   bytesRead = 0;

  147.   // read next byte from eeprom
  148.   ch = EEPROM.read(addr + bytesRead);

  149.   // store it into the user buffer
  150.   buffer[bytesRead] = ch;

  151.   // increment byte counter
  152.   bytesRead++;

  153.   // stop conditions:
  154.   // - the character just read is the string terminator one (0x00)
  155.   // - we have filled the user buffer
  156.   // - we have reached the last eeprom address
  157.   while ( (ch != 0x00) && (bytesRead < bufSize) && ((addr + bytesRead) <= EEPROM_MAX_ADDR) ) {
  158.     // if no stop condition is met, read the next byte from eeprom
  159.     ch = EEPROM.read(addr + bytesRead);

  160.     // store it into the user buffer
  161.     buffer[bytesRead] = ch;

  162.     // increment byte counter
  163.     bytesRead++;
  164.   }

  165.   // make sure the user buffer has a string terminator
  166.   // (0x00) as its last byte
  167.   if ((ch != 0x00) && (bytesRead >= 1)) {
  168.     buffer[bytesRead - 1] = 0;
  169.   }

  170.   return true;
  171. }

复制代码
matrixKeypad.h
  1. // http://playground.arduino.cc/code/Keypad
  2. #define use4x4Keypad //comment this using 3x4 keypad
  3. #ifdef use4x4Keypad
  4.   ////////////////////////////////////////////////////////////////////////////////
  5.   // define 4x4 keyboard
  6.   ////////////////////////////////////////////////////////////////////////////////
  7.   const byte ROWS = 4;  // Four rows
  8.   const byte COLS = 4;  // Four columns
  9.   //Define the keymap
  10.   char keys[ROWS][COLS] = {
  11.     {'1','2','3','A'},
  12.     {'4','5','6','B'},
  13.     {'7','8','9','C'},
  14.     {'*','0','#','D'}
  15.   };
  16.   byte rowPins[ROWS] = {6,7,8,9}; //connect to row pinouts
  17.   byte colPins[COLS] = {2,3,4,5}; //connect to column pinouts
  18. #else
  19.   ////////////////////////////////////////////////////////////////////////////////
  20.   // define 3x4 keyboard
  21.   ////////////////////////////////////////////////////////////////////////////////
  22.   const byte ROWS = 4; //four rows
  23.   const byte COLS = 3; //three columns
  24.   char keys[ROWS][COLS] = {
  25.     {'1','2','3'},
  26.     {'4','5','6'},
  27.     {'7','8','9'},
  28.     {'*','0','#'}
  29.   };
  30.   byte rowPins[ROWS] = {8, 7, 6, 5}; //connect to the row pinouts of the keypad
  31.   byte colPins[COLS] = {4, 3, 2}; //connect to the column pinouts of the keypad
  32. #endif

  33. //// Create the Keypad
  34. Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
复制代码
pitches.h
  1. // http://arduino.cc/en/Tutorial/tone

  2. #define NOTE_B0  31
  3. #define NOTE_C1  33
  4. #define NOTE_CS1 35
  5. #define NOTE_D1  37
  6. #define NOTE_DS1 39
  7. #define NOTE_E1  41
  8. #define NOTE_F1  44
  9. #define NOTE_FS1 46
  10. #define NOTE_G1  49
  11. #define NOTE_GS1 52
  12. #define NOTE_A1  55
  13. #define NOTE_AS1 58
  14. #define NOTE_B1  62
  15. #define NOTE_C2  65
  16. #define NOTE_CS2 69
  17. #define NOTE_D2  73
  18. #define NOTE_DS2 78
  19. #define NOTE_E2  82
  20. #define NOTE_F2  87
  21. #define NOTE_FS2 93
  22. #define NOTE_G2  98
  23. #define NOTE_GS2 104
  24. #define NOTE_A2  110
  25. #define NOTE_AS2 117
  26. #define NOTE_B2  123
  27. #define NOTE_C3  131
  28. #define NOTE_CS3 139
  29. #define NOTE_D3  147
  30. #define NOTE_DS3 156
  31. #define NOTE_E3  165
  32. #define NOTE_F3  175
  33. #define NOTE_FS3 185
  34. #define NOTE_G3  196
  35. #define NOTE_GS3 208
  36. #define NOTE_A3  220
  37. #define NOTE_AS3 233
  38. #define NOTE_B3  247
  39. #define NOTE_C4  262
  40. #define NOTE_CS4 277
  41. #define NOTE_D4  294
  42. #define NOTE_DS4 311
  43. #define NOTE_E4  330
  44. #define NOTE_F4  349
  45. #define NOTE_FS4 370
  46. #define NOTE_G4  392
  47. #define NOTE_GS4 415
  48. #define NOTE_A4  440
  49. #define NOTE_AS4 466
  50. #define NOTE_B4  494
  51. #define NOTE_C5  523
  52. #define NOTE_CS5 554
  53. #define NOTE_D5  587
  54. #define NOTE_DS5 622
  55. #define NOTE_E5  659
  56. #define NOTE_F5  698
  57. #define NOTE_FS5 740
  58. #define NOTE_G5  784
  59. #define NOTE_GS5 831
  60. #define NOTE_A5  880
  61. #define NOTE_AS5 932
  62. #define NOTE_B5  988
  63. #define NOTE_C6  1047
  64. #define NOTE_CS6 1109
  65. #define NOTE_D6  1175
  66. #define NOTE_DS6 1245
  67. #define NOTE_E6  1319
  68. #define NOTE_F6  1397
  69. #define NOTE_FS6 1480
  70. #define NOTE_G6  1568
  71. #define NOTE_GS6 1661
  72. #define NOTE_A6  1760
  73. #define NOTE_AS6 1865
  74. #define NOTE_B6  1976
  75. #define NOTE_C7  2093
  76. #define NOTE_CS7 2217
  77. #define NOTE_D7  2349
  78. #define NOTE_DS7 2489
  79. #define NOTE_E7  2637
  80. #define NOTE_F7  2794
  81. #define NOTE_FS7 2960
  82. #define NOTE_G7  3136
  83. #define NOTE_GS7 3322
  84. #define NOTE_A7  3520
  85. #define NOTE_AS7 3729
  86. #define NOTE_B7  3951
  87. #define NOTE_C8  4186
  88. #define NOTE_CS8 4435
  89. #define NOTE_D8  4699
  90. #define NOTE_DS8 4978
复制代码
本帖最后由 西门庆33 于 18-9-2013 12:32 AM 编辑

回复

使用道具 举报

发表于 18-9-2013 11:43 AM | 显示全部楼层
可以加进我之前家里alarm了。
回复

使用道具 举报

发表于 18-9-2013 10:30 PM | 显示全部楼层
支持下大哥的帖子... 一流的东西啊... 等我的金鱼灯完成了就来玩玩这个东西...
回复

使用道具 举报

楼主
 楼主| 发表于 20-9-2013 10:08 PM | 显示全部楼层
wilson16 发表于 18-9-2013 11:43 AM
可以加进我之前家里alarm了。

是alarm clock还是security alarm?
如果是security alarm不太适合吧?不过也不是不能,反正LCD显示、keypad与密码认证都有了,添加几个输入(zone)就行了。
本帖最后由 西门庆33 于 20-9-2013 10:09 PM 编辑

回复

使用道具 举报

楼主
 楼主| 发表于 20-9-2013 10:12 PM | 显示全部楼层
angels1026 发表于 18-9-2013 10:30 PM
支持下大哥的帖子... 一流的东西啊... 等我的金鱼灯完成了就来玩玩这个东西...

你的水族馆需要密码锁?
回复

使用道具 举报

楼主
 楼主| 发表于 20-9-2013 10:33 PM | 显示全部楼层
注明一下
  1. boolean isValidDate(byte dd, byte mo, byte yy) {
  2.   boolean result = true;
  3.   if (dd <1 || dd>31) result = false;
  4.   if (mo <1 || mo>12) result = false;
  5.   //if (yy <1970 || yy>2099) result = false;
  6.   return result;
  7. }
复制代码
上面代码没有月份及闰年(leap year)確认。要做这点,很简单巴了,每四年的二月就出现29曰,用modulo就行了。例:year % 4
如果得出结果是零时,二月就有29曰,否则就是28曰。

1、3、5、7、8月份则是31曰,剩下2、4、6、9、11是30曰
回复

使用道具 举报

发表于 20-9-2013 11:17 PM | 显示全部楼层
西门庆33 发表于 20-9-2013 10:08 PM
是alarm clock还是security alarm?
如果是security alarm不太适合吧?不过也不是不能,反正LCD显示、ke ...

其实你有很多功能已经符security alarm 了。
回复

使用道具 举报

楼主
 楼主| 发表于 23-9-2013 04:50 PM | 显示全部楼层
有件事必须注意,微控制器的memory(内存)有限,Arduino UNO只有2KB,因此,编程时尽量节省memory。这个Arduino电子密码锁有一个缺点,就是使用了String(字串)。为什么使用String会是缺点呢?

其实String很好用,也容易使用,为了方便编程(应该是不想动脑胫),所以我就使用了String。

String可以用,但要看情况,如果是短时间内使用肯定没问题,如果是一年365天一直开机,且从来没有Reset过,这可能会造成当机。为何会这样呢?

String操作时,是使用动态分配内存方式(allocate memory dynamically),动态内存分配通常会导致内存碎片(memory fragmentation),在短时间内程序会运行正常,长时间使用下可能会耗尽memory而当机。

建议使用char array代替String
回复

使用道具 举报

发表于 23-11-2013 05:31 PM | 显示全部楼层


Uploaded with ImageShack.us


怎么verify不到的。。。
回复

使用道具 举报

楼主
 楼主| 发表于 23-11-2013 09:59 PM | 显示全部楼层
wilson16 发表于 23-11-2013 05:31 PM
Uploaded with ImageShack.us

注意33至39行,那儿有一系列include程序库,其中一些程序库是没有集成在Arduino软件里,必须来自网页下载,然后保存在libraries文件夹里。比如
LiquidCrystal_I2C.h
matrixKeypad.h
Time.h
回复

使用道具 举报

发表于 24-11-2013 12:40 AM | 显示全部楼层
那keypad 的libraries好像有问题。。。
回复

使用道具 举报

发表于 24-11-2013 12:40 AM | 显示全部楼层
西门庆33 发表于 23-11-2013 09:59 PM
注意33至39行,那儿有一系列include程序库,其中一些程序库是没有集成在Arduino软件里,必须来自网页下载 ...

那keypad 的libraries好像有问题。。。

回复

使用道具 举报

楼主
 楼主| 发表于 24-11-2013 08:38 AM | 显示全部楼层
wilson16 发表于 24-11-2013 12:40 AM

是什么问题?

代码第九行,列出了keypad的程序库的下载与使用网址
http://playground.arduino.cc/code/Keypad
回复

使用道具 举报

发表于 25-11-2013 01:05 AM | 显示全部楼层
西门庆33 发表于 24-11-2013 08:38 AM
是什么问题?

代码第九行,列出了keypad的程序库的下载与使用网址

你直接开一个keypad 的example然后verify看看可以用吗?我试过verify有error。



Uploaded with ImageShack.us

回复

使用道具 举报

楼主
 楼主| 发表于 25-11-2013 09:55 AM | 显示全部楼层
wilson16 发表于 25-11-2013 01:05 AM
你直接开一个keypad 的example然后verify看看可以用吗?我试过verify有error。

你的error message是keypad library没有安装或者安装错误。
记得keypad library一定要保存在libraries里,比如\My Documents\Arduino\libraries\keypad
回复

使用道具 举报

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

本版积分规则

 WeChat
 CARI App
Get it FREE Google play
 Instagram
cari_malaysia
FOLLOW
- 版权所有 © 1996-2019 Cari Internet Sdn Bhd 佳礼网络有限公司 (483575-W) -
Private Cloud provided by IPSERVERONE
0.192007s Gzip On
快速回复 返回顶部 返回列表