Alex Swan
Published © MIT

Internet Connected Bubble Machine

Make it possible to activate a bubble machine from anywhere using a Particle Photon.

BeginnerFull instructions provided1 hour950
Internet Connected Bubble Machine

Things used in this project

Hardware components

Photon
Particle Photon
×1
Darlington High Power Transistor
Darlington High Power Transistor
This is the one pictured, and the one I used because it's what the local Radio Shack had available. You can also use a 2N2222 NPN transistor.
×1
Amazing Bubbles Bubble Fountain
I found this one at a grocery store. The nice part about this one is the original power button was an on/off toggle. Any battery powered bubble machine should work.
×1

Story

Read more

Schematics

Bubble Machine Schematic

Physical Breadboard layout

Code

bubbles.ino

C/C++
Use this code in the Particle Firmware IDE.
// This #include statement was automatically added by the Particle IDE.
#include <elapsedMillis.h>

// -----------------------------------------
// Publish and Subscribe Bubble Machine
/* -----------------------------------------

Listen for events on one channel, start and stop a bubble machine
for a few seconds for each event.

------------------------------------------*/


int bubbles = D1;
int boardLed = D7;

elapsedMillis bubblesElapsed;
elapsedMillis ledElapsed;
bool bubblesOn = false;
bool ledOn = false;
unsigned int bubblesInterval = 5000;
unsigned int ledInterval = 250;

// We start with the setup function.

void setup() {
  pinMode(boardLed,OUTPUT); // Our on-board LED is output as well
  pinMode(bubbles,OUTPUT);
  
  bubblesElapsed = 0;
  ledElapsed = 0;

  // Here we are going to subscribe to your buddy's event using Particle.subscribe
  Particle.subscribe("alexboldit_bubbles_command", myHandler);
  // Subscribe will listen for the event buddy_unique_event_name and, when it finds it, will run the function myHandler()
  // (Remember to replace buddy_unique_event_name with your buddy's actual unique event name that they have in their firmware.)
  // myHandler() is declared later in this app.
  
  // Variables to be watched
  Particle.variable("bubblesOn", bubblesOn);
  Particle.function("bubbles", handleStartBubbles);
}


void loop() {
    if( bubblesOn && bubblesElapsed > bubblesInterval ) {
        stopBubbles();
    }
    if( ledOn && ledElapsed > ledInterval ) {
        stopLed();
    }
}


// Now for the myHandler function, which is called when the cloud tells us that our buddy's event is published.
void myHandler(const char *event, const char *data)
{
    // Flash the boardLed to see when people send messages
    startLed();
    if (strcmp(data,"bubbles")==0) {
        startBubbles();
    } else {
        
    }
}


void startLed() {
    ledOn = true;
    ledElapsed = 0;
    digitalWrite(boardLed,HIGH);
}


void stopLed() {
    digitalWrite(boardLed,LOW);
    ledOn = false;
}


int handleStartBubbles(String command) {
    startBubbles();
}

void startBubbles() {
    bubblesOn = true;
    bubblesElapsed = 0;
    digitalWrite(bubbles,HIGH);
    Particle.publish("alexboldit_bubbles_status","on");
}


void stopBubbles(){
    digitalWrite(bubbles,LOW);
    Particle.publish("alexboldit_bubbles_status","off");
    bubblesOn = false;
}

index.html

HTML
A basic web page to control the flow of bubbles
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, minimum-scale=.1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Bubbles</title>

    <!-- Bootstrap -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <style>
    img {
        max-height:100vh;
    }
    h1 {
        text-align:center;
    }
    .container {
        max-width:1080px;
    }
    </style>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-cs-12">
                <h1>Make the World a More Bubbly Place!</h1>
            </div>
            <div class="col-xs-12">
                <button id="bubblesButton" class="btn btn-primary btn-lg btn-block" onclick="moreBubbles()">More Bubbles</button>
            </div>
        </div>
        
    </div>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="//cdn.jsdelivr.net/particle-api-js/5/particle.min.js"></script>
    <script type="text/javascript">
        !function () {
            var particle = new Particle();
            var token = "abcdefghijklmnopqrstuvwxyz1234567890abcd"; // Your Photon access token
            var deviceId = "123456789012345678901234"; // Your Photon's deviceId

            particle.getEventStream({ deviceId: deviceId, auth: token }).then(function(stream) {
              stream.on('alexboldit_bubbles_status', function(data) {
                console.log("Event: " + JSON.stringify(data));
                document.getElementById("bubblesButton").disabled = (data.data == "on");
              });
            });

            // Get the bubbles state
            $.get('https://api.particle.io/v1/devices/' + deviceId + '/bubblesOn?access_token=' + token, function(data){
                // Enable/disable the button
                document.getElementById("bubblesButton").disabled = (data.result == "true");
            });


            moreBubbles = function() {
                console.log("more bubbles");
                document.getElementById("bubblesButton").disabled = true;
                particle.publishEvent({ name: 'alexboldit_bubbles_command', data: "bubbles", auth: token });
            }

        }();
    </script>
</body>
</html>

Credits

Alex Swan

Alex Swan

4 projects • 13 followers

Comments