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 – 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);
}