Project 49 – Twitterbot

Again you will use the circuit with the two temperature sensors. This time you will send regular updates about the status of the two sensors to Twitter. This will give you a simple system for checking on the status of any sensors you have connected to the Arduino.

Twitter is a microblogging service that allows you to send miniature blog posts or “tweets” of up to 140 characters in length. The tweets are publically accessible to anyone who does a search or to those persons who have chosen to subscribe to (or follow) your blog. Twitter is incredibly popular and can be accessed from any web browser or from one of the many Twitter clients that are available, including mobile phone apps. This makes it ideal for sending simple short pieces of information that you can check while on the move.

You will need to go to Twitter.com and create a new account. I recommend creating an account just for tweeting from your Arduino.

As of August 31,2010, Twitter changed its policy regarding third party apps accessing the website. An authentication method known as OAuth is now used that makes it very difficult to tweet directly from an Arduino; prior to this change it was an easy process. Tweeting, at the moment, can only be done via a third party. In other words, you sending the tweet to a website, or proxy, that will tweet on your behalf using the OAuth token (authorization code). The current Twitter library uses this method.

Once you have your account set up, enter the code below.

Enter the Code

At the time this book was written, the Ethernet libraries that the Twitter library relies on currently only work with the Arduino IDE version 0018. You will therefore need to visit the Arduino website, navigate to the download page, and obtain the IDE version 0018. Make sure you only run and upload the code from this version of the IDE. Keep it separate from your current version of the IDE. The EthernetDNS and EthernetDHCP libraries that are used by the Twitter library can be found at http://gkaindl.com/software/arduino-ethernet. Once this library has been updated to work with the latest IDE you can use it instead.

Before you upload the code, you will need a token for the Twitter account. The library you are using has been created by NeoCat and uses his website as a proxy for sending the tweet. This means you must first obtain a token, which is an encrypted version of your username and password, to access the Twitter website. To do this visit NeoCat's website at http://arduino-tweet.appspot.com and click on the “Step 1” link to obtain the token. Copy and paste this into the token section of the code.

Note that because you are using a proxy and have to give your Twitter username and password over to obtain the token, it is advisable to create a new twitter account and keep it anonymous (i.e. don't add any names or e-mail addresses into the Twitter profile of that account). I am sure that it is perfectly safe to use the library with your own account if you wish, but it is better to be safe than sorry.

Next, click the “Step 2” link and obtain the two sets of libraries that the code relies on. Install these in the libraries folder of the 0018 version of the Arduino IDE you downloaded and installed earlier. You will need to restart the IDE before you can use these. The Twitter library also comes with a few examples you can try out. If you wish to read up about the Twitter library you can find it on the Arduino playground at www.arduino.cc/playground/Code/TwitterLibrary.

Once you have your token and libraries installed, enter and upload the code in Listing 17-4.

Listing 17-4. Code for Project 49

// Project 49 – Twitterbot

#include <Ethernet.h>
#include <EthernetDHCP.h>
#include <EthernetDNS.h>
#include <Twitter.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3
#define TEMPERATURE_PRECISION 12

float itempC, itempF, etempC, etempF;
boolean firstTweet = true;
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
DeviceAddress insideThermometer = { 0x10, 0x7A, 0x3B, 0xA9, 0x01, 0x08, 0x00, 0xBF };
DeviceAddress outsideThermometer = { 0x10, 0xCD, 0x39, 0xA9, 0x01, 0x08, 0x00, 0xBE};

byte mac[] = { 0x64, 0xB9, 0xE8, 0xC3, 0xC7, 0xE2 };

// Your Token to tweet (get it from http://arduino-tweet.appspot.com/)
Twitter twitter("608048201-CxY1yQi8ezhvjz60ZVfPHVdzIHbMOD1h2gvoaAIx");

unsigned long interval = 600000; // 10 minutes
unsigned long lastTime; // time since last tweet

// Message to post
char message[140], serialString[60];
// function to get the temperature for a device
void getTemperatures()
{
  itempC = sensors.getTempC(insideThermometer);
  itempF = DallasTemperature::toFahrenheit(itempC);
  etempC = sensors.getTempC(outsideThermometer);
  etempF = DallasTemperature::toFahrenheit(etempC);
}

void tweet(char msg[]) {
   Serial.println("connecting ...");
  if (twitter.post(msg)) {
    int status = twitter.wait();
    if (status == 200) {
      Serial.println("OK. Tweet sent.");
      Serial.println();
      lastTime = millis();
      firstTweet = false;
    } else {
      Serial.print("failed : code ");
      Serial.println(status);
    }
  } else {
    Serial.println("connection failed.");
  }
}

void setup()
{
  EthernetDHCP.begin(mac);
  Serial.begin(9600);
   sensors.begin();
    // set the resolution
  sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);

  sensors.requestTemperatures()

  getTemperatures();
  // compile the string to be tweeted
while (firstTweet) {
sprintf(message, "Int. Temp: %d C (%d F) Ext. Temp: %d C (%d F). Tweeted from Arduino. %ld", int(itempC), int(itempF), int(etempC), int(etempF), millis());   tweet(message);
  }
}
void loop()
{
  EthernetDHCP.maintain();
  sensors.requestTemperatures();
  // compile the string to be printed to the serial monitor
  sprintf(serialString, "Internal Temp: %d C  %d F. External Temp: %d C %d F", int(itempC),
int(itempF), int(etempC), int(etempF));
  delay(500);
  Serial.println(serialString);
  Serial.println();
 
  if (millis() >= (lastTime + interval)) {
  // compile the string to be tweeted
sprintf(message, "Int. Temp: %d C (%d F) Ext. Temp: %d C (%d F). Tweeted from Arduino. %ld", int(itempC), int(itempF), int(etempC), int(etempF), millis());   tweet(message);
    }
delay(10000); // 10 seconds
}

After you have uploaded the code to your Arduino, open the serial monitor window. The Arduino will attempt to connect to Twitter (actually NeoCat's website) and send the tweet. If the first tweet is successful, the output in the serial monitor window will be a bit like this:

connecting ...
OK. Tweet sent.

Internal Temp: 26 C  79 F. External Temp: 26 C 79 F

Internal Temp: 26 C  79 F. External Temp: 26 C 79 F

Internal Temp: 26 C  79 F. External Temp: 26 C 79 F

When the program first runs, it will obtain the temperature and then keep attempting to connect to Twitter in the setup routine before it moves onto the main loop. It will not stop until it successfully connects. If the program fails to connect, you will get a failed : code 403 or connection failed message. If the tweet is successful, it will not tweet again until the interval period has passed. By default, this is set to 10 minutes, though you can change it. Twitter limits you to a maximum of 350 requests per hour, so don't overdo it. You can now access the Twitter website and view the account from anywhere to check up in the temperature readings.

Let's see how this code works.

Project 49 – Twitterbot – Code Overview

The program starts off by including the relevant libraries:

#include <Ethernet.h>
#include <EthernetDHCP.h>
#include <EthernetDNS.h>
#include <Twitter.h>
#include <OneWire.h>
#include <DallasTemperature.h>

The Twitter library needs the three Ethernet libraries to work so they are all included. Next, the defines for the sensors are set:

#define ONE_WIRE_BUS 3
#define TEMPERATURE_PRECISION 12

You create four floats for the temperatures, this time for internal and external temperatures in both C and F:

float itempC, itempF, etempC, etempF;

The first time the program attempts to make a tweet, you want it to keep on trying until it successfully connects and sends the message. Therefore, a Boolean is created and set to true, so you know if you have yet to make your first tweet or not:

boolean firstTweet = true;

As before, you create instances for the one-wire and temperature sensors as well as the addresses for the two sensors:

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress insideThermometer = { 0x10, 0x7A, 0x3B, 0xA9, 0x01, 0x08, 0x00, 0xBF };
DeviceAddress outsideThermometer = { 0x10, 0xCD, 0x39, 0xA9, 0x01, 0x08, 0x00, 0xBE};

You give the Ethernet shield a MAC address:

byte mac[] = { 0x64, 0xB9, 0xE8, 0xC3, 0xC7, 0xE2 };

Next, you create an instance of the Twitter library and pass it the token for your account:

Twitter twitter("608048201-CxY1yQi8ezhvjz60ZVfPHVdzIHbMOD1h2gvoaAIx");

The interval in-between tweets is set

unsigned long interval = 600000; // 10 minutes

as is a variable to store the time you last tweeted.

unsigned long lastTime; // time since last tweet

Two character arrays are created. These will store the message to be tweeted and the message you will output to the serial monitor window.

char message[140], serialString[60];

Now you create some functions. The first one is the function to obtain the temperatures from the two sensors and store them in your variables.

void getTemperatures()
{
  itempC = sensors.getTempC(insideThermometer);
  itempF = DallasTemperature::toFahrenheit(itempC);
  etempC = sensors.getTempC(outsideThermometer);
  etempF = DallasTemperature::toFahrenheit(etempC);
}

Next is the function that will do the tweeting for you. It requires one parameter, which is the character array that has your message in it.

void tweet(char msg[]) {

The user is informed that you are attempting to connect:

Serial.println("connecting ...");

Next, you use the post() method of the Twitter object to send the message. If the post is successful, the function returns true. If it fails to connect, it returns false.

  if (twitter.post(msg)) {

If you connect successfully, then you check the status of the post using the wait() method. This returns the HTTP status code in the response from Twitter.

int status = twitter.wait();

If the status code is 200, this is the HTTP code's way of saying everything is OK. In other words, if the tweet was successfully sent, then the code within the block will execute.

if (status == 200) {

If successful, you inform the user:

Serial.println("OK. Tweet sent.");
Serial.println();

Then set lastTime to the current value in millis(). This is so you can determine how long has passed since the last tweet.

lastTime = millis();

The first time you carry out a successful tweet, you want the program to jump out of the while loop in the setup routine and move onto the main loop, so you set the firstTweet flag to false.

firstTweet = false;

If the status is not 200, i.e. the post failed, then the user is informed and the code passed back for debugging purposes

} else {
      Serial.print("failed : code ");
      Serial.println(status);
}

and if you were not even able to connect in the first place, the user is informed of that instead.

} else {
    Serial.println("connection failed.");
}

The user functions out the way, you now come to the setup routine:

void setup()

First, you begin the EthernetDHCP library and pass it the MAC address:

EthernetDHCP.begin(mac);

DHCP (Dynamic Host Configuration Protocol) is an autoconfiguration protocol used on IP networks. It allows the Ethernet Shield to automatically be assigned an IP address from one that is available from the router. Previously, you manually set the IP address; this time you use the EthernetDHCP library to auto-assign one for you. The tradeoff is your code is much larger.

Next, you begin serial communications at 9600 baud and set up the sensors as before:

Serial.begin(9600);
sensors.begin();
sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);

The temperatures are requested, as you are about to use them:

sensors.requestTemperatures()
getTemperatures();

You now attempt to send your first tweet. The while loop to do this will keep running as long as firstTweet is set to true:

while (firstTweet) {

Next, you use a sprintf command to compile the tweet into the message[] array. You pass it the four sets of temperatures as well as the value of millis(). As millis is an unsigned long number, you use the %ld specifier in sprintf to print a long integer.

sprintf(message, "Int. Temp: %d C (%d F) Ext. Temp: %d C (%d F). Tweeted from Arduino. %ld", int(itempC), int(itempF), int(etempC), int(etempF), millis());  

The reason you add the value of millis() onto the end of the tweet is that Twitter will not post a message that is the same as the last one sent. If the temperatures have not changed since the last tweet, the message will be the same and Twitter will return an error code instead. As you want regular updates every interval period, by adding the value of millis() to the end you will ensure that the message differs from the last one sent. Make sure that your tweet length does not go over 140 characters in total; otherwise, you will end up with weird messages appearing in your Twitter timeline.

Now that you have compiled your message, you pass it to the tweet() function:

tweet(message);

Next comes the main loop, which you will only reach if the first tweet in the setup routine is successful:

void loop()

First, you run a maintain command on the EthernetDHCP library. This keeps the auto-assigned IP address live and valid.

EthernetDHCP.maintain();

The temperatures are updated.

sensors.requestTemperatures();

Then you use a sprintf command to compile the output for the serial monitor. It's more convenient than a whole list of Serial.print() commands so you may as well use it, though it does increase the size of your code.

sprintf(serialString, "Internal Temp: %d C  %d F. External Temp: %d C %d F", int(itempC), int(itempF), int(etempC), int(etempF));

Then the string is output to the serial monitor after a short delay:

delay(500);
Serial.println(serialString);
Serial.println();

Next you ascertain if the interval time has passed since the last tweet, and if so, send another one. You calculate the value of lastTime + interval and see if the current value in millis() is greater than it (i.e. the interval period has passed since the last tweet). If so, you compile the new message and tweet again.

if (millis() >= (lastTime + interval)) {
          sprintf(message, "Int. Temp: %d C (%d F) Ext. Temp: %d C (%d F). Tweeted from
          Arduino. %ld", int(itempC), int(itempF), int(etempC), int(etempF), millis());
          tweet(message);
}

Finally, you have a 10 second delay in-between the updates to the serial monitor so that you don't bombard the user with information:

delay(10000); // 10 seconds

Now that you know how to send tweets from your Arduino, you can use it for all kinds of purposes. How about a potted plant that tweets to let you know it needs watering? Or sensors around a house to tweet whenever anyone enters a room, a doorbell that tweets when someone is at the door, or a cat flap that tells you when your cat has left or entered the house? The possibilities are endless.

Now you've reached the final project in your journey. In this last project, you will use the Ethernet Shield to read some data from the Internet instead of sending data out.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.84.71