Arduino and Ruby: Create a Gmail Notifier

In this article, we’ll build a complete system that allows you to blink an LED when you get email or a ton of other such events.

To run the LED, we’ll use the incredibly popular Arduino platform, and to get data from Gmail, we’ll use the all-mighty Ruby along with a computer.

Let’s dive right in!

Arduino

First of all, if you’re not familiar with them already, Arduinos are quite possibly the coolest things since sliced bread (or were, until the Raspberry Pi was released).

Check out this picture:

ArduinoDiecimilaComponents

That board you see there is something like a “little computer”. But, this kind of computer isn’t nearly powerful enough to run something as enormous as Linux – the primary purpose of this “computer” is to drive things like LEDs, motors, sensors etc. Well, what’s the point of that? The magic is that you can program this little computer to manage its resources in certain ways. That means that we’re going to (somehow) program it to blink an LED when a new email arrives.

How on earth do you program it? Well, you connect it up to a computer, and use the Arduino environment (which is based on Processing), which allows you to write code for it.

Secondly, it controls LEDs by turning on and off its “pins”. If you’ve ever seen an “integrated circuit” or a “chip”, you know what those look like.

The Arduino can also communicate via USB – so, your code on the Arduino can send messages back and forth with the computer.

That’s the general concept. The problem is that the Arduino itself can’t access the internet (yes, yes, I know there are Ethernet shields, but those aren’t part of the Arduino) As a result, we have to somehow feed it the data that we must obtain from Gmail (or whatever email you use) in order for it to turn on the LED. That’s where the Ruby comes in.

Ruby

Ruby, as we’ll all agree, is a fantastic and incredibly versatile language. But, controlling an LED with it is very difficult (especially over USB, which is a pretty high-level protocol), so that’s where we use the Arduino.

We’ll use Ruby to do two things. First, get data from Gmail, including the number of unread emails. Second, pass on that information as “blink” or “not blink” to the Arduino.

Ruby has us covered on both these fronts. The “gmail” gem makes it a snap to access the Gmail API, and the “serialport” gem allows us to communicate with the Arduino over USB. Now, let’s dive into the code!

Arduino code

The Arduino code is based on Processing. This language is very similar to Java and if you have any experience with “curly brace languages”, you should pick it up in no time. In fact, as long as you know any programming language, Processing is meant to be easy to learn.

Here’s the bare minimum Arduino program:

void setup() {

}

void loop() {

}

It is fairly clear. There are two methods/procedures, loop and setup. setup is called (usually) only once, and loop is called repeatedly (as long as the Arduino is given power). Obviously, this code doesn’t really do anything. Let’s do an incredibly simple example, with an LED:

void setup() {
  pinMode(11, OUTPUT);
}

void loop() {
  digitalWrite(11, HIGH);
  delay(500);
  digitalWrite(11, LOW);
  delay(500);
}

In order for this to be successful, you need to connect up an LED with the Arduino on pin 11, with the cathode (positive side) on pin 11 and anode (negative side) on ground.

This code is meant to give us a simple blinking LED – it calls a few functions that the Arduino environment gives us (pinMode, digitalWrite) to accomplish this.

In particular, calling pinMode tells the Arduino that we want pin 11 to be an output pin as opposed to an input pin (typically used for sensors, etc.). Then, in the loop method, we call digitalWrite to turn the LED on and off by setting the pin to high and low (around 5v and around 0v).

But, for our overall project (which, again, is to build a GMail notifier) to work, we need to communicate with the computer. We do this with Serial:

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("RubySource");
}

The confusing line might be the Serial.begin one. It basically sets something called the “baud rate” to 9600 – what that means exactly isn’t really all that important, you just need to know that both the computer and the Arduino must agree on the baud rate. This code repeatedly sends the line “RubySourcen” to the computer over USB. How do you view these messages? If you upload the code to the Arduino, you can click on the “serial monitor” icon at the top right of the Arduino environment in order to see the Arduino talking to you!

Alrighty, you can send stuff on USB to the Arduino. How about receiving?

void setup() {
  Serial.begin(9600);
}

void loop() {
  if(Serial.available() > 0) {
    byte byte_read = Serial.read();
    Serial.print("Got: ");
    Serial.print((char)byte_read);
    Serial.print("n");
  }
}

This time, we’re using the Serial.available and Serial.read functions. They’re both quite simple; the former returns a positive number if bytes are available to be read, the latter reads a single byte (or character, usually) from the stream coming to Arduino.

Awesome, so, now we can read stuff from Serial and blink an LED. We have the parts down, let’s get all the Arduino code working:

void setup() {
  Serial.begin(1200);

  //Set pin 11 to be output pin (connect LED here)
  pinMode(11, OUTPUT);

  //set pin 11 to be high initially; LED is usually on, but, not blinking
  digitalWrite(11, HIGH);
}

//this procedure is called if we need to blink the LED
void blink_led() {

  //we can't just blink it once, because that wouldn't be noticeable
  //so, we blink it three times
  for(int i = 0; i<10; i++) {
    digitalWrite(11, HIGH);
    delay(100);
    digitalWrite(11, LOW);
    delay(100);
  }

  //reset the LED back to just on, not blinking
  digitalWrite(11, HIGH);
}

//this function is called when we get a character
//over USB/Serial
void got_char(char x) {

  //if we get b over Serial
  if(x == 'b') {
    //... blink the LED
    blink_led();
  }
}

void loop() {
  //check if there's any data available on serial
  if(Serial.available() > 0) {
    //if there is, we read it
    byte byte_read = Serial.read();

    //and call "got_char"
    got_char((char)byte_read);
  }
}

There we go! The code is very straightforward, with a few interesting notes. First of all, I decided that the LED should, by default, be on. This means that we can tell if the system has power or not (never mind that the Arduino already has a power LED – LEDs look cool!) so we turn it on during setup.

Second, within blink_led(), we can’t just blink the LED once, because nobody would notice that. Thus, we blink it ten times!

The function of this code is that when the Arduino receives the letter “b” over Serial, it blinks the LED ten times.

Awesome! Now, let’s get into the Ruby code, which communicates with the Internet!

Ruby code

When I first started to map out the project, I thought that the Ruby would be annoyingly difficult because most APIs are always irritating in someway or another.

But, then, I realized that we have the awesome “gmail” gem! Download it immediately:

gem install gmail

We’ll also need something with which we can access and communicate on the USB port with the Arduino. For that, we can use the “serialport” gem:

gem install serialport

Let’s first use the serialport to get a feel for it.

#This code sends a "b" over Serial every 4 seconds
#That means that the LED connected to the Arduino
#will blink every four seconds.

require 'serialport'

#this *will* be different for you
#You need to find out what port your arduino is on
#and also what the corresponding file is on /dev
#You can do this by looking at the bottom right of the Arduino
#environment which tells you what the path.

#this must be same as the baud rate set on the Arduino
#with Serial.begin
baud_rate = 9600

data_bits = 8
stop_bits = 1
parity = SerialPort::NONE

#create a SerialPort object using each of the bits of information
port = SerialPort.new(port_file, baud_rate, data_bits, stop_bits, parity)

wait_time = 4

#for an infinite amount of time
loop do
  port.write "b"

  #wait a little bit before we send the next one
  sleep wait_time
end

We set a few variables (such as baud rate and things called “data bits” and “stop_bits”) and then we are able to communicate with the Arduino.

The most important point to notice is that the port_file variable will be different for you – you have to check what it is using the Arduino environment. If you look at the bottom left corner, you can note the a path that starts with “/dev/”, copy that path into port_file and you should be ready to go!

Once we do that, running code should blink the LED every 4 seconds. Awesome!

Now, let’s add in the gmail gem to watch it all come together:

require 'serialport'
require 'gmail'

#plug in your username and password here
gmail = Gmail.connect("username", "password")

#count the number of unread messages
prev_unread = gmail.inbox.count(:unread)

#this *will* be different for you
#You need to find out what port your arduino is on
#and also what the corresponding file is on /dev
#You can do this by looking at the bottom right of the Arduino
#environment which tells you what the path.
port_file = '/dev/cu.uart'

#this must be same as the baud rate set on the Arduino
#with Serial.begin
baud_rate = 9600

data_bits = 8
stop_bits = 1
parity = SerialPort::NONE

#create a SerialPort object using each of the bits of information
port = SerialPort.new(port_file, baud_rate, data_bits, stop_bits, parity)

wait_time = 4

#for an infinite amount of time
loop do
  #get the number of unread messages in the inbox
  unread = gmail.inbox.count(:unread)

  #lets us know that we've checked the unread messages
  puts "Checked unread."

  #check if the number of unread messages has increased
  #if so, we have a new email! So, blink the LED.
  if unread > prev_unread
    port.write "b"
  end

  #reset the number of unread emails
  prev_unread = unread

  #wait before we make another request to the Gmail servers
  sleep wait_time
end

The code isn’t the most elegant, but it does the job and does it clearly (especially in a tutorial, I think clarity is more important than brevity.)

If you run this, and send yourself an email, you should see the LED blinking! How does it work? It keeps checking the number of unread emails, and if that increases, it blinks the LED. Awesome, right?

Extending it

We’ve completed our project. We built a GMail notifier with an LED. But, is that all we can do with our code?

Absolutely not. First of all, GMail need not be our only source of data. Maybe you can blink the LED (and keep blinking it) if there’s going to be rain tomorrow. Or, maybe when you have a message on Reddit. Or if there’s a new article on RubySource (I like this one). The Arduino code need not change at all, and most of the Ruby code stays the same, too, because all we are changing is the data and our intrepretation of it!

There’s many other directions you can go from here. You could build a notifier system with several LEDs and different data sources that distracts you even more than Reddit and Hacker News already do! With this article, you can now interface the Arduino with Ruby, and therefore, the internet with real-world objects. There’s quite literally a bazillion things you can do (not just with switching around data sources, of course) and you should definitely try more of them!

Wrapping it up

I hope you enjoyed this article about using the Arduino with Ruby. If you actually built the email notifier, give yourself a pat on the back – that’s a pretty cool thing to accomplish! If you have any other ideas, comments and suggestions, drop a comment!

Tweets greatly appreciated :)

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • arjun

    good article.

  • http://plainhunter.com Bill Bolte

    I’ve always wanted to play around with one of these. And using Ruby on top of that. Thanks for the write up.