Go Old School: Build a Pager Using Arduino, Node.js and Twilio

November 24, 2014
Written by

tumblr_mcsiv1h4lx1rk9ouwo1_1280

I remember when I got my first mobile device… a pager. Like many kids who grew up in the ‘90s I wore that pager proudly on my belt. Over a decade later I still miss getting a “911” message from one of my friends and rushing home to call and see what happened. In case you’re wondering, most often I got those messages when someone had gotten a sick new Magic the Gathering card or heard the new Get Up Kids single on the radio. Lately, I’ve been feeling particularly nostalgic. I started wondering if I could recreate that glorious device using hardware I have laying around my house. Thanks to the power of Arduino I did it! Today I’m going to show you how to build your very own pager using Arduino and Twilio.

Our Tools

In order to build our super rad new pager we’re going to need a few supplies:

  • Arduino Uno – The Uno is one of the most popular microcontrollers around and we’ll be using it for our project.
  • Grove Base Shield – This shield will make it a bit easier for us to wire up our LCD.
  • Grove RGB LCD – We’ll use this to display incoming messages.
  • Arduino IDE – You’ll be using this to write the code that will run on the Arduino.
  • Node.js running on your local machine
  • Twilio Account – sign up for free!

Hello Hardware

Let’s start by assembling our hardware and displaying a hello world message on our LCD screen. First, plug the grove baseboard into your arduino:

Wire the I2C connection to your LCD:

Plug your Arduino into your computer via the USB port and launch the Arduino IDE. Use the example Hello World code provided for the LCD:
#include <Wire.h>
#include "rgb_lcd.h"

rgb_lcd lcd;

const int colorR = 255;
const int colorG = 0;
const int colorB = 0;

void setup()
{

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  lcd.setRGB(colorR, colorG, colorB);

  // Print a message to the LCD.
  lcd.print("hello, world!");
  delay(1000);
}

void loop()
{
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);

  // print the number of seconds since reset:
  lcd.print(millis()/1000);
  delay(100);
}

Before we can run this code we need to add the rgb_lcd library to our local setup. Once you pull down the code from github go to Sketch => Import Library => Add Library in the IDE. Select the folder where you saved your code and you should be all set. Now that we’re ready to run our code, we’ll need to make sure we’ve selected our Arduino Uno in the IDE. Go to Tools => Serial Port and pick the port that starts /dev/tty.usbmodem. Make note of this port, we’ll be using it a bit later when we set up our NodeJs app. Once you’ve selected the correct port you can upload your code to the Arduino by clicking the upload button. Beautiful! We’ve got a message displaying and we’re changing the color of the LCD. Why don’t you try changing the message and setting a different color before we move forward?

Receiving Our Messages

Now that we have a message displaying on our LCD we need to build a small node.js app in order to pass the message coming in from a text message. Hop into terminal and let’s install our dependencies:

npm install express body-parser twilio serialport

Now we can create a new file in our favorite text editor (I’ll be using vim) called app.js. At the very start of our file we’ll make sure we require all the modules we’ll be using:

var twilio = require('twilio'),
    SerialPort = require("serialport").SerialPort,
    express = require('express'),
    bodyParser = require('body-parser');

Now we can initialize our serial connection:

var serialPort = new SerialPort("/dev/tty.usbmodem1421", {
  baudrate: 9600
});

Remember that port info I mentioned to take note of when we set up our Arduino Uno? Use this information when you initialize your SerialPort. We can now start laying the foundation for our express app:

var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

If you haven’t used express, it’s a great framework for building apps in NodeJS. Above we’re initializing a new express app and using the bodyParser middleware to help us easily read the information we’ll get from Twilio. Now we can create a new route called /sms that  Twilio will POST to when we get a text message:

app.post('/sms', function(req, res){
  serialPort.write(req.body.Body, function(err, results) {
    if (err) {
      console.log('err ' + err);
    }
    console.log('results ' + results);
  });

  var resp = new twilio.TwimlResponse();
  resp.message(function() {
    this.body('Thanks for paging me. You can also find me on twitter @rickyrobinett')
    .media('http://media.giphy.com/media/y3ADSTHiLwhEs/giphy.gif');
  });
  res.type('text/xml');
  res.send(resp.toString());
});

In this code we’re doing two key things:

  1. Writing to our serialPort with the Body parameter (the body of the incoming text message) passed by Twilio in the POST request.
  2. Responding to the request with some TwiML to let the person paging us know that we got the message.

If you’re in the US or Canada we want to make this an MMS message and send an awesome animated gif. If you currently can’t send MMS with Twilio just remove the .media function call. Finally, let’s open our serial connection and start our HTTP server:

serialPort.open( function () {
  app.listen(3000);
  console.log('Listening on port 3000');
});

Twilio needs to POST to a URL that is available to the outside world. Since we’re running locally we’ll use ngrok to expose our localhost to the outside world. Follow the instructions to install ngrok and then kick it off like this:

ngrok 3000

Now we can log into our Twilio account and set the Message Request URL to our sms route via ngrok:

Try the app out by texting into your new Twilio number and you’ll get the response back.

Displaying Our Messages

We’re now passing our message to the arduino. The next step is to write the code that examines that message and displays it on our LCD. Let’s lay the foundation for our app:

#include <Wire.h>
#include "rgb_lcd.h"

rgb_lcd lcd;

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

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setCursor(0, 1);

  // Print a message to the LCD.
  lcd.print("Ricky's Pager");
  delay(1000);
}

void loop() {
}

This code looks very similar to our hello world code. We’re setting up our LCD with an initial message. Now we can update our loop function so that we can get the content we pass from our node app:

void loop() {
  // Receive data from Node and write it to a String
  String content = "";

  while (Serial.available()) {
    lcd.clear();
    char character = (char)Serial.read();
    content.concat(character);
  }

Breaking down this code, we check to see if the Serial is available (this means we’ve opened the connection from our node code). While the Serial is available we pull each character being passed through and use it to build our string. Once we’ve retrieved all the content we update our LCD to display it:

if(content != "") {
    lcd.setCursor(0, 1);
    lcd.print(content);
    content = "";
  }
}

Fire up your app and give it a try. Try texting a simple “Hello World” and see it in action. Now that we’re displaying the message let’s have some real fun. What if we change the color of the LCD when a new message comes in? We can do that pretty easily by adding this code when we set our new message:

if(content != "") {
  lcd.setRGB(random(255), random(255), random(255));
  lcd.setCursor(0, 1);
  lcd.print(content);
  content = "";
}

Re-upload your app to your arduino and send a text to your Twilio number. The screen should change colors each time you get a new message. This is looking great but there’s one more cool feature I want to show you how to implement. What happens if the message someone sends in is too long? We can write some code that scrolls based on content length:

void loop() {
  // Receive data from NodeJS and write it to a String
  String content = "";

  for (int positionCounter = 0; positionCounter < 16; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft();
    // wait a bit:
    delay(150);
  }

  while (Serial.available()) {
    lcd.clear();
    char character = (char)Serial.read();
    content.concat(character);
  }

  if(content != "") {
    lcd.setRGB(random(255), random(255), random(255));
    lcd.setCursor(0, 1);
    lcd.print(content);
    content = "";
  }
}

If you’re wondering about that magic “16” number, we use that to scroll to the size of our screen. Now text in something longer (like “Brrrooookkklllynn”) to see how the scrolling works.

Party Like It’s 1998

We’ve now built our very own pager with Arduino and Twilio. You can find the full code for this project on github. This pager may not be as portable as we need but it was still a fun project. There are a lot of improvements you can make if you’re feeling eager to take your pager to the next level – add a buzzer so you get an audible indication when a new message comes in, add a Wifi shield so you can take your pager on the go or if want that extra dash of authenticity you can turn an old pager into a case. I am always stoked when I find crazy new things people build with hardware. How are you hacking Twilio + hardware? I’d love to see it: @rickyrobinett or ricky@twilio.com