Navigation

    • Register
    • Login
    • Search
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. Rod MacPherson
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Rod MacPherson

    @Rod MacPherson

    1
    Reputation
    6
    Posts
    650
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online

    Rod MacPherson Follow

    Best posts made by Rod MacPherson

    • RE: RFID Garage door opener

      Nice work. I have yet to pick up an RFID reader to give that part of it a try, but I've modified it a little to have reed sensors for the 2 doors so that I can easily see if the door is open on my phone, and get notifications when the door opens at an unexpected time, like when the controller is set to vacation mode, or at times of night when we would not normally be coming and going.
      I'll be watching for someone to post up a signing version.

      Here's my 2 relay, 2 door sensor version.

      /*
       RFID Garagedoor opener by Bart Eversdijk
       Modified to add door sensors by Rod MacPherson
       
       This sketch is to open a Garage door with an mifare RIFD-tag 
        
        For an Arduino Nano v3
        Connection wiring :
          - nrf24l01+ as descibed on the MySensors website
          - MFRC522 reader/writer MOSI, MISO, SCK, 3.3V and GND as they are on the nrf24101+, but connect RST to pin D7 and connect SDA(SS) to pin D8 
          - LED with 470ohm resistor between GND and pin A3 
          - push button between GND and pin D5
          - 5v relays coil between GND and  pin D4 -> switch pins of the relays should be connected in parallel with your garage door push button. 
          - second relay for second door on pin D3
          
        Features:
        This project can record up to 18 RFID-"tags"
        These card IDs are stored in to EEPROM by keeping them next to the RFID reader when the system in program mode. (Slow blinking LED) When a card is accepted as new card the LED will blink fast for a short time.
        To keep the master-tags (choose your own) next to the RFID reader when pressing the push button. To clear all cards (except the master card) press the push button in program mode for 6 seconds. The LED will now fast blink for a couple of seconds.
        
        Your garage your can be opened by keep a registered RFID tag next to the reader or by clicking the open icon on lock node presented by this plugin.
        By by-passing the alarm node presented by this plug in the RFID will be temporarily disabled.
        When an incorrect (not registered) RFID tag is scanned the alarm is triggered to detect illegal scan attempts   
      
      */
      
      #include <SPI.h>
      #include <MFRC522.h>
      #include <MySensor.h> 
      #include <Bounce2.h>
      
      #define RF_INIT_DELAY   125
      #define ONE_SEC         1000
      #define MAX_CARDS       18
      #define PROG_WAIT       10
      #define HEARTBEAT       10
      #define BAUD            115200
      
      /*Pin definitions*/
      #define LED_PIN         A3
      #define SECONDRELAY     3
      #define GARAGEPIN       4
      #define SWITCH_PIN      5
      #define RST_PIN         7       //  MFRC 
      #define SS_PIN          8       //  MFRC 
      #define DOOR_PIN_L  A0  // Arduino Digital I/O pin for button/reed switch
      #define DOOR_PIN_R  A1  // Arduino Digital I/O pin for button/reed switch
      
      
      MFRC522      mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
      MFRC522::Uid olduid;
      MFRC522::Uid masterkey = { 10, {0,0,0,0, 0,0,0,0, 0,0 },  0 };
      
      byte       countValidCards  = 0;
      MFRC522::Uid validCards[MAX_CARDS];
      
      void       ShowCardData(MFRC522::Uid* uid);
      bool       sameUid(MFRC522::Uid* old, MFRC522::Uid* check);
      void       copyUid(MFRC522::Uid* src, MFRC522::Uid* dest);
      bool       isValidCard(MFRC522::Uid* uid);
      int        releasecnt = 0;
      
      #define    CHILD_ID_ALARM    1
      #define    CHILD_ID_LOCK     2
      #define    CHILD_ID_LOCK2    3
      #define    CHILD_ID_DOOR_L    4
      #define    CHILD_ID_DOOR_R    5
      
      MySensor   gw;
      Bounce     debouncer = Bounce();
      Bounce     debouncerDoorR = Bounce();
      Bounce     debouncerDoorL = Bounce();
      int oldValueR=-1;
      int oldValueL=-1;
      
      int        oldSwitchValue=-1;
      int        switchValue = 0;
      long       timer = -1;
      bool       programmode = false;
      bool       ledon;
      int        programTimer = 0;
      bool       armed = true;
      unsigned long lastTime = 0;
      
      MyMessage  lockMsg(CHILD_ID_LOCK,          V_LOCK_STATUS);
      MyMessage  lock2Msg(CHILD_ID_LOCK2,          V_LOCK_STATUS);
      MyMessage  lockArmMsg(CHILD_ID_ALARM,      V_ARMED);
      MyMessage  wrongMsg(CHILD_ID_ALARM,        V_TRIPPED);
      MyMessage  doorRmsg(CHILD_ID_DOOR_R, V_TRIPPED);
      MyMessage  doorLmsg(CHILD_ID_DOOR_L, V_TRIPPED);
      
      void setup() {
              Serial.begin(BAUD);     // Initialize serial communications with the PC
              pinMode(GARAGEPIN, OUTPUT);     // Initialise in/output ports
              pinMode(SECONDRELAY, OUTPUT);     // Initialise in/output ports
              
              // Make sure MFRC will be disabled on the SPI bus
              pinMode(RST_PIN, OUTPUT);     
              digitalWrite(RST_PIN, LOW);
              pinMode(SS_PIN, OUTPUT);     
              digitalWrite(SS_PIN, LOW);
      
              pinMode(LED_PIN, OUTPUT);
              digitalWrite(LED_PIN, LOW);
              // Setup the button
              pinMode(SWITCH_PIN, INPUT_PULLUP);
      
              // After setting up the button, setup debouncer
              debouncer.attach(SWITCH_PIN);
              debouncer.interval(5);
      
              // Setup the right door sensor
              pinMode(DOOR_PIN_R,INPUT);
              // Activate internal pull-up
              digitalWrite(DOOR_PIN_R,HIGH);
        
              // After setting up the button, setup debouncer
              debouncerDoorR.attach(DOOR_PIN_R);
              debouncerDoorR.interval(5);
              
              // Setup the left door sensor
              pinMode(DOOR_PIN_L,INPUT);
              // Activate internal pull-up
              digitalWrite(DOOR_PIN_L,HIGH);
        
              // After setting up the button, setup debouncer
              debouncerDoorL.attach(DOOR_PIN_L);
              debouncerDoorL.interval(5);
        
      
              // Init mysensors library
              gw.begin(incomingMessage, 5);
              gw.sendSketchInfo("RFID Garage", "1.2"); delay(RF_INIT_DELAY);
              
              // Register all sensors to gw (they will be created as child devices)
              gw.present(CHILD_ID_LOCK, S_LOCK);      delay(RF_INIT_DELAY);
              gw.present(CHILD_ID_LOCK2, S_LOCK);      delay(RF_INIT_DELAY);
              gw.present(CHILD_ID_ALARM, S_MOTION);   delay(RF_INIT_DELAY);
              gw.present(CHILD_ID_DOOR_R, S_DOOR); 
              gw.present(CHILD_ID_DOOR_L, S_DOOR); 
              
              recallEeprom();
              
              // Init MFRC RFID sensor
              SPI.begin();            // Init SPI bus
              mfrc522.PCD_Init();     // Init MFRC522
              ShowReaderDetails();            // Show details of PCD - MFRC522 Card Reader details
      
              gw.send(lockArmMsg.set(armed));
              Serial.println(F("Init done..."));
      }
      
      void loop() {
              timer++;
              delay(HEARTBEAT);
              gw.process();
              debouncer.update();
              debouncerDoorL.update();
              // Get the update value for Left
              int valueL = debouncerDoorL.read(); 
              if (valueL != oldValueL) {
                 // Send in the new value for Left
                 gw.send(doorLmsg.set(valueL==HIGH ? 1 : 0));
                 oldValueL = valueL;
              }
              debouncerDoorR.update();
              // Get the update value for Right
              int valueR = debouncerDoorR.read();
              if (valueR != oldValueR) {
                 // Send in the new value for Right
                 gw.send(doorRmsg.set(valueR==HIGH ? 1 : 0));
                 oldValueR = valueR;
              }
      
              // Get the update value
              int switchValue = debouncer.read();
              if (switchValue != oldSwitchValue) {
                // Send in the new value
                Serial.print (F("Switch "));
                Serial.println (switchValue);
                
                if (switchValue && programmode) {
                     lastTime     = millis() / 1000;
                }
                
                if (!switchValue && programmode && lastTime > 0) {
                     if ( (millis() / 1000) - lastTime > 3) {
                          Serial.println(F("Reset all cards"));  
                          countValidCards  = 0;
                          blinkFast(50);
                     } else {
                        Serial.println(F("Program off"));  
                        digitalWrite(LED_PIN, LOW);
                        programmode = false;
                        
                        storeEeprom();
                     }
                }
                
                if (!switchValue)   {
                    programTimer = 0;
                }
                oldSwitchValue = switchValue;
              }
              
              if (programmode && ((timer % (ONE_SEC / HEARTBEAT)) == 0 ))  {
                  ledon = !ledon;
                  digitalWrite(LED_PIN, ledon);
                  programTimer++;
      
                  // Stop program mode after 20 sec inactivity
                  if (programTimer > PROG_WAIT)  {
                     programmode = false;
                     digitalWrite(LED_PIN, false);
                     Serial.println(F("Program expired"));  
                  }
              }
              
              if ((timer % (200 / HEARTBEAT)) == 0 )   {
                   // Look for new cards
                   if ( ! mfrc522.PICC_IsNewCardPresent()) {
                        if (releasecnt > 0)   {
                            releasecnt--;
                            if (!releasecnt)  {
                                olduid.size = 0;
                                Serial.println(F("release"));
                            }
                          }
                  return;
                  }
                  releasecnt = 5;
          
                 // Select one of the cards
                 if ( ! mfrc522.PICC_ReadCardSerial()) {
                    return;
                 }
          
                 // Dump debug info about the card; PICC_HaltA() is automatically called
                 //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
                 if (!olduid.size || !sameUid(&(mfrc522.uid), &olduid))  {
                      ShowCardData(&(mfrc522.uid));
                      copyUid(&(mfrc522.uid), &olduid);
                      if ( isValidCard(&olduid) )   {
                           OpenDoor(programmode);
                      } else  {
                         if (sameUid(&(mfrc522.uid), &masterkey)) {
                             // Only switch in program mode when mastercard is found AND the program button is pressed
                             if (switchValue)  {
                               Serial.println(F("Program mode"));
                               programmode = true;
                               programTimer = 0;
                               lastTime     = 0;
                             } else {
                               OpenDoor2(programmode);
                             }
                         } else {
                             if (programmode) {
                               Serial.println(F("new card"));
                               programTimer = 0;
                               
                               if (countValidCards < MAX_CARDS)
                               {
                                  // Add card to list...
                                  copyUid(&(mfrc522.uid), &validCards[countValidCards]);
                                  countValidCards++;
                                  blinkFast(15);
                               }
                             } else {
                               Serial.println(F("Invalid card"));
                               if (armed) {
                                  gw.send(wrongMsg.set(1));
                                  delay(2000);
                                  gw.send(wrongMsg.set(0));
                               }
                             }
                         }
                      }
                 }
              }
      }
      
      void ShowCardData(MFRC522::Uid* uid) 
      {
          Serial.print(F("Card UID:"));
          for (byte i = 0; i < uid->size; i++) {
              if(uid->uidByte[i] < 0x10) {
                  Serial.print(F(" 0"));
              } else {
                  Serial.print(F(" "));
                      }
              Serial.print(uid->uidByte[i], HEX);
          } 
          Serial.println();
      }
      
      void copyUid(MFRC522::Uid* src, MFRC522::Uid* dest)
      {
          dest->size = src->size;
          dest->sak  = src->sak;
          
          for (byte i = 0; i < src->size; i++) {
          dest->uidByte[i] = src->uidByte[i];
          }
      }
      
      bool sameUid(MFRC522::Uid* old, MFRC522::Uid* check)
      {
          if (old->size != check->size) {
             return false;
          }
          for (byte i = 0; i < old->size; i++) {
              if (old->uidByte[i] != check->uidByte[i]) {
                  return false;
              }
          }
          return true;
      }
      
      bool isValidCard(MFRC522::Uid* uid)
      {
            for (byte i = 0; i < countValidCards; i++)  {
                if (validCards[i].size != uid->size)  {
                    break;
                }
                for (int j = 0; j < uid->size; j++) {
                    if (validCards[i].uidByte[j] != uid->uidByte[j])  {
                        break;
                    }
                    if (j == (uid->size - 1)) {  
                        return true;
                    }
                }
            }
            return false;
      }
      
      
      void storeEeprom()
      {
          byte address = 0;
          gw.saveState(address++, countValidCards);
          
          for (byte i = 0; i < countValidCards; i++) {
             gw.saveState(address++, validCards[i].size);
             for (byte j = 0; j < 10; j++) {
                gw.saveState(address++, validCards[i].uidByte[j]);
             } 
          }
      }
      
      void recallEeprom()
      {
          byte address = 0;
          
          countValidCards = gw.loadState(address++);
          if (countValidCards > MAX_CARDS) {
             Serial.println(F("Not a valid EEPROM reading set to default"));
             countValidCards = 0;
             storeEeprom();
             return;
          }
          
          for (byte i = 0; i < countValidCards; i++)  {
             validCards[i].size = gw.loadState(address++);
             for (byte j = 0; j < 10; j++)  {
                validCards[i].uidByte[j] = gw.loadState(address++);
             } 
          }
        
      }
      
      void blinkFast(int times)
      {
          for (int i = 0; i < times; i++) { 
             ledon = !ledon;
             digitalWrite(LED_PIN, ledon);
             delay(100);
          }
      }
      
      void OpenDoor(bool fakeOpen)
      {
          Serial.println(F("Open door!"));
          gw.send(lockMsg.set(false));
          
          if (!fakeOpen) { 
            digitalWrite(LED_PIN, HIGH);
            digitalWrite(GARAGEPIN, HIGH); 
          }
          delay(1000);
          
          if (!fakeOpen) { 
            digitalWrite(GARAGEPIN, LOW); 
            digitalWrite(LED_PIN, LOW);
          }
          
          gw.send(lockMsg.set(true));
      }
      
      void OpenDoor2(bool fakeOpen)
      {
          Serial.println(F("Open door 2!"));
          gw.send(lock2Msg.set(false));
          
          if (!fakeOpen) { 
            digitalWrite(LED_PIN, HIGH);
            digitalWrite(SECONDRELAY, HIGH); 
          }
          delay(1000);
          
          if (!fakeOpen) { 
            digitalWrite(SECONDRELAY, LOW); 
            digitalWrite(LED_PIN, LOW);
          }
          
          gw.send(lock2Msg.set(true));
      }
      
      void ShowReaderDetails() {
          // Get the MFRC522 software version
          byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
          Serial.print(F("MFRC522 Software Version: 0x"));
          Serial.print(v, HEX);
          if (v == 0x91) {
              Serial.print(F(" = v1.0"));
              } else if (v == 0x92) {
              Serial.print(F(" = v2.0"));
              } else {
              Serial.print(F(" (unknown)"));
              }
          Serial.println("");
          
              // When 0x00 or 0xFF is returned, communication probably failed
          if ((v == 0x00) || (v == 0xFF)) {
              Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
          }
      }
      
      
      void incomingMessage(const MyMessage &message) 
      {
         if (message.type == V_LOCK_STATUS) {
           // Change relay state
           if (!message.getBool())  {
              switch (message.sensor)
              {
                 case CHILD_ID_LOCK:
                    OpenDoor(false);
                    break;
                 case CHILD_ID_LOCK2:
                    OpenDoor2(false);
                    break;
              }
           }
        
           // Write some debug info
           Serial.print(F("Lock:  "));
           Serial.print(message.sensor);
           Serial.print(F(" status: "));
           Serial.println(message.getBool());
         }
         else 
         {
           if (message.type == V_ARMED)  {
             // Change relay state
             armed = message.getBool();
        
             // Write some debug info
             Serial.print(F("Arm status: "));
             Serial.println(message.getBool());
           }
           else
           {
             // Write some debug info
             Serial.print(F("Incoming msg type: "));
             Serial.print(message.type);
             Serial.print(F(" id: "));
             Serial.print(message.sensor);
             Serial.print(F(" content: "));
             Serial.println(message.getInt());
           }
         }
      }
      
      posted in My Project
      Rod MacPherson
      Rod MacPherson

    Latest posts made by Rod MacPherson

    • RE: RFID Garage door opener

      @Mercury69
      It was written prior to the MySensors 2.0 update.

      You can convert pre- 2.0 sketches by following the instructions on https://forum.mysensors.org/topic/4276/converting-a-sketch-from-1-5-x-to-2-0-x

      If you need a hand just post here with your question, I'll try to help, but it's really not too bad once you get started. I'm in the process of converting all of my code to 2.0 as well.

      posted in My Project
      Rod MacPherson
      Rod MacPherson
    • RE: Glass break sensor?

      Yes, regardless of the source, always check the spec sheet and even take some measurements your self when you get it to be sure.
      You can use resistors as voltage dividers, or use optocouplers/relays, or even burn it off with a step down voltage regulator like an LM7805. You will need to supply ~12V to the sensor too, as that is what it is designed for in a burglar alarm system, so take that into account. This one says it will operate off 9V, but don't count on powering it long off a 9V square battery. 🙂

      posted in Hardware
      Rod MacPherson
      Rod MacPherson
    • RE: Glass break sensor?

      @chaeron They are all over ebay.

      The way they work with a wired alarm system (like almost all wired alarm sensors) is there is a normally closed circuit, and if the sensor detects something it opens the circuit. (this is so that cutting the wire to the sensor also trips the alarm)
      This is dead simple to interface with, just hook it up between VCC a 12V battery and any digital pin (via some method of stepping down the voltage) that is pulled low. If the pin goes low the alarm is triggered.

      [Edits in Bold: slight correction, guess I was more tired than I wanted to admit last night]
      http://www.ebay.com/itm/Generic-Glass-Break-Detector-for-Wired-Wireless-Burglar-Alarm-PA-456-/222030136167?hash=item33b2070367:g:AJgAAOSwyQtVjBN8

      posted in Hardware
      Rod MacPherson
      Rod MacPherson
    • RE: RFID Garage door opener

      Nice work. I have yet to pick up an RFID reader to give that part of it a try, but I've modified it a little to have reed sensors for the 2 doors so that I can easily see if the door is open on my phone, and get notifications when the door opens at an unexpected time, like when the controller is set to vacation mode, or at times of night when we would not normally be coming and going.
      I'll be watching for someone to post up a signing version.

      Here's my 2 relay, 2 door sensor version.

      /*
       RFID Garagedoor opener by Bart Eversdijk
       Modified to add door sensors by Rod MacPherson
       
       This sketch is to open a Garage door with an mifare RIFD-tag 
        
        For an Arduino Nano v3
        Connection wiring :
          - nrf24l01+ as descibed on the MySensors website
          - MFRC522 reader/writer MOSI, MISO, SCK, 3.3V and GND as they are on the nrf24101+, but connect RST to pin D7 and connect SDA(SS) to pin D8 
          - LED with 470ohm resistor between GND and pin A3 
          - push button between GND and pin D5
          - 5v relays coil between GND and  pin D4 -> switch pins of the relays should be connected in parallel with your garage door push button. 
          - second relay for second door on pin D3
          
        Features:
        This project can record up to 18 RFID-"tags"
        These card IDs are stored in to EEPROM by keeping them next to the RFID reader when the system in program mode. (Slow blinking LED) When a card is accepted as new card the LED will blink fast for a short time.
        To keep the master-tags (choose your own) next to the RFID reader when pressing the push button. To clear all cards (except the master card) press the push button in program mode for 6 seconds. The LED will now fast blink for a couple of seconds.
        
        Your garage your can be opened by keep a registered RFID tag next to the reader or by clicking the open icon on lock node presented by this plugin.
        By by-passing the alarm node presented by this plug in the RFID will be temporarily disabled.
        When an incorrect (not registered) RFID tag is scanned the alarm is triggered to detect illegal scan attempts   
      
      */
      
      #include <SPI.h>
      #include <MFRC522.h>
      #include <MySensor.h> 
      #include <Bounce2.h>
      
      #define RF_INIT_DELAY   125
      #define ONE_SEC         1000
      #define MAX_CARDS       18
      #define PROG_WAIT       10
      #define HEARTBEAT       10
      #define BAUD            115200
      
      /*Pin definitions*/
      #define LED_PIN         A3
      #define SECONDRELAY     3
      #define GARAGEPIN       4
      #define SWITCH_PIN      5
      #define RST_PIN         7       //  MFRC 
      #define SS_PIN          8       //  MFRC 
      #define DOOR_PIN_L  A0  // Arduino Digital I/O pin for button/reed switch
      #define DOOR_PIN_R  A1  // Arduino Digital I/O pin for button/reed switch
      
      
      MFRC522      mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
      MFRC522::Uid olduid;
      MFRC522::Uid masterkey = { 10, {0,0,0,0, 0,0,0,0, 0,0 },  0 };
      
      byte       countValidCards  = 0;
      MFRC522::Uid validCards[MAX_CARDS];
      
      void       ShowCardData(MFRC522::Uid* uid);
      bool       sameUid(MFRC522::Uid* old, MFRC522::Uid* check);
      void       copyUid(MFRC522::Uid* src, MFRC522::Uid* dest);
      bool       isValidCard(MFRC522::Uid* uid);
      int        releasecnt = 0;
      
      #define    CHILD_ID_ALARM    1
      #define    CHILD_ID_LOCK     2
      #define    CHILD_ID_LOCK2    3
      #define    CHILD_ID_DOOR_L    4
      #define    CHILD_ID_DOOR_R    5
      
      MySensor   gw;
      Bounce     debouncer = Bounce();
      Bounce     debouncerDoorR = Bounce();
      Bounce     debouncerDoorL = Bounce();
      int oldValueR=-1;
      int oldValueL=-1;
      
      int        oldSwitchValue=-1;
      int        switchValue = 0;
      long       timer = -1;
      bool       programmode = false;
      bool       ledon;
      int        programTimer = 0;
      bool       armed = true;
      unsigned long lastTime = 0;
      
      MyMessage  lockMsg(CHILD_ID_LOCK,          V_LOCK_STATUS);
      MyMessage  lock2Msg(CHILD_ID_LOCK2,          V_LOCK_STATUS);
      MyMessage  lockArmMsg(CHILD_ID_ALARM,      V_ARMED);
      MyMessage  wrongMsg(CHILD_ID_ALARM,        V_TRIPPED);
      MyMessage  doorRmsg(CHILD_ID_DOOR_R, V_TRIPPED);
      MyMessage  doorLmsg(CHILD_ID_DOOR_L, V_TRIPPED);
      
      void setup() {
              Serial.begin(BAUD);     // Initialize serial communications with the PC
              pinMode(GARAGEPIN, OUTPUT);     // Initialise in/output ports
              pinMode(SECONDRELAY, OUTPUT);     // Initialise in/output ports
              
              // Make sure MFRC will be disabled on the SPI bus
              pinMode(RST_PIN, OUTPUT);     
              digitalWrite(RST_PIN, LOW);
              pinMode(SS_PIN, OUTPUT);     
              digitalWrite(SS_PIN, LOW);
      
              pinMode(LED_PIN, OUTPUT);
              digitalWrite(LED_PIN, LOW);
              // Setup the button
              pinMode(SWITCH_PIN, INPUT_PULLUP);
      
              // After setting up the button, setup debouncer
              debouncer.attach(SWITCH_PIN);
              debouncer.interval(5);
      
              // Setup the right door sensor
              pinMode(DOOR_PIN_R,INPUT);
              // Activate internal pull-up
              digitalWrite(DOOR_PIN_R,HIGH);
        
              // After setting up the button, setup debouncer
              debouncerDoorR.attach(DOOR_PIN_R);
              debouncerDoorR.interval(5);
              
              // Setup the left door sensor
              pinMode(DOOR_PIN_L,INPUT);
              // Activate internal pull-up
              digitalWrite(DOOR_PIN_L,HIGH);
        
              // After setting up the button, setup debouncer
              debouncerDoorL.attach(DOOR_PIN_L);
              debouncerDoorL.interval(5);
        
      
              // Init mysensors library
              gw.begin(incomingMessage, 5);
              gw.sendSketchInfo("RFID Garage", "1.2"); delay(RF_INIT_DELAY);
              
              // Register all sensors to gw (they will be created as child devices)
              gw.present(CHILD_ID_LOCK, S_LOCK);      delay(RF_INIT_DELAY);
              gw.present(CHILD_ID_LOCK2, S_LOCK);      delay(RF_INIT_DELAY);
              gw.present(CHILD_ID_ALARM, S_MOTION);   delay(RF_INIT_DELAY);
              gw.present(CHILD_ID_DOOR_R, S_DOOR); 
              gw.present(CHILD_ID_DOOR_L, S_DOOR); 
              
              recallEeprom();
              
              // Init MFRC RFID sensor
              SPI.begin();            // Init SPI bus
              mfrc522.PCD_Init();     // Init MFRC522
              ShowReaderDetails();            // Show details of PCD - MFRC522 Card Reader details
      
              gw.send(lockArmMsg.set(armed));
              Serial.println(F("Init done..."));
      }
      
      void loop() {
              timer++;
              delay(HEARTBEAT);
              gw.process();
              debouncer.update();
              debouncerDoorL.update();
              // Get the update value for Left
              int valueL = debouncerDoorL.read(); 
              if (valueL != oldValueL) {
                 // Send in the new value for Left
                 gw.send(doorLmsg.set(valueL==HIGH ? 1 : 0));
                 oldValueL = valueL;
              }
              debouncerDoorR.update();
              // Get the update value for Right
              int valueR = debouncerDoorR.read();
              if (valueR != oldValueR) {
                 // Send in the new value for Right
                 gw.send(doorRmsg.set(valueR==HIGH ? 1 : 0));
                 oldValueR = valueR;
              }
      
              // Get the update value
              int switchValue = debouncer.read();
              if (switchValue != oldSwitchValue) {
                // Send in the new value
                Serial.print (F("Switch "));
                Serial.println (switchValue);
                
                if (switchValue && programmode) {
                     lastTime     = millis() / 1000;
                }
                
                if (!switchValue && programmode && lastTime > 0) {
                     if ( (millis() / 1000) - lastTime > 3) {
                          Serial.println(F("Reset all cards"));  
                          countValidCards  = 0;
                          blinkFast(50);
                     } else {
                        Serial.println(F("Program off"));  
                        digitalWrite(LED_PIN, LOW);
                        programmode = false;
                        
                        storeEeprom();
                     }
                }
                
                if (!switchValue)   {
                    programTimer = 0;
                }
                oldSwitchValue = switchValue;
              }
              
              if (programmode && ((timer % (ONE_SEC / HEARTBEAT)) == 0 ))  {
                  ledon = !ledon;
                  digitalWrite(LED_PIN, ledon);
                  programTimer++;
      
                  // Stop program mode after 20 sec inactivity
                  if (programTimer > PROG_WAIT)  {
                     programmode = false;
                     digitalWrite(LED_PIN, false);
                     Serial.println(F("Program expired"));  
                  }
              }
              
              if ((timer % (200 / HEARTBEAT)) == 0 )   {
                   // Look for new cards
                   if ( ! mfrc522.PICC_IsNewCardPresent()) {
                        if (releasecnt > 0)   {
                            releasecnt--;
                            if (!releasecnt)  {
                                olduid.size = 0;
                                Serial.println(F("release"));
                            }
                          }
                  return;
                  }
                  releasecnt = 5;
          
                 // Select one of the cards
                 if ( ! mfrc522.PICC_ReadCardSerial()) {
                    return;
                 }
          
                 // Dump debug info about the card; PICC_HaltA() is automatically called
                 //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
                 if (!olduid.size || !sameUid(&(mfrc522.uid), &olduid))  {
                      ShowCardData(&(mfrc522.uid));
                      copyUid(&(mfrc522.uid), &olduid);
                      if ( isValidCard(&olduid) )   {
                           OpenDoor(programmode);
                      } else  {
                         if (sameUid(&(mfrc522.uid), &masterkey)) {
                             // Only switch in program mode when mastercard is found AND the program button is pressed
                             if (switchValue)  {
                               Serial.println(F("Program mode"));
                               programmode = true;
                               programTimer = 0;
                               lastTime     = 0;
                             } else {
                               OpenDoor2(programmode);
                             }
                         } else {
                             if (programmode) {
                               Serial.println(F("new card"));
                               programTimer = 0;
                               
                               if (countValidCards < MAX_CARDS)
                               {
                                  // Add card to list...
                                  copyUid(&(mfrc522.uid), &validCards[countValidCards]);
                                  countValidCards++;
                                  blinkFast(15);
                               }
                             } else {
                               Serial.println(F("Invalid card"));
                               if (armed) {
                                  gw.send(wrongMsg.set(1));
                                  delay(2000);
                                  gw.send(wrongMsg.set(0));
                               }
                             }
                         }
                      }
                 }
              }
      }
      
      void ShowCardData(MFRC522::Uid* uid) 
      {
          Serial.print(F("Card UID:"));
          for (byte i = 0; i < uid->size; i++) {
              if(uid->uidByte[i] < 0x10) {
                  Serial.print(F(" 0"));
              } else {
                  Serial.print(F(" "));
                      }
              Serial.print(uid->uidByte[i], HEX);
          } 
          Serial.println();
      }
      
      void copyUid(MFRC522::Uid* src, MFRC522::Uid* dest)
      {
          dest->size = src->size;
          dest->sak  = src->sak;
          
          for (byte i = 0; i < src->size; i++) {
          dest->uidByte[i] = src->uidByte[i];
          }
      }
      
      bool sameUid(MFRC522::Uid* old, MFRC522::Uid* check)
      {
          if (old->size != check->size) {
             return false;
          }
          for (byte i = 0; i < old->size; i++) {
              if (old->uidByte[i] != check->uidByte[i]) {
                  return false;
              }
          }
          return true;
      }
      
      bool isValidCard(MFRC522::Uid* uid)
      {
            for (byte i = 0; i < countValidCards; i++)  {
                if (validCards[i].size != uid->size)  {
                    break;
                }
                for (int j = 0; j < uid->size; j++) {
                    if (validCards[i].uidByte[j] != uid->uidByte[j])  {
                        break;
                    }
                    if (j == (uid->size - 1)) {  
                        return true;
                    }
                }
            }
            return false;
      }
      
      
      void storeEeprom()
      {
          byte address = 0;
          gw.saveState(address++, countValidCards);
          
          for (byte i = 0; i < countValidCards; i++) {
             gw.saveState(address++, validCards[i].size);
             for (byte j = 0; j < 10; j++) {
                gw.saveState(address++, validCards[i].uidByte[j]);
             } 
          }
      }
      
      void recallEeprom()
      {
          byte address = 0;
          
          countValidCards = gw.loadState(address++);
          if (countValidCards > MAX_CARDS) {
             Serial.println(F("Not a valid EEPROM reading set to default"));
             countValidCards = 0;
             storeEeprom();
             return;
          }
          
          for (byte i = 0; i < countValidCards; i++)  {
             validCards[i].size = gw.loadState(address++);
             for (byte j = 0; j < 10; j++)  {
                validCards[i].uidByte[j] = gw.loadState(address++);
             } 
          }
        
      }
      
      void blinkFast(int times)
      {
          for (int i = 0; i < times; i++) { 
             ledon = !ledon;
             digitalWrite(LED_PIN, ledon);
             delay(100);
          }
      }
      
      void OpenDoor(bool fakeOpen)
      {
          Serial.println(F("Open door!"));
          gw.send(lockMsg.set(false));
          
          if (!fakeOpen) { 
            digitalWrite(LED_PIN, HIGH);
            digitalWrite(GARAGEPIN, HIGH); 
          }
          delay(1000);
          
          if (!fakeOpen) { 
            digitalWrite(GARAGEPIN, LOW); 
            digitalWrite(LED_PIN, LOW);
          }
          
          gw.send(lockMsg.set(true));
      }
      
      void OpenDoor2(bool fakeOpen)
      {
          Serial.println(F("Open door 2!"));
          gw.send(lock2Msg.set(false));
          
          if (!fakeOpen) { 
            digitalWrite(LED_PIN, HIGH);
            digitalWrite(SECONDRELAY, HIGH); 
          }
          delay(1000);
          
          if (!fakeOpen) { 
            digitalWrite(SECONDRELAY, LOW); 
            digitalWrite(LED_PIN, LOW);
          }
          
          gw.send(lock2Msg.set(true));
      }
      
      void ShowReaderDetails() {
          // Get the MFRC522 software version
          byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
          Serial.print(F("MFRC522 Software Version: 0x"));
          Serial.print(v, HEX);
          if (v == 0x91) {
              Serial.print(F(" = v1.0"));
              } else if (v == 0x92) {
              Serial.print(F(" = v2.0"));
              } else {
              Serial.print(F(" (unknown)"));
              }
          Serial.println("");
          
              // When 0x00 or 0xFF is returned, communication probably failed
          if ((v == 0x00) || (v == 0xFF)) {
              Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
          }
      }
      
      
      void incomingMessage(const MyMessage &message) 
      {
         if (message.type == V_LOCK_STATUS) {
           // Change relay state
           if (!message.getBool())  {
              switch (message.sensor)
              {
                 case CHILD_ID_LOCK:
                    OpenDoor(false);
                    break;
                 case CHILD_ID_LOCK2:
                    OpenDoor2(false);
                    break;
              }
           }
        
           // Write some debug info
           Serial.print(F("Lock:  "));
           Serial.print(message.sensor);
           Serial.print(F(" status: "));
           Serial.println(message.getBool());
         }
         else 
         {
           if (message.type == V_ARMED)  {
             // Change relay state
             armed = message.getBool();
        
             // Write some debug info
             Serial.print(F("Arm status: "));
             Serial.println(message.getBool());
           }
           else
           {
             // Write some debug info
             Serial.print(F("Incoming msg type: "));
             Serial.print(message.type);
             Serial.print(F(" id: "));
             Serial.print(message.sensor);
             Serial.print(F(" content: "));
             Serial.println(message.getInt());
           }
         }
      }
      
      posted in My Project
      Rod MacPherson
      Rod MacPherson
    • RE: antenna alignment

      In general, the way radio works you will get best performance with the antennas on both send and receive on the same orientation, (in radio terms this is called vertical or horizontal polarization) but that should not make much difference with these radios. If you are trying to go a long distance for an outdoor application you might want to try the slightly more expensive version with the SMA removable "rubber duck" antenna. There is a video series on Youtube where a guy was testing the range of these radios for use in RC aircraft models. With the small one he was able to transmit/receive at a distance of 100m reliably, with the rubber duck I believe it was around 700m. and with a circular polarization wire antenna about the same, but reliability went up.

      They do seem to be sensitive to interference from anything at all in the line of sight, so if you have old plaster walls or concrete block to go though you might consider the stronger radios as well.

      nRF24L01 range test (arduino) – 17:36
      — iforce2d

      posted in Hardware
      Rod MacPherson
      Rod MacPherson
    • RE: all the gear, no idea

      @Dean I'm still waiting on some Nanos to arrive so I can start playing with this stuff, but I opted to order the parts for the Ethernet gateway as well, because I figure it gives me more flexibility in placement of the gateway to achieve best radio reception, and more flexibility in my ability to switch controllers later on. ...kind of wish I'd thought of making it WiFi, but I didn't want to mess around with the recipe for the controller right out of the gate.

      posted in General Discussion
      Rod MacPherson
      Rod MacPherson