Category: Causual Encounters

A platform for casual encounters with interactive technology – Making Noise

…you should be able to get this working about 2 minutes…

(Looking for Part 1 of this series?)

Next we are going to let people specify a value rather than just on or off.  Let’s let them pick the frequency of a tone!

Here is what it looks like…

Step-by-step setup instructions…

  1. We will start with a stock Yun out of the box. You can reset your Yun back to this state by pushing and holding the “Wifi Reset” button for 30 seconds.
  2. Connect a speaker between pin 8 and ground on the Yun, like this…
    Yun With Speaker
  3. Connect the Yun to your computer – probably via USB. Make sure you select the correct port under Tools->Port and the Yun board under Tools->Board.
  4. Copy/paste the BeepMeSetup sketch [GET CODE] into your Arduino IDE and upload it to the Yun.  You can connect via Serial Monitor in the IDE after the upload completes if you want to watch the action, but it is not necessary.
  5. Wait for the red LED to start blinking a steady once per second. This will let you know that the setup script has completed. It takes about a minute to finish – longer if you recently rebooted the board.
  6. Copy/paste the BlinkMe sketch [GET CODE] into your Arduino IDE and upload it to the Arduino Yun.
  7. Take out your cellphone and connect to the new BeepMe Wifi network coming from the Yun.
  8. Make some noise! Yeay!

The full code for this project is available on GitHub here.

HOW IT WORKS

To get the value from the webpage to the Arduino sketch, we added a new “TONE” command that consists of the letter “T” followed by a 5 digit number specifying the frequency of the tone. So, “T0100” would request a 0100Hz tone.

First let’s a the new tone command to the Arduino sketch. Note we also have to increase the size of the command buffer since this new command can be 6 bytes long. Here is the updated Arduino code…

// Connect a speaker here
#define TONE_PIN 8

 // Forgiving parse of an unsigned int from a string. All non-digits simply ignored.

unsigned int parseUnsignedInt( const char *s , int len ) {

   unsigned int x=0;
 
   while (len--) {
 
      if (isdigit(*s)) {
 
        x*=10;
         x+=(*s)-'0';
 
      }
 
      s++;
 
   }
 
 return(x);

}

// Understood command string formats:
// 'Tnnnnn' where nnnnn is 5 digit frequency specifier - Geneate a tone
// 'N' - Stop any playing tone

#define COMMAND_LEN 6

void processCommand( const char *commandString ) {

  // Use the first byte to specifiy action...
 
  switch (commandString[0]) {
      
    case 'T':  { // Generate a tone of the frequency specified by the 5 digit number after the action...
    
      unsigned int freq = parseUnsignedInt( commandString + 1 , 5 );
    
      if (freq >=50 && freq<=5000 ) {    // Just some sanity checks...
        
          tone( TONE_PIN , freq );   // Play the specified tone
      }
      
      break;
    }
      
    case 'N': {  // Stop any currently playing tone
    
      noTone( TONE_PIN );
      break;
      
    }
      
  }
   
}

// This is the default baud rate for the serial link
#define LININOBAUD 250000 

void setup() {

    Serial1.begin(LININOBAUD); // open serial connection to Linino

}

// We to use this string to indicate where the command is inside the request string...
// Mast match the command string sent by the HTML code
#define COMMAND_PREFIX "COMMAND="

// This is the expected length of the incoming command. For now just turnong on/off so only need 1 bytes

char commandBuffer[COMMAND_LEN];

void loop() {

 // Does this look like a command request?
 if (Serial1.find(COMMAND_PREFIX)) {

    // Read it into the command buffer and only process if long enough...
    if ( Serial1.readBytes( commandBuffer , COMMAND_LEN ) == COMMAND_LEN ) {
      
      processCommand( commandBuffer );
      
    }
  }
}

 

I also added a new “N” command to turn the tone off (it can get annoying). Note again that our code will fail harmlessly if it gets anything unexpected – this is important because we can’t control what hackers might send us over the HTTP link.

Next wel need to update the HTML to let people send the new command.

 

Here is what the new HTML looks like…

<!DOCTYPE html><title>Beep Me</title><body><center>
<script>
  function send(s) {
     r=new XMLHttpRequest();
     r.open('GET','/cgi-bin/control.cgi?COMMAND='+s+'&'+(new Date()).getTime(),false);
     r.send(null);
  }
</script>
<H1>TONE GOES</H1>
<input type='range' id='freq' min='50' max='5000'><br>
<button onclick='send( "T"+("00000"+document.getElementById("freq").value).slice(-5));'>Play</button>
<button onclick='send( "N");'>Stop</button>
</center></body>
 

..and let the tones play!

Hopefully now you can new imagine how you might let people control anything using this system.

A platform for casual encounters with interactive technology – Getting Started

…you should be able to get this working about 2 minutes…

For a super-simple starter project, we will let passers-by remotely control the built-in red LED on the board. Boring – but you should be able to get this working about 2 minutes and it will be easy to extend to more exciting encounters later.

Here is what it looks like…

 

Step-by-step setup instructions…

  1. We will start with a stock Yun out of the box. You can reset your Yun back to this state by pushing and holding the “Wifi Reset” button for 30 seconds.
  2. Connect the Yun to your computer – probably via USB. Make sure you select the correct port under Tools->Port and the Yun board under Tools->Board.
  3. Copy/paste the BlinkMeSetup sketch [GET CODE] into your Arduino IDE and upload it to the Yun.  You can connect via Serial Monitor in the IDE after the upload completes if you want to watch the action, but it is not necessary.
  4. Wait for the red LED to start blinking a steady once per second. This will let you know that the setup script has completed. It takes about a minute to finish – longer if you recently rebooted the board.
  5. Copy/paste the BlinkMe sketch [GET CODE] into your Arduino IDE and upload it to the Arduino Yun.
  6. Take out your cellphone and connect to the new BlinkMe Wifi network coming from the Yun.
  7. Make the light blink! Yeay!

The full code for this project is available on GitHub here.

How It Works

The BlinkMe control webpage has two buttons – on and off…

BlinkMe UI

Here is the HTML code for the controller page…

<!DOCTYPE html>
<title>Control Me</title>

<script>
function send(s) {
	r=new XMLHttpRequest();
	r.open('GET','/cgi-bin/control.cgi?COMMAND='+s+'&'+(new Date()).getTime(),false);
	r.send(null);
}
</script>

<center>
   <H1>LED GOES</H1>
   <button onclick='send(1);'>On</button>
   <button onclick='send(0);'>Off</button>
   <hr>
</center>

You can see that the on button has a send(“1”) and the off button has a send(“0”) wired to it. There is nothing special about the values “1” and “0” – whatever is in the send is what gets eventually to our code running on the Arduino.

Now let’s look at that code running on the Arduino side that receives these commands. Check out the loop function in BlinkMe.c

   ...
void processCommand( const char *commandString ) {

  // Use the first byte to specifiy action...
 
  switch (commandString[0]) {
      
    case '0':
     
    pinMode( LED_PIN, OUTPUT );
     digitalWrite( LED_PIN , LOW );      // Turn off the LED
     break;
     
     
    case '1':
     digitalWrite( LED_PIN , HIGH );      // Turn on the LED
     break;
              
  }
         
}
   ...

We are checking the first character of the received command and if it is “1” then we turn on the LED and if it is “0” then we turn off the LED.  Note that we are ignoring anything else that might be received after the “1” or “0”, and we fail gracefully if there is anything that is not a “1” or a “0”. This is important because people could theoretically send anything they wanted to the Yun over the open link and we want to make sure they that can’t cause any problems.

If you can’t wait to put this out in public, make sure you change the root password on the Yun to something besides the default of “arduino” or else someone can pwn your setup. To change the password, connect to the Yun over Wifi and pull up the admin pages at http://192.168.240.1/luci.

Tune in next time when we will add a slightly more complicated (and annoying!) feature!

FAQ

Q: Why not use the sketch /www subdirectory to get the HTML files onto the Arduino?
A: This feature seems to require you to have an SD card mounted and then you need to manually execute shell commands to get it to work. Just seemed easier to ECHO the files from an easily downloaded setup sketch. Please let me know if I am missing somewhere here.

Q: Why do you run a second uhttpd server on port 8080?
A: This secondary server does nothing but issue HTTP 302 redirects back to the primary server, which serves the control page. But why do we need this? Because we don’t know what page the phone is going to ask for, so we must be ready to serve a redirect for any page (including root). I could not find a good way to have a single uhttpd server that could both serve normal pages and also serve a CGI script for any other requested but not found pages.

Q: How did you get the control screen to pop up automatically upon Wifi connection?
A: This is easy for iPhones- as long as you give them a redirect when they ask for their magic “phone home” page, they will generate the login popup. Android phones seem to be more picky – none of the Android phones I tried will generate a popup if the redirect target webserver is on the same subnet as the phone itself. Instead the phone sits there and eventually says “internet connection is unstable”. To get around this, I use a DNSMASQ alias to send all web requests to the made-up address 1.1.1.1 just to trick them. I have never seen this documented before and even tried to find it in the Android isCaptivePortal source, but couldn’t. If you know where this behavior comes from, please let me know!

Q: Why are the buttons so tiny on my phone?
A: To keep things simple, I am using just generic HTML in these examples. In future episodes, we will use CSS to make the buttons look very nice on phones.

Q: Can I use this on other OpenWRT devices besides the Yun?
A: Sure! You can download a shell script that will directly set everything up here. Then you just have to change the /cgi-bin/control.cgi to communicate with your project how ever it is set up.

Q:Why is there a 300ms delay between when I hit the button on the webpage and when the light comes on?
A: This is caused by the mobile web browser waiting to see if you are going to double-click before sending the button press. We will fix this in later episodes.

Q: Can we do more than just turn an LED on and off?
A: Stay tuned!

Q: Is there any way to send data back from the Arduino to the web control page?
A: Stay tuned!

Q: Is there any way to log visits to the controller web page?
A: Stay tuned!

A platform for casual encounters with interactive technology – Introduction

This series of articles will show you how to easily take any Arduino project and open it up for anyone to control using their cell phone.

What can let people do?

  • Set the color of the lights on your X-mas tree as they walk by your window
  • Add their vote to a survey on a highway billboard as they drive past
  • Check the prices of items while standing in front of a store window
  • Turn on the street lights before walking down an otherwise dark alley
  • Check the temperature of the water in the community pool from the parking lot
  • Find their location and the location of others hiking in a park that has no cellphone coverage
  • Fire a water canon on your roof

We will use the Arduino Yun, which costs about $70.

The Yun will create an open Wifi network that anyone can connect to. When they connect, the a control screen automatically pops and they can immediately start interacting.

You do not need to know anything about Linux or shell scripts or Python or CGI or captive portals or IP chains. If you can make a blinking LED on an Arduino and can stumble though editing an existing HTML file, you know everything you need.

Just to get you excited, here is a project I made that lets anyone walking by control a digit of this giant clock…

It is surprisingly fun to control something that is big and far away.

FAQ

Q: Does my project need an internet connection?
A: Nope! Everything is completely self contained, so you can hide the board anyplace you can find power. In a later project we will even make a solar powered version that can live alone on the top of a mountain.

Q: Why not use m0n0wall or chillispot or another existing hotspot?
A: I tried to get some of the existing hotspots to work on the Yun but eventually it was taking longer than starting from scratch. This strategy is very simple and robust – perfect for a project you want to leave unattended for long periods of time. This is all about easy and reliable.

Q: What not use the YunServer/Bridge library functions?
A: I tried. At first, I could not fit both the YunServer and my application into the Arduino (Just adding the line “YunServer server;” to a sketch costs about 5Kb of memory!).  I spent a long time making my app smaller until I finally got everything to fit and upload, but then it would crash after a while. Turns out that the Bridge uses heap allocated C++ strings and so can cause you to run out of memory unpredictably at run time.