Red Amber Android Tutorial

Contents

Overview

Notice: The Red Amber SDK is not compatible with obsolete Blue Amber devices!

Coordinate system

In GemSDK we use left-handed local coordinate system (fig. above).

GemSDK features:

Start with GemSDK

To begin with: Link to our Api Reference

For quick configuration please download our utility from Google Play Market or apk. With it you can configure Gems list to use and access if from your app.

Add your Gem or Gems to the white list like so (make sure that Gem is really close to the Android device):

Set up your gem

Download the GemSDK library from our download page, put it to the “ProjectDir/ModuleDir/libs” folder.
Then set up the gradle:

project build.gradle:

allprojects {
    repositories {
        jcenter()
        flatDir {
            dirs 'libs'
        }
    }
}

module build.gradle:

dependencies {
    compile(name:'gemsdk-2.0.2', ext:'aar')
}

GemSDK library contains Android service that runs in its own thread and responsible for communication, our API and additional algorithms.

Basic operations with the service:

@Override
protected void onResume() {
    super.onResume();
    //Bind the Gem Service to the app
    GemManager.getDefault().bindService(this);
}

@Override
protected void onPause() {
    super.onPause();
    //Unbind Gem Service from the application
    GemManager.getDefault().unbindService(this);
}

Connecting to the Gem:

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    //Get white list of addresses form the utility app
    String[] whitelist = GemSDKUtilityApp.getWhiteList((Context)this);

    if(whitelist.length > 0) {
        //Get Gem by MAC-address
        gem = GemManager.getDefault().getGem(whitelist[0], gemListener);
    }
}  

or

@Override
protected void onCreate(Bundle savedInstanceState) {
    //Get Gem by certain address. Doesn't require GemSDK Utility app installed
    gem = GemManager.getDefault().getGem("00:80:98:BC:C5:02", gemListener);
}

Disconnecting (Not required):

GemManager.getDefault().releaseGem(gem);

If the Gem wasn’t disconnected manually before unbinding the service, the service will keep connection for 10 sec. If the app returns to foreground and requests connection Gem will be available almost immediately

Receiving data

Basic gem callback that was mantioned above:

private GemListener gemListener = new GemAmbstractListener() {
    @Override
    public void onStateChanged(int state) {
        //States handling
        switch (state) {
            case Gem.STATE_CONNECTED:
                Log.d("GemDemo", "Connected to a gem");
                break;
            case Gem.STATE_DISCONNECTED:
                Log.d("GemDemo", "Gem was disconnected");
                break;
        }
    }

    @Override
    public void onErrorOccurred(int errCode) {
        //Gem not found
        if(errCode == Gem.ERR_CONNECTING_TIMEOUT) {
            Toast.makeText(MainActivity.this, "Gem device not found", Toast.LENGTH_SHORT).show();
        }
    }
};

In order to obtain motion data subscribe to sensors callback. The data streaming will be started directly after connection to the Gem

gem.setSensorsListener(new OnSensorsAbstractListener() {
     @Override
     public void onSensorsChanged(GemSensorsData data) {
         float[] q = data.quaternion; // w x y z
         float[] a = data.acceleration; // x y z
         ...
     }
}

Calibration

To consider current azimuth(yaw) angle as zero for curtain Gem just use

gem.calibrateAzimuth();

And to make rotation completely relative to current rotation use

gem.calibrateOrigin();

Handling taps

Handling tap events is also pretty easy:

gem.setTapListener(new OnTapListener() {
    @Override
    public void onTap(TapData tapData) {
        Log.i("GemDemo", "Tap!");
    }
});

Pedometer

To use pedometer set up the callback:

gem.setPedometerListener(new OnPedometerListener() {
    @Override
    public void OnPedometerUpdate(PedometerData pedometerData) {
        Log.i("GemDemo", "Steps:" + pedometerData.steps);
    }
});

Extensions

Red Amber supports 8 GPIOs, 3 Analog inputs, 1 PWM output, I2C and SPI bus communications.
All this functionality is available via SDK. Physically additional sensors, LED’s, Buttons, and so on should be connected to corresponding pins of development board.

To make effect all the following commands should be executed when Gem is connected!

GPIOs

All the GPIOs will return to the initial state after disconnection.

Any GPIO pin should be configured before use

gem.configDigital(Gem.EXTENSION_DIGITAL_0, Gem.EXTENSION_CONF_OUTPUT);
gem.configDigital(Gem.EXTENSION_DIGITAL_1, Gem.EXTENSION_CONF_INPUT);

//Will rise digitalRead callback when input value changes
gem.configDigital(Gem.EXTENSION_DIGITAL_5, Gem.EXTENSION_CONF_INPUT_NOTIFY);

In addition inputs can be configured with pull-up or pull-down resistor attched:

gem.configDigital(Gem.EXTENSION_DIGITAL_1, Gem.EXTENSION_CONF_INPUT | Gem.EXTENSION_CONF_PULLDOWN);
gem.configDigital(Gem.EXTENSION_DIGITAL_5, Gem.EXTENSION_CONF_INPUT_NOTIFY | Gem.EXTENSION_CONF_PULLUP);

Configuraion can be used also to reset any GPIO to initial state (high-impedance input):

gem.configDigital(Gem.EXTENSION_DIGITAL_1, Gem.EXTENSION_CONF_RESET);

Then you can set them or read their values. Read result will be returned via ExtensionsListener (see below)

gem.writeDigital(Gem.EXTENSION_DIGITAL_0, true);
gem.readDigital(Gem.EXTENSION_DIGITAL_1);

Analog inputs

Analog inputs reads the voltage on corresponding pin

gem.readAnalog(Gem.EXTENSION_ANALOG_0);

Result will be returned via ExtensionsListener in 0..3.6V range (see below)

PWM (Pulse-Width Modulation)

gem.writePWM(2.5f);

Sets PWM output to certain voltage 0V..3.6V. The value is limited by board supply votage. For example, with battery extension board the supply voltage is 3V.

I2C

Up to 16bytes can be written to the I2C bus or read from there per request
Result of read requests will be returned via ExtensionsListener (see below)

//Write directly to the bus to 0x5c address
gem.writeI2C(0x5c, new byte[] { 0, 0x12, 0x14 });

//Write to the 0x5c device to 0x02 register 
gem.writeI2C(0x5c, 0x02, new byte[] { 0, 0x12, 0x14 });

//Read 4 bytes from the device with 0x5c address
gem.readI2C(0x5c, 4);

//Read 4 bytes from 16, register 0x02
gem.readI2C(0x5c, 0x04, 16);

SPI

Up to 16bytes can be written to the I2C bus or read from there per request
Result of read requests will be returned with the same request ID via ExtensionsListener (see below)

//Read 5 bytes from SPI bus. Request ID is 0
gem.readSPI(0, 5);

//Write data to SPI 
gem.writeSPI(new byte[] { 0, 0x12, 0x14 });

//Writes to SPI bus with following reading simultaneously
gem.writeReadSPI(0, new byte[] { 0, 0x12, 0x14 });

Callbacks

Extensions callback is implemented as an abstract class, so there is no need to implement all the functions

gem.setExtensionsListener(new ExtensionsAbstractListener() {
    @Override
    public void onDigitalRead(DigitalInputData data) {
        if(data.id == Gem.EXTENSION_DIGITAL_0) {
            //Your code   
        }
        //Your code
    }

    @Override
    public void onAnalogRead(AnalogInputData data) {
        if(data.id == Gem.EXTENSION_ANALOG_0) {
            //Your code   
        }
        //Your code  
    }

    @Override
    public void public void onI2CRead(I2cData data) {
        if(data.address == 0x5c) {
            //Your code   
        }
        //Your code  
    }

    @Override
    public void onSpiRead(SpiData data) {
        if(data.requestId == 0) {
            //Your code   
        }
        //Your code
    }
});

Using multiple gems

You can call easily use multiple gems (as much as your Android device can handle)

gem1 = GemManager.getDefault().getGem(whitelist[0], gemListener1);
gem2 = GemManager.getDefault().getGem(whitelist[1], gemListener2);

Scanning gems (Advanced)

To your own way of building Gem white list inside your app we provide API for scanning Gems around.

Create scanner class instance and specify its callback:

scanner = new GemScanner(new GemScanListener() {
    @Override
    public void onScanFinish() {
        //Your code here
    }

    @Override
    public void onDeviceDiscovered(final BluetoothDevice device, int rssi) 
    {
        Log.i("GemDemo", "Gem found: " + device.getAddress());
    }
});

Then you can start scanning:

//scanning by default lasts in 25 sec
scanner.scan();
//or specify this time manually
scanner.start(15); //15 sec

Scan process can be stopped earlier:

scanner.stop();  

NOTE: For Android 6 requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permissions

Over-the-Air updating (Advanced)

Currently API is not available. Bur you can update your Gems via Gem SDK Utility for Android mentioned above

Gesture recognition

GemSDK contains gesture recognition library. Check out
Api Reference and corresponding sample project.

Samples

Sample are available on GitHub