I got an email from Dan earlier this week about making a fish tracking aquarium. Being that we’re right in the middle of Shark Week, I respectfully obliged…
This may or may not have implications for real-life shark tracking, but I’ll take an excuse to have my shark tweet me when he (or she, I’m no marine biologist) breaches the perimeter over to the sunny side of the tank.
Of course, I’m doing this with my toy shark-on-a-stick and only a laser level and a light sensor, but it’s possible to make this much more accurate and granular just by adding more strategically placed sensors/light sources into the mix.
Disclaimer: This project was designed purely with fun and proof-of-concept in mind, and in no way is designed to replace the $100 million airport intrusion detection system at JFK. The jet ski was too big and too fast for my 10 gallon fishtank…
I couldn’t find a picture of Tom Cruise doing this
because the lasers in Mission Impossible weren’t visible…
because the lasers in Mission Impossible weren’t visible…
Concept
Most laser security systems rely on infrared sensors that detect changes in heat, based on a beam of light hitting the sensor. If that beam is interrupted, it’s interpreted as a change in the thermal profile on the sensor, and an alarm goes off. Usually the beams are invisible too, so that picture above is mildly inaccurate. Here’s the basic idea of how the project went:
I took a little field trip to Petco and Toys R Us to get a fish tank simulation setup. For the laser pointer, a laser light level I had in the shop worked really nicely, but any standard laser pointer will do.
Building the light sensor/laser setup
I ended up using a real, visible laser for two reasons: first, it’s easy to line up against my light sensor, and second, because I’m shooting the beam through water and 2 glass panels (on either side of my tank), which might otherwise diffuse the beam’s heat profile. Dry museums have it so easy…
On the other side of the tank, I have an Arduino with a light sensor elegantly taped to the glass.
I cut a hole in the wallpaper – on the left side, the laser is hitting the sensor directly. On the right, I moved the laser away, so you can see it the light sensor more clearly.
Chris and I just have some basic code running on the Arduino to get analog readings out from the AMBI light sensor. (The dead simple up-and-running post from way back when, as well as the wiki here). I uploaded the code to the Arduino, checked the output from serial, it seems like I’m good to go!
Connecting the sensor setup to a web-connected Android/BeagleBoard system
I connected the Arduino + Light Sensor to the BeagleBoard/BeagleTouch/Android stack sitting in my freshly dug up Mystery Box.
For a recap on how to connect the Arduino and sensor outputs over serial to output to the BeagleBoard over Android, here’s a link to the Antipasto wiki post. (This can still be tricky even with the Android Ambrosia SD card, so email me justin@liquidware.com, or comment below if you get stuck.)
Once I was able to get readings from the light sensor/Arduino in Android, I wrote a quick little Android APK to do two things:
1) Flash a Red Alert on BeagleTouch screenWhy Twitter? It’s excellent for posting event alerts in an easy to subscribe fashion, and it’s also really easy to have these alerts forwarded to SMS, email, and Facebook. And they have a pretty excellent API, which I’ll get to in the next section.
2) Trigger a tweet to be sent
If nothing is obstructing the the light sensor, the laser drives a light value of about 700-800.
As soon as the laser is obstructed by Bruce the shark himself, that light value drops. Once it’s below 400, the Android program issues a Red Alert warning that the sensor has been tripped, and sends a tweet.
This serial app, which Chris originally wrote for the Liquidware Amber, simply takes the values being sent from the Arduino/light sensor, then funnels it through the following logic:
A ratchet digital filter that detects when the sensor has been obstructed (and resets)
if ( (sensorVal < NIGHT_TRIP_POINT) && (ratchetCounter > ratchetMin))
ratchetCounter--;
if (ratchetCounter == ratchetMin)
time = NIGHT;
if ((sensorVal > DAY_TRIP_POINT) && (ratchetCounter < ratchetMax))
ratchetCounter++;
if (ratchetCounter == ratchetMax)
time = DAY;
Then here are a few of Bruce’s tweet alerts, stored in a String array:
String [] mTweets = {
"Yum.",
"Fish are friends, not food!",
"I am a nice shark, not a mindless eating machine.",
"Anchor! Chum!",
"So, what's a couple of bites like you doing out so late?"
};
Finally, bringing these two pieces together…
if ((time == NIGHT) && (prevTime == DAY)) {
mAlertDlg.setVisibility(View.V
ISIBLE);
if ((time == NIGHT) && (prevTime == DAY)) {
mAlertDlg.setVisibility(View.V
mTweetIndex++;
if (mTweetIndex >= mTweets.length)
mTweetIndex = 0;
Tweet tweet = new Tweet(mContext,
mTweets[mTweetIndex]);
}
I posted the full source code to the Android serial reading application on Github, if you’re interested. Big thanks to the folks who developed the twitter4j Android library!Twitter Alerts from Bruce the Shark
Two of the world’s most famous sharks have been named Bruce (see hints below):
So I figured @BruceSharkAlert would be a fitting Twitter handle. In order to make Tweets actually happen, the code above needs to be linked to an authenticated Twitter developer account. Logging in as BruceSharkAlert on dev.twitter.com, this is what I’ve got:
I created this application…
Filled out the forms and got authentication keys…
(which I neatly chopped out :) They’re required in my Tweet.java file, which requires an authenticated account to automate tweet posts:
package com.liquidware.
networkedserial.app;
package com.liquidware.
import android.os.AsyncTask;
import android.util.Log;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
public class Tweet {
private static final String TAG = "Tweet";
/** Name to store the users access token */
private static final String PREF_ACCESS_TOKEN ="[***your key here***]";
/** Name to store the users access token secret */
private static final String PREF_ACCESS_TOKEN_SECRET ="
[***your key here***] ";
/** Consumer Key generated when you registered your app athttps://dev.twitter.com/apps/ */
private static final String CONSUMER_KEY ="
[***your key here***] ";
/** Consumer Secret generated when you registered your app athttps://dev.twitter.com/apps/ */
private static final String CONSUMER_SECRET = "
[***your key here***] "; //XXX Encode in your app
/** Twitter4j object */
private final Twitter mTwitter;
/** Called when the activity is first created. */
public Tweet(String message) {
Log.i(TAG, "Loading TweetToTwitterActivity");
// Load the twitter4j helper
mTwitter = new TwitterFactory().getInstance();
Log.i(TAG, "Got Twitter4j");
// Tell twitter4j that we want to use it with our app
mTwitter.setOAuthConsumer(CONSUMER_KEY,CONSUMER_SECRET);
Log.i(TAG, "Inflated Twitter4j");
//tweet
new postMessage().execute(message);
}
/**
* Login and tweet
*/
public class postMessage extends AsyncTask {
@Override
protected Void doInBackground(String... message) {
loginAuthorisedUser();
tweetMessage(message[0]);
return null;
}
}
/**
* The user had previously given our app permission to use Twitter
* Therefore we retrieve these credentials and fill out the Twitter4j helper
*/
private void loginAuthorisedUser() {
String token = PREF_ACCESS_TOKEN;
String secret = PREF_ACCESS_TOKEN_SECRET;
// Create the twitter access token from the credentials we got previously
AccessToken at = new AccessToken(token, secret);
mTwitter.setOAuthAccessToken(at);
Log.d(TAG, "Welcome back user.");
}
/**
* Send a tweet on your timeline, with a //Toast msg for success or failure
*/
private void tweetMessage(String message) {
try {
mTwitter.updateStatus(message);
Log.d(TAG, "Tweet successful!");
} catch (TwitterException e) {
e.printStackTrace();
}
}
}
Now Bruce is tweeting one of the above pre-programmed lines (borrowed from Finding Nemo)Phone Perimeter Breach Alerts
From there, I just followed @BruceSharkAlert, and since I have Twitter via SMS already set up, all I had to do was text 40404 (my Twitter “short code”) the command ON BruceSharkAlert. Now Bruce’s Tweets show up on my phone every time he breaks the laser line:
Mike gives us a little video walkthrough here:
When my phone goes off, I like to tell people that my shark tweeted me. Anyway, that’s my tribute to Shark Week, but if I had more time, laser pointers, and light sensors, I’d probably set up a crazy grid defense system. Till next time…
What else could I use this for? Let me know in the comments, over email at justin@liquidware.com or tweet me @liquidware
5 comments:
Bonus points if you can guess what the bracketed numbers are for at the end of each Tweet :)
I'm going to guess they are timestamps ... or possibly IDs.
Close! The Twitter API blocks you from sending too many identical tweets in a short time span because it thinks you've sent them by accident.
The unique ID allows us to keep sending alerts and avoid having them blocked.
By accident ... or perhaps on purpose, like a spambot. :-]
Do you have wrist pulse rate sensors?
Post a Comment