«

»

Apr 07

Print this Post

Bluetooth Servos

Hello everyone.
I’d like to share with you my latest mini-project.

I wanted to control a Pan&Tilt system from my mobile phone.

Note: the audio is in Portuguese, but I took some time to make the English subtitles.

Using:

2 Servos (Pan & Tilt)
1 Arduino Duemilanove
1 Processing Application (running in the computer)
1 Mobile Processing Application (running in the mobile phone)

Code – Arduino

/*
 * BluetoothServos (Arduino)
 * --------------
 * Servo control from the Mobile Phone
 *  Ricardo Dias (2010) - http://ricardo-dias.com/
 */

#include <Servo.h>

// Servo handle
Servo hServoPan;
Servo hServoTilt;

// Servo pin
const int pinServoPan = 9;
const int pinServoTilt = 10;

// Cropping
const int minServoPan = 0;
const int maxServoPan = 180;
const int minServoTilt = 50;
const int maxServoTilt = 150;

// Current values
int valServoPan;
int valServoTilt;

// Auxiliar variables
int received;
char data[5];
boolean dataReady;

void setup() {
  hServoPan.attach(pinServoPan);
  hServoTilt.attach(pinServoTilt);
  valServoPan = maxServoPan - ((maxServoPan - minServoPan)/2);
  valServoTilt = maxServoTilt - ((maxServoTilt - minServoTilt)/2);
  Serial.begin(19200);
  hServoPan.write(valServoPan);
  hServoTilt.write(valServoTilt);
}

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
    int startChar = Serial.read();
    if(startChar == (int)'#'){
      while(Serial.available() < 5); // wait to receive more 5 chars
      for(int i = 0; i < 5; i++){
        data[i] = Serial.read();
      }
    }
    
    // Now I have an array data[] that has 5 chars of information
    // I can do whatever I want with that information
    if(data[0] == '1') valServoTilt+=2;
    if(data[1] == '1') valServoPan+=2;
    if(data[2] == '1') valServoTilt-=2;
    if(data[3] == '1') valServoPan-=2;
    
    // Servo cropping
    if(valServoPan > maxServoPan) valServoPan = maxServoPan;
    else if(valServoPan < minServoPan) valServoPan = minServoPan;
    if(valServoTilt > maxServoTilt) valServoTilt = maxServoTilt;
    else if(valServoTilt < minServoTilt) valServoTilt = minServoTilt;
    
    hServoPan.write(valServoPan);
    hServoTilt.write(valServoTilt);
    
  }
}

Code – Processing

/*
 * BluetoothServos (Processing)
 * --------------
 * Servo control from the Mobile Phone
 *  Ricardo Dias (2010) - http://ricardo-dias.com/
 */

import bluetoothDesktop.*;
import processing.serial.*;

Serial myPort;  // Create object from Serial class

PFont font;
Bluetooth bt;
String msg = "inactive";
Client server;
final String SERVICE_NAME = "simpleService";
boolean connected;

int count = 0;
String recebido = "";

void setup() {
  size(600,300);
  font = createFont("Courier", 15);
  textFont(font);
  try {
    bt = new Bluetooth(this, Bluetooth.UUID_RFCOMM); // RFCOMM

    // Start finding the service
    bt.find();
    msg = "searching...";
  } 
  catch (RuntimeException e) {
    msg = "error. is your bluetooth on?";
    println(e);
  }
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 19200);
}

void draw() {
  background(0);
  fill(255);
  text(msg, 10, height/2);
  if (connected == true){
       if (server.available() > 0){
             recebido = server.readUTF();
             // when the mobile exits the application, it sends "exit"
             if(recebido.equals("exit")){ 
               recebido = "bye bye!";
               exit();
             }
        }
  }
  
  text(recebido, 10, 30);
  String toSend = "#"+recebido+".";
  myPort.write(toSend);
}


// this gets called when the search process is over
void serviceDiscoveryCompleteEvent(Service[] s) {
  Service[] services = (Service[])s;

  msg = "Search completed.";

  // now search for the service we want
  for (int i=0; i<services.length; i++) {
    println(services[i].name);
    if (services[i].name.equals(SERVICE_NAME)) {
      msg = "Service " + SERVICE_NAME + " found";
      
      try {
        // we found our service, so try to connect to it
        // if we try to connect to it more than once, this will throw an error.
        server = services[i].connect();
        msg = "Connected to service " + SERVICE_NAME + " on server " + server.device.name;
        connected = true;
        return;
      } 
      catch (Exception e) {
        msg = "Found service " + SERVICE_NAME + " on Server " + server.device.name + ", but connection failed";
        println(e);
        return;
      }
    } 
  }

  msg = "Service " + SERVICE_NAME + " not found.";
}

Code – Mobile Processing

/*
 * BluetoothServos (Mobile Processing)
 * --------------
 * Servo control from the Mobile Phone
 *  Ricardo Dias (2010) - http://ricardo-dias.com/
 */

import processing.bluetooth.*;

final String SERVICE_NAME = "simpleService";
Bluetooth bt;
String[] clients = new String[0];
Client teste;
PFont font;
String msg;  // status message
boolean clientOn = false;

// teclas
boolean tUp = false;
boolean tRight = false;
boolean tDown = false;
boolean tLeft = false;

void setup() {
  //framerate(15);
  
  // set up font
  font = loadFont();
  textFont(font);

  // initialize Bluetooth library
  bt = new Bluetooth(this, 0x0003); // RFCOMM

  // start service
  bt.start(SERVICE_NAME);

  msg = "Waiting for base...";
}

void destroy() {
  if(clientOn) teste.writeUTF("exit");
  bt.stop();
}

void draw() {
  background(255);

  fill(0);
  text(msg, 3,20);

  // draw connected clients
  for (int i=0; i<clients.length; i++) {
    text(clients[i], 6, 20+(i+1)*17);
  }
  
  if(clientOn){
    String send = "";
    if(tUp) send += "1"; else send += "0";
    if(tRight) send += "1"; else send += "0";
    if(tDown) send += "1"; else send += "0";
    if(tLeft) send += "1"; else send += "0";
    teste.writeUTF(send);
  }
}

void keyPressed() 
{
  if (keyCode == UP) {
    tUp = true;
  }else if (keyCode == RIGHT) {
    tRight = true;
  }else if (keyCode == DOWN) {
    tDown = true;
  }else if (keyCode == LEFT) {
    tLeft = true;
  }
}

void keyReleased() 
{
  if (keyCode == UP) {
    tUp = false;
  }else if (keyCode == RIGHT) {
    tRight = false;
  }else if (keyCode == DOWN) {
    tDown = false;
  }else if (keyCode == LEFT) {
    tLeft = false;
  }
}

// gets called by BT if something happens
void libraryEvent(Object library, int event, Object data) {
  if (library == bt) {
    if (event == Bluetooth.EVENT_CLIENT_CONNECTED && !clientOn) {
      // a new client is connected. 
      teste = (Client)data;
      clients = (String[]) append(clients, ((Client) data).device.name);
      msg = "Linked to:"; 
     clientOn = true; 
    }
  }
}

About the author

Ricardo Dias

Ricardo Dias was born in Entroncamento, Portugal and is studying Electronic and Telecommunications Engineering at University of Aveiro. He is a researcher in robotics and is currently the Team Leader of CAMBADA@MSL team. As a hobby, he is also a freelancer Stage Lighting Designer.

Permanent link to this article: http://ricardo-dias.com/2010/04/07/bluetooth-servos/

Leave a Reply

Your email address will not be published. Required fields are marked *