MassimilianoMichele Valentini
Published © GPL3+

Arduino Tracked Rover Robot Control with Gesture

We use The Tactigon Skin (T-Skin) to control our tracked rover by moving our hand!The rover robot is Arduino base robot with BLE

IntermediateWork in progress2 hours301
Arduino Tracked Rover Robot Control with Gesture

Things used in this project

Hardware components

The Tactigon Skin (T-SKIN)
The Tactigon Skin (T-SKIN)
TACTIGON Skin gesture controller with Arduino SDK
×1
Tracked Rover
tracked rover robot from Lynxmotion
×1
Arduino Pro Mini 328 - 5V/16MHz
SparkFun Arduino Pro Mini 328 - 5V/16MHz
You can use Arduino board or The Tactigon ONE BOARD (with BLE and MCU inside) to control the rover robot
×1
Bluetooth Low Energy (BLE) Module (Generic)
×1
Motor Bridge Cape
Seeed Motor Bridge Cape
use motor bridge in the rover robot
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Code

T-Skin

Arduino
Controller code
/**************************************************/
/* CINGO Controller for T-Skin use only.          */
/* Won't work on The Tactigon One board           */
/* as it's missing button to start communication. */
/* MAC Address updated to work with last receiver */
/* https://thetactigon.com  info@thetactigon.com  */
/**************************************************/

#include <tactigon_led.h>
#include <tactigon_IMU.h>
#include <tactigon_BLE.h>
#include <tactigon_IO.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, 0x31, 0x77, 0x59};
T_BLE_Characteristic accChar, gyroChar, magChar, qChar;

//GPIO
T_GPP gpp1;
T_GPP gpp2;
T_GPP gpp3;
T_GPP gpp4;

boolean transmission = false;
int debounceTime = 300;
int lastTransmissionSwitch, lastGPIO1Switch, lastGPIO2Switch, lastGPIO3Switch = 0;

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);                  //BLE role: CENTRAL
  targetUUID.set("c1c0760d-503d-4920-b000-101e7306b001");     //target characteristic
  bleManager.setTarget(targetMAC, targetUUID);                //target: mac device and its char UUID

  gpp1.init(T_GPP::GPP1, T_GPP::GPP_IN);
  gpp2.init(T_GPP::GPP2, T_GPP::GPP_IN);
  gpp3.init(T_GPP::GPP3, T_GPP::GPP_IN);
  gpp4.init(T_GPP::GPP4, T_GPP::GPP_IN);
}




//////////////////////////////////////////////////////////////////////////////////////////
void loop() {


  char buffData[2];


  int deltaWheel, speedWheel;
  int pitchThreshold, rollThreshold, th1, th2;

  //base engine @ 50Hz (20msec)
  if (GetCurrentMilli() >= (ticks + (1000 / 50))) {
    ticks = GetCurrentMilli();
    //debounce on GPP4 (activate /deactivate transmission)
    if (!gpp4.read()) {
      if (GetCurrentMilli() >= lastTransmissionSwitch + debounceTime) {
        transmission = !transmission;
        lastTransmissionSwitch = GetCurrentMilli();
      }
    }
    if (transmission) {
      //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);

      //compute speed wheel and delta speed wheel 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;
      }


      //convert speedWheel and deltaWheel in command byte for motor control board
      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;

      //fill buffData to write in BLE characteristic
      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();
        }
        //write in BLE characteristic (@ 10Hz in order to not stress control motor board)
        cnt++;
        if (cnt > 5) {
          bleManager.writeToPeripheral((unsigned char *)buffData, 2);
          cnt = 0;
          rLed.on();
        }

      }
    }        else {
      buffData[0] = 0x00;
      buffData[1] = 0x00;
      //debounce on GPP1 (rotate)
      if (!gpp2.read()) {
        if (GetCurrentMilli() >= lastTransmissionSwitch + debounceTime) {
          buffData[0] = 0x01;
          buffData[1] = 0xFF;
          lastGPIO1Switch = GetCurrentMilli();
        }
      }
      //debounce on GPP2 (rotate)
      if (!gpp1.read()) {
        if (GetCurrentMilli() >= lastTransmissionSwitch + debounceTime) {
          buffData[0] = 0x7F;
          buffData[1] = 0x80;
          lastGPIO2Switch = GetCurrentMilli();
        }
      }
      //debounce on GPP3 (stop)
      if (!gpp3.read()) {
        if (GetCurrentMilli() >= lastTransmissionSwitch + debounceTime) {
          buffData[0] = 0x00;
          buffData[1] = 0x00;
          lastGPIO3Switch = GetCurrentMilli();

        }
      }
      bleManager.writeToPeripheral((unsigned char *)buffData, 2);
    }

  }


}

CINGO

Arduino
Receiver 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();
  cingoSpeed((char*)pData, dataLen);
}

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

/*----------------------------------------------------------------------*/
void cingoSpeed(char *spd, uint8_t len) {
  tSerial.write(spd, len);
}



/*----------------------------------------------------------------------*/
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 characteristic UUID
  cmdChar = bleManager.addNewChar(uuid, 18, 1);         //create characteristic
  charProg = cmdChar.setWcb(cbBLEcharWritten);          //setup a callback on characteristic write event

  //init user serial
  tSerial.init(T_UserSerial::B_9600, T_UserSerial::T_SERIAL1);
}



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

  //Cycle on 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;
  }

}

Credits

Massimiliano

Massimiliano

17 projects • 68 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 • 24 followers

Comments

Add projectSign up / Login