MassimilianoMichele Valentini
Published © Apache-2.0

Arduino Rover Control with the Tactigon ONE

We'll look at how to control a simple tracked rover using Euler's angles. The remote controller can be put in a glove and become wearable!

IntermediateProtip2 hours179

Things used in this project

Hardware components

The Tactigon One
The Tactigon One
×2
Arduino UNO & Genuino UNO
Arduino UNO & Genuino UNO
Use this board in Rover Robot
×1
Bluetooth Low Energy (BLE) Module (Generic)
use this module in rover robot
×1
Motor Bridge Cape
Seeed Motor Bridge Cape
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Fritzing Scheme

Connection between The Tactigon and motor control board on the rover
Motori tactigon seriale 4bbpkubip8

Code

CINGO.ino

Arduino
Rover side code
#include <tactigon_led.h>
#include <tactigon_BLE.h>
#include <tactigon_UserSerial.h>


//RGB LEDs
T_Led rLed, bLed, gLed;

//BLE Manager, BLE Characteristic and its UUID
T_BLE bleManager;
T_BLE_Characteristic cmdChar;
UUID uuid;

//UART
T_UserSerial tSerial;

//Used for LEDs cycle
int  ticksLed, stp;

/*----------------------------------------------------------------------*/
void cbBLEcharWritten(uint8_t *pData, uint8_t dataLen)
{
  blinkLEDs();
  velocitaCingoli((char*)pData);

}

/*----------------------------------------------------------------------*/
void cbUartRxByte(uint8_t bb) {

}

/*----------------------------------------------------------------------*/
void cbUartRxLine(const uint8_t *pLine, uint8_t len) {

}

/*----------------------------------------------------------------------*/
void avanti() {
  char mov[] = {0xFF, 0x7F};
  tSerial.write(mov, 2);
}

void indietro() {
  char mov[] = {0x01, 0x80};
  tSerial.write(mov, 2);
}

void frena() {
  char mov[] = {0x00};
  tSerial.write(mov, 1);
}

void destra() {
  char mov[] = {0x01, 0xFF};
  tSerial.write(mov, 2);
}

void sinistra() {
  char mov[] = {0x7F, 0x80};
  tSerial.write(mov, 2);
}

void blinkLEDs() {
  //Blinks LEDs, turned off by next state in loop()
  rLed.on();
  gLed.on();
  bLed.on();
}

/*----------------------------------------------------------------------*/
void velocitaCingoli(char *spd) {
  tSerial.write(spd, strlen(spd));
}

/*----------------------------------------------------------------------*/
void setup() {

  char charProg;

  ticksLed = 0;
  stp = 0;

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

  rLed.off();
  gLed.off();
  bLed.off();

  //init role
  bleManager.InitRole(TACTIGON_BLE_PERIPHERAL);
  //bleManager.setName("CINGO");
  uuid.set("c1c0760d-503d-4920-b000-101e7306b001");   //command char
  cmdChar = bleManager.addNewChar(uuid, 18, 1);
  charProg = cmdChar.setWcb(cbBLEcharWritten);

  //init user serial
  tSerial.init(T_UserSerial::B_9600);
  tSerial.setRxByteCB(cbUartRxByte);
  tSerial.setRxLineCB(cbUartRxLine);

}

/*----------------------------------------------------------------------*/
void loop() {

  //Cycle rgb leds
  if (GetCurrentMilli() >= (ticksLed + (3000 / 1))) {

    ticksLed = GetCurrentMilli();

    if (stp == 0) {
      rLed.on();
      gLed.off();
      bLed.off();
    }
    else if (stp == 1) {
      rLed.off();
      gLed.off();
      bLed.on();
    }
    else if (stp == 2) {
      rLed.off();
      gLed.on();
      bLed.off();
    }
    stp = (stp + 1) % 3;
  }

}

Controller.ino

Arduino
Controller side 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] = {0xbe, 0xa5, 0x7f, 0x2e, 0x7d, 0x4b};
T_BLE_Characteristic accChar, gyroChar, magChar, qChar;
//{0x00,0x0e,0x0b,0x0c,0x4a,0x00};
int ticks, ticksLed, stp, cnt, printCnt, ledCnt;
float roll, pitch, yaw;



void setup() {
  // put your setup code here, to run once:
  ticks = 0;
  ticksLed = 0;
  stp = 0;
  cnt = 0;
  ledCnt = 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("Tacti");
  bleManager.InitRole(TACTIGON_BLE_CENTRAL);                  //role: CENTRAL
  targetUUID.set("c1c0760d-503d-4920-b000-101e7306b001");     //target characteristic
  bleManager.setTarget(targetMAC, targetUUID);                //target: mac device and its char UUID
}
//0000ffe1-0000-1000-8000-00805f9b34fb
//c1c0760d-503d-4920-b000-101e7306b001
void loop() {

  char buffData[2];

  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;

    //forward/backword
    rollThreshold = 10;
    th1 = 90 + rollThreshold;
    th2 = 90 - rollThreshold;
    roll = fabs(roll);


    //build command to rover depending on Euler angles
    //left/right
    pitchThreshold = 10;
    if (pitch < -pitchThreshold || pitch > pitchThreshold) {
      if (pitch < -pitchThreshold) {
        if (roll < th1 && roll > th2) {
          //spin
          deltaWheel = - (fabs(pitch) - pitchThreshold) * 10;
          rLed.on();
          bLed.on();
          gLed.on();
        } else {
          deltaWheel = - (fabs(pitch) - pitchThreshold) * 3;
        }
      }
      else {
        if (roll < th1 && roll > th2) {
          //spin
          deltaWheel = + (fabs(pitch) - pitchThreshold) * 10;
          rLed.on();
          bLed.on();
          gLed.on();
        } else {
          deltaWheel = + (fabs(pitch) - pitchThreshold) * 3;
        }
      }
    }
    else {
      deltaWheel = 0;
    }

    //forward/backward
    if (roll > th1) {
      speedWheel = ((roll - th1) * 3);
    }
    else if (roll < th2) {
      speedWheel = ((roll - th2) * 3);
    }
    else {
      speedWheel = 0;
    }
    int sxC, dxC;
    uint8_t sx, dx;
    sxC = (speedWheel - (-deltaWheel / 4)) + 64;
    dxC = (speedWheel + (-deltaWheel / 4)) + 192;

    if (sxC > 127) {
      sxC = 127;
    } else if (sxC < 1) {
      sxC = 1;
    }
    if (dxC < 128) {
      dxC = 128;
    } else if ( dxC > 255) {
      dxC = 255;
    }
    sx = sxC;
    dx = dxC;
    //command in buffData
    buffData[0] = sx;
    buffData[1] = dx;
    Serial.print("SX: ");
    Serial.println(sx);
    Serial.print("DX: ");
    Serial.println(dx);
    //if connected and attached to peripheral characteristic write in it
    if (bleManager.getStatus() == 3) {
      //signal that connection is on
      bLed.on();
      rLed.off();
      ledCnt++;
      if (ledCnt > 100) {
        ledCnt = 0;
        rLed.off();
        bLed.off();
        gLed.off();
      }
      cnt++;
      if (cnt > 5) {
        cnt = 0;
        bleManager.writeToPeripheral((unsigned char *)buffData, 2);
        rLed.on();
      }
    }
    else
      bLed.off();
  }
}

Credits

Massimiliano

Massimiliano

17 projects • 65 followers
I'm an engineer and I like robotics, embedded systems and linux. I spent a lot of time in automation and firmware development.
Michele Valentini

Michele Valentini

10 projects • 22 followers

Comments

Add projectSign up / Login