Twitter Mood Light – The World’s Mood in a Box using arduino

How’s the world feeling right now? This box tells you.

Powered by: an Arduino, a WiFly wireless module, an RGB LED, and a 9v battery.

I’m a news junkie. I want to know everything that is going on in the world as soon as it happens. I want to wake up and know immediately if something big has happened overnight.

However, I’m an extraordinarily busy man; I don’t have time to read news feeds; reading that headline that I already knew about or don’t care about is time that I’m never getting back!

No. What I need is some way to be constantly in touch with the world’s events as they unfold, alerted when something big happens, and to be made aware of it all faster than awareness itself!

…A way to get a glimpse of the collective human consciousness as an extension of my own.  Something that I don’t have to continually check or poll, but instead, like a part of my body, it will tell me when it’s feeling pain or generally in need of my attention …leaving me time to get on with other things.

And so, I present: The World Mood in a Box!

The Arduino connects directly to any wireless network via the WiFly module, continually searches Twitter for tweets with emotional content, collates the tweets for each emotion, does some math, and then fades the color of the LED to reflect the current World Mood; Red for Anger, Yellow for Happy, Pink for Love, White for Fear, Green for Envy, Orange for Surprise, and Blue for Sadness.

If an unexpectedly high number of tweets of a particular emotion are found, then the LED will flash to alert us to the possibility of a world event that has caused this unusually strong emotional reaction.

For example, a world disaster and it may flash Blue or Red (sadness or anger), if the strong favourite loses a big football game it may fade to Orange (surprise), …and If it flashes White, the collective human mind is feeling extreme fear, and it’s probably best to go hide in a cupboard and sit it out, waiting for sunnier skies and a return to Yellow or Pink.  …OK, I’m not that busy.

Twitter Mood Light

Step 1: How it works

An Arduino connects directly (no computer required!) to any wireless network via the WiFly module, repeatedly searches Twitter for tweets with emotional content (aka sentiment extraction or tapping into the moodosphere), collates the tweets for each emotion, analyzes the data, and fades the color of an LED to reflect the current World Mood:

  • Red for Anger
  • Yellow for Happy
  • Pink for Love
  • White for Fear
  • Green for Envy
  • Orange for Surprise
  • Blue for Sadness

Example search terms to find tweets that may express surprise:

  • “wow”
  • “can’t believe”
  • “unbelievable”
  • “O_o”

If an unexpectedly high number of tweets of a particular emotion are found, then the LED will flash to alert anyone nearby to the possibility of a big world event that has caused this unusually strong emotional reaction.

Example signals:

  • A world disaster and it may flash Blue or Red indicating it best to check a news site to see why everyone is so sad and/or angry.
  • If the strong favourite loses a big football game, it may flash Orange to express the surprise at this unlikely event.
  • If there is a heat wave in London it might turn Yellow to reflect how much happier people now are.
  • If it flashes White, the collective human consciousness is feeling extreme fear and something terrifyingly bad is probably about to happen. Time to hide and/or panic.


  • You could put it on your desk to get an early warning of something big happening somewhere in the world
  • A literal ‘mood light’ at a party or a game whereby you guess what colour it will change to next and for what reason
  • A world mood barometer perhaps next to your bed to decide if it is best to hit snooze until it’s less angry outside
  • A gauge of public sentiment to help you decide when to sell all your stocks and shares, and head to the hills.
  • In a foyer or waiting area or other public space for people to look at and contemplate.
  • Set it to connect to any wireless network and carry it around in the streets, stopping strangers to explain to them that you have managed to capture the world’s mood and have it locked in this here box.

Step 2: All you need is…

I ordered most of the electronics from Sparkfun, and picked up the rest from the local Radioshack. The acrylic I got from a local plastic shop(!) – they cut it and drilled a hole free of charge.


The Acrylic Box

  • 1 x (5″ x 5″ x 0.25″) – the top
  • 4 * (4.75″ x 4.75″ x 0.25″) – the 4 walls
  • 1 x (4.5″ x 4.5″ x 0.25″) – the base
  • 1 x (4.5″ x 4.5″ x 0.125″) – the mirror with a 6mm hole drilled in the middle
  • 4 x (4.25 x 1″ x 0.25″) – the 4 inside walls
  • Acrylic solvent cement
  • Sand paper (to help diffuse the light)


  • Soldering iron
  • A computer
  • Arduino development environment
  • A wireless network (802.11b/g)
  • Pliers
  • Wire stripper

Useful links

The Arduino development tools can be downloaded from here:

and Arduino tutorials start here:

Arduino / WiFly:


Step 3: Connect the Arduino and WiFly to a computer

Sparkfun have a decent tutorial on how to do this:

Firstly, the Wifly breakout board needs to be stacked on top of the arduino and the RX, TX, Vin, Gnd, pin 10, pin 11, pin 12 and pin 13 needed to be connected. I used breakaway headers and soldered the required pins.

Connect to a computer using an A to B USB cable.

Download the Arduino software from here:

Check that you can compile and upload a sample program by following the instructions here:
(remember to set the board and COM ports correctly)

Step 4: Connecting the LED

Only some pins provide 8-bit PWM (Pulse-width modulation)
This gives 256 steps of control from full off (0) to full on (255) for each of the Red, Green and Blue channels of the LED.
PWM pins on the Arduino are 3,5,6,9,10,11. (see
I used 3, 5 and 6.

I used the pliers to bend the legs of the LED, and mounted it on the circuit board. Each resistor is then mounted next to each of the RGB legs, and the wires are twisted together. Then I added the 4 connecting wires and twisted them. Finally, I soldered all the connections.

Note: The pictures illustrate using the same resistor for each colour channel, but I should have used the resistance levels in the data sheet:

180 Ohm for Red
100 Ohm for Green
100 Ohm for Blue

Also note, I covered the back with insulating tape to stop any shorts when putting it all into the box.
Also, from the datasheet, “the Sensor inputs SENS0-7 are extremely sensitive to over voltage. Under no conditions should these pins be driven above 1.2VDC. Placing any voltage above
this will permanently damage the radio module and render it useless.”

Step 5: Choosing good search terms

Twitter allows you to search for recent tweets that contain particular words or phrases.

You can search for tweets that contain any of a list of phrases by using the “+OR+” conjunction.

For example, here is a search request that might find tweets that express Fear:

GET /search.json?q=”i’m+so+scared”+OR+”i’m+really+scared”+OR+”i’m+terrified”+OR+”i’m+really+afraid”+OR+”so+scared+i”&rpp=30&result_type=recent

I spent a long time finding good search phrases.

The search phrases needed to produce tweets that:

  1. very often express the desired emotion.
  2. very rarely express the opposite emotion or no emotion.

Many search phrases that I thought would work, turned out to not work that well when I searched with them.

Smileys have been used with some success to extract whether the sentence is positive or negative, but I didn’t find them useful for extracting anything more.

The trouble with smileys is that a smile can mean so many things ;D

It is often used, it seems, as a kind of qualifier for the whole sentence; since people have to compress their thoughts into 140 characters, the meaning can become ambiguous.

The smiley often then acts as a qualifier that:

  • ‘this is a friendly comment’
  • ‘don’t take this the wrong  way’
  • ‘i am saying hello/goodbye with a smile’
  • ‘this is almost a joke’
  • ‘I know I’m being cheeky’
  • ‘I don’t really mean this’

Phrases using adverbs seemed to produce better results.
“so scared” or “really scared” is better than just “scared” which returns bad results: for example, “not scared”.

Phrases in the first person seemed to produce better results.
Some search phrases give tweets that suggest the author feels the emotion: for example, “i really hate…”, often sounds like they really are full of hate or angry, whereas other phrases containing the word “hate” give tweets that do not seem to express much emotion, like “why do you hate…”

Hyperbole is your best friend, ever:
Using phrases with hyperbole produced good results. Tweets with “I’m terrified” or “I’m petrified” in them were generally more fearful sounding than “I’m scared”

Regardless, the approach is still naive, but statistically, from my tests, it does seem to work well.

While testing the code, I did at one point get the horribly ominous “Flashing White” that signifies the world is feeling intense fear, but since I was still testing it all, I did not hide under the table straight away, but instead, threw caution to the winds, and went on to Twitter to see what people were suddenly so fearful about.

The recent tweets containing the Fear search string (see top of page) were largely relating to a large thunderstorm that had just started somewhere near Florida.

If you’re interested, here are some of those tweets:

  • “Ahhh Thunder I’m so scared of Thunder !!!!! Help some 1”
  • “I’m so scared of lightning now. Like I just ran home praying “
  • “On our way to Narcosses at @Disney world’s Grand Floridian hotel and there’s a tropical storm right now. I’m terrified! …”
  • “I’m in my bathroom til the rain stops. I’m terrified of lightning and thunder…”
  • “I’m terrified of thunder storms *hides in corner*”
  • “I’m terrified of Thunder :(“
  • “If only I was wit my becky during this thunderstorm cause I’m really scared cause of a bad experience”

So… it works! …Well, it needs the numbers tweaking to ignore the world’s “tantrums”, the short-lived fits of emotional outburst, and be more concerned with larger changes that signify bigger news.

Step 6: Download the code

The attached contains 4 subdirectories (or “libraries”) and the Arduino sketch WorldMood.pde

The four libraries need to be copied into the Arduino library directory and then they can be imported as shown.

WorldMood/WorldMood.pde (see below) should be opened in the Arduino development environment.

You then need to correct the “[your network]” and “[your network password]” fields. eg.

#define network (“mynetwork”)
#define password (“mypassword”)

Then the sketch (and libraries) should be compiled and uploaded to the Arduino board.


The next 5 programming steps just give an overview of each of the components and include the most noteworthy parts of the source code…

**** Update ****

If you have a newer board then you may need to change this

struct SPI_UART_cfg SPI_Uart_config = {0x50,0x00,0x03,0x10};

to this:
struct SPI_UART_cfg SPI_Uart_config = {0x60,0x00,0x03,0x10};

See here for more info:

***** End Update ****

// LED setup – only some pins provide 8-bit PWM (Pulse-width modulation)
// output with the analogWrite() function.
// PWM: 3,5,6,9,10,11
#define redPin    (3)
#define greenPin (5)
#define bluePin   (6)
// delay in ms between fade updates
// max fade time = 255 * 15 = 3.825s
#define fadeDelay (15)
// Wifi setup
#define network ([your network])
#define password ([your network password])
#define remoteServer (“”)
const char* moodNames[NUM_MOOD_TYPES] = {
const char* moodIntensityNames[NUM_MOOD_INTENSITY] = {
// the long term ratios between tweets with emotional content
// as discovered by using the below search terms over a period of time.
float tempramentRatios[NUM_MOOD_TYPES] = {
// these numbers can be tweaked to get the system to be more or less reactive
// to be more or less susceptible to noise or short term emotional blips, like sport results
// or bigger events, like world disasters
#define emotionSmoothingFactor (0.1f)
#define moodSmoothingFactor (0.05f)
#define moderateMoodThreshold (2.0f)
#define extremeMoodThreshold (4.0f)
// save battery, put the wifly to sleep for this long between searches (in ms)
// Store search strings in flash (program) memory instead of SRAM.
// edit TWEETS_PER_PAGE if changing the rpp value
prog_char string_0[] PROGMEM = “GET /search.json?q=\”i+love+you\”+OR+\”i+love+her\”+OR+\”i+love+him\”+OR+\”all+my+love\”+OR+\”i’m+in+love\”+OR+\”i+really+love\”&rpp=30&result_type=recent”;
prog_char string_1[] PROGMEM = “GET /search.json?q=\”happiest\”+OR+\”so+happy\”+OR+\”so+excited\”+OR+\”i’m+happy\”+OR+\”woot\”+OR+\”w00t\”&rpp=30&result_type=recent”;
prog_char string_2[] PROGMEM = “GET /search.json?q=\”wow\”+OR+\”O_o\”+OR+\”can’t+believe\”+OR+\”wtf\”+OR+\”unbelievable\”&rpp=30&result_type=recent”;
prog_char string_3[] PROGMEM = “GET /search.json?q=\”i+hate\”+OR+\”really+angry\”+OR+\”i+am+mad\”+OR+\”really+hate\”+OR+\”so+angry\”&rpp=30&result_type=recent”;
prog_char string_4[] PROGMEM = “GET /search.json?q=\”i+wish+i\”+OR+\”i’m+envious\”+OR+ \”i’m+jealous\”+OR+\”i+want+to+be\”+OR+\”why+can’t+i\”+&rpp=30&result_type=recent”;
prog_char string_5[] PROGMEM = “GET /search.json?q=\”i’m+so+sad\”+OR+\”i’m+heartbroken\”+OR+\”i’m+so+upset\”+OR+\”i’m+depressed\”+OR+\”i+can’t+stop+crying\”&rpp=30&result_type=recent”;
prog_char string_6[] PROGMEM = “GET /search.json?q=\”i’m+so+scared\”+OR+\”i’m+really+scared\”+OR+\”i’m+terrified\”+OR+\”i’m+really+afraid\”+OR+\”so+scared+i\”&rpp=30&result_type=recent”;
// be sure to change this if you edit the rpp value above
#define TWEETS_PER_PAGE (30)
PROGMEM const char *searchTwitter Mood LightStrings[] =
void setup()
void loop()
 // create and initialise the subsystems
 WiFly wifly(network, password, SLEEP_TIME_BETWEEN_SEARCHES, Serial);
 WorldMood worldMood(Serial, emotionSmoothingFactor, moodSmoothingFactor, moderateMoodThreshold, extremeMoodThreshold, tempramentRatios);
 LED led(Serial, redPin, greenPin, bluePin, fadeDelay);
 TwitterParser twitterSearchParser(Serial, TWEETS_PER_PAGE);
 char searchString[160];
 while (true)
    for (int i = 0; i < NUM_MOOD_TYPES; i++)
      // read in new search string to SRAM from flash memory
      strcpy_P(searchString, (char*)pgm_read_word(&(searchStrings[i])));
      bool ok = false;
      int retries = 0;
      // some recovery code if the web request fails
      while (!ok)
      {ok = wifly.HttpWebRequest(remoteServer, searchString, &twitterSearchParser);
        if (!ok){Serial.println(“HttpWebRequest failed”);
          if (retries > 3)
           wifly.Reset();  retries = 0;}}}
      float tweetsPerMinute = twitterSearchParser.GetTweetsPerMinute();
      // debug code
      Serial.print(“: tweets per min = “);
      worldMood.RegisterTweets(i, tweetsPerMinute); }
    MOOD_TYPE newMood = worldMood.ComputeCurrentMood();
    MOOD_INTENSITY newMoodIntensity = worldMood.ComputeCurrentMoodIntensity();
    Serial.print(“The Mood of the World is … “);
    Serial.print(” “);
    led.SetColor((int)newMood, (int)newMoodIntensity);
    // save the battery
    // wait until it is time for the next update

About The Author

Scroll to Top