Building an Arduino Fingerprint Lock with Shizhi Technology's TFS-M74A Module

A dorm-room fingerprint lock built with an Arduino Mega, a TFS-M74A module and a servo, with notes on the connected hardware, fingerprint-capacity settings and implementation code.

This fingerprint lock is installed on our dorm room door. A 14 g metal-geared servo operates the lock—yes, our university's door locks really are that bad…
The board is an Arduino Mega, connected to a servo, a 4×4 keypad (the key layout is in the code), a 5110LCD, a microswitch (which switches on power to the fingerprint module), and the star of the show: the TFS-M74A fingerprint module.
By the way, Shizhi Technology's fingerprint modules use compatible protocols and are interchangeable. Their maximum storage capacities differ, so you'll need to change that setting (find it yourself, young grasshopper!).
The connections and such are shown in the code. I should have written them down, but I was too lazy… The 5110 library is LCD5110_Graph; search Baidu if you don't have it.
I live in an eight-person dorm room (those of you in four-person rooms or smaller, please don't rub it in…), so I reserved 16 entries in the names array—one finger from each hand per person. You can change that.
Too lazy to add comments. Work it out for yourselves…

  1. /*  
  2. 指纹锁程序 by SamCui.com at oct 15, 2013  
  3. 更改请注明原作者,谢谢!  
  4. What’s New:   
  5. v2  
  6. 更改指纹传感器,重写部分段落,规范注释.  
  7. 并为完全离机做准备.  
  8. v2.1  
  9. 完成稿  
  10. */  
  11.   
  12. void printStage(int s, int r = 24);   
  13.   
  14. // 指纹识别器常量定义   
  15.   
  16.   #define TIMEOUT             2500   
  17.   
  18.   // 基本应答信息定义   
  19.   #define ACK_SUCCESS         0x00   
  20.   #define ACK_FAIL            0x01   
  21.   #define ACK_FULL            0x04   
  22.   #define ACK_NO_USER           0x05   
  23.   #define ACK_USER_EXIST      0x07   
  24.   #define ACK_TIMEOUT         0x08   
  25.   #define ACK_GO_OUT              0x0F   
  26.   #define ACK_NOTHING             0xEF   
  27.   
  28.   // 用户信息定义   
  29.   #define ACK_ALL_USER        0x00   
  30.   #define ACK_GUEST_USER        0x01   
  31.   #define ACK_NORMAL_USER     0x02   
  32.   #define ACK_MASTER_USER     0x03   
  33.   
  34.   #define USER_MAX_CNT        50   
  35.   
  36.   // 命令定义   
  37.   #define CMD_HEAD              0xF5   
  38.   #define CMD_TAIL              0xF5   
  39.   #define CMD_ADD_1               0x01   
  40.   #define CMD_ADD_2               0x02   
  41.   #define CMD_ADD_3           0x03   
  42.   #define CMD_MATCH             0x0C   
  43.   #define CMD_DEL                   0x04   
  44.   #define CMD_DEL_ALL             0x05   
  45.   #define CMD_USER_CNT        0x09   
  46.   #define CMD_LP_MODE             0x2C   
  47.   #define CMD_FINGER_DETECTED 0x14   
  48.   
  49. // 指纹模块定义结束   
  50.   
  51. // 微动开关接口   
  52.      
  53.   #define SWITCH_PIN              36   
  54.   #define POWER_PIN           37   
  55.   
  56. // LCD5110库   
  57. #include <LCD5110_Graph.h>   
  58. LCD5110 myGLCD(34,33,32,30,31);// 接口   
  59. extern uint8_t SmallFont[];// 设置字体为小   
  60.   
  61. // 键盘库   
  62. #include <Keypad.h>   
  63. const byte ROWS = 4;//4行   
  64. const byte COLS = 4;//4列   
  65.   
  66. // 行列对应内容   
  67. char keys[ROWS][COLS] = {   
  68. {‘1′,’2′,’3′,’A’},   
  69. {‘4′,’5′,’6′,’B’},   
  70. {‘7′,’8′,’9′,’C’},   
  71. {‘*’,’0′,’#’,’D’}   
  72. };   
  73.   
  74. // 相应接口   
  75. byte rowPins[ROWS] = {22,23,24,25};   
  76. byte colPins[COLS] = {26,27,28,29};   
  77. // initialize an instance of class NewKeypad   
  78. Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );   
  79.   
  80. // 指纹识别模块   
  81. // 串口发送子程序,收发串口,返回状态值,并写入q1,q2,q3至uint8_t[3].   
  82. uint8_t TxAndRsCmd(uint8_t packet[], uint8_t cmd, uint8_t p1 = 0, uint8_t p2 = 0, uint8_t p3 = 0, uint8_t p4 = 0)   
  83. {   
  84.   // 发送段   
  85.   uint8_t chk = 0;   
  86.      
  87.   chk ^= cmd;   
  88.   chk ^= p1;   
  89.   chk ^= p2;   
  90.   chk ^= p3;   
  91.   chk ^= p4;   
  92.   
  93.   Serial1.write((uint8_t)CMD_HEAD);   
  94.   Serial1.write((uint8_t)cmd);   
  95.   Serial1.write((uint8_t)p1);   
  96.   Serial1.write((uint8_t)p2);   
  97.   Serial1.write((uint8_t)p3);   
  98.   Serial1.write((uint8_t)p4);   
  99.   Serial1.write((uint8_t)chk);   
  100.   Serial1.write((uint8_t)CMD_TAIL);   
  101.   
  102.   // 接收段   
  103.   int timer = 0;   
  104.   uint8_t reply[8], idx = 0;   
  105.   while (true) {   
  106.     if (timer >= TIMEOUT) return ACK_TIMEOUT;   
  107.     while (!Serial1.available()) {   
  108.       delay(1);   
  109.       timer++;   
  110.       if (timer >= TIMEOUT) return ACK_TIMEOUT;   
  111.     }   
  112.     reply[idx] = Serial1.read();   
  113.     if ((idx == 0) && (reply[0] != CMD_HEAD)){   
  114.       timer++;   
  115.       delay(1);   
  116.       continue;   
  117.     }   
  118.     idx++;   
  119.     if (idx >= 8) {   
  120.       chk = 0;   
  121.       int i;   
  122.       for(i = 1; i <= 5; i++){   
  123.         chk ^= reply[i];   
  124.       }   
  125.       if(reply[1] != cmd || reply[6] != chk || reply[7] != CMD_TAIL){   
  126.         return ACK_FAIL;   
  127.       }   
  128.       for (i = 0; i < 3; i++) {   
  129.         packet[i] = reply[2+i];   
  130.       }   
  131.       return ACK_SUCCESS;   
  132.     }   
  133.   }   
  134.   return ACK_FAIL;   
  135. }   
  136.   
  137. // 指纹添加子程序,返回是否成功,参数k为用户序号.   
  138. uint8_t addUser(int k, uint8_t level = ACK_NORMAL_USER)   
  139. {   
  140.   uint8_t p1, p2, p3;   
  141.   uint8_t m = ACK_NOTHING;   
  142.   uint8_t cmd;   
  143.   uint8_t cmdAdd[] = {CMD_ADD_1, CMD_ADD_2, CMD_ADD_3};   
  144.   int i;   
  145.   
  146.   for (i = 0; i < 3; i++){   
  147.   
  148.     cmd = cmdAdd[i], p1 = (k >> 8), p2 = k, p3 = level;   
  149.     uint8_t packet[] = {ACK_NOTHING, ACK_NOTHING, ACK_NOTHING};   
  150.     for(int j = 0; j < 3; j++){   
  151.       if(m != ACK_SUCCESS || packet[2] != ACK_SUCCESS){   
  152.         m = TxAndRsCmd(packet, cmd, p1, p2, p3);   
  153.         if(m == ACK_SUCCESS && packet[2] == ACK_SUCCESS){   
  154.           printStage((i+1)*4);   
  155.           break;   
  156.         }else if(packet[2] == ACK_USER_EXIST || packet[2] == ACK_FULL){   
  157.           return packet[2];   
  158.         }else if(j >= 2){   
  159.           return ((m == ACK_SUCCESS)? (packet[2]): (m));   
  160.         }   
  161.       }   
  162.     }   
  163.   }   
  164.   return ACK_SUCCESS;   
  165. }   
  166.   
  167. // 删除用户子程序,返回是否成功,参数k为用户序号.   
  168. uint8_t delUser(int k)   
  169. {   
  170.   uint8_t m = ACK_NOTHING, p1, p2;   
  171.   uint8_t cmd;   
  172.   
  173.   uint8_t packet[] = {ACK_NOTHING, ACK_NOTHING, ACK_NOTHING};   
  174.   cmd = CMD_DEL, p1 = (k >> 8), p2 = k;   
  175.   int i;   
  176.   
  177.   for(i = 0; i < 3; i++){   
  178.     if(m != ACK_SUCCESS || packet[2] != ACK_SUCCESS){   
  179.       m = TxAndRsCmd(packet, cmd, p1, p2);   
  180.       if(m == ACK_SUCCESS && packet[2] == ACK_SUCCESS){   
  181.         break;   
  182.       }else if(i >= 2){   
  183.         return ((m == ACK_SUCCESS)? (packet[2]): (m));   
  184.       }   
  185.     }   
  186.   }   
  187.   
  188.   return ACK_SUCCESS;   
  189. }   
  190.   
  191. // 清除所有用户子程序,返回是否成功.   
  192. uint8_t clrAllUser(void)   
  193. {   
  194.   uint8_t m = ACK_NOTHING;   
  195.   uint8_t cmd;   
  196.   
  197.   uint8_t packet[] = {ACK_NOTHING, ACK_NOTHING, ACK_NOTHING};   
  198.   cmd = CMD_DEL_ALL;   
  199.   int i;   
  200.   
  201.   for(i = 0; i < 3; i++){   
  202.     if(m != ACK_SUCCESS || packet[2] != ACK_SUCCESS){   
  203.       m = TxAndRsCmd(packet, cmd);   
  204.       if(m == ACK_SUCCESS && packet[2] == ACK_SUCCESS){   
  205.         break;   
  206.       }else if(i >= 2){   
  207.         return ((m == ACK_SUCCESS)? (packet[2]): (m));   
  208.       }   
  209.     }   
  210.   }   
  211.   
  212.   return ACK_SUCCESS;   
  213. }   
  214.   
  215. // 取用户总数子程序,返回是否成功,赋*t值为用户总数,参数*t为用户总数.   
  216. uint8_t getUserCount(int *t)   
  217. {   
  218.   uint8_t m = ACK_NOTHING;   
  219.   uint8_t cmd;   
  220.   
  221.   uint8_t packet[] = {ACK_NOTHING, ACK_NOTHING, ACK_NOTHING};   
  222.   cmd = CMD_USER_CNT;   
  223.   int i;   
  224.   
  225.   for(i = 0; i < 3; i++){   
  226.     if(m != ACK_SUCCESS || packet[2] != ACK_SUCCESS){   
  227.       m = TxAndRsCmd(packet, cmd);   
  228.       if(m == ACK_SUCCESS && packet[2] == ACK_SUCCESS){   
  229.         int k = packet[0];   
  230.         k <<= 8;   
  231.         k |= packet[1];   
  232.         *t = k;   
  233.         return ACK_SUCCESS;   
  234.       }else if(i >= 2){   
  235.         return ((m == ACK_SUCCESS)? (packet[2]): (m));   
  236.       }   
  237.     }   
  238.   }   
  239.   return ACK_FAIL;   
  240. }   
  241.   
  242. // 指纹1:N比对子程序,返回是否成功,赋*t值为用户id,参数*t为用户id,参数*level为用户等级.   
  243. uint8_t matchUser(int *t, uint8_t *level)   
  244. {   
  245.   uint8_t m = ACK_NOTHING;   
  246.   uint8_t cmd;   
  247.   
  248.   uint8_t packet[] = {ACK_NOTHING, ACK_NOTHING, ACK_NOTHING};   
  249.   cmd = CMD_MATCH;   
  250.   int i;   
  251.   
  252.   for(i = 0; i < 3; i++){   
  253.     if(m != ACK_SUCCESS || packet[2] == ACK_TIMEOUT){   
  254.       m = TxAndRsCmd(packet, cmd);   
  255.       if(m == ACK_SUCCESS && packet[2] != ACK_NO_USER && packet[2] != ACK_TIMEOUT){   
  256.         int k = packet[0];   
  257.         k <<= 8;   
  258.         k |= packet[1];   
  259.         *t = k;   
  260.         *level = packet[2];   
  261.         return ACK_SUCCESS;   
  262.       }else if(packet[2] == ACK_NO_USER){   
  263.         return packet[2];   
  264.       }else if(i >= 2){   
  265.         return ((m == ACK_SUCCESS)? (packet[2]): (m));   
  266.       }   
  267.     }   
  268.   }   
  269.   return ACK_FAIL;   
  270. }   
  271. // 指纹1:N比对子程序,返回是否成功,赋*t值为用户id,参数*t为用户id.   
  272. uint8_t matchUser(int *t)   
  273. {   
  274.   uint8_t m = ACK_NOTHING;   
  275.   uint8_t cmd;   
  276.   
  277.   uint8_t packet[] = {ACK_NOTHING, ACK_NOTHING, ACK_NOTHING};   
  278.   cmd = CMD_MATCH;   
  279.   int i;   
  280.   
  281.   for(i = 0; i < 3; i++){   
  282.     if(m != ACK_SUCCESS || packet[2] == ACK_TIMEOUT){   
  283.       m = TxAndRsCmd(packet, cmd);   
  284.       if(m == ACK_SUCCESS && packet[2] != ACK_NO_USER && packet[2] != ACK_TIMEOUT){   
  285.         int k = packet[0];   
  286.         k <<= 8;   
  287.         k |= packet[1];   
  288.         *t = k;   
  289.         return ACK_SUCCESS;   
  290.       }else if(packet[2] == ACK_NO_USER){   
  291.         return packet[2];   
  292.       }else if(i >= 2){   
  293.         return ((m == ACK_SUCCESS)? (packet[2]): (m));   
  294.       }   
  295.     }   
  296.   }   
  297.   return ACK_FAIL;   
  298. }   
  299.   
  300. // 取用户权限子程序,返回是否成功,赋*t值为用户总数,参数*t为用户总数.   
  301. uint8_t userLevel(int *t)   
  302. {   
  303.   uint8_t m = ACK_NOTHING;   
  304.   uint8_t cmd;   
  305.   
  306.   uint8_t packet[] = {ACK_NOTHING, ACK_NOTHING, ACK_NOTHING};   
  307.   cmd = CMD_MATCH;   
  308.   int i;   
  309.   
  310.   for(i = 0; i < 3; i++){   
  311.     if(m != ACK_SUCCESS || packet[2] == ACK_TIMEOUT){   
  312.       m = TxAndRsCmd(packet, cmd);   
  313.       if(m == ACK_SUCCESS && packet[2] != ACK_NO_USER && packet[2] != ACK_TIMEOUT){   
  314.         *t = packet[2];   
  315.         return ACK_SUCCESS;   
  316.       }else if(packet[2] == ACK_NO_USER){   
  317.         return packet[2];   
  318.       }else if(i >= 2){   
  319.         return ((m == ACK_SUCCESS)? (packet[2]): (m));   
  320.       }   
  321.     }   
  322.   }   
  323.   return ACK_FAIL;   
  324. }   
  325.   
  326. // 指纹识别模块结束   
  327.   
  328. // 在5110上的第n行像素起表示阶段,参数n为第n行像素,参数s为现阶段,共有12阶段.   
  329. void printStage(int s, int r)   
  330. {   
  331. myGLCD.print(“[“, 0, r);   
  332.   
  333. for(int i=1; i<13 && i<s; i++){   
  334.   myGLCD.print(“=”, i*6, r);   
  335. }   
  336. if (s=12) {   
  337.   myGLCD.print(“=”, 72, r);   
  338. }else{   
  339.   myGLCD.print(“>”, s*6, r);   
  340. }   
  341.   
  342. myGLCD.print(“]”, 78, r);   
  343. myGLCD.update();   
  344. }   
  345.   
  346. // 在5110的(0, 28)处打印”Mr. xxx!”信息,参数为人员id,之后应有myGLCD.update()函数上传.   
  347. void printPeople(int peoid)   
  348. {   
  349.   String peoName[16] = {   
  350.     “Mr. Cui!”,“Mr. Cui!”,“Mr. Lin!”,“Mr. Lin!”,“Mr. Jiang!”,“Mr. Jiang!”,“Mr. Yan!”,“Mr. Yan!”,“Mr. Hu!”,“Mr. Hu!”,“Mr. Zhao!”,“Mr. Zhao!”,“Mr. Shang!”,“Mr. Shang!”,“Mr. Zhong!”,“Mr. Zhong!”  
  351.   };   
  352.   myGLCD.print(peoName[peoid], 0, 28);   
  353. }   
  354.   
  355. // 获得6位密码,返回六位字符串,参数gskask为输入提示.   
  356. String getSixKeys(String gskask)   
  357. {   
  358.   gskBack:   
  359.   myGLCD.clrScr();   
  360.   myGLCD.update();   
  361.   myGLCD.print(gskask, 0, 0);   
  362.   myGLCD.update();   
  363.   int gsk = 0;   
  364.   char gskpw[6];   
  365.   while(gsk <= 5){   
  366.     char gskkey = keypad.waitForKey();   
  367.     gskpw[gsk] = gskkey;   
  368.     if(String(gskkey) == “*”){goto gskBack;}   
  369.     myGLCD.print(“*”, gsk*6, 8);   
  370.     myGLCD.update();   
  371.     gsk++;   
  372.     delay(50);   
  373.   }   
  374.   int i;   
  375.   String sixKeys;   
  376.   for(i=0;i<=5;i++){   
  377.     sixKeys = sixKeys + String(gskpw[i]);   
  378.   }   
  379.   return sixKeys;   
  380. }   
  381.   
  382. // 舵机驱动模块   
  383.   
  384.   int servopin = 35;// 舵机方波输出   
  385.   
  386.   // 舵机脉冲发生函数,输出控制舵机的方波,参数angle为转动度数,值的范围为0到165.   
  387.   void servopulse(int angle)   
  388.   {   
  389.     int pulsewidth=(angle*11)+500;  // 将角度转化为500-2480的脉宽值   
  390.     digitalWrite(servopin,HIGH);    // 将舵机接口电平至高   
  391.     delayMicroseconds(pulsewidth);  // 延时脉宽值的微秒数   
  392.     digitalWrite(servopin,LOW);     // 将舵机接口电平至低   
  393.     delayMicroseconds(20000-pulsewidth);   
  394.   }   
  395.   
  396.   // 舵机驱动函数,调用void servopulse(int angle),参数angle为转动度数,值的范围为0到165,参数time为转动时间,以毫秒为单位,应为20的倍数.   
  397.   void servoDrive(int angle,int time)   
  398.   {   
  399.     time /= 20;   
  400.     // 值的范围为0到165   
  401.     // 发送time个脉冲   
  402.     for(int i=0;i<time;i++)   
  403.     {   
  404.       // 引用脉冲函数   
  405.       servopulse(angle);   
  406.     }   
  407.   }   
  408. // 舵机驱动模块结束   
  409.   
  410. void unlock()   
  411. {   
  412.   myGLCD.clrScr();   
  413.   myGLCD.update();   
  414.   myGLCD.print(“Waiting!”, 21, 0);   
  415.   myGLCD.update();   
  416.   int id = 1000;   
  417.   uint8_t m;   
  418.   m = matchUser(&id);   
  419.   
  420.   if(id != 1000 && m == ACK_SUCCESS){   
  421.     myGLCD.print(“ComeIn!”, 21, 8);   
  422.     myGLCD.print(“Welcome,”, 0, 20);   
  423.     printPeople(id);   
  424.     myGLCD.print(“ID:”, 0, 40);   
  425.     myGLCD.print(String(id), 18, 40);   
  426.     myGLCD.update();   
  427.     servoDrive(20,3000);   
  428.     delay(1500);   
  429.     servoDrive(90,2000);   
  430.   }else if(m == ACK_NO_USER){   
  431.     myGLCD.print(“Sorry!”, 21, 8);   
  432.     myGLCD.print(“FngrUndefined!”, 0, 16);   
  433.     myGLCD.update();   
  434.     delay(1500);   
  435.   }   
  436.   myGLCD.clrScr();   
  437.   myGLCD.update();   
  438. }   
  439.   
  440. void adminAddUser()   
  441. {   
  442.   myGLCD.clrScr();   
  443.   myGLCD.update();   
  444.   
  445.   myGLCD.print(”   Add User   “, 0, 0);   
  446.   myGLCD.print(“Input the ID: “, 0, 8);   
  447.   myGLCD.print(“(0~400, and   “, 0, 16);   
  448.   myGLCD.print(“\”#\” for End)”, 0, 24);   
  449.   myGLCD.print(“*=> BackToMenu”, 0, 40);   
  450.   myGLCD.update();   
  451.   
  452.   uint8_t out = 0;   
  453.   int i;   
  454.   char num[] = {0, 0, 0, 0};   
  455.   char key;   
  456.   
  457.   for(i = 0; i < 4; i++){   
  458.     key = keypad.waitForKey();   
  459.     if(i >= 3 && isdigit(key)){   
  460.       myGLCD.print(”   Overflow!  “, 0, 32);   
  461.       myGLCD.update();   
  462.       delay(500);   
  463.       out = 1;   
  464.       break;   
  465.     }else if(isdigit(key)){   
  466.       myGLCD.print(&key, i*6, 32);   
  467.       myGLCD.update();   
  468.       num[i] = key;   
  469.     }else if(key == ‘#’){   
  470.       num[i] = ‘\0’;   
  471.       break;   
  472.     }else if(key == ‘*’){   
  473.       myGLCD.print(”   Backing!   “, 0, 32);   
  474.       myGLCD.update();   
  475.       delay(500);   
  476.       out = 1;   
  477.       break;   
  478.     }else{   
  479.       myGLCD.print(”  Wrong Char  “, 0, 32);   
  480.       myGLCD.update();   
  481.       delay(500);   
  482.       out = 1;   
  483.       break;   
  484.     }   
  485.   }   
  486.   if(out == 1)   
  487.     return;   
  488.   
  489.   i = 0;   
  490.   int k = 0;   
  491.   while(isdigit(num[i])){   
  492.     k = k*10 + (num[i] – ‘0’);   
  493.     i++;   
  494.   }   
  495.   
  496.   if(k>=0 && k<=399){   
  497.     ;   
  498.   }else{   
  499.     myGLCD.print(”   Overflow!  “, 0, 32);   
  500.     myGLCD.update();   
  501.     delay(500);   
  502.     return;   
  503.   }   
  504.   
  505.   myGLCD.clrScr();   
  506.   myGLCD.update();   
  507.   myGLCD.print(”   Add User   “, 0, 0);   
  508.   myGLCD.print(“Put on Your”, 0, 8);   
  509.   myGLCD.print(“Finger!”, 0, 16);   
  510.   myGLCD.update();   
  511.   
  512.   uint8_t m = addUser(k);   
  513.   if(m == ACK_SUCCESS){   
  514.     myGLCD.print(”    SUCCESS!  “, 0, 32);   
  515.     myGLCD.update();   
  516.   }else if(m == ACK_USER_EXIST){   
  517.     myGLCD.print(”  USER EXIST! “, 0, 32);   
  518.     myGLCD.update();   
  519.   }else if(m == ACK_FULL){   
  520.     myGLCD.print(”     FULL!    “, 0, 32);   
  521.     myGLCD.update();   
  522.   }else if(m == ACK_TIMEOUT){   
  523.     myGLCD.print(”   TIMEOUT!   “, 0, 32);   
  524.     myGLCD.update();   
  525.   }else{   
  526.     myGLCD.print(“Unknown Error!”, 0, 32);   
  527.     myGLCD.update();   
  528.   }   
  529.   delay(500);   
  530. }   
  531.   
  532. void adminDelUser()   
  533. {   
  534.   myGLCD.clrScr();   
  535.   myGLCD.update();   
  536.   
  537.   myGLCD.print(”   Del User   “, 0, 0);   
  538.   myGLCD.print(“Input the ID: “, 0, 8);   
  539.   myGLCD.print(“(0~400, and   “, 0, 16);   
  540.   myGLCD.print(“\”#\” for End)”, 0, 24);   
  541.   myGLCD.print(“*=> BackToMenu”, 0, 40);   
  542.   myGLCD.update();   
  543.   
  544.   uint8_t out = 0;   
  545.   int i;   
  546.   char num[] = {0, 0, 0, 0};   
  547.   char key;   
  548.   
  549.   for(i = 0; i < 4; i++){   
  550.     key = keypad.waitForKey();   
  551.     if(i >= 3 && isdigit(key)){   
  552.       myGLCD.print(”   Overflow!  “, 0, 32);   
  553.       myGLCD.update();   
  554.       delay(500);   
  555.       out = 1;   
  556.       break;   
  557.     }else if(isdigit(key)){   
  558.       myGLCD.print(&key, i*6, 32);   
  559.       myGLCD.update();   
  560.       num[i] = key;   
  561.     }else if(key == ‘#’){   
  562.       num[i] = ‘\0’;   
  563.       break;   
  564.     }else if(key == ‘*’){   
  565.       myGLCD.print(”   Backing!   “, 0, 32);   
  566.       myGLCD.update();   
  567.       delay(500);   
  568.       out = 1;   
  569.       break;   
  570.     }else{   
  571.       myGLCD.print(”  Wrong Char  “, 0, 32);   
  572.       myGLCD.update();   
  573.       delay(500);   
  574.       out = 1;   
  575.       break;   
  576.     }   
  577.   }   
  578.   if(out == 1)   
  579.     return;   
  580.   
  581.   i = 0;   
  582.   int k = 0;   
  583.   while(isdigit(num[i])){   
  584.     k = k*10 + (num[i] – ‘0’);   
  585.     i++;   
  586.   }   
  587.   
  588.   if(k>=0 && k<=399){   
  589.     ;   
  590.   }else{   
  591.     myGLCD.print(”   Overflow!  “, 0, 32);   
  592.     myGLCD.update();   
  593.     delay(500);   
  594.     return;   
  595.   }   
  596.   
  597.   uint8_t m = delUser(k);   
  598.   
  599.   if(m == ACK_SUCCESS){   
  600.     myGLCD.print(”    SUCCESS!  “, 0, 32);   
  601.     myGLCD.update();   
  602.   }else if(m == ACK_USER_EXIST){   
  603.     myGLCD.print(”  USER EXIST! “, 0, 32);   
  604.     myGLCD.update();   
  605.   }else if(m == ACK_FULL){   
  606.     myGLCD.print(”     FULL!    “, 0, 32);   
  607.     myGLCD.update();   
  608.   }else if(m == ACK_TIMEOUT){   
  609.     myGLCD.print(”   TIMEOUT!   “, 0, 32);   
  610.     myGLCD.update();   
  611.   }else{   
  612.     myGLCD.print(“Unknown Error!”, 0, 32);   
  613.     myGLCD.update();   
  614.   }   
  615.   delay(500);   
  616. }   
  617.   
  618. void adminClrAllUser()   
  619. {   
  620.   myGLCD.clrScr();   
  621.   myGLCD.update();   
  622.   
  623.   myGLCD.print(” Clr All User “, 0, 0);   
  624.   myGLCD.print(“Input \”#ABC\”  “, 0, 8);   
  625.   myGLCD.print(“for Yes:      “, 0, 16);   
  626.   myGLCD.print(“*=> BackToMenu”, 0, 40);   
  627.   myGLCD.update();   
  628.   
  629.   uint8_t out = 0;   
  630.   int i;   
  631.   char num[] = {0, 0, 0, 0};   
  632.   char key;   
  633.   
  634.   for(i = 0; i < 4; i++){   
  635.     key = keypad.waitForKey();   
  636.     if(key == ‘*’){   
  637.       myGLCD.print(”   Backing!   “, 0, 32);   
  638.       myGLCD.update();   
  639.       delay(500);   
  640.       out = 1;   
  641.       break;   
  642.     }else{   
  643.       myGLCD.print(&key, i*6, 24);   
  644.       myGLCD.update();   
  645.       num[i] = key;   
  646.     }   
  647.   }   
  648.   if(out == 1)   
  649.     return;   
  650.   
  651.   if(num[0] == ‘#’ && num[1] == ‘A’ && num[2] == ‘B’ && num[3] == ‘C’){   
  652.     ;   
  653.   }else{   
  654.     myGLCD.print(” Wrong Verify!”, 0, 32);   
  655.     myGLCD.update();   
  656.     delay(500);   
  657.     return;   
  658.   }   
  659.   
  660.   uint8_t m = clrAllUser();   
  661.   
  662.   if(m == ACK_SUCCESS){   
  663.     myGLCD.print(”    SUCCESS!  “, 0, 32);   
  664.     myGLCD.update();   
  665.     delay(500);   
  666.   }else if(m == ACK_USER_EXIST){   
  667.     myGLCD.print(”  USER EXIST! “, 0, 32);   
  668.     myGLCD.update();   
  669.     delay(500);   
  670.     return;   
  671.   }else if(m == ACK_FULL){   
  672.     myGLCD.print(”     FULL!    “, 0, 32);   
  673.     myGLCD.update();   
  674.     delay(500);   
  675.     return;   
  676.   }else if(m == ACK_TIMEOUT){   
  677.     myGLCD.print(”   TIMEOUT!   “, 0, 32);   
  678.     myGLCD.update();   
  679.     delay(500);   
  680.     return;   
  681.   }else{   
  682.     myGLCD.print(“Unknown Error!”, 0, 32);   
  683.     myGLCD.update();   
  684.     delay(500);   
  685.     return;   
  686.   }   
  687.   
  688. // 间隔   
  689.   myGLCD.clrScr();   
  690.   myGLCD.update();   
  691.   
  692.   myGLCD.print(” Clr All User “, 0, 0);   
  693.   myGLCD.print(“Put on Your”, 0, 8);   
  694.   myGLCD.print(“Finger!”, 0, 16);   
  695.   myGLCD.update();   
  696.   
  697.   m = addUser(1, ACK_MASTER_USER);   
  698.   if(m == ACK_SUCCESS){   
  699.     myGLCD.print(”    SUCCESS!  “, 0, 32);   
  700.     myGLCD.update();   
  701.   }else if(m == ACK_USER_EXIST){   
  702.     myGLCD.print(”  USER EXIST! “, 0, 32);   
  703.     myGLCD.update();   
  704.   }else if(m == ACK_FULL){   
  705.     myGLCD.print(”     FULL!    “, 0, 32);   
  706.     myGLCD.update();   
  707.   }else if(m == ACK_TIMEOUT){   
  708.     myGLCD.print(”   TIMEOUT!   “, 0, 32);   
  709.     myGLCD.update();   
  710.   }else{   
  711.     myGLCD.print(“Unknown Error!”, 0, 32);   
  712.     myGLCD.update();   
  713.   }   
  714.   delay(500);   
  715. }   
  716.   
  717. void adminPanel()   
  718. {   
  719.   while(1){   
  720.     myGLCD.clrScr();   
  721.     myGLCD.update();   
  722.   
  723.     myGLCD.print(“AdminPanel”, 12, 0);   
  724.     myGLCD.print(“A=> Add User”, 0, 8);   
  725.     myGLCD.print(“B=> Del User”, 0, 16);   
  726.     myGLCD.print(“C=> ClrAllUser”, 0, 24);   
  727.     myGLCD.print(“*=> Exit”, 0, 32);   
  728.     myGLCD.print(“Input A,B or C”, 0, 40);   
  729.     myGLCD.update();   
  730.   
  731.     uint8_t out = 0;   
  732.     int timer = 0;   
  733.     switch(keypad.waitForKey()){   
  734.     case ‘A’:   
  735.       adminAddUser();   
  736.       break;   
  737.     case ‘B’:   
  738.       adminDelUser();   
  739.       break;   
  740.     case ‘C’:   
  741.       adminClrAllUser();   
  742.       break;   
  743.     case ‘*’:   
  744.       out = 1;   
  745.       break;   
  746.     default:   
  747.       for(int i = 0; i < 3; i++){   
  748.         myGLCD.print(”              “, 0, 40);   
  749.         myGLCD.update();   
  750.         delay(250);   
  751.         myGLCD.print(“Input A,B or C”, 0, 40);   
  752.         myGLCD.update();   
  753.         delay(250);   
  754.       }   
  755.          
  756.       if(timer >= 2){   
  757.         out = 1;   
  758.         myGLCD.print(”              “, 0, 40);   
  759.         myGLCD.update();   
  760.         myGLCD.print(“Error for 3rd!”, 0, 40);   
  761.         myGLCD.update();   
  762.         delay(500);   
  763.         myGLCD.print(”  Auto Exit!  “, 0, 40);   
  764.         myGLCD.update();   
  765.         delay(500);   
  766.       }   
  767.   
  768.       timer++;   
  769.       break;   
  770.     }   
  771.   
  772.     if(out == 1)   
  773.       break;   
  774.   }   
  775.   myGLCD.clrScr();   
  776.   myGLCD.update();   
  777. }   
  778.   
  779. void adminVerify()   
  780. {   
  781.   myGLCD.clrScr();   
  782.   myGLCD.update();   
  783.   
  784.   myGLCD.print(“AdminPanel”, 12, 0);   
  785.   myGLCD.print(“PutOnYourFinger!”, 0, 8);   
  786.   myGLCD.update();   
  787.   
  788.   int id = 1000;   
  789.   uint8_t level = ACK_ALL_USER;   
  790.   uint8_t m;   
  791.   m = matchUser(&id, &level);   
  792.   
  793.   if(id != 1000 && m == ACK_SUCCESS && level == ACK_MASTER_USER){   
  794.     adminPanel();   
  795.   }else if(m == ACK_NO_USER){   
  796.     myGLCD.print(“Error!”, 21, 16);   
  797.     myGLCD.print(“FngrUndefined!”, 0, 24);   
  798.     myGLCD.update();   
  799.     delay(1500);   
  800.   }else if(level != ACK_MASTER_USER){   
  801.     myGLCD.print(“Error!”, 21, 16);   
  802.     myGLCD.print(“YouAreNotAdmin!”, 0, 24);   
  803.     myGLCD.update();   
  804.     delay(1500);   
  805.   }else if(m == ACK_TIMEOUT){   
  806.     myGLCD.print(“Error!”, 21, 16);   
  807.     myGLCD.print(“Timeout!”, 18, 16);   
  808.     myGLCD.update();   
  809.     delay(1500);   
  810.   }else{   
  811.     myGLCD.print(“Error!”, 21, 16);   
  812.     myGLCD.print(“UnknownError!”, 0, 16);   
  813.     myGLCD.update();   
  814.     delay(1500);   
  815.   }   
  816.   myGLCD.clrScr();   
  817.   myGLCD.update();   
  818. }   
  819.   
  820. void setup()   
  821. {   
  822.   pinMode(servopin,OUTPUT);// 设定舵机接口为输出接口   
  823.   pinMode(SWITCH_PIN,INPUT_PULLUP);// 设定微动开关接口为输入接口,并上拉   
  824.   pinMode(POWER_PIN,OUTPUT);//指纹模块电源接在这里   
  825.   
  826.   Serial1.begin(19200);   
  827.   
  828.   // LCD5110初始化   
  829.   myGLCD.InitLCD();   
  830.   myGLCD.setFont(SmallFont);   
  831.   
  832. }   
  833.   
  834. void loop()   
  835. {   
  836.   myGLCD.print(” Press Sensor “, 0, 4);   
  837.   myGLCD.print(“to Unlock Door”, 0, 12);   
  838.   myGLCD.print(” Press # Key  “, 0, 28);   
  839.   myGLCD.print(“to Login admin”, 0, 36);   
  840.   myGLCD.update();   
  841.   
  842.   if(digitalRead(SWITCH_PIN) == 0){   
  843.     digitalWrite(POWER_PIN,HIGH);   
  844.     delay(500);   
  845.     unlock();   
  846.     digitalWrite(POWER_PIN,LOW);   
  847.   }   
  848.   if(keypad.getKey() == ‘#’){   
  849.     digitalWrite(POWER_PIN,HIGH);   
  850.     delay(500);   
  851.     adminVerify();   
  852.     digitalWrite(POWER_PIN,LOW);   
  853.   }   
  854.   
  855. }   

P.S. You really need to put <!–more–> in the middle of a post like this…

Discussion

Historical comments were archived by the site owner. Each comment identifies its original author and publication time.

View discussion on GitHub

Built with Hugo
Theme Stack designed by Jimmy