A Too-Simple Arduino Library for Handling the Seeeduino Relay Shield (and Generic Relays)

Again, no music. Lucky dogs.

I discussed the Sparkfun Voicebox Shield in a previous entry, and also as a component of that same project I purchased a Seeeduino Relay Shield. Sure, normally I’d just hack up my own PCB for something like this, but it was only twenty bucks and I’m pretty sure I couldn’t build something comparable that cheap and get it that fast.

The relay shield has four relays that are optoisolated, which is a damned useful thing to have when working with 120 volt switching systems, as it lessens the odds of you accidentally turning your microcontroller board into a little charred pile.

This board also has an XBee socket on it, which I was singularly uninterested in, as I don’t have any XBee stuff.

The Seeeduino relay shield is pretty simple in operation: four relays are controlled by four of the digital lines on the Arduino. Nothing simpler. Assert the digital line on the Arduino, and the relay closes. Each of the relays has a NO (normally open) and NC (normally closed) connection, so you can use them in either orientation for your switching logic.

Given how basic this hardware is, it seems pointless to write an encapsulating class library to handle them. So I did it anyway. When you’re writing software projects it’s nice to do something “small” and “easy” to remind yourself of how things go together. So this library serves more as an example of how to write other libraries. The Arduino Playground has an example showing how to write a library, but this is a complete code example that’s actually useful (cough). Rather than being a library that you have to copy over to your Arduino user Libraries folder, this is all encapsulated as a multi-file (multi-tab) sketch, so you can view all the files at once. Plus, from the hate mail I’ve received it seems some people have problems figuring out how to install an Arduino library.

Although this is written with the Seeeduino in mind, the hardware is so generic I figure it should work for any relay control situation, just change the pins. Its purpose is to make reading code involving relays easier (encapsulation).

Since a relay is either “on” or “off” (and whether that’s open or closed depends on whether you use the the NO/NC connection), all you really need is:

  • Function to turn the relay on
  • Function to turn the relay off
  • Function to return the state of the relay (on/off)
  • A housekeeping variable holding the state (private)
  • Bonus: a function to toggle the relay state between on and off, based on what state it was in

You can probably think of a million more complicated functions this absolutely must have. I couldn’t. There’s no XBee support in this library, because there are libraries already for that. Also, I don’t have an XBee to test with.

The library code itself doesn’t use it, but the demo sketch uses the Bounce library, which is a generally useful library for handling buttons in your sketch.

You can download this entire tiny arduino sketch form here. You can download the library from github.

Here’s SeeeduinoRelay.h, which has the class definition.

#ifndef SEEEDUINORELAY_H
#define SEEEDUINORELAY_H

#include "WProgram.h"

// These are the pins that control the relays on the Seeeduino board.  
// If you are modifying this to work with different relay configurations, 
// these are the pins you need to change. 
#define RELAY1PIN 7
#define RELAY2PIN 6
#define RELAY3PIN 5
#define RELAY4PIN 4

// Class Definition. 
class SeeeduinoRelay
{
public: 
  SeeeduinoRelay(int RelayNum, int state);    // Constructor 
  void on();    // Turns relay on 
  void off();   // Turns relay off
  void toggle();  // Toggles state of relay between on and off
  int state();    // returns state of relay (LOW/0/off or HIGH/1/on) 
  int isRelayOn();   // Returns TRUE if the relay is on , false otherwise 
  int isRelayOff();  // Returns TRUE if the relay is off, false otherwise 

private: 
  int relayState;     // Variables holds on/off state of the relay
  int relayPin;       // Variable holds which Arduino pin connected to relay. 
};

#endif   // SEEEDUINORELAY_H

and here’s the SeeeduinoRelay.cpp, which has the implementation:

#include "WProgram.h"
#include "SeeeduinoRelay.h"

//
// The constructor sets up a single relay, specified by RelayNum
// Which is relay 1,2,3 or 4 as specified on the Seeeduino Relay board
// "state" is the initial state (LOW or HIGH)
// 
// Relay Truth Table:
// State     NOx    NCx 
// LOW       open   closed
// HIGH      closed open
//
// The constructor will also properly set the assigned pin to OUTPUT. 
//
SeeeduinoRelay::SeeeduinoRelay(int RelayNum, int state)
{
  if (RelayNum == 1)  relayPin=RELAY1PIN;
  if (RelayNum == 2)  relayPin=RELAY2PIN;
  if (RelayNum == 3)  relayPin=RELAY3PIN; 
  if (RelayNum == 4)  relayPin=RELAY4PIN; 
  pinMode(relayPin, OUTPUT); 

  if (state == LOW) {
    relayState=LOW; 
    off(); 
  } 
  else {
    relayState=HIGH;
    on(); 
  }
}

// Turns the relay on. 
void SeeeduinoRelay::on() 
{
  digitalWrite(relayPin, HIGH); 
  relayState=HIGH; 
}

// Turns the relay off. 
void SeeeduinoRelay::off()
{
  digitalWrite(relayPin, LOW); 
  relayState=LOW; 
}

//Toggles the state of the relay
void SeeeduinoRelay::toggle()
{
  if (relayState==HIGH) {
    off(); 
  } else {
    on(); 
  }
}

// Returns the state of the relay (LOW/0 or HIGH/1)
int SeeeduinoRelay::state()
{
  return(relayState); 
}

// If the relay is on, returns true, otherwise returns false
int SeeeduinoRelay::isRelayOn()
{
  if (relayState==HIGH) 
    return true; 
  else
    return false; 
}

// If the relay is off, returns true, otherwise returns false
int SeeeduinoRelay::isRelayOff()
{
  if (relayState==LOW) 
    return true; 
  else
    return false; 
}

Here’s the demo sketch that ties it all together:

// This simplistic program demonstrates the use of the SeeeduinoRelay 
// library with an Arduino.   Pushbuttons are connected to 
// pins 8/9/10/11 for toggling relays on and off.   
//
// [arduino button pin --------Switch------- GND]
//
// Internal Pullup resistors are activated on input pins.  
//
// Note: Seeeduino has THREE e's, not two as you might think.  Check that
// first when trying to find unresolved references. 
// 
// Shield details: 
// http://www.seeedstudio.com/depot/relay-shield-p-693.html?cPath=132_134
// http://garden.seeedstudio.com/index.php?title=Relay_Shield

#include <Bounce.h>    // http://www.arduino.cc/playground/Code/Bounce
#include "SeeeduinoRelay.h"

// Pin definitions for four buttons connected to the Arduino for testing. 

#define Button1pin 8
#define Button2pin 9 
#define Button3pin 10
#define Button4pin 11

// Define "bounce" objects for input buttons.
// Bounce is really nice, you should use it.  
// http://www.arduino.cc/playground/Code/Bounce
Bounce Button1 = Bounce(Button1pin, 5); 
Bounce Button2 = Bounce(Button2pin, 5); 
Bounce Button3 = Bounce(Button3pin, 5); 
Bounce Button4 = Bounce(Button4pin, 5); 

SeeeduinoRelay RELAY1 = SeeeduinoRelay(1,LOW); 
SeeeduinoRelay RELAY2 = SeeeduinoRelay(2,LOW); 
SeeeduinoRelay RELAY3 = SeeeduinoRelay(3,LOW); 
SeeeduinoRelay RELAY4 = SeeeduinoRelay(4,LOW); 

void setup()
{
  // Setup input pins 
  pinMode(Button1pin, INPUT); 
  digitalWrite(Button1pin, HIGH);  // Activate internal pullup
  pinMode(Button2pin, INPUT); 
  digitalWrite(Button2pin, HIGH);  // Activate internal pullup
  pinMode(Button3pin, INPUT); 
  digitalWrite(Button3pin, HIGH);  // Activate internal pullup
  pinMode(Button4pin, INPUT); 
  digitalWrite(Button4pin, HIGH);  // Activate internal pullup

  Serial.begin(9600);
  Serial.println("Ready"); 

}

// This is the demo loop.   Check state of each button, toggle relay
// and print out status of relays. 
void loop() 
{

  if (Button1.update() ) 
  {
    if (Button1.read() == LOW)  
    {
      Serial.print("Button #1 pressed: "); 
      Serial.print("Relay #1 state was "); 
      Serial.print(RELAY1.state()); 
      RELAY1.toggle(); 
      Serial.print(", now relay is "); 
      Serial.println(RELAY1.state());     
      if (RELAY1.isRelayOn()) Serial.println("Relay #1 is on"); 
      if (RELAY1.isRelayOff()) Serial.println("Relay #1 is off"); 
    }
  }  

  if (Button2.update() ) 
  {
    if (Button2.read() == LOW)  
    {
      Serial.print("Button #2 pressed: "); 
      Serial.print("Relay #2 state was "); 
      Serial.print(RELAY2.state()); 
      RELAY2.toggle(); 
      Serial.print(", now relay is "); 
      Serial.println(RELAY2.state()); 
      if (RELAY2.isRelayOn()) Serial.println("Relay #2 is on"); 
      if (RELAY2.isRelayOff()) Serial.println("Relay #2 is off"); 
    }
  }  

  if (Button3.update() ) 
  {
    if (Button3.read() == LOW)  
    {
      Serial.print("Button #3 pressed: "); 
      Serial.print("Relay #3 state was "); 
      Serial.print(RELAY3.state()); 
      RELAY3.toggle(); 
      Serial.print(", now relay is "); 
      Serial.println(RELAY3.state()); 
      if (RELAY3.isRelayOn()) Serial.println("Relay #3 is on"); 
      if (RELAY3.isRelayOff()) Serial.println("Relay #3 is off"); 
    }
  }  

  if (Button4.update() ) 
  {
    if (Button4.read() == LOW)  
    {
      Serial.print("Button #4 pressed: "); 
      Serial.print("Relay #4 state was "); 
      Serial.print(RELAY4.state()); 
      RELAY4.toggle(); 
      Serial.print(", now relay is "); 
      Serial.println(RELAY4.state()); 
      if (RELAY4.isRelayOn()) Serial.println("Relay #4 is on"); 
      if (RELAY4.isRelayOff()) Serial.println("Relay #4 is off"); 
    }
  }  
}

Oh crap, here comes the picture.

The buttons are connected via one of my Stupidshields, since that way I didn’t have to solder anything to the Seeeduino board for the demo.