/* * MODIFIED BY JOHN DINGLEY FROM Twitter2LCD originally written by Fabrizio Granelli See http://www.instructables.com/id/Displaying-Twitter-feed-without-a-PC/ * ALSO USES TUTORIAL FROM THIS WEBSITE: http://tronixstuff.wordpress.com as the basis of the part of code that gets Arduino to send data back to Twitter * Allows twitter messages to display on an LCD display via arduino and ethernet shield. No PC required! * ALSO ALLOWS CONTROL OF 4 DIGITAL OUTPUT PORTS VIA SIMPLE TWITTER MESSAGES * Also allows Arduino to send data back to the twitter user for example sensor data to complete the very-remote control loop * Twitter2LCD * gets xml data from http://twitter.com/statuses/user_timeline/16297873.rss * reads the most recent tweet from field: * writes the output to the LCD. * NOTES (J Dingley): * Set up your twitter account. Choose a username that has 6 (SIX) characters in it, no more and no less. * - To send a text twitter message to be displayed on the arduino-LCD display, just send it as normal. * - To send a DATA message (to turn one of 4 LED's on trhe arduino digital output ports on or off) send a twitter formatted as follows: * a) Start with a capital "D" , this tells the arduino this twitter has data in it which it needs to look for * b) After the "D" , with no spaces enter FOUR digits. These must be 0 or 1. * c) EXAMPLE: the twitter message D0100 will turn on LED 2, D1000 would turn on LED1, D0010 would turn on LED3, D0001 will turn on LED4 * Therefore you can modify this code to turn relays on and off or control anything you like. *NOTE: If you have sent a lot of tweets in this format, twitter may stop you sending them as it thinks "you have already sent this message" * Options are to add a few random letters after your data tweet, such as D0100kjjkh, so it is now different to your previous D0100 data tweets (code only looks at the 4 digits that come after the D) OR in longer term, DELETE your past tweets!! * Set up for SERIAL LCD display, green 4 line display. * Compiles with Arduino 22 and runs ok on an Arduino UNO. *NOTE: the various libraries have to be added as folders to the main libraries folder within your arduino environment */ //LIBRARIES you will need to have in your libraries folder within arduino #if defined(ARDUINO) && ARDUINO > 18 // If using Arduino 0019 or later, include SPI.h #include <SPI.h> #endif //#include <SPI.h> #include <Ethernet.h> #include <EthernetDHCP.h> #include <TextFinder.h> #include <SoftwareSerial.h> #include <EthernetDNS.h> #include <Twitter.h> //Setup of pins as digital outputs (in this case with LED's attached to them, but intention is to use them to control things with) #define LED1Pin 4 #define LED2Pin 5 #define LED3Pin 6 #define LED4Pin 7 #define DelayFlashPin 9 //this pin flashes while arduino is waiting 1 minute before looking for next tweet long randNumber; int analog1; char myStringBuffer[80]; //byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };//default ethernet shield MAC byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x20, 0x3B };//my particular ethernet shield MAC (this number is WRITTEN on a label on the Ethernet Shield) //byte server[] = {128,242,240,20}; // Twitter...I found this did NOT work so googled to find current Twitter server IP byte server[] = {199,59,148,10}; // Twitter server IP address (checked 29/3/11) Twitter twitter("275938231-D93Q2mTtMv3vg4quP25qOe1Lp5eER09ZdHsbibOE"); //this one is my jddat2 twitter "token" as in instructable. //You need to get your own twitter token and insert it here instead of mine //XXXXXXXXXXXXXXXXXXXX HOW TO GET YOUR TWITTER TOKEN? XXXXXXXXXXXXXXXXXXXXXXXXXX //a) Log onto Twitter (www.twitter.com) and set up an account for these data transfers. We shall call this your machine account // from now on. //b) Make sure your username has SIX (6) characters in it else the arduino data reader code below will need to be modified. //c) Then, open this web tutorial: http://tronixstuff.wordpress.com/2011/03/08/moving-forward-with-arduino-%e2%80%93-chapter-30-%e2%80%93-twitter/ //d) It tells you what to do to get a Twitter TOKEN for your "machine account" that you have just set up. //e) Once you have your token, enter it between the " and " in line of code above that starts with Twitter twitter(".............. //XXXXXXXXXXXXXXXXXXXX END OF HOW TO GET YOUR TWITTER TOKEN XXXXXXXXXXXXXXXXXXXXX char tweet[140]; Client client(server, 80); TextFinder finder( client ); //SETUP SOFTWARE SERIAL FOR LCD DISPLAY #define rxlcdprintPin 2 //sets new software rx as pin2, from LCD serial-LCD display usnit #define txlcdprintPin 3 //sets new software tx pin as pin 3 to LCD serial-LCD display usnit SoftwareSerial lcdSerial = SoftwareSerial (rxlcdprintPin, txlcdprintPin); //define lcdSerial as rxlcdprintPin (2) and txlcdprintPin (3) //END OF SOFTWARE SERIAL LCD DISPLAY SETUP void setup() { Serial.begin(9600); delay(100); //FOR LCD DISPLAY pinMode (rxlcdprintPin, INPUT); pinMode (txlcdprintPin, OUTPUT); lcdSerial.begin(9600);// LCD serial out //end of LCD setup //For digital output pins (with LEDS on them, pins 4 5 6 7, also 13 which flashes as the one minute counter counts down) pinMode(LED1Pin,OUTPUT); pinMode(LED2Pin,OUTPUT); pinMode(LED3Pin,OUTPUT); pinMode(LED4Pin,OUTPUT); pinMode(DelayFlashPin,OUTPUT); Serial.println("Twitter2LCD"); delay(50); //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX lcdSerial.print(19, BYTE); //backlight on delay(50); lcdSerial.print(12, BYTE); //clears screen delay(50); lcdSerial.print("Twitter to LCD"); //lcd text lcdSerial.print(13, BYTE); //newline lcdSerial.print("and 4 control LED's"); //lcd text delay(50); lcdSerial.print(13, BYTE); //newline lcdSerial.print("J.Dingley V1.1"); //lcd text //lcdSerial.print(13, BYTE); //newline delay(500); //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX randomSeed(analogRead(0)); //reads analog port 0 which must have nothing connected to it as a seed for the random number generator EthernetDHCP.begin(mac); } void loop() { //lcd.clear(); if (client.connect()) { //XXXXXXXXXXXXXXX CHANGE THE 9 DIGITS IN STATEMENT BELOW TO THOSE OF YOUR OWN TWITTER RSS feed xxxxxxxxxxxxxxxxxxxxxxx //XXXXXXXXXXXXXXX My instructable tells you how to get your twitter RSS feed number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX client.println("GET http://www.twitter.com/statuses/user_timeline/275938231.rss HTTP/1.0"); // twitter rss for jddat2 client.println(); } else { Serial.println("Connection failed"); delay(200); //XXXXXXXXXXX Display XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX lcdSerial.print(12, BYTE); //clears screen delay(50); lcdSerial.print("Connection"); //lcd text lcdSerial.print(13, BYTE); //newline lcdSerial.print("FAILED"); //lcd text delay(500); //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } if (client.connected()) { // get the last tweet by simply parsing the item and title tags if((finder.find("<item>")&&(finder.getString("<title>","",tweet,140)!=0))) { Serial.println(tweet); delay(100); //XXXXXXXXXXXX Display XXXXXXXXXXXXXXXXXXXXXXXXXXXXX lcdSerial.print(12, BYTE); //clears screen delay(200); lcdSerial.print("tweet coming"); //lcd tweet text //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX delay(500); } else { Serial.println("Could not find item field"); delay(100); //XXXXXXXXXXXXX Display XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX lcdSerial.print(12, BYTE); //clears screen delay(50); lcdSerial.print("Could not find"); //lcd text lcdSerial.print(13, BYTE); //newline lcdSerial.print("item field"); //lcd text //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } } else { Serial.println("Disconnected"); delay(100); lcdSerial.print(12, BYTE); //clears screen delay(50); lcdSerial.print("Disconnected"); //lcd text } client.stop(); client.flush(); /* //XXXXXXXXXXXXX LED control debugging your data read (LED/output pin controller) tweet routine XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Serial.println("LED control routine"); Serial.print("Last Tweet:"); Serial.print(tweet); Serial.print("character at position 8 is:"); //if your username has 6 characters, then position 8 in the tweet should be the letter "D" you used at start of this data-tweet Serial.println(tweet[8]); Serial.print("character at position 9 is:"); //if your username has 6 characters, then position 9 in the tweet should be the first of the 4 control digits (0 or 1)after the "D" Serial.println(tweet[9]); Serial.print("character at position 10 is:");//if your username has 6 characters, then position 10 in the tweet should be the second of the 4 digits after the "D" Serial.println(tweet[10]); Serial.print("character at position 11 is:");//if your username has 6 characters, then position 11 in the tweet should be the third of the 4 digits after the "D" Serial.println(tweet[11]); Serial.print("character at position 12 is:");//if your username has 6 characters, then position 12 in the tweet should be the fourth of the 4 digits after the "D" Serial.println(tweet[12]); */ if (tweet[8] == 68){ //i.e. if character at position 8 of your tweet, where first position is position 0 (zero), is 68 (a capital letter "D" in your tweet //..indicating that the next 4 characters you type will be DATA to the 4 LEDS (i.e. 0's or 1's) then we have a DATA tweet.... //if no "D" as first letter of your tweet (after your automatic username) then it will assume we have a TEXT tweet and just display it but //not use it to alter LED outputs i.e not alter any control pin outputs on the arduino, it will leave them as they were until next data tweet comes along Serial.println("DATA TWEET COMING"); lcdSerial.print(12, BYTE); //clears screen lcdSerial.print("DATA TWEET COMING"); //lcd tweet text delay(2000); lcdSerial.print(12, BYTE); //clears screen lcdSerial.print(" DATA TWEET...."); //lcd tweet text lcdSerial.print(13, BYTE); //newline delay(200); lcdSerial.print(tweet); //lcd tweet text lcdSerial.print(13, BYTE); //newline if (tweet[9] == 49){ //i.e. if character at position 8 of your tweet, where first position is position 0 (zero), is 49 (a number 1 in your tweet) then.... Serial.print("LED Pin 4: ON "); lcdSerial.print("Pin4 ON "); digitalWrite(LED1Pin, HIGH); // Activate LED1 (i.e, digital output pin 4) } else { Serial.print("LED Pin 4: OFF "); lcdSerial.print("Pin4 OFF "); digitalWrite(LED1Pin, LOW); // De-ctivate LED1 (i.e, digital output pin 4) } if (tweet[10] == 49){ Serial.print("LED Pin 5: ON "); lcdSerial.print("Pin5 ON"); digitalWrite(LED2Pin, HIGH); // Activate LED2 (i.e, digital output pin 5) } else {Serial.print("LED Pin 5: OFF "); lcdSerial.print("Pin5 OFF"); digitalWrite(LED2Pin, LOW); // De-activate LED2 (i.e, digital output pin 5) } lcdSerial.print(13, BYTE); //newline if (tweet[11] == 49){ Serial.print("LED Pin 6: ON "); lcdSerial.print("Pin6 ON "); digitalWrite(LED3Pin, HIGH); // Activate LED3 (i.e, digital output pin 6) } else {Serial.print("LED Pin 6: OFF "); lcdSerial.print("Pin6 OFF "); digitalWrite(LED3Pin, LOW); // De-activate LED3 (i.e, digital output pin 6) } if (tweet[12] == 49){ Serial.println("LED Pin 7: ON"); lcdSerial.print("Pin7 ON"); digitalWrite(LED4Pin, HIGH); // Activate LED4 (i.e, digital output pin 7) } else {Serial.println("LED Pin 7: OFF"); lcdSerial.print("Pin7 OFF"); digitalWrite(LED4Pin, LOW); // De-activate LED4 (i.e, digital output pin 7) } } //end of check for a data tweet //XXXXXXXXXXXXXXXXXXXX else if text tweet (no data)just send it to LCD screen and leave LEDS as they were since last data text //REMEMBER, IF YOU START YOUR TEXT TWEETS WITH A LETTER "D" IT SHOULD BE OK AS DATA READER SEES THE D THEN LOOKS FOR "1" VALUES TO TURN ON LEDS WITH //IF IT DOES NOT SEE A "1" IT DEFAULTS THE LED STATUS TO OFF. SO PROBABLY OK MOST OF THE TIME TO START SOME TEXT TWEETS WITH A "D" IF YOU REALLY MUST! else { //XXXXXXXXXXXXXXXXput text tweet onto LCD XXXXXXXXXXXXXXXXXXXXXXXXX lcdSerial.print(12, BYTE); //clears screen Serial.println("TEXT TWEET COMING"); lcdSerial.print("TEXT TWEET COMING"); //lcd tweet text delay(2000); lcdSerial.print(12, BYTE); //clears screen delay(200); Serial.print(tweet); //Serial viewer lcdSerial.print(tweet); //lcd tweet text //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } transmittweet1 (); //send a data tweet to twitter (you could write different versions of transmittweet for different parameters, sent at different time intervals) //60 SECOND DELAY BEFORE LOOKING FOR NEXT TWEET. ALTER THIS TO SUIT YOUR REQUIREMENTS. for (int j=0; j<60; j++) { digitalWrite(DelayFlashPin, HIGH); // Activate Pin 9 LED so you know it is counting down 1 min not just crashed! delay(300); // delay 0.3 second digitalWrite(DelayFlashPin, LOW); // De-activate Pin 9 LED built into arduino board so it flashes on and off delay(700); // delay 0.7 second } } void transmittweet1 (){ //XXXXXXXXXXXXXXXXXXXXXXXXXXXX TRANSMIT A TWEET SECTION xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx //XXXX THIS IS WHERE THE ARDUINO TAKES A MEASUREMENT FROM A SENSOR FOR EXAMPLE AND TWEETS THE VALUE TO MY TWITTER PAGE XXXXXXXXXX // THE TWEET HAS A 4 DIGIT RANDOM NUMBER ATTACHED TO THE END OF IT SO THAT IF THE DATA READING SENT HAS SAME VALUE AS AN EARLIER TWEET //TWITTER WILL STILL ACCEPT IT (TWIITER TENDS TO BLOCK REPEAT IDENTICAL MESSAGES OTHERWISE) // Ethernet Shield Settings // Alter ip, gateway and subnet to suit your own network! byte ip[] = { 192,168,0,77}; // choose your own IP for ethernet shield - this one should work though as it stands byte gateway[] = { 192,168,0,1 }; // insert your network gateway here byte subnet[] = { 255, 255, 255, 0 }; // insert your network subnet address here (Instructable shows you how to do this) //XXXXXXXXXXXXXXXXXX How to find your gateway and subnet ? (leave the ip[] above alone)XXXXXXXXXXXXXXXXX //Probably easier ways to do this but this is what I did: //Open this website: http://portforward.com/help/setup_static_ip_address.htm //Download their software called PF Setup Static IP Address //Run the program, a window will open displaying properties of your system, in particular your router //DO NOT ALTER ANYTHING, JUST LOOK AT THE VALUES AND WRITE THEM DOWN, they include your router ip address, the gateway address and the subnet mask //Close program down, you can delete it later. Not needed again //XXXXXXXXXXXXXXXXX End of how to find your gateway address and subnet mask XXXXXXXXXXXXXXXXXXXXXXXXXXXX delay(5000); Ethernet.begin(mac, ip, gateway, subnet); delay(1000); BufferClear (); //clears myStringBuffer NOTE: buffer has 80 characters at present as max length strcat(myStringBuffer, "Sent to twitter: Analog Pin 1 reading = ["); //adds this to start of myStringBuffer analog1=(analogRead(1)); //reads analog port 1 char measurement1buffer[7]; itoa (analog1,measurement1buffer,10);//converts measured value (0-1023) to a char string. strcat(myStringBuffer, measurement1buffer); //adds this measurement1buffer to my string buffer strcat(myStringBuffer, "] "); //adds this to end of the data value we have just added to the myStringBuffer, the next 4 digits will just be the random ones to be ignored getrandomnumber(); char endbuffer [8]; itoa (randNumber,endbuffer,10); //converts random number into same number but in a char string with ?? a terminal null added strcat(myStringBuffer, endbuffer); //adds this randomly generated 4 digit endbuffer to my string buffer so twitter accepts //and displays new measurements even if they are the same as previous ones!! sendtweet(myStringBuffer); //send the completed tweet text with the 4 digit random number tacked on the end //xxxxxxxxxxxxxxxxxxxxxxxxx END OF TRANSMIT A TWEET function XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } void sendtweet(char msg[]) { Serial.println("connecting ..."); if (twitter.post(msg)) { // Specify &Serial to output received response to Serial. // If no output is required, you can just omit the argument, e.g. // int status = twitter.wait(); int status = twitter.wait(&Serial); if (status == 200) { Serial.println("OK."); } else { Serial.print("failed : code "); Serial.println(status); } } else { Serial.println("connection failed."); } } //string manipulation function for adding each new letter to the existing sentence string void strcat(char* original, char appended) { while (*original++) ; *original++ = appended; if (appended) *original = '\0'; } void BufferClear (){ //to clear the character string ready for a new sentence when "new" is clicked on the screen for (int k = 1;k <= 80;k++){ myStringBuffer[k - 1] = 0; // blank buffer content with null characters } } void getrandomnumber() { // print a random number from 0 to 299 //randNumber = random(300); //Serial.println(randNumber); // print a random number from 1000 to 9999 randNumber = random(1, 9999); Serial.println(randNumber); delay(50); }