General Coding Concepts
Since the Simblee introduces a new concept (a synchronized but self-contained application running on a remote device), there are a few new concepts in the way code is written for the Simblee that we should go over before we dive into the examples.
First and foremost, you’ll notice that any sketch which uses the Simblee UI
library (called “SimbleeForMobile”, hereafter abbreviated SFM) has at least two additional functions:
ui_event(). Let’s explore what these are
ui() is basically the SFM equivalent of the
setup() function. It creates
the default objects that the user will see when connecting the Simblee app to a particular Simblee device and how those objects will behave. It gets called on connection to a new device (maybe – we’ll cover the circumstances under
which a device can cache the interface later).
ui_event() is a callback function which gets triggered when the user “does
something” in the UI. We’ll get into the specifics of what that “something” may be later, but broadly, it’s just what you’d expect: interacts with a button, moves a slider, enters a text value, etc.
This one is simple, if extremely important. During each iteration of
loop(), you need to call this function to handle processing of events from the UI. It’s important to note that, since this function is getting called during
loop(), excessive busy-wait delays (like the
delay() function) will impact the responsiveness of your application more than anything else will.
Here’s a blank SimbleeForMobile sketch, showing all the new features in place.
As mentioned earlier, while the Simblee is a Bluetooth Low Energy device, there is nothing inherently low energy about it while it’s operating normally. In fact, it may be consuming more power than a regular Arduino! In order to realize the benefits of BLE, you must learn to manage the power state of the processor.
Broadly speaking, this means that you’ll want to put the device in low power mode for as much of the time as possible, waking up only when necessary and then powering down again immediately. This “sleep as much as possible protocol” brings us to the next point: host/client synchronization.
We’ll cover this in an example later; for now, I want to point it out to avoid that concept slipping through the cracks.
One of the key problems with BLE is keeping client devices synchronized with their hosts. For a BLE device to minimize power use, it must sleep a lot of the time; this means not necessarily being available to hear a communications request from the host when it is sent. To work around this limitation, the host and client agree on a “wake-up interval”, during which the client will listen for the host and the host will attempt to contact the client. In a bidirectional system, there’s room for a lot of slop; they can repeat messages as often as needed until an acknowledgement is received.
However, some BLE devices are made to be very low power, running on batteries for months at a time or more. One of the ways this is possible is by waking up only long enough to squirt a tiny data packet out into the ether, and then going immediately back to sleep. Host devices must, therefore, be listening during these times, or they’ll miss the packet.
As we’ll see later, it’s possible to set the time gap between these data transmissions to very short times (20ms) to very long times (days). As you might imagine, this means that BLE modules must have very accurate internal real time clocks. This can be used to our advantage for other reasons, as well.