Go Down

Topic: Control arduino101 with mobile device using evothings( example ) (Read 2827 times) previous topic - next topic

govkn

I wanted to present the forum with a working example of a hybrid web app to control the arduino101 with a mobile device using BLE.

In order to replicate this example:

1) Go to www.evothings.com, and read the tutorials there, esp. regarding arduino and BLE. They have an extensive library of tutorials and examples. To date, however, there are no examples using the arduino101. The code in this post will allow you run such an example. They also have some great videos on youtube.

2) Download the EvothingsWorkbench for your OS. EvothingsWorkbench will create a server on your laptop/desktop that will serve up your app to your mobile device.

3) On your mobile device( phone, tablet ) download the EvothingsClient and EvothingsViewer.
All evothings software is free to download and use.

There are download instructions for all this on their website. Try out their HelloWorld example first just to see it work and know that your set-up works.

Note I am using an older mac that has no native BLE support, the BLE has to be on your mobile device and on the arduino 101.

The EvothingsWorkbench download comes with all the examples in a folder called, examples. Go the the folder: examples/arduino-led-onoff-ble. This folder contains the example that I modified to work with the arduino101. You will need to use the attached files to modify it to work with the arduino101. It will NOT work with the arduino101 as it is written.

On the web app/evothings  side:

You will need to replace the the files index.html and arduinoble.js in the examples directory tree. I would rename the files to something like index_old.html. I highly recommend reading these files side by side with the new ones to understand how they works and what changes have been made.

index.html is located in examples/arduino-led-onoff-ble/app/index.html

arduinoble.js is located in examples/arduino-led-onoff-ble/app/libs/evothings/arduinoble/arduinoble.js

On the arduino side:

The example is set so that you can turn 2 servo motors on and off along with 4 leds. There is also a BLE connection indicator led that turns on when mobile device connects to the 101. The leds are connected to pins 13-9. Pin 13 is the connection indicator led. Pins 12-9 are connected to the leds being controlled. I used 220 ohm resistors to connect these leds to the pins.

For the servo motors, I used the Adafruit 16-Channel 12-bit PWM/Servo Shield - I2C interface (PRODUCT ID: 1411) with 2 Continuous Rotation Micro Servo - FS90R (PRODUCT ID: 2442) also from adafruit. The board and driver library work without any modification on the arduino101.  Make sure you have the driver library installed and plug the shield into the arduino101.

 For the software, you will need to upload the following sketch to your arduino101:
cureBLE_3.ino I used the CurieHeartRateMonitor as the base for this code.

Once you have done all this, start up the 101 and launch the serial viewer.
Then start up your Evothings Workbench, click on Tools so you can see the console debug and
then press run for the arduino-led-onoff-ble example.

I have commented the attached code pretty heavily, so you should read this as well.

I am running EvothingsWorkbench 1.2.0 on a mac running OSX Yosemite. I am using an Asus zenpad 7 with android 5.0.2 running the Evothings Clientt app version 1.2.1. You may need to disbale your firewall to run the workbench, remember to re-enable it afterwards.

This is a one-way control app. I am working on modifying one of their other examples to recieve data from the 101 to the tablet. I hope you beat me to it and share it here!


govkn

oops, the forum won;t let me upload file types with a .js or .html extension. I will cut and paste the code into this thread

Here is the index.html code:


<!DOCTYPE html>
<html>
<!--
This is an app that demonstrates how to control an curie/arduino 101 board
using BLE (Bluetooth Low Energy) with a hybrid app. The evothings platform
is used, www.evothings.com.

This the html portion of hybrid app for your curie/arduino101 project.
Note there is some javascripte present in this code. So it is not a
completely 'clean' hybrid app, but hey, the kind folks at evothings
wrote this for us and it got me going with BLE on the arduino101
and my asus zenpad when I couldn;t make naything elese work. So
read, learn, modify, improve and share! Thanks evothings!

This code was modifed by gv on 28/Feb/2016.

-->
<head>

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no
initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />

<title>Arduino LED On/Off BLE</title>

<style>
@import 'ui/css/evothings-app.css';
</style>

<script>
// Redirect console.log to Evothings Workbench.
if (window.hyper && window.hyper.log) { console.log = hyper.log }
window.onerror = function(msg, url, line)
{
console.log(msg + ": " + url + ":" + line);
};
</script>

<script src="cordova.js"></script>
<script src="libs/jquery/jquery.js"></script>
<script src="libs/evothings/evothings.js"></script>
<script src="libs/evothings/arduinoble/arduinoble.js"></script>

</head>

<body ontouchstart=""><!-- ontouchstart="" enables low-delay CSS transitions. -->

<header>
<button class="back" onclick="history.back()">
<img src="ui/images/arrow-left.svg" />
</button>

<img class="logotype" src="ui/images/logo.svg" alt="Evothings" />

<!--<button class="menu" onclick=""><img src="ui/images/menu.svg" /></button>-->
</header>

<h1>Arduino Buttons</h1>

<p id="info">Initializing...</p>
 
<button class="yellow wide" onclick="app.connect()">CONNECT</button>

<br />
  <table>
      <tr><td><button class="green wide big" onclick="app.ledZero()">ZERO</button></td>
          <td><button class="blue wide big"  onclick="app.ledOne()">ONE</button></td></tr>
<br />
 
      <tr><td><button class="red wide big"    onclick="app.ledTwo()">TWO</button></td>
          <td><button class="yellow wide big" onclick="app.ledThree()">THREE</button></td></tr>
     
      <tr><td><button class="blue wide big"   onclick="app.servo0()">SERVO0</button></td>
          <td><button class="blue wide big"   onclick="app.servo1()">SERVO1</button></td></tr>
     
  </table>

<script>
// Application object.
var app = {}

// Connected device.
app.device = null;

  /* ** curie/arduino 101 **
   *
   * These functions were attached to the buttons above.
   * They connect to the characteristics in the ardunioble.js
   * file. The characteristics uuids are specifed there and in
   * the code running on the aruduino101, not here.
   *
   * The numbers sent are processed on the arudino101 side into
   * meaningful state changes of the servo motors and leds.
   * see that code for what the number 0, or other such numbers in:
   *
   *  app.device && app.device.writeDataArray(new Uint8Array([0]));
   *
   * mean. Can't wait to see your curie/arduin101 hybrid apps!
   *
   */

app.ledZero = function()
{
      app.device && app.device.writeDataArray(new Uint8Array([0]));
}

  app.ledOne = function()
  {
       app.device && app.device.writeDataArray(new Uint8Array([1]));
  }

app.ledTwo= function()
{
      app.device && app.device.writeDataArray(new Uint8Array([2]));
}

  app.ledThree = function()
  {
      app.device && app.device.writeDataArray(new Uint8Array([3]));
  }
 
  app.servo0 = function()
  {
      app.device && app.device.writeServo(new Uint8Array([0]));
  }
  app.servo1 = function()
  {
      app.device && app.device.writeServo(new Uint8Array([1]));
  }
app.showMessage = function(info)
{
document.getElementById('info').innerHTML = info
};

// Called when BLE and other native functions are available.
app.onDeviceReady = function()
{
app.showMessage('Touch the connect button to begin.');
};

app.connect = function()
{
evothings.arduinoble.close();
      /* ** curie/arduino101 **
       * connecting to our arduino101 requires that the correct local name for the BLE
       * service is specified here. This is set in the code running on the curie/arduino101
       * with the follwoing line: blePeripheral.setLocalName("curieble");
       * if your local name is something different set it here, it may be case sensitive to check your
       * spelling!
       */
evothings.arduinoble.connect(
'curieble',
function(device)
{
app.device = device;
app.showMessage('Connected! Touch buttons to turn Your LED on/off.');
},
function(errorCode)
{
app.showMessage('Connect error: ' + errorCode + '.');
});
};

document.addEventListener('deviceready', app.onDeviceReady, false);
</script>

</body>

</html>


govkn

And here is arduinoble.js code:

// File: arduinoble.js

// Load library EasyBLE.
evothings.loadScript('libs/evothings/easyble/easyble.js');

/**
 * @namespace
 * @author Mikael Kindborg
 * @description <p>Functions for communicating with an Arduino BLE shield.</p>
 * <p>It is safe practise to call function {@link evothings.scriptsLoaded}
 * to ensure dependent libraries are loaded before calling functions
 * in this library.</p>
 *
 * @todo This is a very simple library that has only write capability,
 * read and notification functions should be added.
 *
 * @todo Add function to set the write characteristic UUID to make
 * the code more generic.
 */

/*
 * intel curie/arduino101 users take note,
 * all modifications made to this code in order for it to work with the arduino101
 * will be highlighted by a comment as such: 'curie/arduino101' as the first line.
 *
 * You should look at the evothings example side by side with this code to learn how
 * it works!
 *
 * This is the javascript part of your hybrid app. In this example some javascript
 * is in the index.html file. This is the way the example was written. This
 * may not be considred porper form for javascript programming
 * but it works and this how platform is free to use, so don't complain,
 * read, learn, make it better and share!
 *
 * this code modified to on 28/February/2016 by gv
 */
evothings.arduinoble = {};

;(function()
{
   // Internal functions.
   var internal = {};

   /**
    * Stop any ongoing scan and disconnect all devices.
    * @public
    */
   evothings.arduinoble.close = function()
   {
      evothings.easyble.stopScan();
      evothings.easyble.closeConnectedDevices();
   };

    /* ** curie/arduin101 users **
     * disregard the comments below about a BLE shield, you wont have a BLE shield
     * connected to your arduino101, the arduino101 comes with BLE onboard!
     * Thanks intel!
     */
 
   /**
    * Called when you've connected to an Arduino BLE shield.
    * @callback evothings.arduinoble.connectsuccess
    * @param {evothings.arduinoble.ArduinoBLEDevice} device -
    * The connected BLE shield.
    */

    /* ** curie/arduin101 users **
     * The local name of our arudino101 ble service is called 'curieble', NOT 'arduinoble'
     * as stated below. This will need to be changed in the index.html code,
     * not here.
     */
 
   /**
    * Connect to a BLE-shield.
    * @param deviceName BLE name if the shield.
    * @param {evothings.arduinoble.connectsuccess} success -
    * Success callback: success(device)
    * @param {function} fail - Error callback: fail(errorCode)
    * @example
    * evothings.arduinoble.connect(
    *   'arduinoble', // Name of BLE shield.
    *   function(device)
    *   {
    *     console.log('connected!');
    *     device.writeDataArray(new Uint8Array([1]));
    *     evothings.arduinoble.close();
    *   },
    *   function(errorCode)
    *   {
    *     console.log('Error: ' + errorCode);
    *   });
    * @public
    */
   evothings.arduinoble.connect = function(deviceName, success, fail)
   {
      evothings.easyble.startScan(
         function(device)
         {
            if (device.name == deviceName)
            {
               evothings.easyble.stopScan();
               internal.connectToDevice(device, success, fail);
            }
         },
         function(errorCode)
         {
            fail(errorCode);
         });
   };

   /**
    * Connect to the BLE shield.
    * @private
    */
   internal.connectToDevice = function(device, success, fail)
   {
      device.connect(
         function(device)
         {
            // Get services info.
            internal.getServices(device, success, fail);
         },
         function(errorCode)
         {
            fail(errorCode);
         });
   };

   /**
    * Read all services from the device.
    * @private
    */
   internal.getServices = function(device, success, fail)
   {
      device.readServices(
         null, // null means read info for all services
         function(device)
         {
            internal.addMethodsToDeviceObject(device);
            success(device);
         },
         function(errorCode)
         {
            fail(errorCode);
         });
   };

   /**
    * Add instance methods to the device object.
    * @private
    */
   internal.addMethodsToDeviceObject = function(device)
   {
      /**
       * Object that holds info about an Arduino BLE shield.
       * @namespace evothings.arduinoble.ArduinoBLEDevice
       */
 
      /**
       * @function writeDataArray
       * @description Write data to an Arduino BLE shield.
       * @param {Uint8Array} uint8array - The data to be written.
       * @memberof evothings.arduinoble.ArduinoBLEDevice
       * @instance
       * @public
       */
 
        /* ** curie/arduino101 **
         * This code functions as the central and will run on a mobile device.
         * See index.html to see how they are used and "connected" to the buttons.
         * The peripheral, our curie/arduino 101, has 2 servo motors and 4 leds
         * attached. The curie/arduino101 service advertises 2 characteristics.
         * One charateristic is for the servos and the other of the leds.
         * The uuids for each characterisitic are custom. Please see the curieBLE_3.ino
         * for more about custom uuids for BLE.
         * Note we could have stuck with one charactersitic for the servos and leds,
         * having two characteristics is a logical separation of the functions
         * on the peripheral and also demonstrates how to put multple characteriscs
         * in this part of the code.
         * Here I kept the function writeCharactersitic from device.writeDataArray in the original code,
         * I just changed the uuid to reflect the custom uuid for the leds.
         * Special Note: I belive these may be case sensitive on the js side, so
         * that is why I have lower case letters in the uuid
         */
      device.writeDataArray = function(uint8array)
      {
         device.writeCharacteristic(
                '917649a2-d98e-11e5-9eec-0002a5d5c51b',
            uint8array,
            function()
            {
               console.log('writeCharacteristic success');
            },
            function(errorCode)
            {
               console.log('writeCharacteristic error: ' + errorCode);
                });
      
            };
        /* ** curie/arduino101 **
         * I used device.writeCharacterisitic as the template for this fucntion
         * which writes to the servos( I should have renamed writeCharacteristic
         * to something like write led, but I was lazy.)
         * The uuid is really the only think you need to change here, it lets the function
         * know which characteristic is which. See index.html for how this is used
         * to cnnect to the servo buttons
         */
        device.writeServo = function(uint8array)
        {
 
            device.writeCharacteristic(
                             
                '917649a1-d98e-11e5-9eec-0002a5d5c51b',
                uint8array,
                function()
                {
                    console.log('servo characteristic success');
                },
                function(errorCode)
                {
                    console.log('servo characteristic error: ' + errorCode);
                });
 
        };
 
   };
})();

jds443

Nicely done.  I think there are many of us struggling to figure out how to expand on the basic BLE examples with our Arduino101's.

I have a couple of questions I'm hoping you can help answer, specifically about defining custom characteristics:

1)  Are there specific UUID's that must be used?
2)  Are there datatypes restrictions?

Thanks!

govkn

Thank you! If you try it out, let me know how it goes.


1)  Are there specific UUID's that must be used?

No, I got the uuid's from an automated uuid generation site. There are uuid's that are specific for ble services, characteristics, etc. These are listed on the ble sig site:

https://developer.bluetooth.org/gatt/Pages/default.aspx

If you use standard/approved uuid's, one major advantage is you can interact then you can interact with software setup[ to use these ble services. That is why the nRF adn phonegap apps can work with the arduino101 heartrate example "out-of-the-box".

I have read that if you are to use a custom uuid( one not reserved/approved for a specific service by the ble sig ), then you must use the entire 128 bit uuid. If you use one that is specified, then you can justt send the 16 bit portion. You can see an example of this in the heart rate monitor sample:

BLEPeripheral blePeripheral;       // BLE Peripheral Device (the board you're programming)
BLEService heartRateService("180D"); // BLE Heart Rate Service

// BLE Heart Rate Measurement Characteristic"
BLECharacteristic heartRateChar("2A37",  // standard 16-bit characteristic UUID
BLERead | BLENotify, 2);  // remote clients will be able to get notifications if this characteristic changes
// the characteristic is 2 bytes long as the first field needs to be "Flags" as per BLE specifications
// https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml


2)  Are there datatypes restrictions?

I don't have a good answer for you on this, except that the CurieBle library has methods to create characteristics with specifc values, such as BLEIntCharacteristic(), BLEFloatCharacteristic(). I am actually experimenting with this now, trying to send int's from A0 and A1 attached to pots back to my android tablet. So if I have results or more info on this, I will share it.

G

Go Up