RoadTest: element14 tinyTILE Intel® Curie™ Based Board
Author: ss_shrenik
Creation date:
Evaluation Type: Independent Products
Did you receive all parts the manufacturer stated would be included in the package?: True
What other parts do you consider comparable to this product?: As far as I know, I could not find a board with such a small footprint having BLE, and IMU sensors. This is a great product out of E14 to help rapid prototyping of BLE + IMU applications such as activity monitors.
What were the biggest problems encountered?: No problems as such as the product had enough supported examples of using it. Simple to setup development environment.
Detailed Review:
So there are many boards out there which have IMU and MCU in a single package, what makes this board unique is that it takes it to next level by providing BLE HW support in the same tiny package, hence the name might be tiny tile. And it lives up to its name. When you put this hardware support in the same IDE as the most popular as Arduino IDE with easy to use supported libraries, it has already made the work simple for beginners.
As with all of my previous road tests, I test boards by testing its capabilities. How to do that? simple, think of some application which can make use of board's HW interfaces.
Without duplicating same spec/feature information in the review, I would leave you a better link for the material regarding TinyTile board.
https://www.element14.com/community/docs/DOC-82913/l/tinytile-intel-curie-module-based-board
Reading its specs/features and looking at its size, two ideas came into my mind.
1. Wearable device
2. Motion HID controller.
And I decided to make BLE Motion Game Controller.
For BLE Motion Game what I needed is Bluetooth LE profile and Motion sensing of our gestures.
Step 1. Setting up the environment for Intel Curie TinyTile
1. I decided to use Arduino IDE environment as it is easy for any prototyping
2. Go to Sketch->include Library->Manage Library and then search for "curie" and install
necessary libraries that you need to use. I needed BLE and IMU libraries so I installed
CurieBLE and CurieIMU libraries.
3. Now you can test some example sketch such as IMU tests or BLE profile tests similar to Arduino.
4. I referred to Battery Monitor BLE example and Orientation detection IMU example from example sketched provided with CurieBLE and CurieIMU libraries.
Step 2. Testing sample examples before using them
In order to understand the existing examples and then tweak them to satisfy our need I tried the BatteryMonitor application.
BatteryMonitor: This example creates battery monitor BLE profile and updates analog value read on one of Curie board's Analog Input. As I wanted to use BLE with my Mac I decided to test on same. I came across one BLE application which can discover profiles, connect and can read characteristics from BLE device.
Below you can see "Inspector Gatt tool" that I found in App store, can discover my device. As I am using BatteryService itself to report Gestures you can see Service Name as Battery Service. From this tool
one can check if we are sending data as expected or not. Or can play with other BLE profiles.
Accelerometer Orientation: This example shows Reading of Accelerometer and then detecting the orientation of the board based on values of x, y, z axis. Which will show up on Serial Terminal. That's what needed, Up/Down, Left/Right to move a car in the game.
Step 3. Implementing BLE Motion Game Controller itself
As you already went through the examples I am referring to I used them to prepare code of BLE Motion Game Controller.
What it does
a. broadcast BLE service
b. Read Accelerometer data and then decide boards position
c. Send direction data over BLE
Following is the code for the reference
tinyTILE Sketch
/***************************************************************************************** * Intel Curie TinyTile Board Element14 Road test * BLE Motion Game Controller * Author : Shrenik Shikhare engineershrenik@gmail.com * Date : 21 July 2017 ****************************************************************************************/ #include "CurieIMU.h" #include <CurieBLE.h> BLEService batteryService("180F"); // Using battery service to send motion information // BLE Battery Level Characteristic" BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID BLERead | BLENotify); // remote clients will be able to // get notifications if this characteristic changes void setup() { Serial.begin(115200); // initialize Serial communication // initialize device Serial.println("Initializing IMU device..."); CurieIMU.begin(); // Set the accelerometer range to 2G CurieIMU.setAccelerometerRange(2); // begin initialization BLE.begin(); /* Set a local name for the BLE device This name will appear in advertising packets and can be used by remote devices to identify this BLE device The name can be changed but maybe be truncated based on space left in advertisement packet */ BLE.setLocalName("BLEGameController"); // Creating BLE name for BLEGameController BLE.setAdvertisedService(batteryService); // add the service UUID batteryService.addCharacteristic(batteryLevelChar); // add the battery level characteristic BLE.addService(batteryService); // Add the BLE Battery service batteryLevelChar.setValue(0); // initial value for this characteristic /* Start advertising BLE. It will start continuously transmitting BLE advertising packets and will be visible to remote BLE central devices until it receives a new connection */ // start advertising BLE.advertise(); Serial.println("Bluetooth device active, waiting for connections..."); } void loop() { // listen for BLE peripherals to connect: BLEDevice central = BLE.central(); int direction = - 1; // the direction // if a central is connected to peripheral: if (central) { Serial.print("Connected to central: "); // print the central's MAC address: Serial.println(central.address()); // as long as the central is still connected: while (central.connected()) { // read accelerometer: int x = CurieIMU.readAccelerometer(X_AXIS); int y = CurieIMU.readAccelerometer(Y_AXIS); int z = CurieIMU.readAccelerometer(Z_AXIS); // calculate the absolute values, to determine the largest int absX = abs(x); int absY = abs(y); int absZ = abs(z); if ( (absZ > absX) && (absZ > absY)) { // base direction on Z if (z > 0) { direction = 0; } else { direction = 1; } } else if ( (absY > absX) && (absY > absZ)) { // base direction on Y if (y > 0) { direction = 2; } else { direction = 3; } } else { // base direction on X if (x < 0) { direction = 4; } else { direction = 5; } } batteryLevelChar.setValue(direction);// Send direction information over BLE delay(100); } } }
Step 4. Host side program to process motion and provide input to control the game.
Obviously, As I wanted to make a Game Controller for Host, I wrote a python program to read BLE and use the direction information in order to move the car. First, I thought I could use HID Keyboard profile to feed keys direction to my Macbook but was not able to connect it successfully to Mac as BT keyboard.
Then I decided to use proven gatttool from Linux machine (gatttool is a handy tool to play with BLE devices), but my game was running on Macbook and Linux in Virtual Machine. So I decided to transfer information read by python program using gatttool to host machine using socket programming.To achieve it, there is tcp server running on macbook and TCP client + gatttool(used pexpect in python to use gatttool) running on Linux virtual machine. The client program will read direction information coming from Battery service and then send commands to tcp server. The server reads this command and then injects keyboard events such as Up/Down, Left/Right respective to the orientation of the board. This will provide you a natural way of playing your favourite racing game with gestures and not with the keyboard.
Below are the code snippets used to process gestures and assign actions to them on host
Code to read BLE characteristic value and transfer it to server
# BLE Motion Game Controller with Intel Curie TinyTile Board client application import pexpect import time import os import socket TCP_IP = '192.168.1.100' TCP_PORT = 8080 BUFFER_SIZE = 1024 DEVICE = "84:68:3E:06:2D:D7" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print("Game Controller address:"), print(DEVICE) # Interactive gatttool to read BLE device child = pexpect.spawn("gatttool -I") # Connect to the device. print("Connecting to Intel Curie"), print(DEVICE), child.sendline("connect {0}".format(DEVICE)) child.expect("Connection successful", timeout=5) print(" Connected BLE Motion Controller!") s.connect((TCP_IP,TCP_PORT)) while True: #Read BT child.sendline("char-read-hnd 0x000b") child.expect("Characteristic value/descriptor: ", timeout=10) child.expect("\r\n", timeout=10) direction = child.before[0:2] #time.sleep(.1) #2-RIGHT #3-LEFT #4-FWD #5-REVERSE if(direction == '02'): print 'RIGHT' s.send("RIGHT") #Send direction to TCP Server Running on Host machine where game is running if(direction == '03'): print 'LEFT' s.send("LEFT") if(direction == "04"): print 'FWD' s.send("FWD") if(direction == "05"): print 'REVERSE' s.send("REVERSE")
Code to read motion data and inject respective keyboard key-event to host machine
# BLE Motion Game Controller with Intel Curie TinyTile Board Server application import pyautogui import os import time import sys import socket TCP_IP = '192.168.1.100' TCP_PORT = 8080 BUFFER_SIZE = 20 # Normally 1024, but we want fast response s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((TCP_IP, TCP_PORT)) s.listen(10) conn, addr = s.accept() print 'Connection address:', addr prev_action = 0 while True: ret_string = conn.recv(BUFFER_SIZE) print (ret_string) if(ret_string.find("RIGHT") == 0): if prev_action != 0: pyautogui.keyDown('right') pyautogui.keyUp('left') prev_action = 0 if(ret_string.find("LEFT") == 0): if prev_action != 1: pyautogui.keyDown('left') pyautogui.keyUp('right') prev_action = 1 if((ret_string.find("RIGHT") != 0) and (ret_string.find("LEFT") != 0) and (ret_string.find("DOWN") != 0) and (ret_string.find("UP") != 0)) : if prev_action != 2: pyautogui.keyUp('right') pyautogui.keyUp('left') pyautogui.keyUp('dowwn') pyautogui.keyUp('up') prev_action = 2 if(ret_string.find("FWD") == 0): if prev_action != 3: pyautogui.keyDown('up') # pyautogui.keyUp('right') # pyautogui.keyUp('left') pyautogui.keyUp('down') prev_action = 3 if(ret_string.find("REVERSE") == 0): if prev_action != 4: pyautogui.keyDown('down') #pyautogui.keyUp('right') #pyautogui.keyUp('left') pyautogui.keyUp('up') prev_action = 4 conn.close()
Why not see it in action :), check below video
https://www.youtube.com/watch?v=dM8qqh5r1WA
Conclusion:
1. Its Tiny as its name suggest, makes possible to use in battery operated applications
2. BLE + IMU on small package make it useful for applications such as wearables for fitness applications, HID devices, monitoring motions wirelessly, etc.
3. You hardly need knowledge of BLE to use this. Basic knowledge such as profile/services should be enough.
4. I would recommend if anyone wanna use it for fitness application. Personally, i would want to create a fitness tracker out of it.
Finally, Thanks to element14 for providing me the opportunity to test and use this tiny board with great capabilities on single package.
-Shrenik
Top Comments
Nice review and great demo.
Having the device control the game was a great idea on how to use the device in position extrapolation to move the car.
Very nice.
DAB