Are You Okay? Widget
When Elizabeth and I got to talking about friends, neighbors, parents, and children we worry about, there was a theme: if we knew they were OK, it would be enough. The hard part is in not knowing if they came home last night or got up this morning. Elizabeth and I worked out what we wanted it to do on my embedded software podcast. We have the technology to alleviate such worries, such as the Are-You-OK? Widget. The Are-You-OK widget contains an Electric Imp, an accelerometer, and an RGB LED to connect to wireless networks to notify loved ones if you're ok or not.
If you put it in a stuffed animal, the person you care about can pat it every day. If they fail to do so, the Imp will tweet at you, send you email, and/or text your phone. Of course, you could put it on their refrigerator, so you’d know they were OK and eating.
This is definitely an advanced tutorial. I’ll show you how I put together the hardware and the software, but, if you haven’t tried Electric Imp before, this may not be the place to start.
The items you will need for this are:
I chose right angle connectors in the kit because it goes better into a box or stuffed animal. Your form factor may vary. I also really like jumper wires over soldering but, if you are more confident on the hardware side, I won’t stop you from soldering. If you are building a plush, you may want to locate the LED and accelerometer away from the main board and batteries.
You will also need this tools and supplies:
- 4x AA batteries
- Basic soldering tools -- a Soldering Iron and Solder
- Hot glue gun (OK, you don’t need one for this project but how can you live without it?)
Building The Hardware
Here's an overview of the hardware hookup:
The build is fairly straight forward. We start with soldering:
- Attach a two pin header to the Electric Imp breakout board for GND and VIN. Solder on the battery wires. Hot glue them to reinforce the connection.
- Break off 9 pins from the header, and solder those to the Imp breakout board.
- Since you’ll need two ground wires (one for the accelerometer and one for the LED), cut the end off of one jumper wire, strip the coating, and solder it to the Imp breakout board. (We can wait to hot glue until the jumper wires are in place.)
- Solder a 6-pin header onto the accelerometer.
Now wire up the system:
|Imp Breakout Pin||Wire Color||Goes To||Use|
|PIN1||Blue||Accel's I1||Interrupt to wake up the Imp.|
|PIN2||Red||LED's red leg||PWM red|
|PIN5||Blue||LED's blue leg||PWM blue|
|PIN7||Green||LED's green leg||PWM green|
|PIN8||Yellow||Accel's SCL||I2C clock signal|
|PIN9||Green||Accel's SDA||I2C data signal|
|GND||Black||LED cathode (longest leg)||Ground|
After you are done, the result should look something like this:
Note: the extra ground wire is soldered on the 2-pin power header and is ready for a battery connection to be soldered to it.
Loading the Code
As with any good Imp program, there are two halves to this code: the device (the Imp itself) and the agent (a server-side process that handles Internet requests and responses). Create a new model in the Imp IDE, and copy/paste the code below into the proper half of the IDE.
Then check out the next couple of pages, where we dissect each section of the code. You'll need to change some constants to make the code work for you.
Note: You can grab the most up-to-date agent and device codes here on GitHub.
What The Software Does (Device)
If you haven’t used the Electric Imp, have a look at the Electric Imp Hookup Guide. You can use the Hello, World code with this system set up as described. It will blink red if you change all instances of
hardware.pin2 in the device code.
However, once your have your Electric Imp talking to your network and downloading code, we can do a lot more. Our device is going to be a bit more complex, as it:
- Controls an RGB LED via PWM to do dimming
- Configures the accelerometer to interrupt when movement exceeds a threshold
- Goes to deep sleep to conserve battery
- On regular wake-ups, reads the battery voltage
At the top of the file are parameters for you to change.
First, set up the hardware to match the hookup instructions.
The ramp up and down, is done via the class
LEDColor. Its functions are:
constructor(redPin, greenPin, bluePin)-- initial creation, this is called with:
local rgbLed = LEDColor(redHWPin, greenHWPin, blueHWPin);.
setGoalColor (red, green, blue)-- sets the state variable
goalLEDto the values passed in.
update()-- writes to the LED with the values in
off()-- turns the LED off.
This is used in conjunction with
ledRamp function to make the LED come up softly, hold for a few seconds, then dim softly. The parameters can be reconfigured, if you want a different profile.
The battery monitoring subsystem is straightforward for AA batteries: read the Imp’s voltage and compare it against expected.
FuelGaugeResetFromBoot-- no initialization is needed for this monitoring.
FuelGaugeReadSoC-- does a bit of math to move from reading to percentage. It depends on the constants
MAX_EXPECTED_VOLTAGEto be set at the top of the file.
In the Going Further section, there is the option of using rechargeable LiPo batteries and monitoring them with a Fuel Gauge board. In that instance, these functions are replaced with more complex ones that speak to another chip via I2C.
The stock Sparkfun MMA8452Q has the address line pulled HIGH, so the I2C address is:
If your accelerometer has the SAO line pulled LOW (the resistor in place on the back of on the Sparkfun board), change the address to
The accelerometer has a few functions you probably won’t need to call directly (they are internal to the subsystem):
writeReg(addressToWrite, dataToWrite)-- writes to accel’s address via I2C.
readSequentialRegs(addressToRead, numBytes)-- reads
numBytesfrom accel’s address over I2C.
readReg(addressToRead)-- calls the above function but for one byte at a time.
AccelerometerSetActive(mode)-- sets the accelerometer into register modification mode or normal (active) mode.
The functions you may want to look at further are:
AccelerometerResetFromBoot()– verifies accel’s existence and configures interrupts and thresholds for the system
AccelerometerIRQ()– called after the accelerometer creates an interrupt.
There in one unused function, there for debugging and amusement:
readAccelData()– get the data from accelerometer.
If you haven’t played with an accelerometer before, they can be fun. Change
IndicateGoodInteraction() to something like this:
Now, the LED will indicate the orientation of the accelerometer every time you move or tap it.
While the code thus far has been for different subsystems, this is the new code for making the Are-You-OK widget do its thing.
GetReadyToSleep()-- sends the Imp to deep sleep. When it restarts, it will resume from the top of the program (so it is different than the
CheckBatteryAndGoToSleep()-- every hour the Imp wakes up to check battery status and send a note to the server.
IndicateGoodInteraction()-- sets the LED to white and starts a ramp.
IndicateLowBattery()-- sets LED to yellow, starts a ramp.
IndicateNoWiFi()-- sets LED to red, starts a ramp.
HandleReasonForWakeup(unused = null)-- the state machine of the device, it looks at the reason for wakeup and acts appropriately.
When the Imp comes back from deep sleep, it runs this code:
Before we get very far into the code, we want the Imp to send this code an error if it has trouble connecting:
The important part there is the
RETURN_ON_ERROR portion. Without this line, the Imp will try to connect but won’t let the device code run. We’ll turn the LED to red if we can’t get connected.
Next, we need to make sure the accelerometer will wake the system up after it goes to sleep:
Note that since the Imp is usually in deep sleep, the
AccelerometerIRQ seldom gets called directld. Instead
HandleReasonForWakeup notes that wakeup reason is
WAKEREASON_PIN1. If the system is not, then this code is responsible for calling
HandleReasonForWakeup. It starts by verifying the system is connected to WiFi. If not, then it tries for 3s before calling
HandleReasonForWakeup. (If the imp is connected, then it immediately calls
Much of the complexity here is due to the goal of having low power usage -- ideally to make the system last for 6 months (or more) on four AAs.
What The Software Does (Agent)
The goal of the agent software is to send user messages if the device fails in some way. For debugging, it is often easier to get messages when something does happen. Thus, there are two output message methodologies.
When debugging, you don’t necessarily want to flood your debug mechanism. If you keep tapping on the unit because you are fine tuning the color of the LED, you don’t want to get 1000 emails or twitter messages.
These next settings control how often you get messages and prevent message flurries:
The next setting is the most important.
These should be set according to how often your device needs attention before it sends you email. If you set it to be too frequent, the person you are monitoring will find it intrusive. If you set it too long, you may not be able to alleviate your worry. Here are some settings I like:
|User needs to move it||Hours||dtNoMotionDetected Setting|
|Three times a day||12||43200|
|Every couple days||60||216000|
With the most frequent setting, remember the user needs to sleep so 12 hours represents a couple hours on either side of night’s rest. As for “every day”, it isn’t 24 hours because that would require the user to interact with the device every day at the same time (or a minute earlier). Using 36 hours instead means that one day can be 8am but the next can be 8pm. The “every couple days” has a similar buffer.
The next setting configures how long the device can fail to communicate before you get an error message. This is likely because the device has lost power or its WiFi is not available.
Peace of mind sometimes means knowing that everything is still working. I updated my system to send a note every few days to say everything is ok.
Actually, everything may be working fine but you should know the device’s batteries are getting low. To that end, we have to decide when the “everything is fine” messages should include “but my battery is getting low”:
Communicating With the Caregiver
The different ways to communicate with the device require permissions. Electric Imp has example code for a number of web services: Xively, Twillio, Twitter, etc. I used the agent code from their repository. For twitter, you’ll need to use the Twitter Developer Center. Then you’ll need the keys to work:
These are at the top of my
agent.nut but the code is a little further down (marked with a section break). It’s relevant function is
Note: if you have trouble with twitter, modify the
twitterDebug function to output messages to the Electric Imp
server.log. Those messages get tedious to look at but are nice when starting out.
Monitoring Multiple Devices
Once you have one of these devices, you may want another. Right after the Settings sections, there is an area to help with monitoring multiple devices:
If you only want one unit, and you want to skip the next steps, edit the code directly and fix the name of the unit and where to send caregiver messages.
The other way to set these server-stored variables is to set up your unit the first time by putting the information in a URL of the form:
If you look at the top of the Imp editor for you agent URL, you'll see something like:
Copy the URL from the editor and add the necessary information in place of the curly braces, so it looks like:
Maxwell is the name of the unit and
@logicalelegance is where I want messages to be sent.
Once the agent code is running, put that URL into a browser and it will write the information into server storage. The next block of code handles the HTTP interaction. After that is the twitter-handling code.
Messages to the User
As noted above, there are two types of output:
userMessage. You may turn off
debugMessage entirely once you are happy with how it is working.
For me, debug messages go to the server log and to my general account at twitter. User messages are called out in the server log (prefaced with "!!!!") and go to the
attn in twitter.
Since these functions are separated, it is straightforward to modify them to email, text, or use another media to inform you of events.
There are three asynchronous timers, each monitoring for things to happen (or not):
- Battery update -- If this times out, we received no battery update: something is wrong since the device isn’t communicating.
- Motion update -- If this times out, the user has not moved the device: send a message to the caregiver to check on their loved one.
- Everything is fine -- If this times out, no errors occurred: send a reassurance message to the caregiver that all is working normally.
These all have the same elements:
- Modifiable timeout from the settings section on the top of the file (
- Timer variable used to start and stop the timer (
- Function that is called when something happens that resets the timer, such as a motion is received from the device (
motionOnDevice), this often causes a debug message.
- Callback when the timer expires (
noMotionFromDevice), this causes a user message.
- Timer creation (
motionUpdateFromDeviceTimer = imp.wakeup(dtNoMotionDetected, noMotionFromDevice);).
Once you see the symmetry between them, it is less of an impenetrable wall of code
Making It Look Good
The technology is interesting, lots of pieces hooked together to make a whole that is greater than its parts. However, the social engineering on this device is critical to its real world use.
I like stuffed animals for the cuteness factor. But putting this in a box on a refrigerator requires less interaction from the person being monitored. In the end, I went for the stuffed animal, modifying an off the shelf plush octopus.
I clipped the LED leads then glued the jumper cables to the leads. I used fishing line to hang the LED in the octopus head.
A little more fishing line attached the accelerometer (which has mounting holes) to the very top of the head. The next step is to attach all of that to the Electric Imp to the battery compartment.
Note that the Imp has to be accessible to the caregiver to set the WiFi information (via the Electric Imp Blink Up method with a smart phone). The batteries themselves should be changeable by the user (i.e. elderly neighbor). Organizing those two goals and getting all the cables to go in correct direction can be tricky. It is a matter of trying it before taping and hot-gluing it together. Of course, I recommend testing before putting it all together.
In the end, I’m pleased with how it turned out. But this is my first one (ahem, this is my first time adding electronics to a plush).
I have plans for the little dog stuffed animal. The first step is to choose a battery module that works for the end device:
Resources and Going Further
The Electric Imp is so flexible that staying on topic can be tough. Once you’ve built one thing, it is easy to think of more features. Here are some ideas for taking this project further.
Make It Rechargeable
Since LiPo batteries are tough to monitor based on voltage along, use a fuel gauge board to do the monitoring.
I created code to make that work with the Are-You-OK system, it drops in to replace the battery monitoring on the device. The hard part is splitting the I2C wires so they go to both the accelerometer or and the fuel gauge. Here is the hook up sketch.
Make It Cheaper
You will be able to remove the accelerometer code, only using the wakeup (pin 1). However, make sure you wire this so that the interrupt doesn’t happen (and the LED doesn’t show) until after the user has released the button.
Another cost cutting area is to replace the beautiful, diffuse LED with individual LEDs and control them directly. Of course, the diffuse one is only $0.95 so to make it cheaper, you may need to buy LEDs in bulk. I’ve ignored the intricacies of LED resistors but you might want to check out the LED tutorial.
Texting and Emailing
Email is also a good solution and there is a great description on how to set that up on the Imp.
While creating a device specific HTTP URL is great for setting the only two parameters, there are others we may want to set which means doing configuration via webpage.
It is pretty silly to set up the frequency of interaction in the code. Also, it would be pretty easy to set the caregiver information and contact methodology in a webpage.
Here, I’ve made a sketch of what I want. Let me know when you are finished, all right?