Aug 02

Arduino Controlled Garage Door – Part 1

Robotics and automation is a lot of fun as a hobby, however it can also be a great tool to solve common problems. Being fairly new to Aurdino and robotics, one area that seems within reach as a beginner’s project is home automation. I recognize that I’m not going to wake up one morning and be ready to deploy a system like SARAH from Eureka, but taking baby steps towards that goal seems like the best way to gain valuable experience and learn the challenges associated with such a system. The ice breaker project I’ve decided to use as a kickoff is a control mechanism for my 2 garage doors.

Current setup

The current setup I have in my garage is 2 Craftsman garage door openers. They are controlled through a set of wireless remote controls as well as a button wired directly to the units that allows the doors to be opened and closed from inside the garage.

garage door openergarage door buttongarage door remote

I want to leave the wireless modules alone, so I’ll be connecting to the wired connection for this project. On some initial testing I discovered that the 2 wire cable connected to the button on the wall is a 25v/2mA powered connection. When the button is pressed it connects the 2 contacts and the door opens, closes or stops. The relays I have are capable of handling 30v at 3A so this was a great fit.

Adding functionality

The main purpose of this project is to develop a system to detect if the garage doors are opened or closed (a problem my wife and I often encounter after leaving the house – did we remember to close the door?) and to be able to open or close the doors from anywhere, perhaps through an app on our smart phones.

This is really a 3 part problem

  1. Create a module that can open and close the doors
  2. Setup Arduino Ethernet to control the module remotely
  3. Develop a way to detect if a garage door is open or closed

Garage Door Control Module

With that in mind my first step is to build a permanent version of the I2C relay circuit from the Relay over I2C article. This modified version will need connect the door opener button circuit. The existing button will stay in place as a manual override (just in case the Arduino based system is not working).

The materials I used are:

Here is what the module looks like:

Relay Control Module - TopRelay Control Module - Botton

As a side note this is the last time I’ll try to solder a board like this, I’m going to have to test out the laser printer method to create a PCB next time.

This is a modified version of the code used in the relay article. When the module received a “1” or “2” over I2C it will switch on the appropriate relay then turn it off.  This essentially simulates a button press.

// Garage Door Control Module
// Fork Robotics 2012
//

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

#define I2C_SLAVE_ADDR  0x26            // i2c slave address
#define RELAY1_PIN         3
#define RELAY2_PIN         4

void setup(){
  pinMode(RELAY1_PIN,OUTPUT);
  pinMode(RELAY2_PIN,OUTPUT);
  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:
          Press(RELAY1_PIN,500);
        break;
        case 0x02:
          Press(RELAY2_PIN,500);
        break;
      }
  }
}

void Press(int RELAY,int ontime){ // poor man's display
    digitalWrite(RELAY,HIGH);
    delay (ontime);
    digitalWrite(RELAY,LOW);
    delay (ontime);
}

The code for the Arduino is the same as the one used in the Relay Control over I2C article.

Here is a video of the initial testing:

Next steps

At this point this module is still a very manual proposition. The module needs to be attached to an Arduino that in turn needs to be connected to a computer. The next step will be to create a web based interface to control this (and others in the future) module.

Jul 09

Cosm and TMP100

All of the devices around us are starting to become data collection points. Every minute of every day many data points are generated. This unwieldy mass of data needs to be logged, processed, stored and displayed in a reasonable way for it to be usable. The question becomes how to do this. One solution for the DIY community is Cosm (formerly Pachub) that allows us to do just that for free. In this article I’ll show you how to setup an account, create a feed and upload temperature readings from an I2C temperature sensor to Cosm via an Arduino Ethernet Shield.

Materials

  • Cosm Account
  • Arduino and Ethernet Shield or Arduino Ethernet
  • Breadboard and jumper wires
  • tmp100 (or other I2C temperature sensor) on a breakout board

Setup a Cosm Account

If you don’t already have one the first thing you need to do is setup a Cosm Account

  1. Go to https://cosm.com
  2. Click the big blue “Get Started” button
  3. Enter an email, username and password then click the “Sign up” button
  4. You’ll get an email with a link to verify your registration
  5. The link will bring you directly into your account
  6. Click on the big plus button
  7. Select Arduino
  8. Give the new feed a title and tags (optional) and press Create
  9. The Cosm Site will give you a sample sketch to upload data. You only need the three lines that start with:
    1. #define APIKEY
    2. #define FEEDID
    3. #define USERAGENT

Arduino wiring

In order to upload the data your Arduino needs to be connected to the internet. If you have an Arduino Ethernet you are ready to go. Otherwise you will need an Ethernet Shield. I already had a couple Arduinos so I decided to go the shield route (Note: the Ethernet Shield will not work with the Arduino Leonard).


Next we need to wire up the TMP100 sensor as shown in the Arduino and TMP100 article.

Sketch

The starter code that Cosm gives you when you create a feed (and the one included in the Arduino IDE) are written to send an analog sensor reading so there are some minor tweaks that need to be done to make it work with an I2C sensor. I’ve included the function to set the accuracy of the TMP100 sensor.
Here is the modified sketch:

/* TMP100 to Cosm
Fork Robotics 2012

Based on: http://arduino.cc/en/Tutorial/CosmClient
*/

#include
#include
#include

#define APIKEY         // your cosm api key
#define FEEDID         // your feed ID
#define USERAGENT      // user agent is the project name

// Set the TMP Address and Resolution here
int tmpAddress = B1001011;
int ResolutionBits = 12;

// assign a MAC address for the ethernet controller.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
// fill in your address here:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

// initialize the library instance:
EthernetClient client;

char server[] = "api.cosm.com";   // name address for cosm API

unsigned long lastConnectionTime = 0;
boolean lastConnected = false;
const unsigned long postingInterval = 10*1000; //delay between updates to cosm.com

void setup() {
  // start serial port:
  Wire.begin();
  Serial.begin(9600);
  // start the Ethernet connection:
  Ethernet.begin(mac);
  SetResolution();
}

void loop() {
  // read the analog sensor:
  float sensorReading = getTemperature();
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    Serial.print("Sending temperature: ");
    Serial.println(sensorReading);
    sendData(sensorReading);
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void sendData(float thisData) {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    client.print("PUT /v2/feeds/");
    client.print(FEEDID);
    client.println(".csv HTTP/1.1");
    client.println("Host: api.cosm.com");
    client.print("X-ApiKey: ");
    client.println(APIKEY);
    client.print("User-Agent: ");
    client.println(USERAGENT);
    client.print("Content-Length: ");

    // calculate the length of the sensor reading in bytes:
    // 8 bytes for "sensor1," + number of digits of the data:
    int thisLength = 8 + getLength(thisData);
    client.println(thisLength);

    // last pieces of the HTTP PUT request:
    client.println("Content-Type: text/csv");
    client.println("Connection: close");
    client.println();

    // here's the actual content of the PUT request:
    client.print("sensor1,");
    client.println(thisData);

  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
   // note the time that the connection was made or attempted:
  lastConnectionTime = millis();
}

// This method calculates the number of digits in the
// sensor reading.  Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

int getLength(int someValue) {
  // there's at least one byte:
  int digits = 1;
  // continually divide the value by ten,
  // adding one to the digit count for each
  // time you divide, until you're at 0:
  int dividend = someValue /10;
  while (dividend > 0) {
    dividend = dividend /10;
    digits++;
  }
  // return the number of digits:
  return digits;
}

float getTemperature(){
  Wire.requestFrom(tmpAddress,2);
  byte MSB = Wire.read();
  byte LSB = Wire.read();
  int TemperatureSum = ((MSB << 8) | LSB) >> 4;
  float celsius = TemperatureSum*0.0625;
  float fahrenheit = (1.8 * celsius) + 32;
  return fahrenheit;
}

void SetResolution(){
  if (ResolutionBits < 9 || ResolutionBits > 12) exit;
  Wire.beginTransmission(tmpAddress);
  Wire.write(B00000001); //addresses the configuration register
  Wire.write((ResolutionBits-9) << 5); //writes the resolution bits
  Wire.endTransmission();
  Wire.beginTransmission(tmpAddress); //resets to reading the temperature
  Wire.write((byte)0x00);
  Wire.endTransmission();
}

Using, modifying and troubleshooting

The address for the I2C is configured the same as it was in the previous TMP100 article but it’s possible to use your own TMP100 address and set the resolution to a finer degree.

To view the information that is uploaded to Cosm simply go to the feed at: https://cosm.com/feeds/xxxxx with “xxxxx” in the link replaced with the feed number Cosm gave you when you setup your new feed. You can also just log into Cosm and they will show you all your active feeds. Keep in mind that the feed data is public by default and you will need to modify the settings of the feed if you want to change this.

As written the code uploads the current temperature in Fahrenheit; if you want Celsius then simply change the return line of the GetTemperature function from “return Fahrenheit” to “return Celsius”

The nice thing about this project is that it doesn’t need to be connected to a computer. You just need power and Ethernet. If you do connect it to a computer you can monitor the status of the sketch by using the serial monitor.

Next Steps

This project presents a simple way to monitor and upload digital I2C readings from a single sensor to Cosm. This function can be integrated into a thermostat type project to add historical data for display or analysis. The next step is to be able to upload data from multiple locations in your home labeled for the room they are in or inside and outside temperatures. This also opens the door to more I2C devices being able to upload data. A single internet connected Arduino can upload hundreds of readings.

Jun 19

Leonardo Wiichuck Mouse

The Arduino Leonardo’s big new feature (thanks to its ATmega32u4 chip) is the ability to emulate a keyboard and/or mouse. This brings up so many possibilities for alternative control schemes for a computer. In this article I’ll show you how to grab the input from a Wii Nunchuck and get your computer to detect it as a mouse.

Wiichuck on Leonardo

I’ve worked with the Wii Nunchuck many times in the past including the Basic Robot I posted about a while back. Unfortunately the physical Wii Chuck adapter, while still a great way to breakout the pins for a nunchuck, is no longer as simple as plugging into pins A2-A5 as it was used on an UNO.
The major difference here is that the Arduino Leonard uses a different microcontroller than was used in the UNO. Because of this the pin mappings for certain functions are now different. One function that has been relocated is the pins used for I2C which is how the Wii Nunchuck communicates with the Arduino. On the UNO (and other boards based off of the ATmega328) the SDA is shared with A4 and the SCL is shared with A5. This is convenient because pin A3 can be used as power and A2 can be used as ground which allows 4 consecutive pins to be used for the Wii Chuck to plug into. However with the Leonardo and its new chip the SDA is shared with D2 and SCL is shared with D3 (they are also broken out to their own pins). In order to connect the Wii Chuck to the Arduino Leonardo you have to use a breadboard to make the appropriate connections.

In addition to the physical change in the pins there are references in the Wii Chuck Library for Ground and Power pins by using the “ports” which are also different. This requires editing the nunchuck_funcs.h file when using it with the Arduino Leonardo. With all that in mind, here is how to complete the project:

  1. Create a New Project with the following code:
    //Wiichuck Mouse
    //Fork Robotics 2012
    
    #include
    #include "nunchuck_funcs.h"
    int loop_cnt=0;
    
    // parameters for reading the joystick:
    int range = 40;               // output range of X or Y movement
    int threshold = range/10;      // resting threshold
    int center = range/2;         // resting position value
    
    boolean mouseIsActive = false;    // whether or not to control the mouse
    int lastSwitchState = LOW;        // previous switch state
    
    void setup() {
      // initilization for the Wiichuck
      nunchuck_init();
      // take control of the mouse:
      Mouse.begin();
    }
    
    void loop() {
      if( loop_cnt > 10 ) { // every 10 msecs get new data
        loop_cnt = 0;
        nunchuck_get_data();
    
        //right and left click control
        int leftState = nunchuck_cbutton();
        if (leftState) Mouse.press(MOUSE_LEFT); else Mouse.release(MOUSE_LEFT);
        int rightState = nunchuck_zbutton();
        if (rightState) Mouse.press(MOUSE_RIGHT); else Mouse.release(MOUSE_RIGHT);
    
        // read the x axis
        int xReading = nunchuck_joyx();
        xReading = map(xReading, 38, 232, 0, range);
        int xDistance = xReading - center;
        if (abs(xDistance) < threshold) {
          xDistance = 0;
        }
    
        // read the y axis
        int yReading = nunchuck_joyy();
        yReading = map(yReading, 38, 232, 0, range);
        int yDistance = yReading - center;
        if (abs(yDistance) < threshold) {
          yDistance = 0;
        }
    
        // move the mouse
        if ((xDistance != 0) || (yDistance != 0)) {
          Mouse.move(xDistance, -yDistance, 0);
        }
      }
      loop_cnt++;
      delay(1);
    }
    
  2. Save the project and close Arduino IDE
  3. Download nunchuck.funcs.h
  4. Save it to the Project folder
  5. Open the project and click the tab for nunchuck_funcs.h
  6. Remove the following lines:
    // Uses port C (analog in) pins as power & ground for Nunchuck
    static void nunchuck_setpowerpins()
    {
    #define pwrpin PORTC3
    #define gndpin PORTC2
        DDRC |= _BV(pwrpin) | _BV(gndpin);
        PORTC &=~ _BV(gndpin);
        PORTC |=  _BV(pwrpin);
        delay(100);  // wait for things to stabilize
    }
    
  7. Press upload

Once the code finishes uploading you should now be able to move the joystick to move the mouse, click C for left click and Z for right click.

Uploading code and using USB emulation

One lesson I learned from this processes is that the Leonardo uses the same processor for running sketches and communicating over USB. The challenge here is that when you emulate a USB device this can overwhelm the Arduino and prevent you from uploading new code. You can avoid this in 2 ways:

The first is to have some way to enable or disable device emulation this could be by pressing a button to enable or disable the device or only sending data when a button is held down.  The second way is to only send data when there is valid input. In this sketch I opted for the latter. It’s done with an if…then statement:

if ((xDistance != 0) || (yDistance != 0)) {
      Mouse.move(xDistance, -yDistance, 0);

What this does is eliminates the sending of null updates when the joystick is centered, allowing you to upload code.

This is a very quick and simple way to demo this feature but there are many other possibilities. It is possible to use the accelerometer in the Wii Nunchuck to move the mouse but I found it hard to control. More importantly it’s possible to use any component that you can interact with can now be a computer interface: hall sensors, distance sensors, or RFID readers. If you’re working on something similar leave a comment, I’d love to hear about it.

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.

Materials:

  • 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: http://arduino.cc/playground/Code/USIi2c
  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(){
  pinMode(Relay1_PIN,OUTPUT);
  pinMode(Relay2_PIN,OUTPUT);
  pinMode(Relay3_PIN,OUTPUT);
  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:
          Switch(Relay1_PIN);
        break;
        case 0x02:
          Switch(Relay2_PIN);
        break;
        case 0x03:
          Switch(Relay3_PIN);
        break;
      }

  }
}

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 &lt;Wire.h&gt;
int selection=0;
int ATtinyAddress=0x26;

void setup(){
    Wire.begin();
    Serial.begin(9600);
    PrintMenu();
}
void loop(){
  if (Serial.available() &gt; 0){
    selection = Serial.read()-48;
    RelaySwitch(ATtinyAddress,selection);
  }
}

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

void RelaySwitch(byte device,byte data) {
  Wire.beginTransmission(device);
  Wire.write(data);
  Wire.endTransmission();
}

Wiring

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.