Introduction: Rapid (a)Simblee: Sending Data Bidirectionally Between a Simblee and a Mobile Device

We're on the home stretch!

We just need to add functionality to our UI!

In this Instructable, we'll be sending data back and forth between the Simblee and your mobile device.

Super. Cool. Stuff. :D

Need the library reference? Here you are!

WARNING! OH NOES!! DANGER AHEAD!

Simblee operates at 3.3V! None of it's pins are 5V tolerant!
Please be careful when designing your circuit! :D

Step 1: Making Some Copy Pasta!

If you haven't already taken a look at the Creating a UI Instructable, I recommend you give that a whirl before getting started here. :)

From the previous Instructable, you should have a basic setup of UI objects.

1. Copy and paste the following code above the setup() function.

uint8_t text_temp;<br>String textFieldString = "";
unsigned long lastUpdated = 0;
unsigned long updateRate = 500; // in milliseconds

// include newlib printf float support (%f used in sprintf below)
asm(".global _printf_float");

2. Copy and paste the following code and replace everything in the loop() function.

unsigned long loopTime = millis();

if (SimbleeForMobile.updatable && updateRate < (loopTime - lastUpdated)) {
    lastUpdated = loopTime; 
    float temp = Simblee_temperature(CELSIUS);
    char buf[16];
    sprintf(buf, "%02f", temp);
    SimbleeForMobile.updateText(text_temp, buf);
}

SimbleeForMobile.process();

3. Copy and paste the following code and replace everything in the ui() function.

text_temp = SimbleeForMobile.drawText(40, 10, "Simblee Temperature");
SimbleeForMobile.setEvents(ui_button, EVENT_PRESS);

4. Copy and paste the following code and replace everything in the ui_event(...) function.

if (event.id == ui_button && event.type == EVENT_PRESS) {
    SimbleeForMobile.updateText(ui_text, textFieldString.c_str());
  } else if (event.id == ui_stepper) {
    SimbleeForMobile.updateValue(ui_slider, event.value);
  } else if (event.id == ui_switch) {
    if (event.value == 0) {
      SimbleeForMobile.updateText(ui_text, "Switch off");
    } else if (event.value == 1) {
      SimbleeForMobile.updateText(ui_text, "Switch on");
    }
  } else if (event.id == ui_segment) {
    switch (event.value) {
      case 0:
        SimbleeForMobile.updateText(ui_text, "Alice text");
        break;

      case 1:
        SimbleeForMobile.updateText(ui_text, "Dave text");
        break;

      case 2:
        SimbleeForMobile.updateText(ui_text, "Peter text");
        break;
    }
  } else if (event.id == ui_textField) { 
    textFieldString = String(event.text);
  }

Step 2: Your UI Has Functionality!

Flash your Simblee with your updated code, and check out your app!

Most of the UI objects that you'll see will change the text at the top of the screen.

Also, the numerical value that you see at the top is actually the temperature of the Simblee!

That text field is being updated every half second!

Pretty rad, right?

Step 3: (Optional) Debrief: Sending and Receiving Data Pt. 1

Just a quick explanation for a few lines of code.

1. We're just adding a few more variables here to show a couple of cool tricks.

You might be wondering what the asm(global...) line is. You can think of it as a library for Simblee to use numbers with decimals.

It MUST be written in order for decimals to appear in your Simblee app.

uint8_t text_temp;<br>String textFieldString = "";
unsigned long lastUpdated = 0;
unsigned long updateRate = 500; // in milliseconds

// include newlib printf float support (%f used in sprintf below)
asm(".global _printf_float");

Step 4: (Important) Debrief: Sending and Receiving Data Pt. 2

There's a bit of stuff to go through here, but let's start with the basics.

Simblee can update the value of any UI object on your phone at any time.

This is what we see here in the code within loop().

unsigned long loopTime = millis();
if (SimbleeForMobile.updatable && updateRate < (loopTime - lastUpdated)) { 
    lastUpdated = loopTime;

//	This is where the UI object updating occurs.
    float temp = Simblee_temperature(CELSIUS);
    char buf[16]; 
    sprintf(buf, "%02f", temp);
    SimbleeForMobile.updateText(text_temp, buf);
}

SimbleeForMobile.updatable is a boolean that tells you when the mobile device can be updated.

We're creating a variable here called temp that holds the temperature of the Simblee.
We're using a character array called buf with a length of 16 to store that temperature using the method sprintf.

To use sprintf, provide a character array, some string format to insert any data, and the data itself.

Then we call the function SimbleeForMobile.updateText to update the text object text_temp with whatever exists in the variable buf.

It can be a bit confusing, so if all else, take the code segment where UI object updating occurs and replace temp with a numerical value of your choosing and update text_temp with any other object ID.

Step 5: (Important) Debrief: Sending and Receiving Data Pt. 3

Almost there!!

Simblee can only receive data from your phone if any of the objects have been modified or manipulated by the user.

Within ui() function, we added two new lines of code.

text_temp = SimbleeForMobile.drawText(40, 10, "Simblee Temperature");
SimbleeForMobile.setEvents(ui_button, EVENT_PRESS);

We're creating a text label and storing the ID to text_temp. More on this in a bit!

Lastly, we attach an "event tag" to a UI object, in this case the ui_button.
Basically, it helps us identify what state the UI object is in when the user interacts with it.

Here's a list of them! [EVENT_PRESS, EVENT_RELEASE, EVENT_DRAG]

We use the method SimbleeForMobile.setEvents to input a UI object ID and an event tag.

Step 6: (Important) Debrief: Sending and Receiving Data Pt. 4

Last bit! I promise!

Most of the user events are handled in the ui_event(...) function.

You can see that it follows a very similar format.

if (event.id == ui_button && event.type == EVENT_PRESS) {
    // This is where we're updating ui_text with the string stored in
    //    the variable textFieldString when a button has been pressed.

    SimbleeForMobile.updateText(ui_text, textFieldString.c_str());
} else if (event.id == ui_stepper) {
    // This is where we update where the slider is at based on what
    //   numerical value the stepper is it. Remember stepper has an
    //   internal counter that keeps track of increments/decrements.

    SimbleeForMobile.updateValue(ui_slider, event.value);
} else if (event.id == ui_switch) {
    // This is where the switch changes the text of ui_text

    if (event.value == 0) {
      SimbleeForMobile.updateText(ui_text, "Switch off");
    } else if (event.value == 1) {
      SimbleeForMobile.updateText(ui_text, "Switch on");
    }
} else if (event.id == ui_segment) {
    //  This is where the changing values for the segment object happens.

    switch (event.value) {
      case 0:
        SimbleeForMobile.updateText(ui_text, "Alice text");
        break;
      case 1:
        SimbleeForMobile.updateText(ui_text, "Dave text");
        break;
      case 2:
        SimbleeForMobile.updateText(ui_text, "Peter text");
        break;
    }
} else if (event.id == ui_textField) {
    // This is where we store the text from ui_textField in textFieldString.

    textFieldString = String(event.text);
}

If you remember, all those functions like drawRect, drawButton, etc. all return a unique object ID value. This is why we have to store them in variable names like ui_button or text_temp.

You can think of ui_event() as a loop running repeatedly, checking to see if your mobile devices sends any new data to the Simblee.

We use a bunch of if statements to check whether a event contains the data we're looking for, and check its parameters for the object we're looking for.

Here's a list of some of them:

event.id : An object ID.

event.type : An event tag that we mentioned the previous tag.

event.value : A numerical value that an object may hold.

event.text : Any text that an object might display.


And that's it!! :)

A few notes!

1. An text or text_field cannot have both data in event.value or event.text. It's either or.

2. The event.value for UI objects like switches and buttons return either 0 or 1 for "on" or "off." Slider and stepper UI objects can return larger values since they are given a numerical range. A segment's event.value is any value within the range [0, numberOfSegmentNames).

If we had Dave, Pete, and Alice as segment names, our segment value could be either 0, 1, or 2.

Step 7: Other Resources...

Hope you enjoyed the Rapid (a)Simblee Instructables so far!

By now, you should be able to create simple, rapid mobile applications with your Simblee while interfacing with your embedded projects.

Make some awesome projects and post 'em in the comments! :)


In terms of resources....

Simblee has some great videos going over some similar concepts more in depth.

Check 'em out on their Youtube channel!

Sparkfun has a wonderful tome about Simblee and its concepts here!

If all else fails, check their site for their Simblee documentation!

You can find the code used in this Instructables at our repo!

Good luck!! And stay tuned for more guides!