Are You Okay? Widget
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.