Chapter 4. RFID Meets Home Automation

Between my officemate and me, we have dozens of devices drawing power in our office: two laptops, two monitors, four or five lamps, a few hard drives, a soldering iron, Ethernet hubs, speakers, and so forth. Even when we’re not here, the room is drawing a lot of power. What devices are turned on at any given time depends largely on which of us is here, and what we’re doing. This project is a system to reduce our power consumption, particularly when we’re not there.

When either of us comes into the room, all we have to do is tap our key fobs on a reader mounted by the door, and the room turns on or off what we normally use. Each of us has a keyring with an RFID-tag key fob. The reader by the door reads the presence or absence of the tags.

The reader is connected to a microcontroller module that controls the AC power lines using a device called the PowerSwitch Tail, shown in Figure 4-1. Each of the various power strips is plugged into one of these. Depending on which tag is read, the microcontroller knows which power strip to turn on or off.

Arduino

The Arduino Uno is a good model of Arduino to get started with, and it will work for all the microncontroller-based projects in this book.

RFID reader

Parallax’s RFID Reader Module, available from Maker Shed as part of a starter pack or by itself.

RFID tags

The starter pack includes several tags, and you can buy them separately.

Breadboard

You can use a half-size or mini breadboard to make connections between the reader and the USB-to-TTL serial adaptor.

2 PowerSwitch Tails

Each one can control 15 amps of current. They are available from Maker Shed.

The RFID module is connected to the microcontroller as in Chapter 3. Connect the microcontroller to the PowerSwitch Tails as shown in Figure 4-2:

First PowerSwitch Tail
  • “1: +in” to Arduino digital pin 2

  • “2: -in” to breadboard ground

Second PowerSwitch Tail
  • “1: +in” to Arduino digital pin 3

  • “2: -in” to breadboard ground

Warning

This project controls high-voltage, high-current alternating current. Even though the PowerSwitch Tail is designed to make this safe, you should take extra care when wiring or rewiring the circuits for this project. Make sure everything is wired correctly and mounted securely before you plug either the Arduino or the PowerSwitch Tails in.

Run this sketch to test the PowerSwitch Tail:

/*
 PowerSwitch Tail test
 language: Wiring/Arduino

*/

const int switchOne = 2; // the first PowerSwitch Tail control pin 1
const int switchTwo = 3; // the second PowerSwitch Tail control pin

void setup() {
  pinMode(switchOne, OUTPUT); // Configure the pins 2
  pinMode(switchTwo, OUTPUT);

  digitalWrite(switchOne, LOW); // Make sure they are off 3
  digitalWrite(switchTwo, LOW);
}

void loop() {

  // turn on first power strip, turn off the second 4
  digitalWrite(switchOne, HIGH);
  digitalWrite(switchTwo, LOW);
  delay(2000);

  // turn on second power strip, turn off the first
  digitalWrite(switchTwo, HIGH);
  digitalWrite(switchOne, LOW);
  delay(2000);

}

Here’s what happens in the sketch:

1

First, the sketch initializes two variables, switchOne and switchTwo, to hold the pin numbers of the two PowerSwitch Tail units you have connected.

2

In setup(), you configure the pins to be OUTPUTs.

3

Next, we make sure the pins are off (this is the default, but it makes it clear that your sketch expects to start with everything off).

4

The loop() function repeatedly turns the first switch on and the second off, then waits two seconds, and does the opposite.

The result is that each PowerSwitch Tail will turn on and off every two seconds. You probably don’t want to leave this running for very long, unless you’re trying to do endurance tests for light bulbs (or whatever you have plugged in).

Now that you’ve got control over your PowerSwitch Tails, you can combine the RFID and the PowerSwitch Tail code.

The following sketch will toggle the state of each PowerSwitch Tail when the corresponding RFID tag is held up to the reader. You can now use the RFID reader like a light (or power strip) switch:

/*
 RFID–to-PowerSwitch Tail control
 language: Wiring/Arduino

 */
#include <SoftwareSerial.h> // Bring in the software serial library 1

const int tagLength = 10;    // each tag ID contains 10 bytes
const int startByte = 0x0A;  // Indicates start of a tag
const int endByte   = 0x0D;  // Indicates end of a tag

const int rxpin = 6; // Pin for receiving data from the RFID reader
const int txpin = 7; // Transmit pin; not used

String currentTag;   // String to hold the tag you're reading 2

String tag[] = { "04162F7CAC", "0415EA09BE"}; // List of tags 3
int numTags = 2;                              // Number in that list

// PowerSwitchTail unit pins and unit states: 4
int numUnits    = 2;          // Two PowerSwitch Tails
int unit[]      = {2, 3};     // Pins 2 and 3
int unitState[] = {LOW, LOW}; // Both start in the off position

long lastRead;       // the time when we last read a tag
long timeOut = 1000; // required time between reads

SoftwareSerial rfidPort(rxpin, txpin); // create a Software Serial port

void setup() {

  lastRead = millis(); // Initalize to the sketch's start time 5

  // begin serial communication with the computer
  Serial.begin(9600);

  // begin serial communication with the RFID module
  rfidPort.begin(2400);

  // Initialize all the PowerSwitchTail controller pins. 6
  for (int thisUnit = 0; thisUnit < numUnits; thisUnit++) {
    pinMode(unit[thisUnit], OUTPUT); // Enable this pin for output
    digitalWrite(unit[thisUnit], unitState[thisUnit]);
  }
}

void loop() {
  // read in and parse serial data: 7
  if (rfidPort.available()) {
    readByte();
  }
}

void readByte() {

  char thisChar = rfidPort.read(); // Read a character from the port 8

  // depending on the byte's value,
  // take different actions:
  switch(thisChar) {
    // if the byte == startByte, you're at the beginning 9
    // of a new tag:
  case startByte:
    currentTag = "";
    break;
  //if the byte == endByte, you're at the end of a tag: 10
  case endByte:
    checkTags();
    break;
  // other bytes, if the current tag is less than  11
  // 10 bytes, you're still reading it:
  default:
    if (currentTag.length() < 10) {
      currentTag += thisChar;
    }
  }
}

void checkTags() {

  // iterate over the list of tags: 12
  for (int thisTag = 0; thisTag < numTags; thisTag++) {

    // if the current tag matches the tag you're on: 13
    if (currentTag.equals(tag[thisTag])) {

      // Only flip a switch if the tag has been away for a while 14
      if (lastRead + timeOut < millis()) {

        // unit number starts at 1, but list position starts at 0:
        Serial.print("unit " + String(thisTag +1));

        // change the status of the corresponding unit: 15
        if (unitState[thisTag] == HIGH) {
          unitState[thisTag] = LOW;
          Serial.println(" turning OFF");
        }
        else {
          unitState[thisTag] = HIGH;
          Serial.println(" turning ON");
        }

        // Set the switch to the new state. (16)
        digitalWrite(unit[thisTag], unitState[thisTag]);
      }
      lastRead = millis(); // mark the last time you got a good tag (17)

    }
  }
}
1

The top part of the sketch is essentially the same as what you saw in the example in Chapter 3.

2

This string contains the tag that’s currently being read. As the RFID reader collects each byte of the tag ID, it will add it to this string until it’s full.

3

This array contains a list of tags that the sketch will accept. This array should have the same number of elements as the array (unit[]) that you’ll see later. That’s because each element in this array corresponds to one PowerSwitch Tail unit. That means that the first RFID tag in the tag[] array will turn the first PowerSwitch Tail on and off, and the second RFID tag will turn the second PowerSwitch Tail on and off.

4

Here’s where you set up an array (unit[]) containing the Arduino pin number corresponding to a single PowerSwitch Tail. You also set up an array to track the current state (HIGH or LOW) of each unit.

5

This variable is used to make sure you don’t continuously toggle a switch on and off as long as you hold a tag in place. The Parallax reader continuously transmits a tag as long as you hold it in place. Later on, you’ll see that the sketch requires that you keep the tag away for at least one second before it will let you toggle a switch.

6

This loop goes over each pin in the unit() array and sets its initial state (LOW, or off).

7

In the loop() function, you look for any serial activity from the RFID reader, and call readByte() if there is any.

8

Here, we read one character from the RFID reader.

9

This switch statement takes action based on what was read from the RFID reader. If it sees the start of tag byte, it initializes the currentTag string.

10

If you reached the end of a tag, call checkTags().

11

Otherwise, keep appending the character to the currentTag string, as long as you don’t exceed the maximum tag length.

12

At the top of checkTags(), start a loop that iterates over the list of tags.

13

For each of the tags in the list, check to see if it matches the one you just read from the RFID reader.

14

This line checks the lastRead variable to make sure you’ve waited long enough before toggling a switch.

15

Here’s where you toggle the switch’s state: if it’s on, set it to LOW, or off. If it’s off, set it to HIGH, or on.

(16)

This line calls digitalWrite() to turn a PowerSwitch Tail on or off.

(17)

Finally, set lastRead to the current time (the time at which you last read a valid tag).

Note that the reader lacks the ability to read multiple tags if more than one tag is in the field. That’s an important limitation. It means that you have to design the interaction so that the person using the system places only one tag at a time, then removes it before the second one is placed. In effect, it means that two people can’t hold their key tags to the reader at the same time. In other words, users of the system need to take explicit action to make something happen. Presence isn’t enough. That’s why I mounted the reader vertically on a wall, so that tags wouldn’t just lay on the antenna all the time.