Arduino Yún + Twitter Streaming API blink example

This is a simple example on how to run some code on the Arduino side of the Arduino Yún on specific events fired through the Twitter Streaming API

i.e. when a tweet containing a specific #hashtag is twitted, Arduino blinks an LED

I love this experiment because it’s near real time and it gives a lot of possibilities, and it’s very easy to set up

Requirements

  • An Arduino Yún (obviously) with an external SD card (required for hosting the Python libraries you’ll need)
  • A twitter app you own
  • The Tweepy library for Python
  • And, finally… this code
  • 🙂

Instructions

“I love instructions, they give me confidence.”
me

  1. In case you haven’t done it yet, upgrade your Arduino Yún to the latest version and expand it’s disk space using the SD card
  2. Log to your Arduino using ssh
  3. Install a bunch of useful stuff
     $ opkg update
     $ opkg install git
     $ opkg install python-expat
     $ opkg install python-openssl
     $ opkg install python-bzip2
    

    easy_install

     $ opkg install distribute
    

    pip

     $ easy_install pip
    

    tweepy

     $ pip install tweepy
    

    or install it manually cloning it from github

      $ git clone https://github.com/tweepy/tweepy.git
      $ cd tweepy
      $ python setup.py install
    
  4. If you don’t have one, create your twitter app
    and get your consumer key and consumer secret. Then, generate an access token and get your access token and access token secret

  5. Create a working folder for all the scripts (i.e. /root/python)

     $ mkdir /root/python
     $ cd /root/python
    

    and, while in the python folder, clone the Twitter Blink example

      $ git clone git@github.com:amicojeko/TwitterBlink.git
    

    don’t forget to make the kill_processes.sh script executable!

      $ chmod +x kill_processes.sh
    
  6. Then use vi or nano (I personally installed vim) to put your twitter app configuration data into the streaming.py script, and to configure the string to be searched inside the Twitter Stream Maelstrom
     $ nano streaming.py
    

    now everything should be ready.

  7. Open the Arduino IDE and load the TwitterBlink.ino script that is in the Arduino folder (you can download it from GitHub )

  8. Configure the script folder (in case you created a folder different from root/python/ in the previuos steps)

    You can customize the script for your needings, in it’s initial configuration it will blink the LED attached to pin 13 (and the built in LED as well) so it’s perfect for testing

  9. Upload the script to Arduino, it should start working as soon as it’s uploaded

  10. Have fun!!

cheers!

Jeko

The social media hamster

(la muerte peluda is back)


Every hackathon we host at Mikamai usually means a lot of leftovers. From pizza crusts to burned LEDs, you can find a lot of useful and useless stuff even in the deepest and darkest corners of our huge open space.

And in one of these dark corners I found a scared little friend, which I suddenly decided to adopt.

image

We became BFFs, and we do everything together, coding, drinking, pranking the teammates and cycling, but he wanted to be useful to me, so I went into my cove and start thinking… what an ex cartoon eating plush hamster can do for me?

The answer was quite obvious! He can warn me whenever someone tweets me or cites me in a tweet! Genius!

So, here are the ingredients

  • Twitter streaming APIs
  • Electric IMP (I decided to use an Electric Imp just because I had a spare one, you can even use a spark core or an Arduino Yún)
  • A servo
  • Chopsticks
  • Some screws
  • Cable ties
  • Something heavy
  • Obviously, absulutely essential, a plush hamster
  • An USB power adapter or a USB battery pack if you want your project to be portable

image

I also used an LED for visual debugging, I tried to put a pair of LEDs instead of my hamster’s eyes, but it was too scary, and it remembered a lot my creepy doll, so I decided not to use them

Then I had to make the hamster move with the servo. It’s just a prototype, so I decided to keep it very very simple, and I secured the hamster to the servo with a chopstick, some copper wire and some screws to keep the hamster from doing a barrel roll. The surgery was not so traumatic, so my hamster is still happy. Then I fixed the servo to an heavy metal plate with a cable tie, just to provide a solid base.

I drilled some holes to the chopstick

image

Then put some screws in it and i secured the chopstick to the servo

image

And I used a bit of copper wire to secure the hamster to the screws

image

image

And a cable tie to fix the servo to the metal plate

image

Now everything’s in place!

image

The circuit is dead simple. Just connect the power pins of the servo to the GND-VIN pins of the Electric Imp, and the third pin to the Imp’s pin number 7

image

The Electric Imp is one of the easiest platforms to configure, thanks to the Blink app, so you can have it online in a couple of minutes. You can even use your phone as hotspot, it works perfectly and it makes your social hamster fully portable.

image

Now, the code. The Electric imp platform gives you all the instruments to interact with the whole world of APIs and webservices. Basically, the code is splitted in two: An agent, that runs on the Electric Imp Cloud servers, and a device, which is your electric Imp

[Copy & Paste from the official Electric Imp documentation]

The agent object represents the imp’s agent: the server-side Squirrel, running in the Electric Imp’s cloud servers, that deals with Internet requests and responses on behalf of the imp. The agent object is used to mediate communication between the imp and its agent.

The device object represents the server-based agent’s view of the imp and is used to mediate communication between the agent and the imp.

[End of copy&paste]

So here we go with our agent code. It’s based on the useful twitter library included in the Electric Imp webservices reference. I also added this piece of code to generate the tweet event manually

// test function for manual hamster shaking
function requestHandler(request, response) {
  try {
    // check if the user sent led as a query parameter
    if ("tweet" in request.query) {
        device.send("tweet", null); 
    }
    // send a response back saying everything was OK.
    response.send(200, "tweet test ok");
  } catch (ex) {
    response.send(500, "Internal Server Error: " + ex);
  }
}

// register the HTTP handler
http.onrequest(requestHandler);

To enable the twitter stream real time parsing, I just needed to configure these twitter constants

// Twitter Keys
const API_KEY = "";
const API_SECRET = "";
const AUTH_TOKEN = "";
const TOKEN_SECRET = "";

and this line

twitter.stream("@jeko", onTweet);

which basically tells to the stream object to catch all the tweets containing the string “@jeko”

So, here’s the complete agent code

// Copyright (c) 2013 Electric Imp
// This file is licensed under the MIT License
// http://opensource.org/licenses/MIT

// Twitter Keys
const API_KEY = "";
const API_SECRET = "";
const AUTH_TOKEN = "";
const TOKEN_SECRET = "";

class Twitter {
    // OAuth
    _consumerKey = null;
    _consumerSecret = null;
    _accessToken = null;
    _accessSecret = null;

    // URLs
    streamUrl = "https://stream.twitter.com/1.1/";
    tweetUrl = "https://api.twitter.com/1.1/statuses/update.json";

    // Streaming
    streamingRequest = null;
    _reconnectTimeout = null;
    _buffer = null;


    constructor (consumerKey, consumerSecret, accessToken, accessSecret) {
        this._consumerKey = consumerKey;
        this._consumerSecret = consumerSecret;
        this._accessToken = accessToken;
        this._accessSecret = accessSecret;

        this._reconnectTimeout = 60;
        this._buffer = "";
    }

    /***************************************************************************
     * function: Tweet
     *   Posts a tweet to the user's timeline
     * 
     * Params:
     *   status - the tweet
     *   cb - an optional callback
     * 
     * Return:
     *   bool indicating whether the tweet was successful(if no cb was supplied)
     *   nothing(if a callback was supplied)
     **************************************************************************/
    function tweet(status, cb = null) {
        local headers = { };

        local request = _oAuth1Request(tweetUrl, headers, { "status": status} );
        if (cb == null) {
            local response = request.sendsync();
            if (response && response.statuscode != 200) {
                server.log(format("Error updating_status tweet. HTTP Status Code %i:rn%s", response.statuscode, response.body));
                return false;
            } else {
                return true;
            }
        } else {
            request.sendasync(cb);
        }
    }

    /***************************************************************************
     * function: Stream
     *   Opens a connection to twitter's streaming API
     * 
     * Params:
     *   searchTerms - what we're searching for
     *   onTweet - callback function that executes whenever there is data
     *   onError - callback function that executes whenever there is an error
     **************************************************************************/
    function stream(searchTerms, onTweet, onError = null) {
        server.log("Opening stream for: " + searchTerms);
        // Set default error handler
        if (onError == null) onError = _defaultErrorHandler.bindenv(this);

        local method = "statuses/filter.json"
        local headers = { };
        local post = { track = searchTerms };
        local request = _oAuth1Request(streamUrl + method, headers, post);


        this.streamingRequest = request.sendasync(

            function(resp) {
                // connection timeout
                server.log("Stream Closed (" + resp.statuscode + ": " + resp.body +")");
                // if we have autoreconnect set
                if (resp.statuscode == 28) {
                    stream(searchTerms, onTweet, onError);
                } else if (resp.statuscode == 420) {
                    imp.wakeup(_reconnectTimeout, function() { stream(searchTerms, onTweet, onError); }.bindenv(this));
                    _reconnectTimeout *= 2;
                }
            }.bindenv(this),

            function(body) {
                 try {
                    if (body.len() == 2) {
                        _reconnectTimeout = 60;
                        _buffer = "";
                        return;
                    }

                    local data = null;
                    try {
                        data = http.jsondecode(body);
                    } catch(ex) {
                        _buffer += body;
                        try {
                            data = http.jsondecode(_buffer);
                        } catch (ex) {
                            return;
                        }
                    }
                    if (data == null) return;

                    // if it's an error
                    if ("errors" in data) {
                        server.log("Got an error");
                        onError(data.errors);
                        return;
                    } 
                    else {
                        if (_looksLikeATweet(data)) {
                            onTweet(data);
                            return;
                        }
                    }
                } catch(ex) {
                    // if an error occured, invoke error handler
                    onError([{ message = "Squirrel Error - " + ex, code = -1 }]);
                }
            }.bindenv(this)

        );
    }

    /***** Private Function - Do Not Call *****/
    function _encode(str) {
        return http.urlencode({ s = str }).slice(2);
    }

    function _oAuth1Request(postUrl, headers, data) {
        local time = time();
        local nonce = time;

        local parm_string = http.urlencode({ oauth_consumer_key = _consumerKey });
        parm_string += "&" + http.urlencode({ oauth_nonce = nonce });
        parm_string += "&" + http.urlencode({ oauth_signature_method = "HMAC-SHA1" });
        parm_string += "&" + http.urlencode({ oauth_timestamp = time });
        parm_string += "&" + http.urlencode({ oauth_token = _accessToken });
        parm_string += "&" + http.urlencode({ oauth_version = "1.0" });
        parm_string += "&" + http.urlencode(data);

        local signature_string = "POST&" + _encode(postUrl) + "&" + _encode(parm_string);

        local key = format("%s&%s", _encode(_consumerSecret), _encode(_accessSecret));
        local sha1 = _encode(http.base64encode(http.hash.hmacsha1(signature_string, key)));

        local auth_header = "oauth_consumer_key=""+_consumerKey+"", ";
        auth_header += "oauth_nonce=""+nonce+"", ";
        auth_header += "oauth_signature=""+sha1+"", ";
        auth_header += "oauth_signature_method=""+"HMAC-SHA1"+"", ";
        auth_header += "oauth_timestamp=""+time+"", ";
        auth_header += "oauth_token=""+_accessToken+"", ";
        auth_header += "oauth_version="1.0"";

        local headers = { 
            "Authorization": "OAuth " + auth_header
        };

        local url = postUrl + "?" + http.urlencode(data);
        local request = http.post(url, headers, "");
        return request;
    }

    function _looksLikeATweet(data) {
        return (
            "created_at" in data &&
            "id" in data &&
            "text" in data &&
            "user" in data
        );
    }

    function _defaultErrorHandler(errors) {
        foreach(error in errors) {
            server.log("ERROR " + error.code + ": " + error.message);
        }
    }

}

twitter <- Twitter(API_KEY, API_SECRET, AUTH_TOKEN, TOKEN_SECRET);

function onTweet(tweetData) {
    // log the tweet, and who tweeted it (there is a LOT more info in tweetData)
    server.log(format("%s - %s", tweetData.text, tweetData.user.screen_name));
    device.send("tweet", null); 
}


// test function for manual hamster shaking
function requestHandler(request, response) {
  try {
    // check if the user sent led as a query parameter
    if ("tweet" in request.query) {
        device.send("tweet", null); 
    }
    // send a response back saying everything was OK.
    response.send(200, "tweet test ok");
  } catch (ex) {
    response.send(500, "Internal Server Error: " + ex);
  }
}

twitter.stream("yoursearchstring", onTweet);

// register the HTTP handler
http.onrequest(requestHandler);

Then, here’s the device code, based on the electric Imp PWM Servo example

// These values may be different for your servo
const SERVO_MIN = 0.03;
const SERVO_MAX = 0.1;

// create global variable for servo and configure
servo <- hardware.pin7;
servo.configure(PWM_OUT, 0.02, SERVO_MIN);

// assign pin9 to a global variable
led <- hardware.pin9;
// configure LED pin for DIGITAL_OUTPUT
led.configure(DIGITAL_OUT);

// global variable to track current state of LED pin
state <- 0;
// set LED pin to initial value (0 = off, 1 = on)
led.write(state);



// expects a value between 0.0 and 1.0
function SetServo(value) {
  local scaledValue = value * (SERVO_MAX-SERVO_MIN) + SERVO_MIN;
  servo.write(scaledValue);
}

// expects a value between -80.0 and 80.0
function SetServoDegrees(value) {
  local scaledValue = (value + 81) / 161.0 * (SERVO_MAX-SERVO_MIN) + SERVO_MIN;
  servo.write(scaledValue);
}

// current position (we'll flip between 0 and 1)
position <- 0;

function HamsterDance() {
  SetServoDegrees(-10);
  imp.sleep(0.5);
  SetServoDegrees(0);
  imp.sleep(0.2);
  SetServoDegrees(-15);
  imp.sleep(0.2);
  SetServoDegrees(5);  
  imp.sleep(0.2);
  SetServoDegrees(-20);
  imp.sleep(0.2);
  SetServoDegrees(0);
  imp.sleep(0.2);
  SetServoDegrees(-78);
} 


function ShakeRattleAndRoll(ledState){
    server.log("Let's shake the hamster!");  
    // turn on the led for visual debugging
    led.write(1);
    // 
    HamsterDance();
    imp.sleep(2);
    // turn off the led
    led.write(0);

} 

// initialize the servo to the start position
SetServoDegrees(-78);

//shake the hamster when got a tweet message from the Agent
agent.on("tweet", ShakeRattleAndRoll);

And… that’s it! Just connect the Electric Imp to a power source, configure the wifi via the Electric Imp mobile App, and start tweeting! Your hamster will be soo happy to warn you whenever a tweet is coming!!

Ciao and happy hacking!

Stefano

AtTiny85 based capacitive sensor LED switch

Not so much time ago, I met a girl, and she designs ceramic lamps.

viondesign.com

I mean, the lamps are really, really gorgeous, and they are illuminated by a 12V LED module.

As soon as I saw one of these lamps, I decided to make some experiments with them, because they are so beautiful that the classic ON/OFF switch did not do justice to them.

Recently, I studied the Arduino capsense library for other purposes, and I thought that a capacitive sensor would have been a very nice way to turn the lamp on and off without the use of a regular switch.

The basic idea was to paint the inside of the lamp with some conductive paint and use the lamp itself as a switch.

So, here’s what I did.

First of all, the prototyping. The best thing about AtTinys is that you can use Arduino for prototyping, and then, with very small code adjustments, burn the code into the AtTiny, make the circuit supersmall, and go to production.

I started from the basic Capacitive Sensor library example.

It worked nice, but the reading was not very stable, and since I linked the LED intensity directly to the sensor reading, the LED was flickering a lot (as you can see in this video)

So I followed the instructions, and put a very small capacitor (20pF) between the sensor (an aluminium foil for prototyping) and ground. That helped a lot, but it wasn’t enough.

Then I decided to add some smoothing code to my sketch.. Open source code is soooo cool 🙂 You always find someone that can really help you 🙂

The original code takes the average reading between 100 readings, but since the AtTiny is much slower than the Arduino (1Mhz vs 16 Mhz) I decided to make an average reading between 10 values, and it worked great for me.

Ok, now the LED turns on and off when my hand is close to the sensor. But I wanted it to stay on or off, like a regular switch does. So I put this code, that works in this way: if the sensor reaches the maximum value (when I touch it), then I switch the lamp on/off and I stop the reading for a second.

So this is the final code for Arduino.

#include <CapacitiveSensor.h>

int cap_pin_out = 4;
int cap_pin_in = 2;
int lowcap = 300;  // just above reading when noting is near
int highcap = 1800; // cap reading when almost touching
CapacitiveSensor   capsense = CapacitiveSensor(cap_pin_out, cap_pin_in);  // 10M resistor between pins 1 & 2, pin 2 is sensor pin, add a wire and or foil if desired
int ledPin = 13;
int dur = 10; //duration is 10 loops
int brightness;
bool isOn = 0;

/* smoothing */
const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
long total = 0;                  // the running total
int average = 0;                // the average

void setup()
{
  pinMode(ledPin, OUTPUT); // output pin
  pinMode(cap_pin_in, INPUT); // output pin
  pinMode(cap_pin_out, OUTPUT); // output pin

  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading = numReadings)
    // ...wrap around to the beginning:
    index = 0;

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits

  long start = millis();

  brightness = map(average, lowcap, highcap, 0, 255);
  brightness = constrain(brightness, 0, 255);

  if (isOn == true && brightness == 255) {
    isOn = false;
    delay(500);
  } else if (isOn == false && brightness == 255) {
    isOn = true;
    delay(500);
  }

  if (isOn == true) {
    analogWrite(ledPin, 255);
  } else {
    analogWrite(ledPin, brightness);
  }

  delay(10);

}

At this point I had a couple of things left to do: first of all, to control an hi-power 12V led, instead of a 5V one, and, second, try to power the circuit with the 12V LED power supply.

To control an 12V LED, I used a TIP102, that is a really heavy duty affordable NPN darlington transistor. It’s perfect to control LED strips, hi power LEDs and LED modules. The connection is really easy, it just needs an 1K resistor and this simple scheme

Since the ATTiny can be powered at 5V, and I did not want to use two power supplies, I decided to use this 12v to 5v voltage converter. It’s very simple to use: just connect the IN Pins to the 12V and you get 5V from the output pins (yes, I know, I should have used a capacitor for stability, but the AtTiny is very forgiving and works perfectly even without it)

Ok now that everything was perfect, I burned the code to the AtTiny. If you need some instructions on how to do that, here’s a step by step tutorial I wrote some time ago.

I had to make some minor adjustments to the code: I changed the sensor pins form 4,2 to 1,2 and the LED pin from 13 to 0… and boom! we’re ready to change platform! 🙂

So here’s the schematics for the AtTiny85

The circuit is pretty simple and can be easily assembled on a protoboard.

I painted the inside of the lamp with this paint, so now the inside of the skull is conductive and can be used as a capacitive sensor.

To connect the sensor wire to this paint, I used some BareConductive electric paint

The assembled circuit was so tiny that fitted perfectly inside the skull

A little hint: when using capacitive sensor, is very important to ground the circuit, so be sure to have a ground connection between the circuit, the power supply, and the mains ground.

Here is the final result… isn’t it nice? 🙂

Ciao!

Jeko

Another important thing with capacitive sensors is grounding.

The Creepy Doll

Here at Mikamai, we often organise events and hackathons. After the last hackathon, someone left an old doll, and it was kinda creepy… so why not make it even creepier?

I decided to put two red LEDs instead of the eyes, and a vibration sensor to turn on the LEDs when you shake the doll. Everything is powered by an AtTiny85 and a single CR2032 battery.

Materials and tools

image

Materials:

image

Tools:

  • A sharp cutter
  • Hot glue gun
  • A soldering iron and solder
  • Needle and thread, to sew it back
  • optional – a Dremel to drill the eyes

Prototyping and testing the circuit

image

Using the AtTiny 85 is a great choice for those who are familiar with Arduino, because you have the possibility to use the Arduino IDE to program it. This means that you can prototype the circuit with Arduino before deploying it to the AtTiny.

So I wrote this code, and I built a simple testing circuit with Arduino.

#import <Arduino.h>


int led = 0; // LEDs pin
int button = 2; // Tilt sensor pin
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by
int storedVal = 0;     // used to save the tilt sensor state

void setup() {
  pinMode(button, INPUT_PULLUP); // initialize the button pin a pullup input, so I don't have to use an external pullup resistor.
  pinMode(led, OUTPUT); // initialize the digital pin as an output.
}


void loop() {

  int sensorVal = digitalRead(2); // Read the sensor state

  if (sensorVal != storedVal) { //if the sensor value has changed, blink the eyes
    storedVal = sensorVal; // store the sensor state
    fadeEyes(); // call the eyes led fade function
  } else {
    digitalWrite(led, LOW); // otherwise, turn the led off
  }

  delay(10); // a small delay for debouncing the sensor
}

void fadeEyes() {

  for (int i = 0; i < 768; i++) { //cycle 3 times

    analogWrite(led, brightness); // set the brightness of led pin:
    if (brightness == 255) { // at maximum brightness, wait 5 seconds
      delay(5000); 
    }
    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // reverse the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
      fadeAmount = -fadeAmount;
    }

    // wait for 30 milliseconds to see the dimming effect
    delay(100);

  }

  digitalWrite(led, LOW);
}   

The code is pretty simple: it waits for a changement in the tilt sensor state, and when it happens, it starts a little loop fading the leds brightness

When the code works on Arduino, you are ready to deploy it on your AtTiny85

Moving to AtTiny85

Programming an AtTiny with an Arduno can be tricky, but fear not! I made a very simple tutorial on how to do that with the latest Arduino IDE and Arduino Uno/diecimila or Arduino Leonardo/Yun. Just follow these steps, and you can easily use this sketch on the AtTiny85

Testing the AtTiny85 based circuit

image

image

Now we can move the programmed AtTiny on a new breadboard, following this scheme

There is no resistor on the LED because I’m using a 3.3V coin battery. The circuit should start working as soon as you plug the battry: when the tilt sensor is shook, the LED fades 🙂

Making the circuit

image

Now that everything is tested, we can make the circuit. I decided to use a stripboard because even if it’s a little big, the result will be more stable and short circuit proof. Start placing the components on the stripboard and soldering them, the circuit is supersimple so this should be a very easy task.

I’ve put the LEDs in parallel, I know that I should have used a small resistor, but I was more focused on the simplicity of the project than on its life expectation, plus, it will be powered by a 3.3V battery, so I didn’t really care about it 🙂

The only precaution was to put some tape on the led wires to avoid short circuits.

Now you can test the circuit alone. If everything is fine, you can move to the next step

The doll surgery

image

With the cutter, remove some stitches from the doll and remove the head’s stuffing. Than drill the holes on the eyes. I used a Dremel for this task, but you can even use the cutter. Now insert the circuit, starting from the eyes. When the led pupils are in the holes, pour a lot of hot glue from the inside of the head, so you will be sure that the LEDs will stay at their place. Then put some more stuffing, the circuit, some more stuffing, the tilt sensor and the rest of the stuffing. In this way you are sure that everything won’t accidentally move and you will reduce the risk of short circuits to the minimum.

I suggest to use some velcro or a couple of buttons to close back the doll, so you can change the battery whanever you want

You’re done!

image

Arduino Yún Extra WiFi Reset Button

One of the biggest problems with Arduino Yún is that the WiFi reset button is embedded on the board, and it’s very difficult to reach. Once you have packed you project in an enclosure, there’s no way to reset the wifi settings, unless the wifi reset button is reachable through a pinhole.

But how does the integrated wifi reset button work? When it’s pressed for more than 5 seconds, Arduino calls a little script: /usr/bin/wifi-reset-and-reboot

So I’ve made a very simple sketch that does exactly the same: it waits for our extra reset button to be pressed for more than 5 seconds, and when it happens it calls the same exact script using the Yún’s Bridge library.

So you can add your extra wifi reset button, and put it where you want!

Here’s the code

#include <Process.h>

const int  buttonPin = 7;  // the pin that the pushbutton is attached to
const int ledPin = 13;     // the pin that the LED is attached to

int buttonPushTimer = 0;   // timer for the reset button
int buttonState = 0;       // current state of the button
int lastButtonState = 0;   // previous state of the button

void setup() {
  Bridge.begin();
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, start the timer
    if (buttonState == LOW) {
      buttonPushTimer = millis();
    }
  }
  else {
    // if the state has changed, and the button is still pressed, check the timer
    if (buttonState == LOW) {
      if (millis() > buttonPushTimer + 5000) {
        // if the button has been pressed for 5 seconds, reset arduino wifi
        wifi_reset();
      }
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  lastButtonState = buttonState;
}



void wifi_reset() {
  //blink led 10 times
  for (int i = 0; i < 10; i++) {
    digitalWrite(ledPin, HIGH);
    delay(50);
    digitalWrite(ledPin, LOW);
    delay(50);
  }
  // call the wifi reset script
  Process p;
  p.runShellCommand("wifi-reset-and-reboot");
}

I Hope it was useful!

Happy resetting!

Jeko

How to program an ATTiny85 (or ATTiny45) with an Arduino + Arduino ISP + Arduino 1.5.x

Yes, this is yet another tutorial on how to program an ATTiny with Arduino, but time changes, things are evolving fast, and tutorials need to be updated.

This is a very short and concise tutorial, so I won’t explain what an ATTiny is and why it is useful to program it with an Arduino, as these argument are largely covered. Here you will find instructions on how to program an ATTiny85 (or 45) with an Arduino Leonardo, Arduino Yún, Arduino UNO and Diecimila with the most recent version of the Arduino Software (1.5.x)

image

You will need:

  • Arduino Leonardo, Yún, UNO or Diecimila
  • A Breadboard
  • Hookup wire
  • ATtiny85 (or ATtiny45)
  • 10uF 16V electrolytic capacitor (for Arduino UNO or Diecimila)
  • 220ohm ¼ watt resistor
  • LED

Step 1

First of all, you will need to download the Arduino Tiny plugin from here, so your Arduino software will be able to program the ATTiny.

If you want to make it work with Arduino 1.0.x software, just download this file instead!

Then unzip it and copy the “Tiny” folder into an “hardware” folder that you have to create into your sketches folder.

The final result sholud be

arduino_sketches_folder/hardware/tiny

Inside the “tiny” folder, you will find an “avr” folder. Inside this folder, there is a file named “Prospective Boards.txt”. Just rename it into “boards.txt”

When you will start the Arduino Software, you will find new boards under the Tools > Board menu, as in this picture.

Step 2

Now we have to make the proper connections between the Arduino Board and the ATTiny

image

Arduino UNO/Diecimila

Arduino PIN 10  --> ATTiny Reset PIN 
Arduino PIN 11  --> ATTiny PIN 0
Arduino PIN 12  --> ATTiny PIN 1
Arduino PIN 13  --> ATTiny PIN 2
Arduino GND PIN --> ATTiny PIN GND PIN
Arduino +5V PIN --> ATTiny PIN VCC PIN

as in the picture below

image

or for Arduino Leonardo/Yún

Arduino PIN 10          --> ATTiny Reset PIN
Arduino ICSP MOSI PIN   --> ATTiny PIN 0
Arduino ICSP MISO PIN   --> ATTiny PIN 1
Arduino ICSP SCK PIN    --> ATTiny PIN 2
Arduino GND PIN         --> ATTiny PIN GND PIN
Arduino +5V PIN         --> ATTiny PIN VCC PIN

image

Step 3

Open the File > Examples > ArduinoISP Sketch and upload it on your Arduino

Arduino Leonardo/Yún

Only fo these platforms, you have to make this changements to the Arduino ISP sketch, BEFORE uploading it

// January 2008 by Randall Bohn
// - Thanks to Amplificar for helping me with the STK500 protocol
// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
// - The SPI functions herein were developed for the AVR910_ARD programmer 
// - More information at http://code.google.com/p/mega-isp

#include "pins_arduino.h"
#define RESET     10

#define LED_HB    13
#define LED_ERR   8
#define LED_PMODE 7
#define PROG_FLICKER true

Now upload it to your Arduino.

Step 4

Load the File > Examples > 01.Basic > Blink Sketch, and change this line

int led = 13;

to

int led = 0;

this is because the ATTiny has only 6 output pins (0,1,2,3,4,5) and so we will use the pin 0 instead of the pin 13

Step 5

Choose the proper board settings (i.e. Attiny85 @ 1Mhz), then choose Tools > Programmer > Arduino as ISP. Now you can upload the “blink” example to the ATTiny85

If everything went fine, you will see something like

avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85
avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85

in the output window of the Arduino Software. Don’t care about the warnings, they’re normal.

If something went wrong, you will find a message like

avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.

This means that you have to check your connections again, it happend a lot to me the first time I tried to use an Arduino Leonardo instead of an Arduino UNO, because the ICSP Pins are mapped in a different way on the Leonardo/Yún boards.

Step 6

Now we can test it! To build a simple test circuit, for the “blink” example, just build this simple circuit

image

When you power up the ATTiny85, the LED sholud start blinking.

I hope this tutorial is useful to you as it would be useful to me if I was able to find one: I got more then an headache trying to put all the pieces together: the proper plugins, the connections and the little software modifications…

Cheers!

Jeko

You Can’t Touch This! – An Evil Arduino Based Alarm System

You can’t touch this!

title

This was my entry for the Connected Home Project Contest by Make Magazine

This project consists in a movement sensor (PIR) plus a camera and a wifi connected device (Arduino Yún was my choice, but it can be easily substitued with a RaspberryPi). Optionally, speakers can be connected to reproduce an alarm sound.

The purpose is clear. You don’t want your kids to steal your food from the cupboard, or from the fridge, or someone to open your locket, or you want to take pictures to your pet stealing food, or you are Dwight Schrute and you want to finally unmask the coworker that puts your stuff into jelly… so you hide the device into the cupboard/fridge/locket, and when the device detects some movement, it will take a picture and post it right to your email! And if you use IFTTT, then you can automatically post the picture of the thief to Facebook, Twitter and show the thief’s face to the entire world!

The project is very simple, it doesn’t require any soldering/electronics skills and it can be assembled in minutes.

As I said before, my platform choice is Arduino Yún, because it’s very easy to use, and it’s easy to configure the wifi settings. It’s a bit more expensive than the RaspberryPi, but if you use the Yún you can give you project to someone else as a gift, and anyone can configure the wifi settings, while this may be a difficult task with the RaspberryPi, without connecting it to a monitor/mouse/keyboard. But if you like it, I can easily make a Raspberry version.

So, here are the ingredients

  • Arduino Yún
  • PIR Sensor
  • UVC compatible USB Camera (don’t worry: almost all the USB cameras are UVC compatible)
  • Micro USB power adapter or USB Battery pack
  • Recommended: micro SD card
  • Optional: USB Sound card
  • Optional: USB HUB (if you want both the USB Camera and the USB Sound card)

totalone

Ok, let’s start!

Step 1

Arduino basic configuration

First of all, you need to configure your Arduino Yún network settings. This should be pretty easy following this guide

Then test the connection to your Arduino: in your browser type http://arduino.local, you will see the Arduino web interface

If it works, open SSH session

$ssh root@arduino.local

the default password is “arduino”

Then let’s install some useful packages

$opkg update
$opkg install openssh-sftp-server

Why the openssh-sftp-server? Because it would be easier for you to upload and download files from/to the Arduino: now you can use a generic SFTP client (filezilla, transmit or cyberduck) instead of SCP command

If you have one, I highly recommend to put a micro SD card into the Arduino Yún. It will be automatically mounted in /mnt/sda1

Then, we will install the USB Camera and USB Soundcard on the Yún

Step 2

Installing and testing the USB Camera

The UVC package is already available fot Linino via opkg, so installing the Camera is a very easy step, just connect to your Yún via ssh and type

$ opkg update
$ opkg install kmod-video-uvc

We also need a software for taking pictures, I used fswebcam that is supersmall and very easy to use

$ opkg install fswebcam

Step 3

Take your first picture

First of all, be sure to use and SD card for storage or you will quickly fill the Arduino internal storage, and you don’t want to do that. If you are using an SD card, you should see it mounted in /mnt/sda1. If it’s not, put a FAT32 formatted micro SD card into the SD Card Slot, and reboot your Arduino

Now plug the camera to the USB host port, and type

$ cd /mnt/sda1
$ fswebcam test.png

If everything is ok, you took your first picture! Take a look to your SD card contents 🙂

This means that now we can take pictures from our Arduino sketch, via the Yún’s Bridge library, in this way

Process.runShellCommand("fswebcam /mnt/sda1/test.png");

Step 4 (optional)

Install the sound card

Open an ssh session to the yun, and type:

$opkg install kmod-usb-audio
$opkg install madplay

End of the story. Now you have sound support on the Arduino Yún. I only tried MP3 playback, I didn’t try to record some audio yet, but I’ll try soon!

To test it just copy an mp3 audio file to the SD card, and type

$cd /mnt/sda1
$madplay yoursound.mp3  

This means that now we can take play sounds from our Arduino sketch, via the Yún’s Bridge library, in this way

Process.runShellCommand("madplay /mnt/sda1/test.mp3");

We’re learning a lot of interesting things!! 🙂

Step 5

The Email script

Now we can take pictures and play sounds… But we want more from our Arduino! We want to send them via email.

So, how can we do? The answer is very easy… python script! Even if the Arduino Yún integrates the Temboo library, I wanted this project to be as much portable as possible, so we will use a very simple python script to encode the image file and send it to our email.

I’m assuming that you are using GMail, but the script can be easily adapted to any SMTP server

Create a new file, call it “sendemail.py” and paste this code into it

# coding=utf-8

# Copyright (C) 2014  Stefano Guglielmetti

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import smtplib, os, sys
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

#From address, to address, subject and message body
from_address    = 'FROM_ADDRESS@EMAIL.COM'
to_address      = ['YOUR_ADDRESS@EMAIL.COM']
email_subject   = 'Alert!!! Zombies!!! Ahead!!!'
email_body      = 'A non dead intruder has been detected and needs to be eliminated!'

# Credentials (if needed)
username = 'EMAIL_LOGIN'
password = 'EMAIL_PASSWORD'

# The actual mail send
server = 'smtp.gmail.com:587'

def send_mail(send_from, send_to, subject, text, files=[], server="localhost"):
    assert type(send_to)==list
    assert type(files)==list

    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach( MIMEText(text) )

    for f in files:
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(f,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
        msg.attach(part)

    smtp = smtplib.SMTP(server)
    smtp.starttls()
    smtp.login(username,password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.close()

send_mail(from_address, to_address, email_subject, email_body, [sys.argv[1]], server) #the first command line argument will be used as the image file name

now you have to customise the email settings

#From address, to address, subject and message body
from_address    = 'FROM_ADDRESS@EMAIL.COM'
to_address      = ['YOUR_ADDRESS@EMAIL.COM']
email_subject   = 'Alert!!! Zombies!!! Ahead!!!'
email_body      = 'A non dead intruder has been detected and needs to be eliminated!'

# Credentials (if needed)
username = 'EMAIL_LOGIN'
password = 'EMAIL_PASSWORD'

# The actual mail send
server = 'smtp.gmail.com:587'

so change the from address, to address and so on to match your settings

Now you can upload the script to the Arduino Yún SD card via SFTP (or SCP, if you prefer), then open an SSH session to the Yún and test it typing

$cd /mnt/sda1
$python sendemail.py test.png

And in a few seconds you will receive an email with the picture attachment… amazing!

Step 6

Let’s build the circuit!

Don’t worry, this is supereasy, there is nothing to solder, just assemble few parts

I used this PIR sensor, because it’s reliable and easy to use.

Just follow this scheme

image

We’ve connected the PIR sensor, and a LED that will turn on when the device detects some movement

Step 7

Now it’s time to add the Arduino Sketch

Copy this code to the Arduino IDE and upload it to your Yún

/* 
 * Switches a LED, takes a picture and sends it via email
 * according to the state of the sensors output pin.
 * Determines the beginning and end of continuous motion sequences.
 *
 * @author: Stefano Guglielmetti / stefano (at) mikamai (dot) com / http://jeko.net
 * @date:   feb 5, 2014  
 *
 * based on the example by Kristian Gohlke / krigoo (_) gmail (_) com / http://krx.at
 * http://playground.arduino.cc/Code/PIRsense
 *
 * stefano guglielmetti (cleft) 2014 
 *
 * released under a creative commons "Attribution-NonCommercial-ShareAlike 2.0" license
 * http://creativecommons.org/licenses/by-nc-sa/2.0/de/
 *
 *
 * The Parallax PIR Sensor is an easy to use digital infrared motion sensor module. 
 * (http://www.parallax.com/detail.asp?product_id=555-28027)
 *
 * The sensor's output pin goes to HIGH if motion is present.
 * However, even if motion is present it goes to LOW from time to time, 
 * which might give the impression no motion is present. 
 * This program deals with this issue by ignoring LOW-phases shorter than a given time, 
 * assuming continuous motion is present during these phases.
 *  
 */

#include <Bridge.h>

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 10;        

//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 5000;  

boolean lockLow = true;
boolean takeLowTime;  

int pirPin = 6;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;

Process p;
String imageName;

/////////////////////////////
//SETUP
void setup(){
  Bridge.begin();
  Serial.begin(9600);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

////////////////////////////
//LOOP
void loop(){

  if(digitalRead(pirPin) == HIGH){
    digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
    if(lockLow){  
      //makes sure we wait for a transition to LOW before any further output is made:
      lockLow = false;            
      Serial.println("---");
      Serial.print("motion detected at ");
      Serial.print(millis()/1000);
      Serial.println(" sec"); 

      imageName = uniqueFileName("png"); //generate a new, uniqe file name

      p.runShellCommand("fswebcam /mnt/sda1/" + imageName); //takes the picture
      while(p.running()); //wait till the process ends
      p.runShellCommand("madplay /mnt/sda1/sounds/sirena.mp3"); //play the siren sound
      while(p.running()); //wait till the process ends
      p.runShellCommand("python /mnt/sda1/sendemail.py /mnt/sda1/" + imageName); //sends the picture via email
      while(p.running()); //wait till the process ends

      delay(50);
    }         
    takeLowTime = true;
  }

  if(digitalRead(pirPin) == LOW){       
    digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

    if(takeLowTime){
      lowIn = millis();          //save the time of the transition from high to LOW
      takeLowTime = false;       //make sure this is only done at the start of a LOW phase
    }
    //if the sensor is low for more than the given pause, 
    //we assume that no more motion is going to happen
    if(!lockLow && millis() - lowIn > pause){  
      //makes sure this block of code is only executed again after 
      //a new motion sequence has been detected
      lockLow = true;                        
      Serial.print("motion ended at ");      //output
      Serial.print((millis() - pause)/1000);
      Serial.println(" sec");
      delay(50);
    }
  }
}


/* A simple function to generate unique timestamp based filenames */

String uniqueFileName(String ext){
  String filename = "";
  p.runShellCommand("date +%s");
  while(p.running()); 

  while (p.available()>0) {
    char c = p.read();
    filename += c;
  } 

  filename.trim();
  filename += "." + ext;

  return filename;
}  

After 10 seconds (calibration time) it will start working and making pictures!!!

This is the assembled project

assembled

All the files of this project are available in my GitHub account

…and check the Youtube Video again!

I really hope you enjoyed this project!

Cheers, Stefano

Arduino Yún social photo camera

After making an USB Audio card work with Arduino Yún, the logical second step was try to use an USB camera instead, and it worked! I was so amazed by this new huge set of possibilitities to create, that I started a little weekend project: to build an Arduino based Facebook photo camera

I was so into this project that I didn’t realize that, even if the single steps are very simple, they’re quite a lot! So I decided to write this step-by-step tutorial and to split it into … articles.

Just to be clear:

The goal

To build photocamera that shoots pictures and publishes them directly to a specific Facebook Album.

Ingredients

The Steps

  1. Install the USB Camera on Arduino Yún
  2. Take your first picture
  3. Create the Facebook Application
  4. Post your first picture with the Temboo API
  5. Install the Temboo SDK on Arduino Yún
  6. Make the python script and publish your first photo to Facebook from Arduino
  7. Create the Arduino sketch
  8. Put everything together

1. Install the USB Camera on Arduino Yún

I assume that your Arduino Yún is already configured for wi-fi (or connected via the Ethernet port), and that you have SSH access to it, if not, follow this link to configure the wifi network and this link to connect via SSH.

The UVC package is already available fot Linino via opkg, so installing the Camera is a very easy step, just connect to your Yún via ssh and type

$ opkg update
$ opkg install kmod-video-uvc

We also need a software for taking pictures, I used fswebcam that is supersmall and very easy to use

$ opkg install fswebcam

Now we can test it!

2. Take your first picture

First of all, be sure to use and SD card for storage or you will quickly fill the Arduino internal storage, and you don’t want to do that. If you are using an SD card, you should see it mounted in /mnt/sda1. If it’s not, put a FAT32 formatted micro SD card into the SD Card Slot, and reboot your Arduino

Now plug the camera to the USB host port, and type

$ cd /mnt/sda1
$ fswebcam test.png

If everything is ok, you took your first picture!

This means that now we can take pictures from our Arduino sketch, via the Yún’s Bridge library, in this way

Process.runShellCommand("fswebcam /mnt/sda1/test.png");

Now we will learn how to share them on Facebook using Temboo.

3. Create the Facebook Application

This is easy, but you must be a Facebook developer to do that. That simply means that you have to accomplish these easy steps before starting. Done? ok! So now let’s create a blank Facebook Application

image creation

and configure it in this way:

configuration

 Create a Temboo Application

First of all, register on Temboo. When you’re in, create a new application, then go to https://temboo.com/library/Library/Facebook/Publishing/UploadPhoto/

add new credentials for the new Facebook app.

temboo config

Choose oAuth wizard, go directly to the third step and copy and paste the app id & app secret from your Facebook application.

Go to the next step, click on launch authorisation and grant the authorisation to the Facebook application.

Now you have the access token

Click on use these values and save, copy and paste the access token in the access token form field if needed.

Now you need the target album id. to get an album id, just go on Facebook, open an album (not a single photo) and the URL will look like this.

albumid

The album id is the highlighted part. copy and paste it into the AlbumID field on Temboo

I also choose to open the Optional Input section and to put a custom message 🙂

message

If you take a look to the sample code, Temboo has made pretty much all the job for you, but we need to make some changes, we will make them later. Now we need some gratification, so let’s post our first picture!

4. Post your first picture with the Temboo API

You already put your Access Token and the desired AlbumID. The only thing that’s missing is the Base64 Encoded image. So go to http://www.freeformatter.com/base64-encoder.html and paste the URI of the image you want to encode, then copy the encoded string and paste it into the Temboo interface.

https://i0.wp.com/i.imgur.com/DT1Ij8U.png?w=640

Click TRY IT OUT and voilà, the image it’s magically posted on your album!

5. Install the Temboo SDK on Arduino Yún

We will use the Temboo API from a Python script, so we need to download the SDK. The download page is here https://temboo.com/download, all we have to do is download the Python SDK and unzip it into the root folder of your Micro SD card (it will unzip into a /temboo folder).

A very important step is installing OpenSSL support for Python, as the Temboo libraries will try to use SSL to publish the photos.

$ opkg update
$ opkg install python-openssl

6. Make the python script and publish your first photo to Facebook from Arduino

As I wrote before, the generated code from Temboo is a good starting point, but we need to make some modifications in order to make it work.

# Instantiate the Choreo, using a previously instantiated TembooSession object, eg:
# session = TembooSession('jeko', 'APP_KEY_NAME', 'APP_KEY_VALUE')
uploadPhotoChoreo = UploadPhoto(session)

# Get an InputSet object for the choreo
uploadPhotoInputs = uploadPhotoChoreo.new_input_set()

# Set credential to use for execution
uploadPhotoInputs.set_credential('ArduinoCamera')

# Set inputs
uploadPhotoInputs.set_Message("This photo has been shot and published with an Arduino Yún")
uploadPhotoInputs.set_AlbumID("")

# Execute choreo
uploadPhotoResults = uploadPhotoChoreo.execute_with_results(uploadPhotoInputs)

Download my version of the script and copy it into the root folder of the SD card. Here’s what I did.

Step number one, the encoding. I’m italian and we use a lot of accented characters, so I’ll use UTF-8 as the default script encoding, so I added

# coding=utf-8

at the top of my script. Now we need to read the photo from the disk, and to base64 encode it, so we will need the base64 and the sys libraries.

import base64
import sys

The Temboo libraries are not included in the generated script by Temboo, so we will have to add them

from temboo.core.session import TembooSession
from temboo.Library.Facebook.Publishing import UploadPhoto

The script will read the first argument, and use it as the name of the image file to encode

with open(str(sys.argv[1]), "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())

In this line you have to put your Temboo’s account name, and the app name and key (from this page)

session = TembooSession('ACCOUNT_NAME', 'APP_KEY_NAME', 'APP_KEY_VALUE')

You’ll also need to put yout access token, message (if you want one) and Album ID into the script

uploadPhotoInputs.set_AccessToken("ACCESS_TOKEN")
uploadPhotoInputs.set_Message("MESSAGE")
uploadPhotoInputs.set_AlbumID("ALBUM_ID")   

The rest of the script is basically identical to the Temboo’s example.

We can now try to publish our first photo with the script!

$fswebcam testpic.jpg
$python sendphoto.py testpic.jpg 

At this point I strongly hope that it’s working for you as it’s working for me (otherwise contact me and we will try to solve the problem together) because you have just published your first picture to Facebook with Arduino! The only missing step is to make an Arduino sketch to take and send the picture without using SSH

7. Create the Arduino sketch

I started from the basic “Button” example, as I wanted the camera to be triggered by a simple Pushbutton. The circuit is the same of the button example. Just download this arduino sketch

you can customise the LED and Button pin if you want

const int buttonPin = 2; // pin for the pushbutton 
const int ledPin =  13; // pin for the status led

as well as the path for the photos and the Python script (important! this folder must contain the Temboo SDK)

String path = "/mnt/sda1/"; // path of the images and script file 

The setup is pretty simple, we will use the Bridge library to invoke the Python script, and the Serial library for a very basic debugging

void setup() {
    Bridge.begin(); // The bridge library is used to run processes on the linux side
    pinMode(ledPin, OUTPUT);      
    pinMode(buttonPin, INPUT); 
    Serial.begin(57600); // Serial port for debugging
    filename = "test";
}

Then, when the pushbutton is pressed, the script generates a new timestamp based filename running the “date +%s” command

if (buttonState == LOW) {
    filename = "";
    p.runShellCommand("date +%s"); //generate a timestamp
    while(p.running()); // wait until the command has finished running

    while (p.available()>0) {
        char c = p.read(); //reads the first available character
        filename += c; //and adds it to the filename string
    } 

    filename.trim(); //used to avoid trailing spaces or newline characters
    filename += ".png"; //finally I add the png extension

This part of the code will take the picture and send it to Facebook using the Bridge library

p.runShellCommand("fswebcam " + path + filename); //let's take the picture
while(p.running());  //waits till the picture is saved
Serial.println("picture taken"); 

p.runShellCommand("python " + path + "sendphoto.py " + path + filename); //sends the picture to facebook 
while(p.running()); 
Serial.println("picture sent"); //last debug message    

8. Put everything together

Ok! Everything is ready! Just upload the code to Arduino, push the button and… Smile!! You’re on Facebook! 🙂

I really hope that you enjoyed this tutorial, it opens a lot of possibilities! Trap cameras, cameras triggered by doors, by sounds or any kind of sensor… I’d really like to see your projects and share them!

Cheers and happy hacking!

Stefano