Introduction: Use Twitter and Weather to Post Notes and Temperature to Office Door
Synopsis
========
The goal of this project is to use a Twitter account to send
notes to your office door, which is equipped with a 20x4 LCD
(display). This project presents basically an implementation of
the idea discussed in this IEEE Spectrum article:
http://spectrum.ieee.org/geek-life/hands-on/send-a-tweet-to-your-office-door
As an enhancement, it also displays the current temperature (read in
from weather.gov) in a given location. The implementation is based on
the combination of an Arduino Uno board with an Arduino Ethernet
Shield. The total cost is roughly $120. It is assumed that you
are familiar with Arduino tools.
Hardware and software
=====================
Hardware
--------
$45.95 - Arduino Ethernet Shield: http://www.sparkfun.com/products/9026
$29.95 - Arduino Uno: http://www.sparkfun.com/products/9950
$14.95 - 20x4 LCD White on Blue: http://www.hacktronics.com/LCDs/20-x-4-LCD-White-on-Blue/flypage.tpl.html (could get similar from sparkfun.com to minimize shipping costs)
$11.95 - Arduino Project Enclosure: http://www.sparkfun.com/products/10088 (hosts both the board and the shield)
$3.95 - USB Cable A to B - 6 Foot: http://www.sparkfun.com/products/512 (optional; you should have one already)
$2.99 - 9 Conductor 24 AWG Stranded-Shielded 6FT: http://www.frys.com/product/3550794?site=sr:SEARCH:MAIN_RSLT_PG (to hook-up the LCD display to the board)
$2.99 - 3FT CAT6 Patch Cable: http://www.frys.com/product/5979924?site=sr:SEARCH:MAIN_RSLT_PG (to hook-up the board to your Internet router)
$1.90 - 6 Pin Right Angle Female Header: http://www.sparkfun.com/products/9429 (two of them; for LCD connection)
$1.90 - Project Box: http://www.futurlec.com/ProjectBoxes.shtml (for display)
--------------
$116.53 - TOTAL
Software
--------
-- Arduino sketch: included at the end of this instructable. The sketch
must be changed to meet your individual specifications. It contains
comments with description of each change and how it may be done.
-- You will need to compile and load the sketch to the board with Arduino tools: http://arduino.cc/en/Main/Software
In order to be able to compile it you will also need the following libraries for your Arduino tools:
-- Arduino EthernetDHCP: http://gkaindl.com/software/arduino-ethernet/dhcp
-- Text Finder library: http://www.arduino.cc/playground/Code/TextFinder
Arduino sketch: bzdoor2lcd.pde
------------------------------
// Get "selected" latest tweet from Twitter account "BZDoor" and display it on the
// LCD display, which I have fixed on my office door. By selected I mean tweets that
// start with the key "BZD" only. I use the Twitter account to post notes on my
// office door about office hours, being out for coffee, etc. :-)
//
// The circuit:
// LCD pins 1,3,5,16 to Arduino digital pin GND
// LCD pin 2 to Arduino digital pin +5V
// LCD pin 15 via Resitor 330 Ohms to Arduino digital pin +5V
// LCD pin 14 to Arduino digital pin 2
// LCD pin 13 to Arduino digital pin 3
// LCD pin 12 to Arduino digital pin 4
// LCD pin 11 to Arduino digital pin 5
// LCD pin 4 to Arduino digital pin 9
// LCD pin 6 to Arduino digital pin 8
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetDHCP.h>
#include <TextFinder.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 8, 5, 4, 3, 2);
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x4F, 0x8A };
byte ip[] = { 192,168,1,177 };
byte server[] = { 199,59,148,10 }; // twitter.com
byte server_weather[] = { 140,90,113,200 }; // weather.gov
#define NUM_CHAR_USERNAME 7 // "BZDoor:" is username with 6 characters + :
#define TWEET_OFFSET NUM_CHAR_USERNAME + 5 // useful info from tweet to be displayed appears after "BZDoor: BZD "
char tweet[NUM_CHAR_USERNAME + 140]; // 147 = "BZDoor:" + 140 for actual tweet
char old_tweet[] = { "BZDoor: BZD No updates. Have a nice day! Current temp: NA Cris " };
char temperature[8];
Client client(server, 80);
TextFinder finder(client);
Client client_weather(server_weather, 80);
TextFinder finder_weather(client_weather);
void setup()
{
lcd.begin(4,20);
lcd.clear();
lcd.print("BZDoor2LCD");
Serial.begin(9600);
Serial.println("BZDoor2LCD");
Ethernet.begin(mac, ip);
}
void loop()
{
// (1) check if new tweet is present in BZDoor account;
check_for_new_valid_tweet();
// (2) check for temperature; also display signature;
check_for_new_temperature();
// (3) clean up;
client.stop();
client.flush();
client_weather.stop();
client_weather.flush();
// (4) also clear the "tweet" storage array; otherwise if latest tweet is shorter
// than the previous one, remnants from the previous will become part of the latest;
for ( int i=0; i<NUM_CHAR_USERNAME+140; i++) tweet[i] = ' ';
// (5) delay 2 minutes before next update;
delay(120000);
}
void check_for_new_valid_tweet() {
// responsible with 1st and 2nd rows of the 4x20 LCD;
// connect to Twitter (RSS of user BZDoor: 316663659) and get the latest tweet;
// this check will be done every other 2 minutes, so if more tweets have been posted
// have been posted within these 2 minutes only the latest tweet will be processed;
if ( client.connect()) {
client.println("GET http://www.twitter.com/statuses/user_timeline/316663659.rss HTTP/1.0"); // BZDoor;
client.println();
} else {
lcd.setCursor(0,0); lcd.print( "Twitter connection ");
lcd.setCursor(0,1); lcd.print( "failed! ");
Serial.println("Twitter connection failed.");
}
if ( client.connected()) {
// get the last tweet in BZDoor's account by simply parsing the item and title tags;
if ( (finder.find("<item>") && (finder.getString("<title>","</title>",tweet,140)!=0)) ) {
// only tweets that start with the three characters "BZD" will be displayed
// on the LCD display on the office door; all others will be printed only to
// the Arduino's serial monitor
Serial.println(tweet);
// a regular tweet in BZDoor's account is always in one of two formats:
// 1) "BZDoor: This is a Hello World! tweet!", which is not displayed on LCD;
// 2) "BZDoor: BZD Some update", which is displayed on LCD because starts with key BZD;
if ( tweet[8] == 'B' && tweet[9] == 'Z' && tweet[10] == 'D') {
// this is a tweet that has an update from BZDoor to be displayed on the office door;
display_tweet(tweet);
// also copy this latest twit to old_tweet array;
strncpy(old_tweet, tweet, 80+TWEET_OFFSET);
} else {
display_tweet(old_tweet); // first time this says no new updates;
}
} else {
lcd.setCursor(0,0); lcd.print( "Could not find item ");
lcd.setCursor(0,1); lcd.print( "field in last twit ");
Serial.println("Could not find item field in last twit");
}
} else {
lcd.setCursor(0,0); lcd.print( "Disconnected from ");
lcd.setCursor(0,1); lcd.print( "twitter ");
Serial.println("Disconnected from twitter");
}
}
void display_tweet( char msg[]) {
// display only 40 characters on the first two rows of the
// 20x4 LCD display; the third and fourth rows are used for
// temperature and signature display;
lcd.clear();
// display tweet's first 40 chars;
lcd.setCursor(0,0);
for ( int i=TWEET_OFFSET; i<TWEET_OFFSET+20; i++) {
if (msg[i] != 0) lcd.print(msg[i]);
else lcd.print(' ');
}
lcd.setCursor(0,1);
for ( int i=TWEET_OFFSET+20; i<TWEET_OFFSET+40; i++) {
if (msg[i] != 0) lcd.print(msg[i]);
else lcd.print(' ');
}
// print also to serial monitor;
char buffer_row[20];
strncpy( buffer_row, msg+TWEET_OFFSET, 20); buffer_row[20] = '\0';
Serial.println(buffer_row);
strncpy( buffer_row, msg+TWEET_OFFSET+20, 20); buffer_row[20] = '\0';
Serial.println(buffer_row);
}
void check_for_new_temperature() {
// responsible with 3rd and 4th rows of the 4x20 LCD;
// connect to www.weather.gov and get temperature for Fargo airport;
if ( client_weather.connect()) {
client_weather.println("GET /xml/current_obs/KFAR.xml HTTP/1.0");
client_weather.println();
} else {
lcd.setCursor(0,2); lcd.print( "Weather connection ");
lcd.setCursor(0,3); lcd.print( "failed! ");
Serial.println("Weather connection failed.");
}
if ( client_weather.connected()) {
if ( (finder_weather.getString("<temp_f>","</temp_f>",temperature,8)!=0) ) {
lcd.setCursor(0,2);
lcd.print("Curr temp: "); lcd.print(temperature); lcd.print(" F");
lcd.setCursor(0,3); lcd.print("Cris ");
// print also to serial monitor
Serial.println("Curr temp: "); Serial.println(temperature); Serial.println(" F");
Serial.println("Cris ");
} else {
lcd.setCursor(0,2); lcd.print("Current temp: NA");
lcd.setCursor(0,3); lcd.print("Cris ");
Serial.println("Couldn't find temp_f in weather stream");
}
} else {
lcd.setCursor(0,2); lcd.print("Current temp: NA");
lcd.setCursor(0,3); lcd.print("Cris ");
Serial.println("Disconnected from weather");
}
}
3 Comments
11 years ago on Introduction
This is an awesome project! And I'm working on it, but can you please specify what was soldered to the LCD and what was connected to the ethernet shield and were? If you can that would help me finish mine. Thank You :D
Reply 11 years ago on Introduction
The provided sketch (or C program) describes the connections, which must
be made to realize the whole system:
// LCD pins 1,3,5,16 to Arduino digital pin GND
// LCD pin 2 to Arduino digital pin +5V
// LCD pin 15 via Resitor 330 Ohms to Arduino digital pin +5V
// LCD pin 14 to Arduino digital pin 2
// LCD pin 13 to Arduino digital pin 3
// LCD pin 12 to Arduino digital pin 4
// LCD pin 11 to Arduino digital pin 5
// LCD pin 4 to Arduino digital pin 9
// LCD pin 6 to Arduino digital pin 8
What is soldered on the back of the LCD is related to the first and third
lines above.
The first line, "// LCD pins 1,3,5,16 to Arduino digital pin GND",
says that pins 1,3,5, and 16 of the LCD are connected to the GND pin
of the Arduino board. To realize that I soldered short wires on the
back of the LCD to basically sort-circuit these pins. In this way,
I only need one wire - I used the black wire - of the
"9 Conductor 24 AWG" cable to connect to the GND pin of the Arduino
board. Note that the pins' types, names, or numbers of the Arduino board
are the same as for the Ethernet shield, which is fixed on top of the
board. These are clearly marked on the board. Also, the pin numbers
(from 1 to 16) are also clearly marked on the back of the LCD.
The third line: "// LCD pin 15 via Resistor 330 Ohms to Arduino digital pin +5V",
is realized by soldering the resistor on the back of the LCD
between pins 15 and 2. Then, pin 2 of the LCD is connected through
one of the wires of the "9 Conductor 24 AWG" cable - I used the
red wire - to the "digital pin +5V" of the Arduino board (or
more precisely of the Ethernet shield). This is illustrated by
the second line: "LCD pin 2 to Arduino digital pin +5V".
Lastly, to realize the connections of the LCD to the board/shield,
I soldered on the back of the LCD the two "6 Pin Right Angle Female
Header" as indicated in Figure 2. Eight out of the nine available
wires of the "9 Conductor 24 AWG" cable are then inserted into these
headers. The other endings of the same eight wires are inserted into
corresponding headers of the shield. The correspondence between LCD
pins and the board/shield pins is described by the sketch lines above.
I hope this helps to clarify things.
Reply 11 years ago on Introduction
Awesome!! Thank you very much!