ch08

BlinkOnCommand.pde

/*
 * BlinkOnCommand - turns an LED on or off
 */

int ledPin = 13;

void setup() {
  Serial.begin(115200);    // Open a connection to the Bluetooth Mate
  pinMode(ledPin, OUTPUT); // Activate the LED
}

void loop() {
  
  // Look for data coming in from the Bluetooth Mate
  if (Serial.available() > 0) {
    char cmd = Serial.read(); // Read the character
    Serial.print(cmd);        // Echo the character back
    
    // '1' turns on the LED, '0' turns it off
    if (cmd == '1') {
      digitalWrite(ledPin, HIGH);
    } else if (cmd == '0') {
      digitalWrite(ledPin, LOW);
    }
  }
  delay(20);
}

fullRotation.pde

// fullRotation.pde - Turn continuous rotation servo clockwise, 
// counterclockwise and stop. 
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com

#include <Servo.h> 

Servo myServo; 
int servoPin = 2;

void servoClockWise()
{
    myServo.write(85);
    delay(1000);
}

void servoCounterClockWise()
{
    myServo.write(95);
    delay(1000);
}


void servoStop()
{
    myServo.write(90);
    delay(1000);
}

void setup()
{
  myServo.attach(servoPin);
}

void loop()
{
  servoClockWise();
  servoStop();
  servoCounterClockWise();
  servoStop();
}

footballBotDirections.pde

// footballBotDirections.pde - Move forward, backward, turn right and left.
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com

#include <Servo.h>

int servoRightPin = 2;
int servoLeftPin  = 3;
Servo servoRight;
Servo servoLeft;

void moveForward()
{
  servoLeft.write(180);
  servoRight.write(0);
}

void moveBack() 
{
  servoLeft.write(0);
  servoRight.write(180);
}

void turnRight() 
{
  servoLeft.write(180);
  servoRight.write(180);
} 

void turnLeft() 
{
  servoLeft.write(0);
  servoRight.write(0);
} 

void stopMoving()
{
  servoLeft.write(90);
  servoRight.write(90);
}

void setup()
{
  servoRight.attach(servoRightPin);
  servoLeft.attach(servoLeftPin);
}
 
void loop()
{
    moveForward();
    delay(1000);
    stopMoving();
    delay(1000);
    
    moveBack();
    delay(1000);
    stopMoving();
    delay(1000);

    turnRight();
    delay(1000);
    stopMoving();
    delay(1000);

    turnLeft();
    delay(1000);
    stopMoving();
    delay(1000);
}

footballBotKick.pde

/ footballBotKick.pde - Kick
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com

#include <Servo.h>

int servoKickPin = 4; 
Servo kickerServo;

int kickerNeutral = 130; 
int kickerKick    = 10; 
long kickerWait   = 750; 

void kick() 
{
  kickerServo.write(kickerKick);
  delay(kickerWait);
  kickerServo.write(kickerNeutral);
}

void setup() 
{
  kickerServo.attach(servoKickPin);
  kickerServo.write(kickerNeutral);
}
 
void loop() 
{
    kick();
    delay(5000);
}

Creating_ a_Simple_User_Interface.txt

// (c) Tero Karvinen & Kimmo Karvinen http://BotBook.com
 
package fi.sulautetut.android.uiandvibra;
 
import android.app.Activity; 
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
 
public class UiAndVibra extends Activity {
    TextView statusTv;
    TextView messagesTv;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initGUI(); 
    }
 
    @Override
    public void onResume() { 
        super.onResume();
        statusTv.setText("One-line status. "); 
        messagesTv.append(
          "This message box \nwill have\n many lines of text... ");
        vibrate();
    }
 
    void initGUI() 
    {
        // Window
        setRequestedOrientation(
                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        // Contents 
        LinearLayout container=new LinearLayout(this);
        container.setOrientation(android.widget.LinearLayout.VERTICAL);
        statusTv = new TextView(this);  
        container.addView(statusTv);
        messagesTv = new TextView(this);
        container.addView(messagesTv);
        // Show
        setContentView(container); 
    }
 
    void vibrate() 
    {
        Vibrator vibra = (Vibrator) getSystemService(
                Context.VIBRATOR_SERVICE); 
        vibra.vibrate(200); 7
    } 
}

accelerometer.txt

// Acceleration - print accelerometer values 
// (c) Tero Karvinen & Kimmo Karvinen http://BotBook.com
 
package fi.sulautetut.android.acceleration;
 
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
 
public class Acceleration 
    extends Activity 
    implements SensorEventListener 
{
    TextView statusTv; 
    TextView messagesTv;
    SensorManager sensorManager;
    Sensor sensor;
    float g=9.81f; // m/s**2 
    float x, y, z; // gravity along axis, times earth gravity 
 
    /*** Main - automatically called methods ***/
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initGUI();
    }
 
    @Override
    public void onResume() 
    {
        super.onResume(); 
        initAccel(); 
        msg("Running. ");
    } 
 
    @Override
    public void onPause() {
        super.onPause();
        closeAccel(); 
        msg("Paused. \n");
    }
 
    @Override
    public void onSensorChanged(SensorEvent event) { 
        x=event.values[1]/g;    // earth gravity along axis results 1.0
        y=event.values[2]/g;
        z=event.values[0]/g;
        statusTv.setText(String.format( 
                "x: %3.2f y: %3.2f, z: %3.2f", 
                x, y, z));
    }
 
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Must have when Activity implements SensorEventListener. 
    }
 
 
 
    /*** Accelerometer ***/
 
    void initAccel()
    {
        msg("Accelerometer initialization... ");
        sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE); 
        sensor=sensorManager.getDefaultSensor( 
                Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(
                this, 
                sensor, 
                sensorManager.SENSOR_DELAY_NORMAL );
    }
 
    void closeAccel()
    {
        msg("Accelerometer closing... ");
        sensorManager.unregisterListener(this, sensor);
    }
 
 
 
    /*** User interface ***/
 
    void initGUI()
    {
        // Window
        setRequestedOrientation(
                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        // Contents 
        LinearLayout container=new LinearLayout(this);
        container.setOrientation(android.widget.LinearLayout.VERTICAL);
        statusTv = new TextView(this);
        container.addView(statusTv);
        messagesTv = new TextView(this);
        messagesTv.setText("");
        container.addView(messagesTv);
        setContentView(container); 
        msg("User interface created. ");
    }
 
    public void msg(String s)
    {
        if (7<=messagesTv.getLineCount()) messagesTv.setText(""); 
        messagesTv.append(s);
    }
}

serialSample.pde

// serialSample.pde - test serial port over Bluetooth
// (c) Tero Karvinen & Kimmo Karvinen http://BotBook.com
 
int ledPin =  13;
 
void setup()
{
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200); // bits per second
}
 
void loop()
{
  digitalWrite(ledPin, HIGH);
  Serial.println("Hello Serial (over Bluetooth)!");
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
}

tBlueClient.java

// tBlueClient.java - read from serial port over Bluetooth
// (c) Tero Karvinen & Kimmo Karvinen http://BotBook.com
 
package fi.sulautetut.android.tblueclient;
 
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
 
 
public class TBlueClient extends Activity {
    TBlue tBlue;
    TextView messagesTv; 
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initGUI();
    }
 
    @Override
    public void onResume() 1
    {
        super.onResume();
        tBlue=new TBlue("00:07:80:83:AB:6A"); // You must change this! 2
        if (tBlue.streaming()) {
            messagesTv.append("Connected succesfully! ");
        } else {
            messagesTv.append("Error: Failed to connect. ");
        } 
        String s="";
        while (tBlue.streaming() && (s.length()<10) ) { 3
            s+=tBlue.read(); 4
        }
        messagesTv.append("Read from Bluetooth: \n"+s);
    }
 
    @Override
    public void onPause()
    {
        super.onPause();
        tBlue.close(); 5
    } 
 
    public void initGUI()
    {
        LinearLayout container=new LinearLayout(this);
        messagesTv = new TextView(this);
        container.addView(messagesTv);
        setContentView(container); 
    }
}

Football.java

// Football.java - control Arduino over Bluetooth to play ball
// (c) Tero Karvinen & Kimmo Karvinen http://BotBook.com

package fi.sulautetut.android.football;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

public class Football extends Activity implements SensorEventListener {
    String robotBtAddress="00:07:80:83:AB:6A"; // Change this 
    TextView statusTv;
    TextView messagesTv;
    TBlue tBlue; 
    SensorManager sensorManager;
    Sensor sensor;
    float g=9.81f; // m/s**2
    float x, y, z, l, r;
    boolean kick; 
    int skipped; // continuously skipped sending because robot not ready
    Handler timerHandler; 
    Runnable sendToArduino; 

    /*** Main - automatically called methods ***/

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initGUI(); 
        timerHandler = new Handler(); 
        sendToArduino = new Runnable() { 
            public void run() {
                sendLR(); 
                timerHandler.postDelayed(this, 250); 
            }
        };
    }

    @Override
    public void onResume() 
    {
        super.onResume(); 
        initAccel();

        timerHandler.postDelayed(sendToArduino, 1000); 
        
        skipped=9999; // force Bluetooth reconnection 
    } 

    @Override
    public void onPause() {
        super.onPause();
        r = 0; 
        l = 0;
        sendLR();

        closeAccel();
        closeBluetooth();

        timerHandler.removeCallbacks(sendToArduino); 
        msg("Paused. \n");
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        x=event.values[1]/g;    // earth gravity along axis results 1.0
        y=event.values[2]/g;
        z=event.values[0]/g;
        updateLR(); 
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Must have when Activity implements SensorEventListener. 
    }



    /*** User interface ***/

    void initGUI()
    {
        // Window
        setRequestedOrientation(
                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        // Contents 
        LinearLayout container=new LinearLayout(this);
        container.setOrientation(android.widget.LinearLayout.VERTICAL);
        statusTv = new TextView(this);
        Log.i("FB", "User interface half way.. ");
        container.addView(statusTv);
        //msg("statusTv added. ");  
        messagesTv = new TextView(this);
        messagesTv.setText("");
        container.addView(messagesTv);
        setContentView(container); 
    }

    public void msg(String s)
    {
        Log.i("FB", s);
        if (7<=messagesTv.getLineCount()) messagesTv.setText("");
        messagesTv.append(s);
    }

    void vibrate()
    {
        Vibrator vibra = (Vibrator) getSystemService(
                Context.VIBRATOR_SERVICE);
        vibra.vibrate(200); 
    } 



    /*** Accelerometer ***/

    void initAccel()
    {
        msg("Accelerometer initialization... ");
        sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
        sensor=sensorManager.getDefaultSensor(
                Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(
                this, 
                sensor, 
                sensorManager.SENSOR_DELAY_NORMAL);
    }

    void closeAccel()
    {
        msg("Accelerometer closing... ");
        sensorManager.unregisterListener(this, sensor);
    }



    /*** Bluetooth ***/

    void initBluetooth()
    {
        msg("Bluetooth initialization... ");
        skipped=0; 
        tBlue=new TBlue(robotBtAddress);
        if (tBlue.streaming()) {
            msg("Bluetooth OK. ");
        } else {
            msg("Error: Bluetooth connection failed. ");
        }
    }

    void closeBluetooth()
    {
        msg("Bluetooth closing...");
        tBlue.close();
    }



    /*** Motor calculations for left and right ***/

    void updateLR() 
    {
        kick=false;
        if (1.5<Math.abs(y)) kick=true; 
        l=y;
        r=l;
        l+=x;
        r-=x;

        if (l+r<0) { // make reverse turn work like in a car 
            float tmp=l;
            l=r;
            r=tmp;
        }

        l=constrain(l);
        r=constrain(r);
    }

    float constrain(float f) 
    {
        if (f<-1) f=-1;
        if (1<f) f=1;
        return f;
    }

    void sendLR()
    {
        if ( (skipped>20) ) { 
            closeAccel();
            initBluetooth();
            initAccel();
        }
        if (!tBlue.streaming()) { 
            msg("0");
            skipped++;
            return;
        }

        String s=""; 
        s+="S";
        s+=(char) Math.floor(l*5 + 5);    // 0 <= l <= 10
        s+=(char) Math.floor(r*5 + 5);    // 0 <= l <= 10
        if (kick) s+="k"; else s+="-";
        s+="U";

        statusTv.setText(String.format(
                "%s    left: %3.0f%% right: %3.0f%%, kick: %b.", 
                s, Math.floor(l*100), Math.floor(r*100), 
                kick));

        tBlue.write("?"); 
        String in=tBlue.read(); 
        msg(""+in);
        if (in.startsWith("L") && tBlue.streaming()) {
            Log.i("fb", "Clear to send, sending... ");
            tBlue.write(s); 
            skipped=0;
        } else {
            Log.i("fb", "Not ready, skipping send. in: \""+ in+"\"");
            skipped++; 
            msg("!");
        }
        if (kick) vibrate(); 
    }

}

footballrobot.pde

// footballrobot.pde - Footballrobot for cellphone control 
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com

#include <Servo.h>

// Keep track of how far along we are reading a message
const int READY = 1;                // Ready to receive a message
const int RECEIVED_START = 2;       // Received the start character: 'S'
const int RECEIVED_LEFT_SPEED = 3;  // Received the left speed
const int RECEIVED_RIGHT_SPEED = 4; // Received the right speed
const int RECEIVED_KICK = 5;        // Received the kick indicator

int state = READY;

// Define the pins and declare the servo objects.
int servoRightPin=2;
int servoLeftPin=3;
int servoKickPin=4;

Servo kickerServo;
Servo servoRight;
Servo servoLeft;

// Various positions and settings for the kicker.
int kickerNeutral = 130;
int kickerKick    = 10;
long kickerWait   = 750;

// Limit our speed; this needs to be a value between 0 and 90
int maxSpeed = 10;

// Current speeds/kicker setting
int kickNow=0; 
int leftSpeed  = 90;
int rightSpeed = 90;

// Temporary speed variables used while we are processing a command.
int newLeftSpeed;
int newRightSpeed;

int ledPin=13;  // LED output pin

void kick()
{
  kickerServo.write(kickerKick);
  delay(kickerWait);
  kickerServo.write(kickerNeutral);
  //Serial.println("Kicking!");
}

void move()
{
  servoLeft.write(leftSpeed);
  servoRight.write(rightSpeed);
}

void stopMoving()
{
  leftSpeed = 90;
  rightSpeed = 90;
}

void setup()
{

//  pinMode(rxPin, INPUT);
//  pinMode(txPin, OUTPUT);
//  mySerial.begin(1200);


  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);

  servoRight.attach(servoRightPin);
  servoLeft.attach(servoLeftPin);

  kickerServo.attach(servoKickPin);
  kickerServo.write(kickerNeutral);

  stopMoving();

  Serial.begin(57600);
  digitalWrite(ledPin, LOW);
}

void loop()
{

  if (Serial.available()) {

    int ch = Serial.read(); // Read a character
    
    switch (state) {
    case READY:
      if ('S' == ch) {
        state = RECEIVED_START; // We'll be in this state 
                                // next time through loop()
      } 
      else if ('?' == ch) {
        Serial.print("L"); // Let the phone know we are listening
      }
      break;
      
    case RECEIVED_START:
      if (ch >= 0 && ch <= 10) { // Make sure the values are in range
        state = RECEIVED_LEFT_SPEED;
        
        // Set the temporary left speed value
        newLeftSpeed = map(int(ch), 0, 10, 90-maxSpeed, 90+maxSpeed); 
      } 
      else { // Invalid input--go back to the ready state
        state = READY;
      }
      break;
      
    case RECEIVED_LEFT_SPEED:
      if (ch >= 0 && ch <= 10) { // Make sure the values are in range
        state = RECEIVED_RIGHT_SPEED;

        // Set the temporary right speed value
        newRightSpeed = 180 - map(int(ch), 0, 10, 90-maxSpeed, 90+maxSpeed); 
      } 
      else { // Invalid input--go back to the ready state
        state = READY;
      }
      break;
      
    case RECEIVED_RIGHT_SPEED:
      if ('k' == ch) { // 'k' for kick
        kickNow = 1;
      } 
      else { // anything else means don't kick
        kickNow = 0;
      }
      state = RECEIVED_KICK;
      break;

    case RECEIVED_KICK:
      if ('U' == ch) { // Reached the end of the message
      
        leftSpeed = newLeftSpeed;   // Set the speeds
        rightSpeed = newRightSpeed;
        
        if (kickNow) { // Are we supposed to kick now?
          kick();
        } 
        
        // Return to the ready state, clear the kick flag
        state = READY;
        kickNow = 0;
        break;
      }
    }
  }
  
  if (state == READY) {
    move();
  }
  delay(10); // Give the microcontroller a brief rest
}

centerFullRotation.pde

// centerFullRotation.pde &#8211; Halt a continuous rotation servo 
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com

#include <Servo.h>
 
Servo myServo;
int servoPin = 2;
 
void setup() 
{ 
  myServo.attach(servoPin);
} 
 
void loop() 
{ 
  myServo.write(90);
  delay(20);
} 

footballBotSerialControl.pde

// footballBotSerialControl.pde - Call move functions from serial console.
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com

#include <Servo.h>
int servoRightPin = 2;
int servoLeftPin  = 3;
int servoKickPin = 4;

Servo kickerServo;
Servo servoRight;
Servo servoLeft;

int kickerNeutral = 130;
int kickerKick    = 10;
long kickerWait   = 750;

void kick()
{
  kickerServo.write(kickerKick);
  delay(kickerWait);
  kickerServo.write(kickerNeutral);
}

void moveForward()
{
  servoLeft.write(180);
  servoRight.write(0);
}

void moveBack()
{
  servoLeft.write(0);
  servoRight.write(180);
}

void turnRight()
{
  servoLeft.write(180);
  servoRight.write(180);
} 

void turnLeft()
{
  servoLeft.write(0);
  servoRight.write(0);
} 

void stopMoving()
{
  servoLeft.write(90);
  servoRight.write(90);
}

void setup()
{
  servoRight.attach(servoRightPin);
  servoLeft.attach(servoLeftPin);

  kickerServo.attach(servoKickPin);
  kickerServo.write(kickerNeutral);
  
  stopMoving();

  Serial.begin(115200); 
  Serial.println("Football robot. (c) 2008 Karvinen ");
}

void loop()
{
  if ( Serial.available() ) { 
    char ch = Serial.read(); 

    switch (ch) {
    case '8': 
      moveForward();
      delay(250);
      stopMoving();
      break;
    case '2':
      moveBack();
      delay(250);
      stopMoving();
      break;
    case '6':
      turnRight();
      delay(250);
      stopMoving();
      break;
    case '4':
      turnLeft();
      delay(250);
      stopMoving();
      break;
    case '5':
      kick();
      break;  
    }
  }
}

Finding_the_Center_Point.pde

#include <Servo.h>
 
Servo myServo;
int servoPin = 2;
 
void setup() 
{ 
  myServo.attach(servoPin);
  Serial.begin(115200);   // bit/s 
} 
 
void loop() 
{ 
  for (int i=0; i<=180; i=i+1) { 
    myServo.write(i); 
    Serial.println(i);
    delay(150); 
  }
}

footballBotForward.pde

// footballBotForward.pde - Move forward
// (c) Kimmo Karvinen & Tero Karvinen http://BotBook.com

#include <Servo.h>

int servoRightPin = 2; 
int servoLeftPin  = 3;
Servo servoRight; 
Servo servoLeft;

void moveForward() 
{
  servoLeft.write(180); // full speed in one direction
  servoRight.write(0);  // full speed in the other
}

void stopMoving() 
{
  servoLeft.write(90);
  servoRight.write(90);
}


void setup() 
{
  servoRight.attach(servoRightPin);
  servoLeft.attach(servoLeftPin);
}

void loop() 
{
  moveForward();
  delay(1000);
  stopMoving();
  delay(1000);
}