├── .gitignore ├── Alarm.pde ├── README.md ├── libraries ├── Button │ ├── AlphaLicense.txt │ ├── Button.cpp │ ├── Button.h │ ├── Examples │ │ └── Button │ │ │ └── Button.pde │ └── keywords.txt ├── EEPROM │ ├── EEPROM.cpp │ ├── EEPROM.h │ ├── examples │ │ ├── eeprom_clear │ │ │ └── eeprom_clear.pde │ │ ├── eeprom_read │ │ │ └── eeprom_read.pde │ │ └── eeprom_write │ │ │ └── eeprom_write.pde │ └── keywords.txt ├── Keypad │ ├── Examples │ │ ├── CustomKeypad │ │ │ └── CustomKeypad.pde │ │ ├── DynamicKeypad │ │ │ └── DynamicKeypad.pde │ │ ├── EventKeypad │ │ │ └── EventKeypad.pde │ │ └── HelloKeypad │ │ │ └── HelloKeypad.pde │ ├── Keypad.cpp │ ├── Keypad.h │ └── keywords.txt └── ShiftRegLCD │ ├── ShiftRegLCD.cpp │ ├── ShiftRegLCD.h │ ├── examples │ ├── CustomChar │ │ └── CustomChar.pde │ ├── CustomChar2 │ │ └── CustomChar2.pde │ ├── HelloWorld │ │ └── HelloWorld.pde │ ├── HelloWorld2 │ │ └── HelloWorld2.pde │ └── SerialDisplay │ │ └── SerialDisplay.pde │ └── keywords.txt └── schematic ├── 4x4-Matrix-Keypad.png ├── LCD_2-wire.png └── Relay.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /Alarm.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino-based Burglar and Fire Alarm System GPL Source Code 3 | Copyright (C) 2010-2012 mykh 4 | 5 | This file is part of the Arduino-based Burglar and Fire Alarm System GPL Source Code ("Alarm Source Code"). 6 | 7 | Alarm Source Code is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Alarm Source Code is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Alarm Source Code. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | //#define TEST 28 | //#define EVENTS_LOG_ENABLED 29 | //#define LANG_UKR 30 | //#define USE_ANALOG_FIRE_SENSOR // not tested, since I haven't an analog fire sensor. details: http://www.seeedstudio.com/wiki/Grove_-_Gas_Sensor%28MQ2%29 31 | 32 | #ifdef USE_ANALOG_FIRE_SENSOR 33 | const static float FireSensorThreshold = 0.5; // set value from 0 to 1. 34 | #endif 35 | 36 | #if defined(ARDUINO) && (ARDUINO < 19) 37 | // copied from WProgram.h 38 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 39 | const static uint8_t A0 = 54; 40 | const static uint8_t A1 = 55; 41 | const static uint8_t A2 = 56; 42 | const static uint8_t A3 = 57; 43 | const static uint8_t A4 = 58; 44 | const static uint8_t A5 = 59; 45 | const static uint8_t A6 = 60; 46 | const static uint8_t A7 = 61; 47 | const static uint8_t A8 = 62; 48 | const static uint8_t A9 = 63; 49 | const static uint8_t A10 = 64; 50 | const static uint8_t A11 = 65; 51 | const static uint8_t A12 = 66; 52 | const static uint8_t A13 = 67; 53 | const static uint8_t A14 = 68; 54 | const static uint8_t A15 = 69; 55 | #else 56 | const static uint8_t A0 = 14; 57 | const static uint8_t A1 = 15; 58 | const static uint8_t A2 = 16; 59 | const static uint8_t A3 = 17; 60 | const static uint8_t A4 = 18; 61 | const static uint8_t A5 = 19; 62 | const static uint8_t A6 = 20; 63 | const static uint8_t A7 = 21; 64 | #endif 65 | #endif 66 | 67 | #define BoolToHighLow(val) (val ? HIGH : LOW) 68 | 69 | const static byte PIN_BAD = 0xFF; 70 | // Keypad pins 71 | const static byte PinKeypad_Col0 = 3; 72 | const static byte PinKeypad_Col1 = 4; 73 | const static byte PinKeypad_Col2 = 5; 74 | const static byte PinKeypad_Col3 = 6; 75 | const static byte PinKeypad_Row0 = 7; 76 | const static byte PinKeypad_Row1 = 8; 77 | const static byte PinKeypad_Row2 = 9; 78 | const static byte PinKeypad_Row3 = 10; 79 | // ShiftRegLCD pins 80 | const static uint8_t PinLCD_Backlight = 13; 81 | const static uint8_t PinLCD_Data = 12; 82 | const static uint8_t PinLCD_Clock = 11; 83 | // Alarm pins 84 | const static byte PinAlarm_Out = A0; 85 | const static byte PinAlarm_In = A1; 86 | const static byte PinAlarm_Tamper = A2; 87 | const static byte PinLed = A3; 88 | const static byte PinFire = A4; //PIN_BAD; 89 | const static byte PinBuzzer = 2; 90 | //const static byte PinGSM_TX = 1; 91 | //const static byte PinGSM_RX = 0; 92 | 93 | const static byte SettingsMagic = 0x11; 94 | const static byte PasswordLength_Max = 17; 95 | struct AlarmSettings 96 | { 97 | byte magic; 98 | char alarmPassword1[PasswordLength_Max]; 99 | // char alarmPassword2[PasswordLength_Max]; 100 | // char alarmPassword3[PasswordLength_Max]; 101 | // char alarmPassword4[PasswordLength_Max]; 102 | char menuPassword[PasswordLength_Max]; 103 | unsigned int keypadDebounceTime; 104 | unsigned int lcdBacklightTime; 105 | unsigned int beforeTurnOnDelay; 106 | unsigned int beforeAlarmDelay; 107 | unsigned int alarmOutMask; 108 | unsigned int alarmInMask; 109 | unsigned int alarmTamperMask; 110 | unsigned int alarmFireMask; 111 | unsigned int alarmStatOutCount; 112 | unsigned int alarmStatInCount; 113 | unsigned int alarmStatTamperCount; 114 | unsigned int alarmStatFireCount; 115 | } 116 | settings = 117 | { 118 | SettingsMagic, // magic 119 | "1111", // alarmPassword1, 120 | // "1111", // alarmPassword2, 121 | // "1111", // alarmPassword3, 122 | // "1111", // alarmPassword4, 123 | "0000", // menuPassword 124 | 80, // keypadDebounceTime 125 | 60000, // lcdBacklightTime 126 | 30000, // beforeTurnOnDelay 127 | 15000, // beforeAlarmDelay 128 | 0xFFFFFFFF, // alarmOutMask - all outputs are enabled 129 | 0xFFFFFFFF, // alarmInMask - all inputs are enabled 130 | 0xFFFFFFFF, // alarmTamperMask - all tampers are enabled 131 | 0xFFFFFFFF, // alarmFireMask - all fire inputs are enabled 132 | 0, // alarmStatOutCount 133 | 0, // alarmStatInCount 134 | 0, // alarmStatTamperCount 135 | 0, // alarmFireCount 136 | }; 137 | 138 | void saveSettings(void) 139 | { 140 | byte* p = (byte*)&settings; 141 | for (int i = 0; i < sizeof(AlarmSettings); i++) 142 | EEPROM.write(i, p[i]); 143 | }; 144 | 145 | void loadSettings(void) 146 | { 147 | byte magic = EEPROM.read(0); 148 | if (magic != SettingsMagic) 149 | { 150 | saveSettings(); 151 | return; 152 | } 153 | 154 | byte* p = (byte*)&settings; 155 | for (int i = 0; i < sizeof(AlarmSettings); i++) 156 | p[i] = EEPROM.read(i); 157 | }; 158 | 159 | /////////////////// ShiftRegLCDExt /////////////////// 160 | 161 | class ShiftRegLCDExt: public ShiftRegLCD 162 | { 163 | private: 164 | const uint8_t pinBacklight; 165 | public: 166 | ShiftRegLCDExt(uint8_t srdata, uint8_t srclock, uint8_t srbacklight, uint8_t enable, uint8_t lines); 167 | 168 | unsigned long lcdBacklightOnTime; 169 | 170 | void setBacklight(bool on); 171 | void setBacklightOn(); 172 | void printn(char ch, int n); 173 | }; 174 | 175 | ShiftRegLCDExt::ShiftRegLCDExt(uint8_t srdata, uint8_t srclock, uint8_t srbacklight, uint8_t enable, uint8_t lines) 176 | : ShiftRegLCD(srdata, srclock, enable, lines), pinBacklight(srbacklight), lcdBacklightOnTime(0) 177 | { 178 | pinMode(pinBacklight, OUTPUT); 179 | #ifdef LANG_UKR 180 | static const uint8_t ch_d[8] = {14, 10, 10, 10, 10, 31, 17, 0}; 181 | static const uint8_t ch_ya[8] = {15, 17, 17, 15, 9, 9, 17, 0}; 182 | static const uint8_t ch_sh[8] = {17, 17, 21, 21, 21, 21, 31, 0}; 183 | static const uint8_t ch_l[8] = {15, 9, 9, 9, 9, 9, 17, 0}; 184 | static const uint8_t ch_uj[8] = {6, 17, 19, 21, 25, 17, 17, 0}; 185 | 186 | createChar(1, ch_d); 187 | createChar(2, ch_ya); 188 | createChar(3, ch_sh); 189 | createChar(4, ch_l); 190 | createChar(5, ch_uj); 191 | #endif 192 | } 193 | 194 | void ShiftRegLCDExt::setBacklight(bool on) 195 | { 196 | digitalWrite(pinBacklight, BoolToHighLow(on)); 197 | } 198 | 199 | void ShiftRegLCDExt::setBacklightOn() 200 | { 201 | setBacklight(true); 202 | lcdBacklightOnTime = millis(); 203 | } 204 | 205 | void ShiftRegLCDExt::printn(char ch, int n) 206 | { 207 | for (int i = 0; i < n; i++) 208 | print(ch); 209 | } 210 | 211 | /////////////////// ShiftRegLCDExt /////////////////// 212 | 213 | // LCD Init 214 | ShiftRegLCDExt lcd(PinLCD_Data, PinLCD_Clock, PinLCD_Backlight, TWO_WIRE, 2 /* lines */); 215 | 216 | /////////////////// KeypadExt /////////////////// 217 | 218 | class KeypadExt: public Keypad 219 | { 220 | public: 221 | const static char KeyMenu = 'a'; 222 | const static char KeyEnter = 'd'; 223 | const static char KeyBackspace = 'c'; 224 | const static char KeyEsc = 'b'; 225 | const static char KeyLeft = '*'; 226 | const static char KeyRight = '#'; 227 | private: 228 | const static int bufferLenMax = 16; 229 | char buffer[bufferLenMax + 1]; 230 | public: 231 | KeypadExt(char *userKeymap, byte *row, byte *col, byte rows, byte cols); 232 | 233 | char getKey(); 234 | char gets(bool onlyDigits = false); 235 | char* getBuffer(); 236 | void setBuffer(const char* str); 237 | void clearBuffer(); 238 | }; 239 | 240 | KeypadExt::KeypadExt(char *userKeymap, byte *row, byte *col, byte rows, byte cols) 241 | : Keypad(userKeymap, row, col, rows, cols) 242 | { 243 | clearBuffer(); 244 | } 245 | 246 | char KeypadExt::getKey() 247 | { 248 | char key = Keypad::getKey(); 249 | if (key != NO_KEY) 250 | lcd.setBacklightOn(); 251 | return key; 252 | } 253 | 254 | char KeypadExt::gets(bool onlyDigits) 255 | { 256 | char key = getKey(); 257 | int len = strlen(buffer); 258 | switch (key) 259 | { 260 | case NO_KEY: 261 | case KeypadExt::KeyMenu: 262 | case KeypadExt::KeyEnter: 263 | case KeypadExt::KeyEsc: 264 | case KeypadExt::KeyLeft: 265 | case KeypadExt::KeyRight: 266 | break; 267 | case KeypadExt::KeyBackspace: 268 | if (len > 0) 269 | buffer[len - 1] = '\0'; 270 | break; 271 | default: 272 | if (onlyDigits && !isdigit(key)) 273 | break; 274 | if (len < bufferLenMax) 275 | { 276 | buffer[len] = key; 277 | buffer[len + 1] = '\0'; 278 | }; 279 | break; 280 | } 281 | #ifdef TEST 282 | if (key != NO_KEY) 283 | { 284 | Serial.print("Buffer "); 285 | Serial.println(buffer); 286 | } 287 | #endif 288 | return key; 289 | } 290 | 291 | char* KeypadExt::getBuffer() 292 | { 293 | return buffer; 294 | } 295 | 296 | void KeypadExt::setBuffer(const char* str) 297 | { 298 | if (strlen(str) <= bufferLenMax) 299 | strcpy(buffer, str); 300 | } 301 | 302 | void KeypadExt::clearBuffer() 303 | { 304 | buffer[0] = '\0'; 305 | } 306 | 307 | /////////////////// KeypadExt /////////////////// 308 | 309 | /////////////////// ButtonExt /////////////////// 310 | 311 | class ButtonExt: public Button 312 | { 313 | protected: 314 | unsigned long pressedLastTime; 315 | unsigned int debounceTime; 316 | public: 317 | ButtonExt(uint8_t buttonPin, uint8_t buttonMode=PULLDOWN, unsigned int _debounceTime=50); 318 | 319 | bool isPressedExt(); 320 | }; 321 | 322 | ButtonExt::ButtonExt(uint8_t buttonPin, uint8_t buttonMode, unsigned int _debounceTime) 323 | : Button(buttonPin, buttonMode), debounceTime(_debounceTime), pressedLastTime(0) 324 | { 325 | } 326 | 327 | bool ButtonExt::isPressedExt() 328 | { 329 | bool result = Button::isPressed(); 330 | return result; 331 | if (result || (debounceTime == 0)) 332 | { 333 | pressedLastTime = 0; 334 | return result; 335 | }; 336 | unsigned long now = millis(); 337 | if (pressedLastTime == 0) 338 | { 339 | pressedLastTime = now; 340 | return false; 341 | } 342 | if (pressedLastTime > now) 343 | { 344 | if (now <= debounceTime) 345 | return false; 346 | else 347 | pressedLastTime = now - debounceTime; 348 | }; 349 | result = ((now - pressedLastTime) <= debounceTime); 350 | return result; 351 | } 352 | 353 | /////////////////// ButtonExt /////////////////// 354 | 355 | // Keypad init 356 | const static byte rowsKeypad = 4; 357 | const static byte colsKeypad = 4; 358 | char keys[rowsKeypad][colsKeypad] = { 359 | {'1','2','3', 'a'}, 360 | {'4','5','6', 'b'}, 361 | {'7','8','9', 'c'}, 362 | {'*','0','#', 'd'} 363 | }; 364 | 365 | byte rowPins[rowsKeypad] = {PinKeypad_Row0, PinKeypad_Row1, PinKeypad_Row2, PinKeypad_Row3}; //connect to the row pinouts of the keypad 366 | byte colPins[colsKeypad] = {PinKeypad_Col0, PinKeypad_Col1, PinKeypad_Col2, PinKeypad_Col3}; //connect to the column pinouts of the keypad 367 | 368 | KeypadExt keypad = KeypadExt(makeKeymap(keys), rowPins, colPins, rowsKeypad, colsKeypad); 369 | 370 | /////////////////// Menu /////////////////// 371 | 372 | class MenuBase 373 | { 374 | private: 375 | const char* name; 376 | bool menuActive; 377 | public: 378 | MenuBase(const char* _name) 379 | : name(_name) 380 | { 381 | setActive(false); 382 | } 383 | virtual void setActive(bool _active) 384 | { 385 | menuActive = _active; 386 | } 387 | bool isActive(void) 388 | { 389 | return menuActive; 390 | } 391 | const char* getName() 392 | { 393 | return name; 394 | } 395 | virtual char* getHint(void) 396 | { 397 | return ""; 398 | } 399 | virtual bool process(void) = 0; 400 | }; 401 | 402 | class MenuItemValue 403 | { 404 | public: 405 | virtual void load(void) 406 | { 407 | keypad.clearBuffer(); 408 | } 409 | virtual bool save(void) 410 | { 411 | return true; 412 | } 413 | char* getLastError() 414 | { 415 | return "Invalid input"; 416 | } 417 | }; 418 | 419 | class MenuItemUIntValue: public MenuItemValue 420 | { 421 | private: 422 | unsigned int* value; 423 | public: 424 | MenuItemUIntValue(unsigned int* _value) 425 | : value(_value) 426 | { 427 | } 428 | virtual void load(void) 429 | { 430 | ltoa(*value, keypad.getBuffer(), 10); 431 | } 432 | virtual bool save(void) 433 | { 434 | *value = atol(keypad.getBuffer()); 435 | saveSettings(); 436 | return true; 437 | } 438 | }; 439 | 440 | class MenuItemMaskValue: public MenuItemValue 441 | { 442 | private: 443 | unsigned int* value; 444 | public: 445 | MenuItemMaskValue(unsigned int* _value) 446 | : value(_value) 447 | { 448 | } 449 | virtual void load(void) 450 | { 451 | ltoa((*value & 1), keypad.getBuffer(), 10); 452 | } 453 | virtual bool save(void) 454 | { 455 | *value = (atol(keypad.getBuffer()) == 0) ? 0 : 1; 456 | saveSettings(); 457 | return true; 458 | } 459 | }; 460 | 461 | class MenuItemStrValue: public MenuItemValue 462 | { 463 | private: 464 | char* value; 465 | public: 466 | MenuItemStrValue(char* _value) 467 | : value(_value) 468 | { 469 | } 470 | virtual void load(void) 471 | { 472 | keypad.setBuffer(value); 473 | } 474 | virtual bool save(void) 475 | { 476 | strcpy(value, keypad.getBuffer()); 477 | saveSettings(); 478 | return true; 479 | } 480 | }; 481 | 482 | class MenuItem: public MenuBase 483 | { 484 | public: 485 | MenuItemValue* value; 486 | 487 | MenuItem(const char* _name, MenuItemValue* _value); 488 | 489 | bool process(); 490 | 491 | void setActive(bool _active); 492 | char* getHint(void); 493 | void print(void); 494 | }; 495 | 496 | class Menu: public MenuBase 497 | { 498 | protected: 499 | int itemCount; 500 | int currIndex; 501 | MenuBase** items; 502 | public: 503 | Menu(const char* _name, int _index, MenuBase** _item); 504 | 505 | bool process(); 506 | }; 507 | 508 | MenuItem::MenuItem(const char* _name, MenuItemValue* _value) 509 | : MenuBase(_name), value(_value) 510 | { 511 | } 512 | 513 | bool MenuItem::process() 514 | { 515 | char ch = keypad.gets(); 516 | switch (ch) 517 | { 518 | case KeypadExt::KeyEsc: 519 | setActive(false); 520 | keypad.clearBuffer(); 521 | return true; 522 | case KeypadExt::KeyEnter: 523 | if (value->save()) 524 | { 525 | setActive(false); 526 | keypad.clearBuffer(); 527 | return true; 528 | } 529 | { 530 | lcd.clear(); 531 | lcd.print(value->getLastError()); 532 | delay(2000); 533 | return false; 534 | } 535 | } 536 | if (ch != NO_KEY) 537 | print(); 538 | return false; 539 | } 540 | 541 | void MenuItem::setActive(bool _active) 542 | { 543 | MenuBase::setActive(_active); 544 | if(_active) 545 | { 546 | value->load(); 547 | lcd.cursor(); 548 | print(); 549 | } 550 | else 551 | lcd.noCursor(); 552 | } 553 | 554 | char* MenuItem::getHint(void) 555 | { 556 | if (!isActive()) 557 | value->load(); 558 | return keypad.getBuffer(); 559 | } 560 | 561 | void MenuItem::print(void) 562 | { 563 | lcd.clear(); 564 | lcd.print(getName()); 565 | lcd.setCursor(0, 1); 566 | lcd.print(getHint()); 567 | } 568 | 569 | Menu::Menu(const char* _name, int _itemCount, MenuBase** _items) 570 | : MenuBase(_name), itemCount(_itemCount), items(_items), currIndex(0) 571 | { 572 | } 573 | 574 | bool Menu::process() 575 | { 576 | if (isActive()) 577 | { 578 | char ch = keypad.getKey(); 579 | switch (ch) 580 | { 581 | case KeypadExt::KeyEsc: 582 | setActive(false); 583 | return true; 584 | case KeypadExt::KeyEnter: 585 | setActive(false); 586 | items[currIndex]->setActive(true); 587 | return false; 588 | case KeypadExt::KeyLeft: 589 | if (currIndex == 0) 590 | currIndex = itemCount - 1; 591 | else 592 | currIndex--; 593 | break; 594 | case KeypadExt::KeyRight: 595 | if (currIndex == (itemCount - 1)) 596 | currIndex = 0; 597 | else 598 | currIndex++; 599 | break; 600 | } 601 | lcd.clear(); 602 | lcd.print(currIndex + 1); 603 | lcd.print('.'); 604 | lcd.print(items[currIndex]->getName()); 605 | lcd.setCursor(0, 1); 606 | lcd.print(items[currIndex]->getHint()); 607 | delay(100); 608 | } 609 | else 610 | if (items[currIndex]->process()) 611 | setActive(true); 612 | 613 | return false; 614 | } 615 | 616 | /////////////////// Menu /////////////////// 617 | 618 | // Menu init 619 | MenuItemUIntValue menuDebounceTimeVal(&settings.keypadDebounceTime); 620 | MenuItemUIntValue menuBeforeTurnOnDelayVal(&settings.beforeTurnOnDelay); 621 | MenuItemUIntValue menuBeforeAlarmDelayVal(&settings.beforeAlarmDelay); 622 | MenuItemUIntValue menuBacklightTimeVal(&settings.lcdBacklightTime); 623 | 624 | MenuItemStrValue menuAlarmPasswordVal(settings.alarmPassword1); 625 | MenuItemStrValue menuMenuPasswordVal(settings.menuPassword); 626 | 627 | MenuItemMaskValue menuAlarmOutVal(&settings.alarmOutMask); 628 | MenuItemMaskValue menuAlarmInVal(&settings.alarmInMask); 629 | MenuItemMaskValue menuAlarmTamperVal(&settings.alarmTamperMask); 630 | MenuItemMaskValue menuAlarmFireVal(&settings.alarmFireMask); 631 | 632 | MenuItemUIntValue menuAlarmOutStatVal(&settings.alarmStatOutCount); 633 | MenuItemUIntValue menuAlarmInStatVal(&settings.alarmStatInCount); 634 | MenuItemUIntValue menuAlarmTamperStatVal(&settings.alarmStatTamperCount); 635 | MenuItemUIntValue menuAlarmFireStatVal(&settings.alarmStatFireCount); 636 | 637 | const static int menuDelayItemCount = 4; 638 | MenuItem menuBeforeTurnOnDelay("Turn On", &menuBeforeTurnOnDelayVal); 639 | MenuItem menuItemDelayAlarm("Alarm", &menuBeforeAlarmDelayVal); 640 | MenuItem menuItemDelayDebounce("Key Debounce", &menuDebounceTimeVal); 641 | MenuItem menuItemDelayBacklight("LCD backlight", &menuBacklightTimeVal); 642 | MenuBase* menuDelayItems[menuDelayItemCount] = 643 | { 644 | &menuBeforeTurnOnDelay, 645 | &menuItemDelayAlarm, 646 | &menuItemDelayDebounce, 647 | &menuItemDelayBacklight 648 | }; 649 | Menu menuDelay("Delays (in ms)", menuDelayItemCount, menuDelayItems); 650 | 651 | const static int menuPinsItemCount = 4; 652 | MenuItem menuItemAlarmOut("Out", &menuAlarmOutVal); 653 | MenuItem menuItemAlarmIn("In", &menuAlarmInVal); 654 | MenuItem menuItemAlarmTamper("Tamper", &menuAlarmTamperVal); 655 | MenuItem menuItemAlarmFire("Fire", &menuAlarmFireVal); 656 | MenuBase* menuPinsItems[menuPinsItemCount] = 657 | { 658 | &menuItemAlarmOut, 659 | &menuItemAlarmIn, 660 | &menuItemAlarmTamper, 661 | &menuItemAlarmFire 662 | }; 663 | Menu menuPins("Pins mask", menuPinsItemCount, menuPinsItems); 664 | 665 | #ifdef EVENTS_LOG_ENABLED 666 | const static int menuPinsStatItemCount = 4; 667 | MenuItem menuItemAlarmOutStat("Out stat", &menuAlarmOutStatVal); 668 | MenuItem menuItemAlarmInStat("In stat", &menuAlarmInStatVal); 669 | MenuItem menuItemAlarmTamperStat("Tamper stat", &menuAlarmTamperStatVal); 670 | MenuItem menuItemAlarmFireStat("Fire stat", &menuAlarmFireStatVal); 671 | MenuBase* menuPinsStatItems[menuPinsStatItemCount] = 672 | { 673 | &menuItemAlarmOutStat, 674 | &menuItemAlarmInStat, 675 | &menuItemAlarmTamperStat, 676 | &menuItemAlarmFireStat 677 | }; 678 | Menu menuPinsStat("Statistics", menuPinsStatItemCount, menuPinsStatItems); 679 | #endif 680 | 681 | const static int menuMainItemCount = 4 682 | #ifdef EVENTS_LOG_ENABLED 683 | + 1 684 | #endif 685 | ; 686 | MenuItem menuItemPasswordAlarm("Alarm Password", &menuAlarmPasswordVal); 687 | MenuItem menuItemPasswordMenu("Menu Password", &menuMenuPasswordVal); 688 | MenuBase* menuMainItems[menuMainItemCount] = 689 | { 690 | //&menuDateTime, 691 | &menuDelay, 692 | &menuPins, 693 | #ifdef EVENTS_LOG_ENABLED 694 | &menuPinsStat, 695 | #endif 696 | &menuItemPasswordAlarm, 697 | &menuItemPasswordMenu 698 | }; 699 | Menu menu("", menuMainItemCount, menuMainItems); 700 | 701 | /////////////////// Alarm //////////////////////////// 702 | 703 | enum AlarmState {asBeforeArmed, asArmed, asBeforeAlarm, asAlarm, asDisarmed, asMenuPwdPromt, asMenuShow}; 704 | enum AlarmLedMode {lmOff, lmOn, lmBlink}; 705 | 706 | #ifdef LANG_UKR 707 | const char* lcdPasswordPromt = "BBE\1ITb KO\1 "; 708 | const char* lcdPasswordWrong = "HEBIPHU\5 KO\1"; 709 | const char* lcdBeforeArmMsg1 = "\1O BBIMKHEH\2"; 710 | const char* lcdBeforeArmMsg2 = "3A\4U\3U\4OCb "; 711 | const char* lcdArmModeOnMsg = "BBIMKHEHO !"; 712 | const char* lcdArmModeOffMsg = "BUMKHEHO"; 713 | const char* lcdMotionDetectedMsg = "PYX"; 714 | const char* lcdFireDetectedMsg = "FIRE"; 715 | #else 716 | const char* lcdPasswordPromt = "ENTER PASSWORD "; 717 | const char* lcdPasswordWrong = "WRONG PASSWORD"; 718 | const char* lcdBeforeArmMsg1 = "WILL BE ARMED"; 719 | const char* lcdBeforeArmMsg2 = "IN "; 720 | const char* lcdArmModeOnMsg = "ARMED !"; 721 | const char* lcdArmModeOffMsg = "DISARMED"; 722 | const char* lcdMotionDetectedMsg = "MOTION"; 723 | const char* lcdFireDetectedMsg = "FIRE"; 724 | #endif 725 | 726 | const char KeyAlarmOn = KeypadExt::KeyEnter; 727 | const char KeyAlarmOff = KeypadExt::KeyEnter; 728 | const char KeyAlarmMenu = 'a'; 729 | 730 | class Alarm 731 | { 732 | protected: 733 | const static unsigned int lcdPrintDelay = 250; 734 | const static unsigned int lcdShowInvalidPasswordMessageTime = 2500; 735 | const static unsigned int ledBlinkTime = 500; 736 | const static byte passwordLenMax = 8; 737 | 738 | const byte pinOut; 739 | const byte pinLed; 740 | const byte pinBuzzer; 741 | const byte pinTamper; 742 | const byte pinIn; 743 | const byte pinFire; 744 | 745 | unsigned long lcdPrintLastTime; 746 | unsigned long lcdShowInvalidPasswordMessageLastTime; 747 | unsigned long ledBlinkLastTime; 748 | unsigned long currStateStartTime; 749 | 750 | bool ledOn; 751 | volatile AlarmState currState; 752 | AlarmLedMode ledMode; 753 | bool showInvalidPasswordMessage; 754 | 755 | ButtonExt btnInput; 756 | ButtonExt btnTamper; 757 | #ifndef USE_ANALOG_FIRE_SENSOR 758 | ButtonExt btnFire; 759 | #endif 760 | 761 | bool lcdCanPrint(); 762 | 763 | bool passwordPromt(bool _showInvalidPasswordMessage); 764 | 765 | void setAlarm(bool on); 766 | void setBuzzer(bool on); 767 | void setLedMode(AlarmLedMode _ledMode); 768 | void setState(const AlarmState _newState); 769 | bool isFireDetected(); 770 | 771 | void process_BeforeArmed(); 772 | void process_Armed(); 773 | void process_BeforeAlarm(); 774 | void process_Alarm(); 775 | void process_Disarmed(); 776 | void process_MenuPwdPromt(); 777 | void process_MenuShow(); 778 | 779 | void enter_BeforeArmed(); 780 | void enter_Armed(); 781 | void enter_BeforeAlarm(); 782 | void enter_Alarm(); 783 | void enter_Disarmed(); 784 | void enter_MenuPwdPromt(); 785 | void enter_MenuShow(); 786 | 787 | void leave_BeforeArmed(); 788 | void leave_Armed(); 789 | void leave_BeforeAlarm(); 790 | void leave_Alarm(); 791 | void leave_Disarmed(); 792 | void leave_MenuPwdPromt(); 793 | void leave_MenuShow(); 794 | public: 795 | Alarm(AlarmState _state, byte _pinOut, byte _pinIn, byte _pinTamper, byte _pinFire, byte _pinLed, byte _pinBuzzer); 796 | 797 | void init(); 798 | 799 | void process(); 800 | }; 801 | 802 | Alarm::Alarm(AlarmState _state, byte _pinOut, byte _pinIn, byte _pinTamper, byte _pinFire, byte _pinLed, byte _pinBuzzer) 803 | : currState(_state), pinOut(_pinOut), pinIn(_pinIn), pinTamper(_pinTamper), pinFire(pinFire), pinLed(_pinLed), pinBuzzer(_pinBuzzer), 804 | btnInput(_pinIn, PULLUP), btnTamper(_pinTamper, PULLUP) 805 | #ifndef USE_ANALOG_FIRE_SENSOR 806 | , btnFire(_pinFire, PULLUP) 807 | #endif 808 | { 809 | currStateStartTime = 0; 810 | lcdPrintLastTime = 0; 811 | lcdShowInvalidPasswordMessageLastTime = 0; 812 | ledBlinkLastTime = 0; 813 | ledMode = lmOff; 814 | ledOn = false; 815 | showInvalidPasswordMessage = false; 816 | if (pinOut != PIN_BAD) 817 | pinMode(pinOut, OUTPUT); 818 | if (pinLed != PIN_BAD) 819 | pinMode(pinLed, OUTPUT); 820 | if (pinBuzzer != PIN_BAD) 821 | pinMode(pinBuzzer, OUTPUT); 822 | if (pinIn != PIN_BAD) 823 | pinMode(pinIn, INPUT); 824 | if (pinTamper != PIN_BAD) 825 | pinMode(pinTamper, INPUT); 826 | #ifdef USE_ANALOG_FIRE_SENSOR 827 | if (pinFire != PIN_BAD) 828 | pinMode(pinFire, INPUT); 829 | #endif 830 | } 831 | 832 | void Alarm::init() 833 | { 834 | lcd.clear(); 835 | lcd.setBacklightOn(); 836 | setState(currState); 837 | } 838 | 839 | bool Alarm::lcdCanPrint() 840 | { 841 | unsigned long now = millis(); 842 | if (lcdPrintLastTime > now) 843 | lcdPrintLastTime = 0; 844 | if ((now - lcdPrintLastTime) > lcdPrintDelay) 845 | { 846 | lcdPrintLastTime = now; 847 | return true; 848 | } 849 | else 850 | return false; 851 | } 852 | 853 | bool Alarm::passwordPromt(bool _showInvalidPasswordMessage) 854 | { 855 | unsigned long now = millis(); 856 | if (_showInvalidPasswordMessage) 857 | { 858 | showInvalidPasswordMessage = true; 859 | lcdShowInvalidPasswordMessageLastTime = now; 860 | lcd.clear(); 861 | lcd.print(lcdPasswordWrong); 862 | return false; 863 | } 864 | if (showInvalidPasswordMessage) 865 | { 866 | if (lcdShowInvalidPasswordMessageLastTime > now) 867 | lcdShowInvalidPasswordMessageLastTime = 0; 868 | if ((now - lcdShowInvalidPasswordMessageLastTime) > lcdShowInvalidPasswordMessageTime) 869 | showInvalidPasswordMessage = false; 870 | if (showInvalidPasswordMessage) 871 | { 872 | if (lcdCanPrint()) 873 | { 874 | lcd.clear(); 875 | lcd.print(lcdPasswordWrong); 876 | } 877 | return false; 878 | } 879 | } 880 | char key = keypad.gets(); 881 | if (lcdCanPrint() || (key != NO_KEY)) 882 | { 883 | lcd.clear(); 884 | lcd.print(lcdPasswordPromt); 885 | lcd.setCursor(0, 1); 886 | lcd.printn('*', strlen(keypad.getBuffer())); 887 | lcd.setBacklightOn(); 888 | } 889 | return (key == KeypadExt::KeyEnter); 890 | } 891 | 892 | bool Alarm::isFireDetected() 893 | { 894 | #ifdef USE_ANALOG_FIRE_SENSOR 895 | if (pinFire == PIN_BAD) 896 | return false; 897 | else 898 | { 899 | float value = (float)analogRead(pinFire) / 1024.0; 900 | return (value > FireSensorThreshold); 901 | } 902 | #else 903 | return !btnFire.isPressedExt(); 904 | #endif 905 | } 906 | 907 | void Alarm::setAlarm(bool on) 908 | { 909 | if (settings.alarmOutMask & 1) 910 | digitalWrite(pinOut, BoolToHighLow(on)); 911 | } 912 | 913 | void Alarm::setBuzzer(bool on) 914 | { 915 | digitalWrite(pinBuzzer, BoolToHighLow(on)); 916 | } 917 | 918 | void Alarm::setLedMode(AlarmLedMode _ledMode) 919 | { 920 | ledMode = _ledMode; 921 | } 922 | 923 | void Alarm::setState(const AlarmState _newState) 924 | { 925 | switch(currState) 926 | { 927 | case asBeforeArmed: 928 | leave_BeforeArmed(); 929 | break; 930 | case asArmed: 931 | leave_Armed(); 932 | break; 933 | case asBeforeAlarm: 934 | leave_BeforeAlarm(); 935 | break; 936 | case asAlarm: 937 | leave_Alarm(); 938 | break; 939 | case asDisarmed: 940 | leave_Disarmed(); 941 | break; 942 | case asMenuPwdPromt: 943 | leave_MenuPwdPromt(); 944 | break; 945 | case asMenuShow: 946 | leave_MenuShow(); 947 | break; 948 | }; 949 | switch(_newState) 950 | { 951 | case asBeforeArmed: 952 | enter_BeforeArmed(); 953 | break; 954 | case asArmed: 955 | enter_Armed(); 956 | break; 957 | case asBeforeAlarm: 958 | enter_BeforeAlarm(); 959 | break; 960 | case asAlarm: 961 | enter_Alarm(); 962 | break; 963 | case asDisarmed: 964 | enter_Disarmed(); 965 | break; 966 | case asMenuPwdPromt: 967 | enter_MenuPwdPromt(); 968 | break; 969 | case asMenuShow: 970 | enter_MenuShow(); 971 | break; 972 | }; 973 | currState = _newState; 974 | currStateStartTime = millis(); 975 | } 976 | 977 | void Alarm::process() 978 | { 979 | unsigned long now = millis(); 980 | // backlight 981 | lcd.setBacklight((now - lcd.lcdBacklightOnTime) <= settings.lcdBacklightTime); 982 | // led 983 | if (ledMode == lmBlink) 984 | { 985 | if (ledBlinkLastTime > now) 986 | ledBlinkLastTime = 0; 987 | if ((now - ledBlinkLastTime) > ledBlinkTime) 988 | { 989 | ledBlinkLastTime = now; 990 | ledOn = !ledOn; 991 | } 992 | } 993 | else 994 | ledOn = (ledMode == lmOn); 995 | digitalWrite(pinLed, BoolToHighLow(ledOn)); 996 | // correct start time 997 | if (currStateStartTime > now) 998 | currStateStartTime = 0; 999 | 1000 | if (currState != asAlarm) 1001 | { 1002 | if ((settings.alarmTamperMask & 1) && !btnTamper.isPressedExt()) 1003 | { 1004 | #ifdef TEST 1005 | Serial.println("Tamper pin is disconnected"); 1006 | #endif 1007 | setState(asAlarm); 1008 | #ifdef EVENTS_LOG_ENABLED 1009 | settings.alarmStatTamperCount++; 1010 | saveSettings(); 1011 | #endif 1012 | } 1013 | } 1014 | // process 1015 | switch(currState) 1016 | { 1017 | case asBeforeArmed: 1018 | process_BeforeArmed(); 1019 | break; 1020 | case asArmed: 1021 | process_Armed(); 1022 | break; 1023 | case asBeforeAlarm: 1024 | process_BeforeAlarm(); 1025 | break; 1026 | case asAlarm: 1027 | process_Alarm(); 1028 | break; 1029 | case asDisarmed: 1030 | process_Disarmed(); 1031 | break; 1032 | case asMenuPwdPromt: 1033 | process_MenuPwdPromt(); 1034 | break; 1035 | case asMenuShow: 1036 | process_MenuShow(); 1037 | break; 1038 | }; 1039 | } 1040 | 1041 | void Alarm::enter_BeforeArmed() 1042 | { 1043 | // ? setLedMode(lmOn); 1044 | } 1045 | 1046 | void Alarm::process_BeforeArmed() 1047 | { 1048 | unsigned long workTime = millis() - currStateStartTime; 1049 | if (lcdCanPrint()) 1050 | { 1051 | lcd.clear(); 1052 | lcd.print(lcdBeforeArmMsg1); 1053 | lcd.setCursor(0, 1); 1054 | lcd.print(lcdBeforeArmMsg2); 1055 | lcd.print((settings.beforeTurnOnDelay - workTime) / 1000); 1056 | lcd.setBacklightOn(); 1057 | } 1058 | if (workTime > settings.beforeTurnOnDelay) 1059 | setState(asArmed); 1060 | } 1061 | 1062 | void Alarm::leave_BeforeArmed() 1063 | { 1064 | lcd.clear(); 1065 | } 1066 | 1067 | void Alarm::enter_Armed() 1068 | { 1069 | setLedMode(lmOn); 1070 | // to avoid false positives 1071 | keypad.getKey(); 1072 | delay(200); 1073 | } 1074 | 1075 | void Alarm::process_Armed() 1076 | { 1077 | if (lcdCanPrint()) 1078 | { 1079 | lcd.clear(); 1080 | lcd.print(lcdArmModeOnMsg); 1081 | }; 1082 | 1083 | if ((settings.alarmFireMask & 1) && isFireDetected()) 1084 | { 1085 | #ifdef TEST 1086 | Serial.println("Fire detected"); 1087 | #endif 1088 | setState(asBeforeAlarm); 1089 | #ifdef EVENTS_LOG_ENABLED 1090 | settings.alarmStatFireCount++; 1091 | saveSettings(); 1092 | #endif 1093 | return; 1094 | } 1095 | 1096 | if ((settings.alarmInMask & 1) && !btnInput.isPressedExt()) 1097 | { 1098 | #ifdef TEST 1099 | Serial.println("Input pin is disconnected"); 1100 | #endif 1101 | setState(asBeforeAlarm); 1102 | #ifdef EVENTS_LOG_ENABLED 1103 | settings.alarmStatInCount++; 1104 | saveSettings(); 1105 | #endif 1106 | return; 1107 | } 1108 | 1109 | char key = keypad.getKey(); 1110 | if (key == NO_KEY) 1111 | return; 1112 | 1113 | if (key == KeyAlarmOff) 1114 | setState(asBeforeAlarm); 1115 | } 1116 | 1117 | void Alarm::leave_Armed() 1118 | { 1119 | setLedMode(lmOff); 1120 | lcd.clear(); 1121 | } 1122 | 1123 | void Alarm::enter_BeforeAlarm() 1124 | { 1125 | setBuzzer(true); 1126 | } 1127 | 1128 | void Alarm::process_BeforeAlarm() 1129 | { 1130 | unsigned long workTime = millis() - currStateStartTime; 1131 | if (workTime > settings.beforeAlarmDelay) 1132 | setState(asAlarm); 1133 | if (passwordPromt(false)) 1134 | { 1135 | bool pwdMatch = (strcmp(keypad.getBuffer(), settings.alarmPassword1) == 0); 1136 | keypad.clearBuffer(); 1137 | if (pwdMatch) 1138 | setState(asDisarmed); 1139 | else 1140 | passwordPromt(true); 1141 | } 1142 | } 1143 | 1144 | void Alarm::leave_BeforeAlarm() 1145 | { 1146 | setBuzzer(false); 1147 | lcd.clear(); 1148 | } 1149 | 1150 | void Alarm::enter_Alarm() 1151 | { 1152 | setAlarm(true); 1153 | setBuzzer(true); 1154 | setLedMode(lmBlink); 1155 | // TODO: Send SMS 1156 | 1157 | #ifdef EVENTS_LOG_ENABLED 1158 | settings.alarmStatOutCount++; 1159 | saveSettings(); 1160 | #endif 1161 | } 1162 | 1163 | void Alarm::process_Alarm() 1164 | { 1165 | if (passwordPromt(false)) 1166 | { 1167 | bool pwdMatch = (strcmp(keypad.getBuffer(), settings.alarmPassword1) == 0); 1168 | keypad.clearBuffer(); 1169 | if (pwdMatch) 1170 | setState(asDisarmed); 1171 | else 1172 | passwordPromt(true); 1173 | } 1174 | } 1175 | 1176 | void Alarm::leave_Alarm() 1177 | { 1178 | setAlarm(false); 1179 | setBuzzer(false); 1180 | setLedMode(lmOff); 1181 | // ? SMS 1182 | lcd.clear(); 1183 | } 1184 | 1185 | void Alarm::enter_Disarmed() 1186 | { 1187 | // to avoid false positives 1188 | keypad.getKey(); 1189 | delay(200); 1190 | } 1191 | 1192 | void Alarm::process_Disarmed() 1193 | { 1194 | if (lcdCanPrint()) 1195 | { 1196 | lcd.clear(); 1197 | lcd.print(lcdArmModeOffMsg); 1198 | lcd.setCursor(0, 1); 1199 | if ((settings.alarmInMask & 1) && !btnInput.isPressedExt()) 1200 | { 1201 | lcd.print(lcdMotionDetectedMsg); 1202 | lcd.print(" "); 1203 | } 1204 | if ((settings.alarmFireMask & 1) && isFireDetected()) 1205 | lcd.print(lcdFireDetectedMsg); 1206 | } 1207 | 1208 | char key = keypad.getKey(); 1209 | switch (key) 1210 | { 1211 | case KeyAlarmMenu: 1212 | setState(asMenuPwdPromt); 1213 | break; 1214 | case KeyAlarmOn: 1215 | setState(asBeforeArmed); 1216 | break; 1217 | } 1218 | } 1219 | 1220 | void Alarm::leave_Disarmed() 1221 | { 1222 | lcd.clear(); 1223 | } 1224 | 1225 | void Alarm::enter_MenuPwdPromt() 1226 | { 1227 | } 1228 | 1229 | void Alarm::process_MenuPwdPromt() 1230 | { 1231 | if (passwordPromt(false)) 1232 | { 1233 | bool pwdMatch = (strcmp(keypad.getBuffer(), settings.menuPassword) == 0); 1234 | keypad.clearBuffer(); 1235 | if (pwdMatch) 1236 | setState(asMenuShow); 1237 | else 1238 | { 1239 | lcd.clear(); 1240 | lcd.print(lcdPasswordWrong); 1241 | delay(2000); 1242 | setState(asDisarmed); 1243 | } 1244 | } 1245 | } 1246 | 1247 | void Alarm::leave_MenuPwdPromt() 1248 | { 1249 | } 1250 | 1251 | void Alarm::enter_MenuShow() 1252 | { 1253 | menu.setActive(true); 1254 | } 1255 | 1256 | void Alarm::process_MenuShow() 1257 | { 1258 | if (menu.process()) 1259 | setState(asDisarmed); 1260 | } 1261 | 1262 | void Alarm::leave_MenuShow() 1263 | { 1264 | keypad.clearBuffer(); 1265 | } 1266 | 1267 | /////////////////// Alarm //////////////////////////// 1268 | 1269 | // Alarm init 1270 | Alarm alarm(asBeforeArmed/*asDisarmed*/, PinAlarm_Out, PinAlarm_In, PinAlarm_Tamper, 1271 | PinFire, PinLed, PinBuzzer); 1272 | 1273 | void setup() 1274 | { 1275 | #ifdef TEST 1276 | Serial.begin(9600); 1277 | #endif 1278 | loadSettings(); 1279 | keypad.setDebounceTime(settings.keypadDebounceTime); 1280 | alarm.init(); 1281 | } 1282 | 1283 | void loop() 1284 | { 1285 | alarm.process(); 1286 | } 1287 | 1288 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino-based Burglar and Fire Alarm System 2 | =========================================== 3 | Quick video on youtube: http://youtu.be/SJTbPBYI8FU 4 | 5 | ![ScreenShot](https://raw.github.com/mykh/Burglar-and-Fire-Alarm-System-Arduino/gh-pages/images/alarm.jpeg) 6 | 7 | Used Libraries 8 | ============== 9 | * Button 10 | * EEPROM 11 | * Keypad 12 | * ShiftRegLCD 13 | -------------------------------------------------------------------------------- /libraries/Button/AlphaLicense.txt: -------------------------------------------------------------------------------- 1 | /* 2 | || 3 | || @file AlphaLicense.txt 4 | || @version 1.0 5 | || @author Alexander Brevig 6 | || @contact alexanderbrevig@gmail.com 7 | || 8 | || @description 9 | || | Descripbe the rights and expectations when using my code 10 | || # 11 | || 12 | || @license 13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved. 14 | || | http://www.gnu.org/licenses/lgpl.html 15 | || # 16 | || 17 | */ 18 | 19 | All content is released into the public domain, under the terms of the GNU LGPL (latest version). 20 | All code is intellectual property, unless stated otherwise. 21 | All usage of my code is permitted, as long as the headers stay intact ( from /* to */ ) or comply to these rules: 22 | *) You are not permitted to change any of these fields, and they should stay as is: 23 | @file 24 | @version 25 | @author 26 | @contact 27 | @licence 28 | *) You are permitted to modify the @description field, remember to update the changelog 29 | *) You are permitted to add these fields 30 | @contribution 31 | This field has to be inserted immediatly after the @contact with a 'blank' line above and below (blank as in '||') 32 | The changelog should indicate what is contributed 33 | @dependencies 34 | This field has to be inserted immediatly after the @description with a 'blank' line above and below (blank as in '||') 35 | @configuration 36 | This field has to be inserted immediatly after the @description or, if existant, the @dependencies with a 'blank' line above and below (blank as in '||') 37 | *) You are permitted and expected to add to the changelog, if changes or contributions are made. 38 | 39 | Example Header (the header to this file modified according to rules) 40 | /* 41 | || 42 | || @file AlphaLicense.txt 43 | || @version 1.0 44 | || @author Alexander Brevig 45 | || @contact alexanderbrevig@gmail.com 46 | || 47 | || @contribution 48 | || | Name Surname - www.domain.com - contact@domain.com 49 | || # 50 | || 51 | || @description 52 | || | Descripbe the rights and expectations when using my code 53 | || # 54 | || 55 | || @dependencies 56 | || | This file depends on the user having accsess to the internet, in order to read the LGPL 57 | || # 58 | || 59 | || @configuration 60 | || | No configuration needed 61 | || # 62 | || 63 | || @license 64 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved. 65 | || | http://www.gnu.org/licenses/lgpl.html 66 | || # 67 | || 68 | */ 69 | -------------------------------------------------------------------------------- /libraries/Button/Button.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | || 3 | || @file Button.cpp 4 | || @version 1.6 5 | || @author Alexander Brevig 6 | || @contact alexanderbrevig@gmail.com 7 | || 8 | || @description 9 | || | Provide an easy way of making buttons 10 | || # 11 | || 12 | || @license 13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved. 14 | || | This code is subject to AlphaLicence.txt 15 | || | alphabeta.alexanderbrevig.com/AlphaLicense.txt 16 | || # 17 | || 18 | */ 19 | 20 | //include the class definition 21 | #include "Button.h" 22 | 23 | /* 24 | || <> 25 | || @parameter buttonPin sets the pin that this switch is connected to 26 | || @parameter buttonMode indicates PULLUP or PULLDOWN resistor 27 | */ 28 | Button::Button(uint8_t buttonPin, uint8_t buttonMode){ 29 | this->pin=buttonPin; 30 | pinMode(pin,INPUT); 31 | buttonMode==PULLDOWN ? pulldown() : pullup(); 32 | state = 0; 33 | bitWrite(state,CURRENT,!mode); 34 | } 35 | 36 | /* 37 | || Set pin HIGH as default 38 | */ 39 | void Button::pullup(void){ 40 | mode=PULLUP; 41 | digitalWrite(pin,HIGH); 42 | } 43 | 44 | /* 45 | || Set pin LOW as default 46 | */ 47 | void Button::pulldown(void){ 48 | mode=PULLDOWN; 49 | //digitalWrite(pin,LOW); 50 | } 51 | 52 | /* 53 | || Return the bitWrite(state,CURRENT, of the switch 54 | */ 55 | bool Button::isPressed(void){ 56 | bitWrite(state,PREVIOUS,bitRead(state,CURRENT)); 57 | if (digitalRead(pin) == mode){ 58 | bitWrite(state,CURRENT,false); 59 | } else { 60 | bitWrite(state,CURRENT,true); 61 | } 62 | if (bitRead(state,CURRENT) != bitRead(state,PREVIOUS)){ 63 | bitWrite(state,CHANGED,true); 64 | }else{ 65 | bitWrite(state,CHANGED,false); 66 | } 67 | return bitRead(state,CURRENT); 68 | } 69 | 70 | /* 71 | || Return true if the button has been pressed 72 | */ 73 | bool Button::wasPressed(void){ 74 | if (bitRead(state,CURRENT)){ 75 | return true; 76 | } else { 77 | return false; 78 | } 79 | } 80 | 81 | /* 82 | || Return true if state has been changed 83 | */ 84 | bool Button::stateChanged(void){ 85 | return bitRead(state,CHANGED); 86 | } 87 | 88 | /* 89 | || Return true if the button is pressed, and was not pressed before 90 | */ 91 | bool Button::uniquePress(void){ 92 | return (isPressed() && stateChanged()); 93 | } 94 | 95 | /* 96 | || @changelog 97 | || | 2009-05-05 - Alexander Brevig : Added uniquePress() 98 | || | 2009-04-24 - Alexander Brevig : Added wasPressed() 99 | || | 2009-04-12 - Alexander Brevig : Added constructor 100 | || | Shortened logic 101 | || | 2009-04-10 - Alexander Brevig : Namechange from Switch 102 | || | 2009-04-07 - Alexander Brevig : Altered API 103 | || | 2008-10-23 - Alexander Brevig : Initial Release 104 | || | 2008-10-22 - Alexander Brevig : Class implemented 105 | || # 106 | */ 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /libraries/Button/Button.h: -------------------------------------------------------------------------------- 1 | /* 2 | || 3 | || @file Button.h 4 | || @version 1.6 5 | || @author Alexander Brevig 6 | || @contact alexanderbrevig@gmail.com 7 | || 8 | || @description 9 | || | Provide an easy way of making buttons 10 | || # 11 | || 12 | || @license 13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved. 14 | || | This code is subject to AlphaLicence.txt 15 | || | alphabeta.alexanderbrevig.com/AlphaLicense.txt 16 | || # 17 | || 18 | */ 19 | 20 | #ifndef BUTTON_H 21 | #define BUTTON_H 22 | 23 | #if defined(ARDUINO) && (ARDUINO >= 100) 24 | #include "Arduino.h" 25 | #else 26 | #include "WProgram.h" 27 | #endif 28 | 29 | #define PULLUP HIGH 30 | #define PULLDOWN LOW 31 | 32 | #define CURRENT 0 33 | #define PREVIOUS 1 34 | #define CHANGED 2 35 | 36 | class Button{ 37 | public: 38 | Button(uint8_t buttonPin, uint8_t buttonMode=PULLDOWN); 39 | void pullup(); 40 | void pulldown(); 41 | bool isPressed(); 42 | bool wasPressed(); 43 | bool stateChanged(); 44 | bool uniquePress(); 45 | private: 46 | uint8_t pin; 47 | uint8_t mode; 48 | uint8_t state; 49 | }; 50 | 51 | #endif 52 | 53 | /* 54 | || @changelog 55 | || | 1.6 2009-05-05 - Alexander Brevig : Added uniquePress, it returns true if the state has changed AND the button is pressed 56 | || | 1.5 2009-04-24 - Alexander Brevig : Added stateChanged, @contribution http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?action=viewprofile;username=klickadiklick 57 | || | 1.4 2009-04-24 - Alexander Brevig : Added wasPressed, @contribution http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?action=viewprofile;username=klickadiklick 58 | || | 1.3 2009-04-12 - Alexander Brevig : Added constructor with one parameter Button(uint8_t buttonPin) 59 | || | 1.2 2009-04-10 - Alexander Brevig : Namechange from Switch to Button 60 | || | 1.1 2009-04-07 - Alexander Brevig : Altered API 61 | || | 1.0 2008-10-23 - Alexander Brevig : Initial Release 62 | || # 63 | */ 64 | 65 | 66 | -------------------------------------------------------------------------------- /libraries/Button/Examples/Button/Button.pde: -------------------------------------------------------------------------------- 1 | /* 2 | || 3 | || @file Button.pde 4 | || @version 1.1 5 | || @author Alexander Brevig 6 | || @contact alexanderbrevig@gmail.com 7 | || 8 | || @description 9 | || | Display the intuitive way of using a button when using this Hardware Abstraction class 10 | || # 11 | || 12 | || @license 13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved. 14 | || | This code is subject to AlphaLicence.txt 15 | || | alphabeta.alexanderbrevig.com/AlphaLicense.txt 16 | || # 17 | || 18 | */ 19 | 20 | #include 21 | 22 | //create a Button object at pin 12 23 | /* 24 | || Wiring: 25 | || GND -----/ ------ pin 12 26 | */ 27 | Button button = Button(12,PULLUP); 28 | 29 | void setup(){ 30 | pinMode(13,OUTPUT); //debug to led 13 31 | } 32 | 33 | void loop(){ 34 | if(button.isPressed()){ 35 | digitalWrite(13,HIGH); 36 | }else{ 37 | digitalWrite(13,LOW); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /libraries/Button/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Buttons 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | Button KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | isPressed KEYWORD2 16 | wasPressed KEYWORD2 17 | stateChanged KEYWORD2 18 | uniquePress KEYWORD2 19 | pullup KEYWORD2 20 | pulldown KEYWORD2 21 | 22 | ####################################### 23 | # Constants (LITERAL1) 24 | ####################################### 25 | 26 | PULLUP LITERAL1 27 | PULLDOWN LITERAL1 28 | -------------------------------------------------------------------------------- /libraries/EEPROM/EEPROM.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | EEPROM.cpp - EEPROM library 3 | Copyright (c) 2006 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /****************************************************************************** 21 | * Includes 22 | ******************************************************************************/ 23 | 24 | #include 25 | #if defined(ARDUINO) && (ARDUINO >= 100) 26 | #include "Arduino.h" 27 | #else 28 | #include "WConstants.h" 29 | #endif 30 | #include "EEPROM.h" 31 | 32 | /****************************************************************************** 33 | * Definitions 34 | ******************************************************************************/ 35 | 36 | /****************************************************************************** 37 | * Constructors 38 | ******************************************************************************/ 39 | 40 | /****************************************************************************** 41 | * User API 42 | ******************************************************************************/ 43 | 44 | uint8_t EEPROMClass::read(int address) 45 | { 46 | return eeprom_read_byte((unsigned char *) address); 47 | } 48 | 49 | void EEPROMClass::write(int address, uint8_t value) 50 | { 51 | eeprom_write_byte((unsigned char *) address, value); 52 | } 53 | 54 | EEPROMClass EEPROM; 55 | -------------------------------------------------------------------------------- /libraries/EEPROM/EEPROM.h: -------------------------------------------------------------------------------- 1 | /* 2 | EEPROM.h - EEPROM library 3 | Copyright (c) 2006 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef EEPROM_h 21 | #define EEPROM_h 22 | 23 | #include 24 | 25 | class EEPROMClass 26 | { 27 | public: 28 | uint8_t read(int); 29 | void write(int, uint8_t); 30 | }; 31 | 32 | extern EEPROMClass EEPROM; 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /libraries/EEPROM/examples/eeprom_clear/eeprom_clear.pde: -------------------------------------------------------------------------------- 1 | /* 2 | * EEPROM Clear 3 | * 4 | * Sets all of the bytes of the EEPROM to 0. 5 | */ 6 | 7 | #include 8 | 9 | void setup() 10 | { 11 | // write a 0 to all 512 bytes of the EEPROM 12 | for (int i = 0; i < 512; i++) 13 | EEPROM.write(i, 0); 14 | 15 | // turn the LED on when we're done 16 | digitalWrite(13, HIGH); 17 | } 18 | 19 | void loop() 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /libraries/EEPROM/examples/eeprom_read/eeprom_read.pde: -------------------------------------------------------------------------------- 1 | /* 2 | * EEPROM Read 3 | * 4 | * Reads the value of each byte of the EEPROM and prints it 5 | * to the computer. 6 | */ 7 | 8 | #include 9 | 10 | // start reading from the first byte (address 0) of the EEPROM 11 | int address = 0; 12 | byte value; 13 | 14 | void setup() 15 | { 16 | Serial.begin(9600); 17 | } 18 | 19 | void loop() 20 | { 21 | // read a byte from the current address of the EEPROM 22 | value = EEPROM.read(address); 23 | 24 | Serial.print(address); 25 | Serial.print("\t"); 26 | Serial.print(value, DEC); 27 | Serial.println(); 28 | 29 | // advance to the next address of the EEPROM 30 | address = address + 1; 31 | 32 | // there are only 512 bytes of EEPROM, from 0 to 511, so if we're 33 | // on address 512, wrap around to address 0 34 | if (address == 512) 35 | address = 0; 36 | 37 | delay(500); 38 | } 39 | -------------------------------------------------------------------------------- /libraries/EEPROM/examples/eeprom_write/eeprom_write.pde: -------------------------------------------------------------------------------- 1 | /* 2 | * EEPROM Write 3 | * 4 | * Stores values read from analog input 0 into the EEPROM. 5 | * These values will stay in the EEPROM when the board is 6 | * turned off and may be retrieved later by another sketch. 7 | */ 8 | 9 | #include 10 | 11 | // the current address in the EEPROM (i.e. which byte 12 | // we're going to write to next) 13 | int addr = 0; 14 | 15 | void setup() 16 | { 17 | } 18 | 19 | void loop() 20 | { 21 | // need to divide by 4 because analog inputs range from 22 | // 0 to 1023 and each byte of the EEPROM can only hold a 23 | // value from 0 to 255. 24 | int val = analogRead(0) / 4; 25 | 26 | // write the value to the appropriate byte of the EEPROM. 27 | // these values will remain there when the board is 28 | // turned off. 29 | EEPROM.write(addr, val); 30 | 31 | // advance to the next address. there are 512 bytes in 32 | // the EEPROM, so go back to 0 when we hit 512. 33 | addr = addr + 1; 34 | if (addr == 512) 35 | addr = 0; 36 | 37 | delay(100); 38 | } 39 | -------------------------------------------------------------------------------- /libraries/EEPROM/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Ultrasound 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | EEPROM KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | ####################################### 16 | # Constants (LITERAL1) 17 | ####################################### 18 | 19 | -------------------------------------------------------------------------------- /libraries/Keypad/Examples/CustomKeypad/CustomKeypad.pde: -------------------------------------------------------------------------------- 1 | /* @file CustomKeypad.pde 2 | || @version 1.0 3 | || @author Alexander Brevig 4 | || @contact alexanderbrevig@gmail.com 5 | || 6 | || @description 7 | || | Demonstrates changing the keypad size and key values. 8 | || # 9 | */ 10 | #include 11 | 12 | const byte ROWS = 4; //four rows 13 | const byte COLS = 4; //four columns 14 | //define the cymbols on the buttons of the keypads 15 | char hexaKeys[ROWS][COLS] = { 16 | {'0','1','2','3'}, 17 | {'4','5','6','7'}, 18 | {'8','9','A','B'}, 19 | {'C','D','E','F'} 20 | }; 21 | byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad 22 | byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad 23 | 24 | //initialize an instance of class NewKeypad 25 | Keypad cusomKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 26 | 27 | void setup(){ 28 | Serial.begin(9600); 29 | } 30 | 31 | void loop(){ 32 | char customKey = cusomKeypad.getKey(); 33 | 34 | if (customKey != NO_KEY){ 35 | Serial.println(customKey); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /libraries/Keypad/Examples/DynamicKeypad/DynamicKeypad.pde: -------------------------------------------------------------------------------- 1 | /* @file DynamicKeypad.pde 2 | || @version 1.0 3 | || @author Mark Stanley 4 | || @contact mstanley@technologist.com 5 | || 6 | || @dificulty: Intermediate 7 | || 8 | || *** THE KEYPAD REQUIRES PULL-UP RESISTORS ON THE ROW PINS. *** 9 | || 10 | || @description 11 | || | This is a demonstration of keypadEvents. It's used to switch between keymaps 12 | || | while using only one keypad. The main concepts being demonstrated are: 13 | || | 14 | || | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding. 15 | || | How to use setHoldTime() and why. 16 | || | Making more than one thing happen with the same key. 17 | || | Assigning and changing keymaps on the fly. 18 | || | 19 | || | Another useful feature is also included with this demonstration although 20 | || | it's not really one of the concepts that I wanted to show you. If you look 21 | || | at the code in the PRESSED event you will see that the first section of that 22 | || | code is used to scroll through three different letters on each key. For 23 | || | example, pressing the '2' key will step through the letters 'd', 'e' and 'f'. 24 | || | 25 | || | 26 | || | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding 27 | || | Very simply, the PRESSED event occurs imediately upon detecting a pressed 28 | || | key and will not happen again until after a RELEASED event. When the HOLD 29 | || | event fires it always falls between PRESSED and RELEASED. However, it will 30 | || | only occur if a key has been pressed for longer than the setHoldTime() interval. 31 | || | 32 | || | How to use setHoldTime() and why 33 | || | Take a look at keypad.setHoldTime(500) in the code. It is used to set the 34 | || | time delay between a PRESSED event and the start of a HOLD event. The value 35 | || | 500 is in milliseconds (mS) and is equivalent to half a second. After pressing 36 | || | a key for 500mS the HOLD event will fire and any code contained therein will be 37 | || | executed. This event will stay active for as long as you hold the key except 38 | || | in the case of bug #1 listed above. 39 | || | 40 | || | Making more than one thing happen with the same key. 41 | || | If you look under the PRESSED event (case PRESSED:) you will see that the '#' 42 | || | is used to print a new line, Serial.println(). But take a look at the first 43 | || | half of the HOLD event and you will see the same key being used to switch back 44 | || | and forth between the letter and number keymaps that were created with alphaKeys[4][5] 45 | || | and numberKeys[4][5] respectively. 46 | || | 47 | || | Assigning and changing keymaps on the fly 48 | || | You will see that the '#' key has been designated to perform two different functions 49 | || | depending on how long you hold it down. If you press the '#' key for less than the 50 | || | setHoldTime() then it will print a new line. However, if you hold if for longer 51 | || | than that it will switch back and forth between numbers and letters. You can see the 52 | || | keymap changes in the HOLD event. 53 | || | 54 | || | 55 | || | In addition... 56 | || | You might notice a couple of things that you won't find in the Arduino language 57 | || | reference. The first would be #include . This is a standard library from 58 | || | the C programming language and though I don't normally demonstrate these types of 59 | || | things from outside the Arduino language reference I felt that its use here was 60 | || | justified by the simplicity that it brings to this sketch. 61 | || | That simplicity is provided by the two calls to isalpha(key) and isdigit(key). 62 | || | The first one is used to decide if the key that was pressed is any letter from a-z 63 | || | or A-Z and the second one decides if the key is any number from 0-9. The return 64 | || | value from these two functions is either a zero or some positive number greater 65 | || | than zero. This makes it very simple to test a key and see if it is a number or 66 | || | a letter. So when you see the following: 67 | || | 68 | || | if (isalpha(key)) // this tests to see if your key was a letter 69 | || | 70 | || | And the following may be more familiar to some but it is equivalent: 71 | || | 72 | || | if (isalpha(key) != 0) // this tests to see if your key was a letter 73 | || | 74 | || | And Finally... 75 | || | To better understand how the event handler affects your code you will need to remember 76 | || | that it gets called only when you press, hold or release a key. However, once a key 77 | || | is pressed or held then the event handler gets called at the full speed of the loop(). 78 | || | 79 | || | *** THE KEYPAD REQUIRES PULL-UP RESISTORS ON THE ROW PINS. *** 80 | || # 81 | */ 82 | #include 83 | #include 84 | 85 | // Define the keymaps. The blank spot (lower left) is the space character. 86 | char alphaKeys[4][3] = { 87 | { 'a','d','g' }, 88 | { 'j','m','p' }, 89 | { 's','v','y' }, 90 | { ' ','.','#' } 91 | }; 92 | 93 | char numberKeys[4][3] = { 94 | { '1','2','3' }, 95 | { '4','5','6' }, 96 | { '7','8','9' }, 97 | { ' ','0','#' } 98 | }; 99 | 100 | boolean alpha = false; // Start with the numeric keypad. 101 | 102 | char* keypadMap = (alpha == true) ? makeKeymap(alphaKeys) : makeKeymap(numberKeys); 103 | 104 | // Connect keypad ROW0, ROW1, ROW2 and ROW3 to these pins, eg. ROW0 = Arduino pin2. 105 | byte rowPins[] = { 9, 8, 7, 6 }; 106 | 107 | // Connect keypad COL0, COL1 and COL2 to these pins, eg. COL0 = Arduino pin6. 108 | byte colPins[] = { 12, 11, 10 }; 109 | 110 | //create a new Keypad 111 | Keypad keypad = Keypad(keypadMap, rowPins, colPins, sizeof(rowPins), sizeof(colPins)); 112 | 113 | const byte ledPin = 13; // Use the LED on pin 13. 114 | 115 | void setup() { 116 | Serial.begin(9600); 117 | digitalWrite(ledPin, HIGH); // Turns the LED on. 118 | keypad.addEventListener(keypadEvent); // Add an event listener. 119 | keypad.setHoldTime(500); // Default is 1000mS 120 | keypad.setDebounceTime(250); // Default is 50mS 121 | } 122 | 123 | void loop() { 124 | char key = keypad.getKey(); 125 | 126 | if (alpha) { // Flash the LED if we are using the letter keymap. 127 | digitalWrite(ledPin,!digitalRead(ledPin)); 128 | delay(100); 129 | } 130 | } 131 | 132 | // Take care of some special events. 133 | void keypadEvent(KeypadEvent key) { 134 | static char virtKey = NO_KEY; // Stores the last virtual key press. (Alpha keys only) 135 | static char physKey = NO_KEY; // Stores the last physical key press. (Alpha keys only) 136 | static char buildStr[12]; 137 | static byte buildCount; 138 | static byte pressCount; 139 | 140 | switch (keypad.getState()) 141 | { 142 | case PRESSED: 143 | if (isalpha(key)) { // This is a letter key so we're using the letter keymap. 144 | if (physKey != key) { // New key so start with the first of 3 characters. 145 | pressCount = 0; 146 | virtKey = key; 147 | physKey = key; 148 | } 149 | else { // Pressed the same key again... 150 | virtKey++; // so select the next character on that key. 151 | pressCount++; // Tracks how many times we press the same key. 152 | } 153 | if (pressCount > 2) { // Last character reached so cycle back to start. 154 | pressCount = 0; 155 | virtKey = key; 156 | } 157 | Serial.print(virtKey); // Used for testing. 158 | } 159 | if (isdigit(key) || key == ' ' || key == '.') Serial.print(key); 160 | if (key == '#') Serial.println(); 161 | break; 162 | 163 | case HOLD: 164 | if (key == '#') { // Toggle between keymaps. 165 | if (alpha == true) { // We are currently using a keymap with letters 166 | keypad.begin(*numberKeys); // and want to change to numbers. 167 | alpha = false; 168 | } 169 | else { // Or, we are currently using a keymap with numbers 170 | keypad.begin(*alphaKeys); // and want to change to letters. 171 | alpha = true; 172 | } 173 | } 174 | else { // Some key other than '#' was pressed. 175 | buildStr[buildCount++] = (isalpha(key)) ? virtKey : key; 176 | buildStr[buildCount] = '\0'; 177 | Serial.println(); 178 | Serial.println(buildStr); 179 | } 180 | break; 181 | 182 | case RELEASED: 183 | if (buildCount >= sizeof(buildStr)) buildCount = 0; // Our string is full. Start fresh. 184 | break; 185 | 186 | } // end switch-case 187 | } // end keypad events 188 | -------------------------------------------------------------------------------- /libraries/Keypad/Examples/EventKeypad/EventKeypad.pde: -------------------------------------------------------------------------------- 1 | /* @file EventSerialKeypad.pde 2 | || @version 1.0 3 | || @author Alexander Brevig 4 | || @contact alexanderbrevig@gmail.com 5 | || 6 | || @description 7 | || | Demonstrates using the KeypadEvent. 8 | || # 9 | */ 10 | #include 11 | 12 | const byte ROWS = 4; //four rows 13 | const byte COLS = 4; //four columns 14 | char keys[ROWS][COLS] = { 15 | {'1','2','3','A'}, 16 | {'4','5','6','B'}, 17 | {'7','8','9','C'}, 18 | {'#','0','*','D'} 19 | }; 20 | byte rowPins[ROWS] = {2,3,4,5}; //connect to the row pinouts of the keypad 21 | byte colPins[COLS] = {6,7,8,9}; //connect to the column pinouts of the keypad 22 | 23 | Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); 24 | byte ledPin = 13; 25 | 26 | boolean blink = false; 27 | 28 | void setup(){ 29 | Serial.begin(9600); 30 | pinMode(ledPin, OUTPUT); // sets the digital pin as output 31 | digitalWrite(ledPin, HIGH); // sets the LED on 32 | keypad.addEventListener(keypadEvent); //add an event listener for this keypad 33 | } 34 | 35 | void loop(){ 36 | char key = keypad.getKey(); 37 | 38 | if (key != NO_KEY) { 39 | Serial.println(key); 40 | } 41 | if (blink){ 42 | digitalWrite(ledPin,!digitalRead(ledPin)); 43 | delay(100); 44 | } 45 | } 46 | 47 | //take care of some special events 48 | void keypadEvent(KeypadEvent key){ 49 | switch (keypad.getState()){ 50 | case PRESSED: 51 | switch (key){ 52 | case '#': digitalWrite(ledPin,!digitalRead(ledPin)); break; 53 | case '*': 54 | digitalWrite(ledPin,!digitalRead(ledPin)); 55 | break; 56 | } 57 | break; 58 | case RELEASED: 59 | switch (key){ 60 | case '*': 61 | digitalWrite(ledPin,!digitalRead(ledPin)); 62 | blink = false; 63 | break; 64 | } 65 | break; 66 | case HOLD: 67 | switch (key){ 68 | case '*': blink = true; break; 69 | } 70 | break; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /libraries/Keypad/Examples/HelloKeypad/HelloKeypad.pde: -------------------------------------------------------------------------------- 1 | /* @file HelloKeypad.pde 2 | || @version 1.0 3 | || @author Alexander Brevig 4 | || @contact alexanderbrevig@gmail.com 5 | || 6 | || @description 7 | || | Demonstrates the simplest use of the matrix Keypad library. 8 | || # 9 | */ 10 | #include 11 | 12 | const byte ROWS = 4; //four rows 13 | const byte COLS = 3; //three columns 14 | char keys[ROWS][COLS] = { 15 | {'1','2','3'}, 16 | {'4','5','6'}, 17 | {'7','8','9'}, 18 | {'#','0','*'} 19 | }; 20 | byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad 21 | byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad 22 | 23 | Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); 24 | 25 | void setup(){ 26 | Serial.begin(9600); 27 | } 28 | 29 | void loop(){ 30 | char key = keypad.getKey(); 31 | 32 | if (key != NO_KEY){ 33 | Serial.println(key); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /libraries/Keypad/Keypad.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | || 3 | || @file Keypad.h 4 | || @version 1.8 5 | || @author Mark Stanley, Alexander Brevig 6 | || @contact mstanley@technologist.com, alexanderbrevig@gmail.com 7 | || 8 | || @description 9 | || | This library provides a simple interface for using matrix 10 | || | keypads. It supports the use of multiple keypads with the 11 | || | same or different sets of keys. It also supports user 12 | || | selectable pins and definable keymaps. 13 | || # 14 | || 15 | || @license 16 | || | This library is free software; you can redistribute it and/or 17 | || | modify it under the terms of the GNU Lesser General Public 18 | || | License as published by the Free Software Foundation; version 19 | || | 2.1 of the License. 20 | || | 21 | || | This library is distributed in the hope that it will be useful, 22 | || | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | || | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | || | Lesser General Public License for more details. 25 | || | 26 | || | You should have received a copy of the GNU Lesser General Public 27 | || | License along with this library; if not, write to the Free Software 28 | || | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 29 | || # 30 | || 31 | */ 32 | 33 | #include "Keypad.h" 34 | 35 | // <> Allows custom keymap. pin configuration and keypad size 36 | Keypad::Keypad(char *userKeymap, byte *row, byte *col, byte rows, byte cols) 37 | { 38 | rowPins = row; 39 | columnPins = col; 40 | 41 | size.rows = rows; 42 | size.columns = cols; 43 | 44 | begin(userKeymap); 45 | 46 | lastUpdate = 0; 47 | debounceTime = 50; 48 | holdTime = 1000; 49 | keypadEventListener = 0; 50 | currentKey = NO_KEY; 51 | state = IDLE; 52 | 53 | initializePins(); 54 | } 55 | 56 | // Let the user define a keymap - assume the same row- / columncount as defined in constructor 57 | void Keypad::begin( char *userKeymap){ 58 | keymap = userKeymap; 59 | } 60 | 61 | // Returns the keykode of the pressed key, or NO_KEY if no key is pressed 62 | char Keypad::getKey(){ 63 | char key = NO_KEY; // Assume that no key is pressed, this is the default return for getKey() 64 | for (byte c=0; c= holdTime) && digitalRead(rowPins[r]) == LOW){ 71 | transitionTo(HOLD); 72 | } 73 | // Button release 74 | if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == HIGH){ 75 | transitionTo(RELEASED); 76 | currentKey = NO_KEY; 77 | } 78 | } 79 | // Button pressed event. The user pressed a button. 80 | else if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == LOW){ 81 | digitalWrite(columnPins[c],HIGH); // De-activate the current column. 82 | key = keymap[c+(r*size.columns)]; 83 | lastUpdate = millis(); 84 | goto EVALUATE_KEY; // Save resources and do not attempt to parse to keys at a time 85 | } 86 | } 87 | digitalWrite(columnPins[c],HIGH); // De-activate the current column. 88 | } 89 | 90 | EVALUATE_KEY: 91 | if (key != NO_KEY && key != currentKey){ 92 | currentKey = key; 93 | transitionTo(PRESSED); 94 | return currentKey; 95 | } 96 | else{ 97 | return NO_KEY; 98 | } 99 | } 100 | 101 | 102 | KeypadState Keypad::getState(){ 103 | return state; 104 | } 105 | 106 | void Keypad::setDebounceTime(unsigned int debounce){ 107 | debounceTime = debounce; 108 | } 109 | void Keypad::setHoldTime(unsigned int hold){ 110 | holdTime = hold; 111 | } 112 | 113 | void Keypad::addEventListener(void (*listener)(char)){ 114 | keypadEventListener = listener; 115 | } 116 | 117 | //private 118 | void Keypad::transitionTo(KeypadState newState){ 119 | if (state!=newState){ 120 | state = newState; 121 | if (keypadEventListener!=NULL){ 122 | keypadEventListener(currentKey); 123 | } 124 | } 125 | } 126 | 127 | void Keypad::initializePins(){ 128 | for (byte r=0; r= 100) 37 | #include "Arduino.h" 38 | #else 39 | #include "WProgram.h" 40 | #endif 41 | 42 | #define makeKeymap(x) ((char*)x) 43 | 44 | typedef char KeypadEvent; 45 | 46 | typedef enum { 47 | IDLE=0, 48 | PRESSED, 49 | RELEASED, 50 | HOLD 51 | } KeypadState; 52 | 53 | typedef struct { 54 | byte rows : 4; 55 | byte columns : 4; 56 | } KeypadSize; 57 | 58 | const char NO_KEY = '\0'; 59 | #define KEY_RELEASED NO_KEY 60 | 61 | class Keypad { 62 | public: 63 | /* 64 | Keypad(); 65 | Keypad(byte row[], byte col[], byte rows, byte cols); 66 | */ 67 | Keypad(char *userKeymap, byte *row, byte *col, byte rows, byte cols); 68 | 69 | //void begin(); //DEPRECATED! 70 | void begin(char *userKeymap); 71 | char getKey(); 72 | KeypadState getState(); 73 | void setDebounceTime(unsigned int debounce); 74 | void setHoldTime(unsigned int hold); 75 | void addEventListener(void (*listener)(char)); 76 | 77 | private: 78 | void transitionTo(KeypadState newState); 79 | void initializePins(); 80 | 81 | char *keymap; 82 | byte *rowPins; 83 | byte *columnPins; 84 | KeypadSize size; 85 | KeypadState state; 86 | char currentKey; 87 | unsigned long lastUpdate; 88 | unsigned int debounceTime; 89 | unsigned int holdTime; 90 | void (*keypadEventListener)(char); 91 | }; 92 | 93 | #endif 94 | 95 | /* 96 | || @changelog 97 | || | 1.8 2009-07-08 - Alexander Brevig : No longer uses arrays 98 | || | 1.7 2009-06-18 - Alexander Brevig : This library is a Finite State Machine 99 | || | every time a state changes the keypadEventListener will trigger, if set 100 | || | 1.7 2009-06-18 - Alexander Brevig : Added setDebounceTime 101 | || | setHoldTime specifies the amount of microseconds before a HOLD state triggers 102 | || | 1.7 2009-06-18 - Alexander Brevig : Added transitionTo 103 | || | 1.6 2009-06-15 - Alexander Brevig : Added getState() and state variable 104 | || | 1.5 2009-05-19 - Alexander Brevig : Added setHoldTime() 105 | || | 1.4 2009-05-15 - Alexander Brevig : Added addEventListener 106 | || | 1.3 2009-05-12 - Alexander Brevig : Added lastUdate, in order to do simple debouncing 107 | || | 1.2 2009-05-09 - Alexander Brevig : Changed getKey() 108 | || | 1.1 2009-04-28 - Alexander Brevig : Modified API, and made variables private 109 | || | 1.0 2007-XX-XX - Mark Stanley : Initial Release 110 | || # 111 | */ 112 | -------------------------------------------------------------------------------- /libraries/Keypad/keywords.txt: -------------------------------------------------------------------------------- 1 | Keypad KEYWORD1 2 | KeypadEvent KEYWORD1 3 | 4 | begin KEYWORD2 5 | getKey KEYWORD2 6 | getState KEYWORD2 7 | setHoldTime KEYWORD2 8 | addEventListener KEYWORD2 9 | 10 | # this is a macro that converts 2d arrays to pointers 11 | makeKeymap KEYWORD2 12 | 13 | # this is a way to standardize the client code, help enhance the use of the name keypadEvent 14 | keypadEvent KEYWORD2 15 | 16 | NO_KEY LITERAL1 17 | KEY_RELEASED LITERAL1 18 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/ShiftRegLCD.cpp: -------------------------------------------------------------------------------- 1 | // ShiftRegLCD - Shiftregister-based LCD library for Arduino 2 | // 3 | // Connects an LCD using 2 or 3 pins from the Arduino, via an 8-bit ShiftRegister (SR from now on). 4 | // 5 | // Acknowledgements: 6 | // 7 | // Based very much on the "official" LiquidCrystal library for the Arduino: 8 | // ttp://arduino.cc/en/Reference/Libraries 9 | // and also the improved version (with examples CustomChar1 and SerialDisplay) from LadyAda: 10 | // http://web.alfredstate.edu/weimandn/arduino/LiquidCrystal_library/LiquidCrystal_index.html 11 | // and also inspired by this schematics from an unknown author (thanks to mircho on the arduino playground forum!): 12 | // http://www.scienceprog.com/interfacing-lcd-to-atmega-using-two-wires/ 13 | // 14 | // Modified to work serially with the shiftOut() function, an 8-bit shiftregister (SR) and an LCD in 4-bit mode. 15 | // 16 | // Shiftregister connection description (NEW as of 2007.07.27) 17 | // 18 | // Bit #0 - N/C - not connected, used to hold a zero 19 | // Bits #1 - N/C 20 | // Bit #2 - connects to RS (Register Select) on the LCD 21 | // Bits #3 - #6 from SR connects to LCD data inputs D4 - D7. 22 | // Bit #7 - is used to enabling the enable-puls (via a diode-resistor AND "gate") 23 | // 24 | // 2 or 3 Pins required from the Arduino for Data, Clock, and Enable (optional). If not using Enable, 25 | // the Data pin is used for the enable signal by defining the same pin for Enable as for Data. 26 | // Data and Clock outputs/pins goes to the shiftregister. 27 | // LCD RW-pin hardwired to LOW (only writing to LCD). Busy Flag (BF, data bit D7) is not read. 28 | // 29 | // Any shift register should do. I used 74LS164, for the reason that's what I had at hand. 30 | // 31 | // Project homepage: http://code.google.com/p/arduinoshiftreglcd/ 32 | // 33 | // History 34 | // 2009.05.23 raron, but; based mostly (as in almost verbatim) on the "official" LiquidCrystal library. 35 | // 2009.07.23 raron (yes exactly 2 months later). Incorporated some proper initialization routines 36 | // inspired (lets say copy-paste-tweaked) from LiquidCrystal library improvements from LadyAda 37 | // Also a little re-read of the datasheet for the HD44780 LCD controller. 38 | // 2009.07.25 raron - Fixed comments. I really messed up the comments before posting this, so I had to fix it. 39 | // Also renamed a function, but no improvements or functional changes. 40 | // 2009.07.27 Thanks to an excellent suggestion from mircho at the Arduiono playgrond forum, 41 | // the number of wires now required is only two! 42 | // 2009.07.28 Mircho / raron - a new modification to the schematics, and a more streamlined interface 43 | // 2009.07.30 raron - minor corrections to the comments. Fixed keyword highlights. Fixed timing to datasheet safe. 44 | 45 | #include "ShiftRegLCD.h" 46 | #include 47 | #include 48 | #include 49 | #if defined(ARDUINO) && (ARDUINO >= 100) 50 | #include "Arduino.h" 51 | #else 52 | #include "WProgram.h" 53 | #endif 54 | 55 | // Assuming 1 line 8 pixel high font 56 | ShiftRegLCD::ShiftRegLCD(uint8_t srdata, uint8_t srclock, uint8_t enable) { 57 | init(srdata, srclock, enable, 1, 0); 58 | } 59 | // Set nr. of lines, assume 8 pixel high font 60 | ShiftRegLCD::ShiftRegLCD(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines) { 61 | init(srdata, srclock, enable, lines, 0); 62 | } 63 | // Set nr. of lines and font 64 | ShiftRegLCD::ShiftRegLCD(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font) { 65 | init(srdata, srclock, enable, lines, font); 66 | } 67 | 68 | 69 | void ShiftRegLCD::init(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font) 70 | { 71 | _two_wire = 0; 72 | _srdata_pin = srdata; _srclock_pin = srclock; _enable_pin = enable; 73 | if (enable == TWO_WIRE) 74 | { 75 | _enable_pin = _srdata_pin; 76 | _two_wire = 1; 77 | } 78 | pinMode(_srclock_pin, OUTPUT); 79 | pinMode(_srdata_pin, OUTPUT); 80 | pinMode(_enable_pin, OUTPUT); 81 | 82 | if (lines>1) 83 | _numlines = LCD_2LINE; 84 | else 85 | _numlines = LCD_1LINE; 86 | 87 | _displayfunction = LCD_4BITMODE | _numlines; 88 | 89 | // For some displays you can select a 10 pixel high font 90 | // (Just in case I removed the neccesity to have 1-line display for this) 91 | if (font != 0) 92 | _displayfunction |= LCD_5x10DOTS; 93 | else 94 | _displayfunction |= LCD_5x8DOTS; 95 | 96 | // At this time this is for 4-bit mode only, as described above. 97 | // Page 47-ish of this (HD44780 LCD) datasheet: 98 | // http://www.datasheetarchive.com/pdf-datasheets/Datasheets-13/DSA-247674.pdf 99 | // According to datasheet, we need at least 40ms after power rises above 2.7V 100 | // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 101 | delayMicroseconds(50000); 102 | init4bits(LCD_FUNCTIONSET | LCD_8BITMODE); 103 | delayMicroseconds(4500); // wait more than 4.1ms 104 | // Second try 105 | init4bits(LCD_FUNCTIONSET | LCD_8BITMODE); 106 | delayMicroseconds(150); 107 | // Third go 108 | init4bits(LCD_FUNCTIONSET | LCD_8BITMODE); 109 | 110 | // And finally, set to 4-bit interface 111 | init4bits(LCD_FUNCTIONSET | LCD_4BITMODE); 112 | 113 | // Set # lines, font size, etc. 114 | command(LCD_FUNCTIONSET | _displayfunction); 115 | // Turn the display on with no cursor or blinking default 116 | _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 117 | display(); 118 | // Clear it off 119 | clear(); 120 | // Initialize to default text direction (for romance languages) 121 | _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 122 | // set the entry mode 123 | command(LCD_ENTRYMODESET | _displaymode); 124 | home(); 125 | } 126 | 127 | 128 | // ********** high level commands, for the user! ********** 129 | void ShiftRegLCD::clear() 130 | { 131 | command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 132 | delayMicroseconds(2000); // this command takes a long time! 133 | } 134 | 135 | void ShiftRegLCD::home() 136 | { 137 | command(LCD_RETURNHOME); // set cursor position to zero 138 | delayMicroseconds(2000); // this command takes a long time! 139 | } 140 | 141 | void ShiftRegLCD::setCursor(uint8_t col, uint8_t row) 142 | { 143 | int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 144 | if ( row > _numlines ) 145 | row = _numlines-1; // we count rows starting w/0 146 | command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 147 | } 148 | 149 | // Turn the display on/off (quickly) 150 | void ShiftRegLCD::noDisplay() { 151 | _displaycontrol &= ~LCD_DISPLAYON; 152 | command(LCD_DISPLAYCONTROL | _displaycontrol); 153 | } 154 | void ShiftRegLCD::display() { 155 | _displaycontrol |= LCD_DISPLAYON; 156 | command(LCD_DISPLAYCONTROL | _displaycontrol); 157 | } 158 | 159 | // Turns the underline cursor on/off 160 | void ShiftRegLCD::noCursor() { 161 | _displaycontrol &= ~LCD_CURSORON; 162 | command(LCD_DISPLAYCONTROL | _displaycontrol); 163 | } 164 | void ShiftRegLCD::cursor() { 165 | _displaycontrol |= LCD_CURSORON; 166 | command(LCD_DISPLAYCONTROL | _displaycontrol); 167 | } 168 | 169 | // Turn on and off the blinking cursor 170 | void ShiftRegLCD::noBlink() { 171 | _displaycontrol &= ~LCD_BLINKON; 172 | command(LCD_DISPLAYCONTROL | _displaycontrol); 173 | } 174 | void ShiftRegLCD::blink() { 175 | _displaycontrol |= LCD_BLINKON; 176 | command(LCD_DISPLAYCONTROL | _displaycontrol); 177 | } 178 | 179 | // These commands scroll the display without changing the RAM 180 | void ShiftRegLCD::scrollDisplayLeft(void) { 181 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 182 | } 183 | void ShiftRegLCD::scrollDisplayRight(void) { 184 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 185 | } 186 | 187 | // This is for text that flows Left to Right 188 | void ShiftRegLCD::shiftLeft(void) { 189 | _displaymode |= LCD_ENTRYLEFT; 190 | command(LCD_ENTRYMODESET | _displaymode); 191 | } 192 | 193 | // This is for text that flows Right to Left 194 | void ShiftRegLCD::shiftRight(void) { 195 | _displaymode &= ~LCD_ENTRYLEFT; 196 | command(LCD_ENTRYMODESET | _displaymode); 197 | } 198 | 199 | // This will 'right justify' text from the cursor 200 | void ShiftRegLCD::shiftIncrement(void) { 201 | _displaymode |= LCD_ENTRYSHIFTINCREMENT; 202 | command(LCD_ENTRYMODESET | _displaymode); 203 | } 204 | 205 | // This will 'left justify' text from the cursor 206 | void ShiftRegLCD::shiftDecrement(void) { 207 | _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 208 | command(LCD_ENTRYMODESET | _displaymode); 209 | } 210 | 211 | // Allows us to fill the first 8 CGRAM locations with custom characters 212 | void ShiftRegLCD::createChar(uint8_t location, const uint8_t charmap[]) { 213 | location &= 0x7; // we only have 8 locations 0-7 214 | command(LCD_SETCGRAMADDR | location << 3); 215 | for (int i=0; i<8; i++) { 216 | write(charmap[i]); 217 | } 218 | command(LCD_SETDDRAMADDR); // Reset display to display text (from pos. 0) 219 | } 220 | 221 | // ******************** 222 | 223 | void ShiftRegLCD::command(uint8_t value) { 224 | send(value, LOW); 225 | } 226 | 227 | #if defined(ARDUINO) && (ARDUINO >= 100) 228 | size_t ShiftRegLCD::write(uint8_t value) { 229 | send(value, HIGH); 230 | return 1; 231 | } 232 | #else 233 | void ShiftRegLCD::write(uint8_t value) { 234 | send(value, HIGH); 235 | } 236 | #endif 237 | 238 | // For sending data via the shiftregister 239 | void ShiftRegLCD::send(uint8_t value, uint8_t mode) { 240 | uint8_t val1, val2; 241 | if ( _two_wire ) shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); // clear shiftregister 242 | digitalWrite( _enable_pin, LOW ); 243 | mode = mode ? SR_RS_BIT : 0; // RS bit; LOW: command. HIGH: character. 244 | val1 = mode | SR_EN_BIT | ((value >> 1) & 0x78); // upper nibble 245 | val2 = mode | SR_EN_BIT | ((value << 3) & 0x78); // lower nibble 246 | shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 ); 247 | digitalWrite( _enable_pin, HIGH ); 248 | delayMicroseconds(1); // enable pulse must be >450ns 249 | digitalWrite( _enable_pin, LOW ); 250 | if ( _two_wire ) shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); // clear shiftregister 251 | shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val2 ); 252 | digitalWrite( _enable_pin, HIGH ); 253 | delayMicroseconds(1); // enable pulse must be >450ns 254 | digitalWrite( _enable_pin, LOW ); 255 | delayMicroseconds(40); // commands need > 37us to settle 256 | } 257 | 258 | // For sending data when initializing the display to 4-bit 259 | void ShiftRegLCD::init4bits(uint8_t value) { 260 | uint8_t val1; 261 | if ( _two_wire ) shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); // clear shiftregister 262 | digitalWrite( _enable_pin, LOW ); 263 | val1 = SR_EN_BIT | ((value >> 1) & 0x78); 264 | shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 ); 265 | digitalWrite( _enable_pin, HIGH ); 266 | delayMicroseconds(1); // enable pulse must be >450ns 267 | digitalWrite( _enable_pin, LOW ); 268 | delayMicroseconds(40); // commands need > 37us to settle 269 | } 270 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/ShiftRegLCD.h: -------------------------------------------------------------------------------- 1 | #ifndef ShiftRegLCD_h 2 | #define ShiftRegLCD_h 3 | 4 | #include 5 | #include "Print.h" 6 | 7 | // commands 8 | #define LCD_CLEARDISPLAY 0x01 9 | #define LCD_RETURNHOME 0x02 10 | #define LCD_ENTRYMODESET 0x04 11 | #define LCD_DISPLAYCONTROL 0x08 12 | #define LCD_CURSORSHIFT 0x10 13 | #define LCD_FUNCTIONSET 0x20 14 | #define LCD_SETCGRAMADDR 0x40 15 | #define LCD_SETDDRAMADDR 0x80 16 | 17 | // flags for display entry mode 18 | #define LCD_ENTRYRIGHT 0x00 19 | #define LCD_ENTRYLEFT 0x02 20 | #define LCD_ENTRYSHIFTINCREMENT 0x01 21 | #define LCD_ENTRYSHIFTDECREMENT 0x00 22 | 23 | // flags for display on/off control 24 | #define LCD_DISPLAYON 0x04 25 | #define LCD_DISPLAYOFF 0x00 26 | #define LCD_CURSORON 0x02 27 | #define LCD_CURSOROFF 0x00 28 | #define LCD_BLINKON 0x01 29 | #define LCD_BLINKOFF 0x00 30 | 31 | // flags for display/cursor shift 32 | #define LCD_DISPLAYMOVE 0x08 33 | #define LCD_CURSORMOVE 0x00 34 | #define LCD_MOVERIGHT 0x04 35 | #define LCD_MOVELEFT 0x00 36 | 37 | // flags for function set 38 | #define LCD_8BITMODE 0x10 39 | #define LCD_4BITMODE 0x00 40 | #define LCD_2LINE 0x08 41 | #define LCD_1LINE 0x00 42 | #define LCD_5x10DOTS 0x04 43 | #define LCD_5x8DOTS 0x00 44 | 45 | // two-wire indicator constant 46 | #define TWO_WIRE 204 47 | #define SR_RS_BIT 0x04 48 | #define SR_EN_BIT 0x80 49 | 50 | 51 | class ShiftRegLCD : public Print { 52 | public: 53 | ShiftRegLCD(uint8_t srdata, uint8_t srclockd, uint8_t enable); 54 | ShiftRegLCD(uint8_t srdata, uint8_t srclockd, uint8_t enable, uint8_t lines); 55 | ShiftRegLCD(uint8_t srdata, uint8_t srclockd, uint8_t enable, uint8_t lines, uint8_t font); 56 | void clear(); 57 | void home(); 58 | 59 | void noDisplay(); 60 | void display(); 61 | void noBlink(); 62 | void blink(); 63 | void noCursor(); 64 | void cursor(); 65 | void scrollDisplayLeft(); 66 | void scrollDisplayRight(); 67 | void printLeft(); 68 | void printRight(); 69 | void shiftLeft(); 70 | void shiftRight(); 71 | void shiftIncrement(); 72 | void shiftDecrement(); 73 | 74 | void createChar(uint8_t, const uint8_t[]); 75 | void setCursor(uint8_t, uint8_t); 76 | #if defined(ARDUINO) && (ARDUINO >= 100) 77 | virtual size_t write(uint8_t); 78 | #else 79 | virtual void write(uint8_t); 80 | #endif 81 | void command(uint8_t); 82 | private: 83 | void init(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font); 84 | void send(uint8_t, uint8_t); 85 | void init4bits(uint8_t); 86 | uint8_t _srdata_pin; 87 | uint8_t _srclock_pin; 88 | uint8_t _enable_pin; 89 | uint8_t _two_wire; 90 | 91 | uint8_t _displayfunction; 92 | uint8_t _displaycontrol; 93 | uint8_t _displaymode; 94 | uint8_t _numlines; 95 | 96 | }; 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/examples/CustomChar/CustomChar.pde: -------------------------------------------------------------------------------- 1 | // Example creating custom characters 0-7 on a HD44700 compatible LCD 2 | // using 2-wire connection to LCD 3 | 4 | #include 5 | 6 | ShiftRegLCD srlcd(12, 13, TWO_WIRE); 7 | 8 | void setup() 9 | { 10 | uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4}; 11 | uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0}; 12 | uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0}; 13 | uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0}; 14 | uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0}; 15 | uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0}; 16 | uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0}; 17 | uint8_t retarrow[8] = {0x1,0x1,0x5,0x9,0x1f,0x8,0x4}; 18 | 19 | srlcd.createChar(0, bell); 20 | srlcd.createChar(1, note); 21 | srlcd.createChar(2, clock); 22 | srlcd.createChar(3, heart); 23 | srlcd.createChar(4, duck); 24 | srlcd.createChar(5, check); 25 | srlcd.createChar(6, cross); 26 | srlcd.createChar(7, retarrow); 27 | 28 | for (uint8_t i=8;i>0;i--) srlcd.write(i); 29 | 30 | srlcd.print(" CUSTOM CHARACTERS"); 31 | } 32 | 33 | void loop() 34 | { 35 | } 36 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/examples/CustomChar2/CustomChar2.pde: -------------------------------------------------------------------------------- 1 | // Example creating custom characters 0-7 on a HD44700 compatible LCD 2 | // using 2-wire connection to LCD 3 | 4 | #include 5 | 6 | ShiftRegLCD srlcd(12, 13, TWO_WIRE); 7 | 8 | void setup() 9 | { 10 | // very simple characters, could be used for a bar-graph 11 | uint8_t customchar[][8] ={ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F }, 12 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F }, 13 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, 14 | { 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F }, 15 | { 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, 16 | { 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, 17 | { 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, 18 | { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F } }; 19 | 20 | 21 | // Program the characters into the LCD 22 | 23 | for (uint8_t c = 0;c<8;c++) { 24 | srlcd.createChar(c, customchar[c]); 25 | } 26 | 27 | for (uint8_t i=0;i<8;i++) srlcd.write(i); 28 | srlcd.print("CUSTOM CHARS"); 29 | for (uint8_t i=8;i>0;i--) srlcd.write(i-1); 30 | } 31 | 32 | void loop() 33 | { 34 | } 35 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/examples/HelloWorld/HelloWorld.pde: -------------------------------------------------------------------------------- 1 | // 2-wire connection to a HD44780-compatible LCD via shiftregister with: 2 | // Data (and Enable) on Arduino pin 12 3 | // Clock on Arduino pin 13 4 | // 5 | // Shiftregister bits #0 - #1 - not used (bit #0 must be set to zero) 6 | // Shiftregister bit #2 - connects to LCD RS (Register Select) 7 | // Shiftregister bits #3 - #6 on LCD data inputs D4-D7. 8 | // Shiftregister bit #7 - used for enabling the Enable puls. 9 | // LCD R/!W (or rw) hardwired to GND (write to LCD only, no reading from) 10 | // 11 | // USAGE: ShiftRegLCD LCDobjectvariablename(Datapin, Clockpin, Enablepin or TWO_WIRE [, Lines [, Font]]]) 12 | // where Lines and Font are optional. 13 | // Enablepin: can be replaced by constant TWO_WIRE, if using only 2 wires. 14 | // Lines: 1 or 2 lines (or more if possible) 15 | // Font : 0 or 1, small or big font (8 or 10 pixel tall font, if available). 16 | 17 | #include 18 | 19 | ShiftRegLCD srlcd(12, 13, TWO_WIRE); 20 | 21 | void setup() 22 | { 23 | // Print a message to the LCD. 24 | srlcd.print("HELLO, WORLD!"); 25 | } 26 | 27 | void loop() 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/examples/HelloWorld2/HelloWorld2.pde: -------------------------------------------------------------------------------- 1 | // 3-wire connection to a HD44780-compatible LCD via shiftregister with: 2 | // Data on pin 12 3 | // Clock on pin 13 4 | // Enable on pin 8 5 | // 6 | // Shiftregister bits #0 - #1 - not used (bit #0 must be set to zero) 7 | // Shiftregister bit #2 - connects to LCD RS (Register Select) 8 | // Shiftregister bits #3 - #6 on LCD data inputs D4-D7. 9 | // Shiftregister bit #7 - used for enabling the Enable puls. 10 | // LCD R/!W (or rw) hardwired to GND (write to LCD only, no reading from) 11 | // 12 | // USAGE: ShiftRegLCD LCDobjectvariablename(Datapin, Clockpin, Enablepin or TWO_WIRE [, Lines [, Font]]]) 13 | // where Lines and Font are optional. 14 | // Enablepin: can be replaced by constant TWO_WIRE, if using only 2 wires. 15 | // Lines: 1 or 2 lines (or more if possible) 16 | // Font : 0 or 1, small or big font (8 or 10 pixel tall font, if available). 17 | 18 | #include 19 | 20 | ShiftRegLCD srlcd(12, 13, 8); 21 | 22 | void setup() 23 | { 24 | // Print a message to the LCD. 25 | srlcd.print("HELLO, WORLD!"); 26 | } 27 | 28 | void loop() 29 | { 30 | } 31 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/examples/SerialDisplay/SerialDisplay.pde: -------------------------------------------------------------------------------- 1 | // Displays text sent over the serial port (e.g. from the Serial Monitor) on 2 | // an attached LCD, using 2-wire connection to the LCD. 3 | 4 | #include 5 | 6 | ShiftRegLCD srlcd(12, 13, TWO_WIRE); 7 | 8 | void setup() 9 | { 10 | Serial.begin(9600); 11 | } 12 | 13 | void loop() 14 | { 15 | // when characters arrive over the serial port... 16 | if (Serial.available()) { 17 | // wait a bit for the entire message to arrive 18 | delay(100); 19 | // clear the screen 20 | srlcd.clear(); 21 | // read all the available characters 22 | while (Serial.available() > 0) { 23 | // display each character to the LCD 24 | srlcd.write(Serial.read()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libraries/ShiftRegLCD/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For ShiftRegLCD 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ShiftRegLCD KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | clear KEYWORD2 16 | home KEYWORD2 17 | print KEYWORD2 18 | noDisplay KEYWORD2 19 | display KEYWORD2 20 | noBlink KEYWORD2 21 | blink KEYWORD2 22 | noCursor KEYWORD2 23 | cursor KEYWORD2 24 | scrollDisplayLeft KEYWORD2 25 | scrollDisplayRight KEYWORD2 26 | printLeft KEYWORD2 27 | printRight KEYWORD2 28 | shiftLeft KEYWORD2 29 | shiftRight KEYWORD2 30 | shiftIncrement KEYWORD2 31 | shiftDecrement KEYWORD2 32 | createChar KEYWORD2 33 | setCursor KEYWORD2 34 | 35 | ####################################### 36 | # Constants (LITERAL1) 37 | ####################################### 38 | -------------------------------------------------------------------------------- /schematic/4x4-Matrix-Keypad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykh/Burglar-and-Fire-Alarm-System-Arduino/d52fde9da445c21b4bccd23cab87b4a2e31f6893/schematic/4x4-Matrix-Keypad.png -------------------------------------------------------------------------------- /schematic/LCD_2-wire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykh/Burglar-and-Fire-Alarm-System-Arduino/d52fde9da445c21b4bccd23cab87b4a2e31f6893/schematic/LCD_2-wire.png -------------------------------------------------------------------------------- /schematic/Relay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykh/Burglar-and-Fire-Alarm-System-Arduino/d52fde9da445c21b4bccd23cab87b4a2e31f6893/schematic/Relay.png --------------------------------------------------------------------------------