Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: EthernetNetIf TextLCD mbed HTTPServer ID12RFID
main.cpp
00001 // RFID Cat Door Project 00002 // The code runs on mbed and implements RFID Cat Door system. System comprises 3 sensors (RFID Reader, Proximity sensor, Reed sensor) 00003 // and 1 actuator (Solenoid door lock). System operates either in offline or online mode (if IP address is acquired). In online mode 00004 // a web page is created describing system's state. A lockdown override is available in online mode locking down the system. 00005 // The system is controlled by a state machine and provides RFID-based entry control. Exit is allowed without authorization. 00006 00007 //#define NO_HW // uncomment if there's no HW attached to mbed 00008 00009 #include "mbed.h" // mbed library 00010 #include "ID12RFID.h" // ID12 RFID Reader library 00011 #include "TextLCD.h" // OrangeBoard LCD library 00012 #include "EthernetNetIf.h" // Ethernet library 00013 #include "HTTPServer.h" // HTTP Server library 00014 #include "HTTPRequestHandler.h" // HTTP Request Handler library 00015 #include <string> 00016 00017 EthernetNetIf eth; 00018 HTTPServer svr; 00019 class CatDoorHandler; 00020 00021 // State Machine Events 00022 enum Event { DoorOpenEvent, DoorClosedEvent, ProximityEvent, AuthTagReadEvent, DoorUnlockedTimeoutEvent, None }; 00023 string eventNames[] = { "DoorOpen", "DoorClosed", "Proximity", "AuthTagRead", "DoorUnlockedTimeout", "None" }; 00024 Event event = None; 00025 00026 // State Machine States 00027 enum State { DoorLockedClosed, DoorUnlockedClosed, DoorUnlockedOpen }; 00028 string stateNames[] = { "Door Locked & Closed", "Door Unlocked & Closed", "Door Unlocked & Open" }; 00029 State state = DoorLockedClosed; 00030 00031 bool bLockdown = false; // variable indicating a lockdown from the web page 00032 00033 // Cat's possible locations 00034 enum Location { Inside, Outside, Unknown }; 00035 string locationNames[] = { "Inside", "Outside", "Unknown" }; 00036 00037 // Each cat has tag, name, and location 00038 struct cat { int tag; string name; Location location; }; 00039 // List of authorized cats 00040 cat cats[] = { 00041 5454121, "Yellow", Unknown, 00042 //9733970, "Blue", Unknown, 00043 //463733, "Red", Unknown 00044 }; 00045 int catsN = sizeof(cats)/sizeof(cat); 00046 int catId = 0; // current cat ID 00047 00048 TextLCD lcd(p24, p26, p27, p28, p29, p30); // OrangeBoard LCD 00049 ID12RFID rfid(p14); // uart rx for ID12 RFID reader 00050 DigitalIn _door_open(p17); // reed sensor, 0 indicates door open 00051 DigitalIn _proximity(p16); // proximity sensor, 0 indicates an object within 10 cm 00052 DigitalOut unlock_door(p21); // solenoid, 1 will unlock the door 00053 00054 DigitalOut door_unlocked_led(LED1); // ON when door is unlocked 00055 DigitalOut door_open_led(LED2); // ON when door is open 00056 DigitalOut proximity_led(LED3); // ON when proximity sensor is triggered 00057 PwmOut rfid_read_led(LED4); // DIM = unauthorized tag read; BRIGHT = authorized tag read 00058 00059 const float LED_DIM = 0.05; 00060 const float LED_BRIGHT = 1; 00061 00062 // Authorized RFID Tag Read Event 00063 Timer tagReadTimer; 00064 bool IsAuthTagReadEvent() { 00065 if(rfid.readable()) { 00066 int tag = rfid.read(); // read the tag 00067 tagReadTimer.reset(); 00068 tagReadTimer.start(); // start 5 sec timer 00069 00070 lcd.cls(); lcd.locate(0, 0); lcd.printf("Tag: %08d", tag); 00071 for (int i = 0; i < catsN; ++i) { // find if tag is authorized 00072 if (cats[i].tag == tag) { 00073 catId = i; 00074 lcd.locate(0, 1); lcd.printf("Cat: %s", cats[i].name.c_str()); 00075 rfid_read_led = LED_BRIGHT; 00076 return true; 00077 } 00078 } 00079 00080 lcd.locate(0, 1); lcd.printf("Cat: Unknown"); // unknown tag 00081 rfid_read_led = LED_DIM; 00082 } 00083 if (tagReadTimer.read() > 5.0) { // each tag is shown for 5 sec 00084 tagReadTimer.stop(); 00085 tagReadTimer.reset(); 00086 rfid_read_led = 0; 00087 lcd.cls(); 00088 } 00089 return false; 00090 } 00091 00092 // Proximity Event 00093 bool IsProximityEvent() { 00094 bool result = false; 00095 static bool wasProximity = false; // last state 00096 bool bProximity = !_proximity.read(); // 0 indicates an object within 10 cm 00097 proximity_led = bProximity; 00098 if (bProximity & !wasProximity) // create event on transition only 00099 result = true; 00100 wasProximity = bProximity; 00101 return result; 00102 } 00103 00104 // Door Open Event 00105 bool IsDoorOpenEvent() { 00106 bool result = false; 00107 static bool wasOpen = false; // last state 00108 bool bDoorOpen = !_door_open.read(); // 0 indicates door open 00109 door_open_led = bDoorOpen; 00110 if (bDoorOpen & !wasOpen) // create event on transition only 00111 result = true; 00112 wasOpen = bDoorOpen; 00113 return result; 00114 } 00115 00116 // Door Closed Event 00117 Timer doorClosedTimer; 00118 bool IsDoorClosedEvent() { 00119 bool result = false; 00120 static bool wasClosed = true; // last state 00121 bool bDoorClosed = _door_open.read(); 00122 if (bDoorClosed & !wasClosed) { // start timer when door closes 00123 doorClosedTimer.reset(); 00124 doorClosedTimer.start(); 00125 } 00126 // event is only created if door has been closed for more than 1.2 sec 00127 if (bDoorClosed & doorClosedTimer.read() > 1.2) { 00128 doorClosedTimer.stop(); 00129 doorClosedTimer.reset(); 00130 result = true; 00131 } 00132 wasClosed = bDoorClosed; 00133 return result; 00134 } 00135 00136 // Door locking/unlocking code 00137 Timer doorUnlockedTimer; 00138 void UnlockDoor(bool req) { 00139 unlock_door = (req) ? 1 : 0; 00140 door_unlocked_led = unlock_door; 00141 if (req) { 00142 doorUnlockedTimer.reset(); 00143 doorUnlockedTimer.start(); 00144 } 00145 } 00146 00147 // Door Unlocked Timeout Event 00148 bool IsDoorUnlockedTimeoutEvent() { 00149 if (doorUnlockedTimer.read() > 5.0) { // fires if door has been unlocked for more than 5 sec 00150 doorUnlockedTimer.stop(); 00151 doorUnlockedTimer.reset(); 00152 return true; 00153 } 00154 return false; 00155 } 00156 00157 // State Machine Logic 00158 void CatDoorStateMachine(Event event) { 00159 static Location destination = Outside; // destination variable helps determine location of a cat 00160 printf("State: %s\t Event: %s\n", stateNames[state].c_str(), eventNames[event].c_str()); 00161 00162 switch(state) 00163 { 00164 case DoorLockedClosed : 00165 if (bLockdown) break; // bLockdown doesn't let state machine exit DoorLockedClosed state 00166 switch(event) 00167 { 00168 case ProximityEvent : 00169 UnlockDoor(true); // unlock door 00170 state = DoorUnlockedClosed; 00171 destination = Outside; // cat's coming outside 00172 break; 00173 case AuthTagReadEvent : 00174 UnlockDoor(true); // unlock door 00175 state = DoorUnlockedClosed; 00176 destination = Inside; // cat's coming inside 00177 break; 00178 default : 00179 break; 00180 } 00181 break; 00182 case DoorUnlockedClosed : 00183 switch(event) 00184 { 00185 case DoorUnlockedTimeoutEvent : // lock door after 5 sec 00186 UnlockDoor(false); // lock door 00187 state = DoorLockedClosed; 00188 break; 00189 case DoorOpenEvent : 00190 state = DoorUnlockedOpen; 00191 break; 00192 default : 00193 break; 00194 } 00195 break; 00196 case DoorUnlockedOpen : 00197 switch(event) 00198 { 00199 case DoorClosedEvent : // door closed, can lock it now 00200 UnlockDoor(false); // lock door 00201 state = DoorLockedClosed; 00202 cats[catId].location = destination; // cat's location determined 00203 break; 00204 default : 00205 break; 00206 } 00207 break; 00208 default : 00209 break; 00210 } 00211 } 00212 00213 int main() { 00214 bool bEthPresent = true; // online/offline mode variable 00215 lcd.cls(); lcd.locate(0, 0); lcd.printf("RFID Cat Door"); 00216 lcd.locate(0, 1); lcd.printf("Setting up ^..^"); 00217 printf("RFID Cat Door\n"); 00218 printf("Setting up Ethernet ^..^\n"); 00219 EthernetErr ethErr = eth.setup(); // Ethernet setup 00220 if (ethErr) { 00221 printf("Error %d in Ethernet setup\n", ethErr); 00222 printf("Operating in offline mode ^..^\n"); 00223 lcd.cls(); lcd.printf("Offline mode"); 00224 bEthPresent = false; // offline mode set 00225 } 00226 else { 00227 printf("Ethernet setup OK\n"); 00228 printf("Operating in online mode ^..^\n"); 00229 IpAddr ip = eth.getIp(); // IP address 00230 lcd.cls(); lcd.locate(0, 0); lcd.printf("Online mode, IP:"); 00231 lcd.locate(0, 1); lcd.printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); 00232 00233 svr.addHandler<CatDoorHandler>("/"); // our HTTP handler added 00234 svr.bind(80); // port 80 bound 00235 } 00236 00237 while(1) { 00238 if (bEthPresent) 00239 Net::poll(); // service HTTP requests 00240 00241 #ifndef NO_HW 00242 if (IsAuthTagReadEvent()) { 00243 event = AuthTagReadEvent; // Authorized Tag Read Event 00244 CatDoorStateMachine(event); 00245 } 00246 #endif 00247 if (IsProximityEvent()) { 00248 event = ProximityEvent; // Proximity Event 00249 CatDoorStateMachine(event); 00250 } 00251 00252 if (IsDoorOpenEvent()) { 00253 event = DoorOpenEvent; // Door Open Event 00254 CatDoorStateMachine(event); 00255 } 00256 00257 if (IsDoorClosedEvent()) { 00258 event = DoorClosedEvent; // Door Closed Event 00259 CatDoorStateMachine(event); 00260 } 00261 00262 if (IsDoorUnlockedTimeoutEvent()) { 00263 event = DoorUnlockedTimeoutEvent; // Door Unlocked Timeout Event 00264 CatDoorStateMachine(event); 00265 } 00266 } 00267 } 00268 00269 // Cat Door HTTP Handler will handle HTTP GET requests 00270 class CatDoorHandler : public HTTPRequestHandler 00271 { 00272 public: 00273 CatDoorHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : 00274 HTTPRequestHandler(rootPath, path, pTCPSocket){} 00275 00276 virtual ~CatDoorHandler(){} 00277 00278 static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket) 00279 { return new CatDoorHandler(rootPath, path, pTCPSocket); } 00280 00281 virtual void doGet() // handles HTTP GET requests 00282 { 00283 string _path = path(); // path will have "lockdown=yes" if lockdown checkbox was checked 00284 printf("doGet path: %s\n", _path.c_str()); 00285 bLockdown = (_path.find("lockdown=yes") == string::npos) ? false : true; 00286 if (bLockdown) { 00287 lcd.cls(); lcd.printf("System Lockdown!"); 00288 } 00289 else { 00290 lcd.cls(); 00291 } 00292 00293 // Create HTML page with status information, lockdown checkbox, and submit/refresh button 00294 string rs = "<html><head><title>RFID Cat Door</title></head><body><h3>RFID Cat Door</h3>"; 00295 string ds = "Door Status: <i>" + stateNames[state] + "</i><br>"; 00296 string cs = "Cat Status: <i>" + locationNames[cats[catId].location] + "</i><p>"; 00297 string ld = (bLockdown) ? " checked" : ""; // lockdownn checkbox reflects system lockdown state 00298 string fr = "<form method='get' action=''>" 00299 "<input type='checkbox' name='lockdown' value='yes'" + ld + "> Lockdown System <p>" 00300 "<input type='submit' value='Submit/Refresh Data'></form></body></html>"; 00301 rs += ds + cs + fr; 00302 setContentLen(rs.length()); 00303 respHeaders()["Connection"] = "close"; 00304 writeData(rs.c_str(), rs.length()); 00305 } 00306 00307 virtual void doPost() {} 00308 virtual void doHead() {} 00309 virtual void onReadable() {} 00310 virtual void onWriteable() {} 00311 virtual void onClose() {} 00312 };
Generated on Fri Jul 15 2022 05:26:09 by
1.7.2