We used The Tactigon to control an Arduino-powered robot via BLE. Moving The Tactigon as a 3D steering wheel is awesome!

This post will show how to take advantages of The Tactigon’s BLE Central capabilities. We wanted to control our robot by using The Tactigon as a “3D steering wheel” controlling speed with pitch and steering with roll. We made so few changes in the Alphabot2 original Bluetooth example code and wrote a sketch for The Tactigon to connect to the robot’s BLE characteristic and write in wheels speeds.

What We Need

  • The Tactigon with a configured Arduino IDE
  • Robot. We used a 2 wheels robot with Arduino board and BLE radio interfaced with UART. Other kind of robots or custom ones can work as well.
  • Robot BLE MAC Address and Characteristic
  • Fun

Gathering BLE MAC Address and characteristic

After our environment is configured and our boards are ON, we need to gather BLE MAC Address and Characteristic. To do so we used a free android application called BLE Scanner.


1Scanning-576x1024.png

Few seconds after the application should show the robot’s BLE:

2MACADD_OK-576x1024.png

As we see, all BLE devices around us are showed in this section. We need to write down the Waveshare_BLE MAC address: in this instance it is: 00:0E:0B:0C:4A:00

By clicking on the CONNECT button we access to device’s informations as attribute, service and custom characteristic.


3Characteristic-576x1024.png

Here we need to write down the CUSTOM CHARACTERISTIC UUID, in this case: 0000ffe1-0000-1000-8000-00805f9b34fb .

With this items we can set our Tactigon BLE to act as BLE Central in the setup() section of the code.

The Tactigon Sketch

Loop

In this section we have the core of the sketch. At a frequency of 50Hz, we update quaternions and euler angles.

loop_quaternion_euler.png

Analizyng pitch angle provided by Tactigon library, we can determine steering radius by slowing internal wheel and accelerating external wheel.


pitch_steering_radius.png

Analizying roll, instead, we can determine travel speed of the robot.

roll_travel_speed.png

With a sprintf we prepare the buffer to write in the characteristic.

sprintf_buffer.png

Robot Sketch

Since our Bluetooth sends received data over UART, we get wheels speed directly in the serial buffer.

We have set robot pins as follows, all as output:


robot_pins.png

To parse the command we first read all the serial buffer and verify if it is longer than 0:

loop_parse1.png

If the command contains “Wh” we can so parse the string and gather leftSpeed and rightSpeed.


robot_parse_wheel.png

The direct_motor function assign the speed transmitted by The Tactigon to each wheel of the robot. By doing so The Tactigon will act as a virtual-steering wheel!

direct_motor.png

Final Considerations

This sketch shows a potential application of The Tactigon, with the BLE Central mode is possible to connect to existing BLE devices and gather informations or control them.

Stay tuned for more Tactigon’s code!

Alphabot2 Code

The Tactigon Code

    #include <tactigon_led.h>
#include <tactigon_IMU.h>
#include <tactigon_BLE.h>


extern int ButtonPressed;

T_Led rLed, bLed, gLed;



T_QUAT qMeter;
T_QData qData;

T_BLE bleManager;
UUID targetUUID;
uint8_t targetMAC[6] = {0x00,0x0e,0x0b,0x0c,0x4a,0x00};
T_BLE_Characteristic accChar, gyroChar, magChar, qChar;

int ticks, ticksLed, stp, cnt, printCnt;
float roll, pitch, yaw;



void setup() {
  // put your setup code here, to run once:
  ticks = 0;
  ticksLed = 0;
  stp = 0;
  cnt = 0;

  //init leds
  rLed.init(T_Led::RED);
  gLed.init(T_Led::GREEN);
  bLed.init(T_Led::BLUE);
  rLed.off();
  gLed.off();
  bLed.off();

  //init BLE 
  bleManager.setName("Tactigon");
  bleManager.InitRole(TACTIGON_BLE_CENTRAL);                  //role: CENTRAL
  targetUUID.set("0000ffe1-0000-1000-8000-00805f9b34fb");     //target characteristic
  bleManager.setTarget(targetMAC, targetUUID);                //target: mac device and its char UUID
}

void loop() {

  char buffData[24];  
  int deltaWheel, speedWheel;
  int pitchThreshold, rollThreshold, th1, th2;

  //update BLE characteristics @ 50Hz (20msec)
  if(GetCurrentMilli() >= (ticks +(1000 / 50)))
  {    
    ticks = GetCurrentMilli();
        
    //get quaternions and Euler angles
    qData = qMeter.getQs();      

    //Euler angles: rad/sec --> degrees/sec    
    roll = qData.roll * 360/6.28;
    pitch = qData.pitch * 360/6.28;
    yaw = qData.yaw * 360/6.28;


    //build command to rover depending on Euler angles                  
    //left/right
    pitchThreshold = 15;
    if(pitch < -pitchThreshold || pitch > pitchThreshold)
    {
      if(pitch<-pitchThreshold)
      {
        deltaWheel =- (fabs(pitch) - pitchThreshold)*3;
      }
      else
      {
        deltaWheel =+ (fabs(pitch) - pitchThreshold)*3;
      }      
    }
    else
    {
      deltaWheel=0;
    }

    //forward/backword
    rollThreshold = 15;
    th1 = 90 + rollThreshold;
    th2 = 90 - rollThreshold;
    roll = fabs(roll);
    if(roll > th1)
    {
      speedWheel = (roll - th1) * 3;
    }
    else if(roll < th2)
    {
      speedWheel = (roll - th2) * 3;
    }
    else
    {
      speedWheel = 0;
    }
    
    //command in buffData
    sprintf(buffData,"Wh(%d)(%d)", speedWheel-(-deltaWheel/2), speedWheel+(-deltaWheel/2));

    
    //if connected and attached to peripheral characteristic write in it
    if(bleManager.getStatus() == 3)
    {
      //signal that connection is on
      bLed.on();
      
      //send command every 100msec
      rLed.off();
      cnt++;
      if(cnt > 5)
      {
        cnt = 0;
        bleManager.writeToPeripheral((unsigned char *)buffData, strlen(buffData));
        rLed.on();        
      }    
    }


    //say hello on serial monitor every second and blink green led
    printCnt++;
    rLed.off();
    if(printCnt > 50)
    {      
      //Serial.println("Hello!");
      //Serial.println(roll);
      printCnt = 0;
      rLed.on();
    }    
    
  }  
}
The Tactigon

Maker Pro Logo
Continue to site
Quote of the day

-