May 22

Relay Control Over I2C

Relays are pretty fun to work with. They take all of the DIY electronics stuff and bring it to the “real world” where high voltages and amps live. Relays are all around us and many people don’t even know it. Next time you turn on your TV, oven, or coffee maker and it makes a click, that’s the sound of a relay.

In a previous article I wrote about programming an ATtiny to run Arduino code. There is also a library that allows you to make ATtiny chips I2C slave devices that can be addressed by an Arduino. With this combination you can control up to 3 relays per 8 pin ATtiny. It’s actually possible to have 4 relays per ATtiny85, however, it requires burning the bootloader to disable the reset pin which also prevents you from uploading code.


  • ArduinoISP setup from previous article
  • ATtiny85 (or any compatible ATtiny chip)
  • 3 relays (with a switching voltage of 5V)
  • 3 LEDs with resistors
  • 2 pull up resistors (4.7k Ohm)
  • Jumper wires

Program the ATtiny85

In this project the ATtiny is acting as the slave device. It simply waits for commands to be sent. When it receives a 1, 2 or 3 it switches the corresponding relay. If the relay is currently off it switches it on, if it is currently on, it switches it off.
The code that needs to be uploaded requires the I2C library for the ATtiny chips.

  1. Download the code here:
  2. Create a “libraries” folder inside the Arduino Sketch folder
  3. Extract the zip file to the libraries folder you just created.
  4. Open Arduino program and paste the code below
  5. Select the ATtiny as the board
  6. Select Arduino ISP as the programmer
  7. Upload
// ATTiny based I2C relay control
// ForkRobotics 2012

#include "TinyWireS.h"                  // wrapper class for I2C slave routines

#define I2C_SLAVE_ADDR  0x26            // i2c slave address
#define Relay1_PIN  1
#define Relay2_PIN  4
#define Relay3_PIN  3

void setup(){
  TinyWireS.begin(I2C_SLAVE_ADDR);      // init I2C Slave mode

void loop(){
  byte byteRcvd = 0;
  if (TinyWireS.available()){           // got I2C input!
    byteRcvd = TinyWireS.receive();     // get the byte from master
      switch (byteRcvd) {
        case 0x01:
        case 0x02:
        case 0x03:


void Switch(int relay){
    if (digitalRead(relay) == HIGH){ digitalWrite(relay,LOW);}
    else {digitalWrite(relay,HIGH);}

Program the Arduino

The Arduino in this equation is doing the sending of commands. The Arduino can be configured to send these commands in response to any input but for the purposes of this experiment we are using the serial console. Here is the code for the Arduino:

// Control menu for I2C relay control
// 2012 ForkRobotics

#include <Wire.h>
int selection=0;
int ATtinyAddress=0x26;

void setup(){
void loop(){
  if (Serial.available() > 0){
    selection =;

void PrintMenu(){
  Serial.println("--- Relay Menu ---");
  Serial.println("1: Switch Relay 1");
  Serial.println("2: Switch Relay 2");
  Serial.println("3: Switch Relay 3");

void RelaySwitch(byte device,byte data) {


In this example the LEDs are used as an example of a completed circuit but it could be anything that meets the capacity of the relay. Here is the wiring for the example.

Update (3/27/2013) – Here is the Fritzing File used to create this: ATtiny85 I2C Relay
I2C Relay wiringHere is what my board looks like:

I2C Relay Module
Here is the video of it working:

Next Steps

This is a simple demo of the power of controlling relays over I2C. At this point the ATtiny relay module is only capable of switching the relays, however, with a more complex function on both sides it is possible to send specific commands to power a device off, on or blink for a period of time.