The LightBlue Bean is a small low energy Bluetooth Arduino microcontroller with a built in 3-axis accelerometer and temperature sensor. It’s quite an interesting way to add connectivity to objects via Bluetooth connectivity instead of Wi-Fi. It has digital and analog pins like a typical Arduino, so you can expand what it can do by adding new elements to the set up.
In order to add new elements, a bit of soldering is required. For this article, I wanted a solder-free demo that anyone with a LightBlue Bean can follow along with, so we’ll be focusing on the built in accelerometer. A few months ago, I put together an IFTTT demo here on SitePoint which automatically turns off my LIFX light when I set my Jawbone UP24 to sleep mode. It is a nice touch but I still need to get my smartphone out to turn on my lights each night. I’d prefer something more automatic and decided to try out a few technology experiments to turn the lights on in convenient ways too. In this article, I’ll cover the first of my prototypes – I’ll be using a LightBlue Bean to detect my door movements and turn my lights on or off depending on if my door is opened or closed.
For those who are a fan of the LightBlue Bean, there is a newer version of the LightBlue Bean on Kickstarter right now called the LightBlue Bean+ which looks pretty neat! It has a rechargable battery, solderless connectors and plenty more useful features. There are only a few days left to put in your pledge!
How This Will Work
Our demo will work like so:
- Stick the LightBlue Bean on the door we want to track.
- Upload an Arduino sketch which watches for accelerometer changes (the door swinging one way or the other) and sends a message via the Bean Loader Virtual Serial.
- Set up a Node server watching for the serial messages coming through.
- Set the responses to those messages in the Node server to send a HTTP request to IFTTT’s Maker channel to tell it to turn on the light.
- Set the LightBlue Bean to Virtual Serial mode.
- Run the Node server and close your door to see your light turn on!
Additional rules could be included in our Node server later on to ensure that the code only runs during certain times of day too (to avoid the light going on when it really doesn’t need to be). Or even better – add on a photo resistor to detect automatically if the light is needed!
Setting Up Your LightBlue Bean
If you are completely new to using the LightBlue Bean, you’ll need to have both the latest Arduino software and the Bean Loader software installed on your Windows 8.1 or Mac computer (apparently the Bean Loader software does not work on older Windows PCs). The guides to getting your LightBlue Bean connected up to your Mac or PC are pretty thorough on the LightBlue Bean website:
This demo has all been set up on Mac OSX but should theoretically work on Windows too.
The steps in this article will assume you are comfortable with the basics of putting a sketch onto your LightBlue Bean, if not, run through the “Getting Started” link for your OS above first.
Our Arduino Sketch Code
All the code is available on GitHub for you to use and adapt for any purpose you choose!
Our Arduino sketch contains most of the brains behind the door watching and looks like so:
int minXVal = 0;
int maxXVal = 0;
int minYVal = 0;
int maxYVal = 0;
int minZVal = 0;
int maxZVal = 0;
int movement = 15;
bool ready = false;
void setup() {
Serial.begin();
}
void loop() {
AccelerationReading acceleration = Bean.getAcceleration();
if (!ready) {
for (int i = 0; i < 100; i++) {
if (acceleration.xAxis > maxXVal) {
maxXVal = acceleration.xAxis;
} else if (acceleration.xAxis < minXVal) {
minXVal = acceleration.xAxis;
}
if (acceleration.yAxis > maxYVal) {
maxYVal = acceleration.yAxis;
} else if (acceleration.yAxis < minYVal) {
minYVal = acceleration.yAxis;
}
if (acceleration.zAxis > maxZVal) {
maxZVal = acceleration.zAxis;
} else if (acceleration.zAxis < minZVal) {
minZVal = acceleration.zAxis;
}
delay(10);
}
ready = true;
} else {
if (acceleration.zAxis < minZVal - movement) {
String stringToPrint = "CLOSED";
Serial.println(stringToPrint);
} else if (acceleration.zAxis > maxZVal + movement) {
String stringToPrint = "OPEN";
Serial.println(stringToPrint);
}
}
Bean.sleep(1000);
}
Our Sketch Code Explained
To start with, you’ll see a range of variables called minXVal
, maxXVal
, minYVal
, maxYVal
, minZVal
and maxZVal
. These track our LightBlue Bean’s initial accelerometer readings. Within my demo code, we only really use the z values, however I’ve left the others in here as you may need to use their values for your own implementations (e.g. if you place the Bean in a different orientation on the door or have a different sort of door, like a sliding door). The accelerometer tracks the force of gravity on each side of the Bean. We only want to know about the changes in these forces, so we need to know the range of forces acting on the Bean originally when it is stationary on our open door. This is where we store those values:
int minXVal = 0;
int maxXVal = 0;
int minYVal = 0;
int maxYVal = 0;
int minZVal = 0;
int maxZVal = 0;
Next we set a variable called movement
which is the level of movement we’ll accept before triggering the action. You’ll need to adjust this to suit your own situation (your door may move a lot more subtly whilst open than mine). In the sample code, we’re allowing for movement of about -15 to +15 from our min and max values before we trigger anything:
int movement = 15;
We will need time to run the initial test of the min and max values, so we use the ready
variable to tell our loop whether we are ready to start watching for door movements within our min and max ranges:
bool ready = false;
In our setup()
Arduino function, we set the serial connection to start running when the Arduino is ready:
void setup() {
Serial.begin();
}
Within our loop, we perform all our watching of our accelerometer values from the Bean. This will all be readable via the acceleration
variable we set up at the start of the loop()
function:
void loop() {
AccelerationReading acceleration = Bean.getAcceleration();
// Our accelerometer tests
}
Our first accelerometer readings will be the ones for realising our minimum and maximum values. These are run when ready
is initially false. The initial readings are taken 100 times, one every 10 milliseconds which should be ready with min and max values in about a second. Once it has gone through this loop, we set ready
to true so it can go to the next phase. We’re jumping ahead of ourselves there though, first we’ll go over what’s in this loop.
if (!ready) {
for (int i = 0; i < 100; i++) {
// Our accelerometer readings
delay(10);
}
ready = true;
}
Within each 10 millisecond reading, we read in each axis’ accelerometer value via acceleration.xAxis
, acceleration.yAxis
and acceleration.zAxis
. We compare each to the current max and min values we have stored for each axis and if it is greater than or less than the respective value, we update it to the new minimum or maximum:
if (acceleration.xAxis > maxXVal) {
maxXVal = acceleration.xAxis;
} else if (acceleration.xAxis < minXVal) {
minXVal = acceleration.xAxis;
}
// Repeated for y and z axes.
The next phase is the one in which we watch for movement that occurs outside of the min/max values that is greater than our movement
variable.
For the door movement, I only needed to test the z values as that was the axis which changed most when my door swung open and closed. If they were less than the minimum resting value, then my door was being closed and if they were greater than the maximum resting value, the door was being opened. This may be different for your if your LightBlue Bean is placed differently on your door. Experiment and see what works for you!
For each, we send either “OPEN” or “CLOSED” over the software serial port via Serial.println(stringToPrint)
.
else {
if (acceleration.zAxis < minZVal - movement) {
String stringToPrint = "CLOSED";
Serial.println(stringToPrint);
} else if (acceleration.zAxis > maxZVal + movement) {
String stringToPrint = "OPEN";
Serial.println(stringToPrint);
}
}
Attaching Your Bean
Before you put that code onto your Bean, stick your LightBlue Bean onto your door in your preferred manner. I used Blu Tack as a temporary thing but the Bean seemed light enough to stick perfectly fine with it. For my sample code, I attached my LightBlue Bean like so:
Setting up LIFX and IFTTT
In order to be able to tell our LIFX bulbs to turn on and off, we’ll set up an IFTTT rule to do so. I set up recipes to turn the lights on when the door is closed and turn them off if I open the door again to leave the room.
I’ll assume readers know the basics of IFTTT for this article. If not, have a quick read of my earlier article on Connecting LIFX Light Bulbs to the IoT Using IFTTT.
The two recipes we create will have the Maker channel as the trigger channel and the event names of “bean_door_closed” (turns on our lights) and “bean_door_opened” (turns off our lights). The action channel will be LIFX with the action of “Turn lights on” or “Turn lights off”. They should look like this when complete:
Our Node Server Code Explained
The code for the Node server looks like so:
var port = process.env.PORT || 5000,
SerialPort = require("serialport").SerialPort,
serialPort = new SerialPort("/dev/cu.LightBlue-Bean", {
baudrate: 57600
}),
request = require('request');
serialPort.on("open", function () {
console.log("Connected to LightBlue Bean serial port");
serialPort.on("data", function(data) {
console.log("Data: " + data);
data = data + "";
if (data == "CLOSED") {
request.post({
url: "http://maker.ifttt.com/trigger/bean_door_closed/with/key/YOURKEYHERE"
}, function(error, response, body) {
console.log(body);
if (error) console.log("Error was ", error);
});
} else if (data == "OPEN") {
request.post({
url: "http://maker.ifttt.com/trigger/bean_door_open/with/key/YOURKEYHERE"
}, function(error, response, body) {
console.log(body);
if (error) console.log("Error was ", error);
});
}
});
});
The start of the server sets up our serial port capabilities through the node-serialport module, setting it to watch at 57600 baud. We also define our request module which is the one that will make our HTTP calls to IFTTT.
var SerialPort = require("serialport").SerialPort,
serialPort = new SerialPort("/dev/cu.LightBlue-Bean", {
baudrate: 57600
}),
request = require('request');
We then open the connection to our serial port and start watching the serial port for any messages. It logs out any messages it receives (we should see a list of “Data: OPEN” and “Data: CLOSED” logs when the door opens and closes).
serialPort.on("open", function () {
console.log("Connected to LightBlue Bean serial port");
serialPort.on("data", function(data) {
console.log("Data: " + data);
data = data + "";
// Responding to "OPEN" and "CLOSED"
}
}
If the data we receive is the string "CLOSED"
, we make a HTTP request to http://maker.ifttt.com/trigger/bean_door_closed/with/key/YOURKEYHERE
(replacing YOURKEYHERE
with the key IFTTT provides you on the Maker channel page). On success, we log the response from IFTTT which should look something like "Congratulations! You've fired the bean_door_closed event"
.
We do the same for "OPEN"
just switching out the action within the URL from bean_door_closed
to bean_door_open
.
if (data == "CLOSED") {
request.post({
url: "http://maker.ifttt.com/trigger/bean_door_closed/with/key/YOURKEYHERE"
}, function(error, response, body) {
console.log(body);
if (error) console.log("Error was ", error);
});
} else if (data == "OPEN") {
// Same pattern!
}
Running Everything
If you haven’t already, stick the Bean onto your door as described earlier and then program your LightBlue Bean with the sketch.
Then, right click your Bean in the Bean Loader and select “Use for Virtual Serial”. This sets up a virtual serial port for any messages from your LightBlue Bean to stream through.
Install all dependencies for your Node server by running the usual:
npm install
Then run your server:
node index.js
(If either of the above commands look like gibberish to you, I’d recommend reading up on Node a little bit before attempting this!)
Open and close that door! You should see the logs show calls to your IFTTT server depending on the door swing. I found it took a bit of adjusting of the movement
sensitivity to get this working nicely, so you might need to adjust it a bit.
If you placed the LightBlue Bean on the other side of the door, I think you may need to switch the outputs of “CLOSED” and “OPEN” in your Arduino sketch, as the Bean is facing the opposite way.
Conclusion
That is how to use the LightBlue Bean, IFTTT, LIFX and Node to magically turn a light off and on depending on whether the door swings open or closed! You could adapt this code to instead detect if an object is picked up or moved (imagine sending a Tweet to your account anytime someone tries to open a box or drawer). The LightBlue Bean is small enough for it to be out of the way and quite easy to attach to things!
If you do use this code to create a genius security system to protect your sugar loving colleagues from taking your sweets (or something equally as important like your laptop!), or any other interesting use I haven’t thought of – please do leave a note in the comments or get in touch with me on Twitter (@thatpatrickguy), I’d love to hear about what you’ve built!
I’m also putting together a set of curated links relating to developing on the LightBlue Bean on my new accompanying website at DevDiner.com. So if you do come across links around the web on this topic which you find very useful, please get in touch with me so I can add those to the guide!
PatCat is the founder of Dev Diner, a site that explores developing for emerging tech such as virtual and augmented reality, the Internet of Things, artificial intelligence and wearables. He is a SitePoint contributing editor for emerging tech, an instructor at SitePoint Premium and O'Reilly, a Meta Pioneer and freelance developer who loves every opportunity to tinker with something new in a tech demo.