Here is some slightly updated code for the Arduino Serial Slave. All I have done is convert the if/then blocks to switch() in the mainline for consistancy and to make it easier to add new secondary commands.
BeagleComm.pde:
Code:
/*
http://www.arduino.cc/en/Tutorial/SerialCallResponse
Created 26 Sept. 2005
by Tom Igoe
Modified 14 April 2009
by Tom Igoe and Scott Fitzgerald
Modified 20-May-2010
Dale Weber <robotguy@hybotics.org>
Version: 0.10
Date: 20-May-2010
Purpose: Added remote serial control commands to read sensors and send readings back through the UART.
Version: 0.20
Date: 31-May-2010
Purpos: Added the remote Dump (D) command to allow dumping sensor data to a terminal.
Version: 0.21
Date: 03-Jun-2010
Purpose: Changed all if/then statements to switch() blocks to make adding new secondary commands easier.
*/
//#include <Servo.h>
#include "BeagleComm.h"
int inValue = 0; // Incoming serial byte
byte ir[6]; // IR sensor data;
byte ping[8]; // Ultrasonic semsor data
//Servo pan, tilt;
// Establish contact with the master controller
void establishContact() {
while (Serial.available() <= 0) {
Serial.print('!', BYTE); // Send a '!'
delay(300);
}
}
/*
http://www.arduino.cc/en/Tutorial/Ping
created 3 Nov 2008
by David A. Mellis
modified 30 Jun 2009
by Tom Igoe
This example code is in the public domain.
*/
// Read distance from a PING ultrasonic sensor
// Code taken from the Arduino Playground. Returns distance in cm.
long read_ping (byte pin) {
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm;
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
delayMicroseconds(2);
digitalWrite(pin, HIGH);
delayMicroseconds(5);
digitalWrite(pin, LOW);
// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pin, INPUT);
duration = pulseIn(pin, HIGH);
// Convert the time into a distance
// inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
// Serial.print("\nPin ");
// Serial.print(pin, DEC);
// Serial.print(": ");
// Serial.print(cm, DEC);
return cm;
}
long microsecondsToInches(long microseconds) {
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}
// Read Sharp GP2D12 IR sensor.
// Code taken from the Arduino Playground. Returns distance in cm
int read_gp2d12 (byte pin) {
int tmp;
tmp = analogRead(pin);
if (tmp < 3)
return -1; // Invalid value
tmp = (6787.0 /((float)tmp - 3.0)) - 4.0;
return tmp;
}
// Convert lower case to upper case
char toUpper (char inp) {
if ((inp >= 97) & (inp <= 122))
return inp - 32;
else
return 0xFF;
}
// blink a heartbeat LED
void do_heartbeat (void) {
digitalWrite(HEARTBEAT_PIN, HIGH);
delay(250);
digitalWrite(HEARTBEAT_PIN, LOW);
delay(250);
}
void setup() {
byte i;
pinMode(HEARTBEAT_PIN, OUTPUT);
// start serial port at 115200 bps:
Serial.begin(115200);
// Initialize sensor arrays
for (i = 0; i < IR_MAX; i++)
ir[i] = 0;
for (i = 0; i < PING_MAX; i++)
ping[i] = 0;
establishContact(); // Send a byte to establish contact until receiver responds
}
// Responds to commands from the master controller and updates sensor readings
void loop() {
byte errorNr = 0, sensorNr = 0; // Eorror number, Sensor index number
byte angle = -85, increment = 10; // Scan angle and increment
byte pin, inValue; // Pin number to read (analog or digital)
boolean scanarea = false; // Scan flag
char maincmd, seccmd; // Main and secondary command chars
errorNr = 0;
do_heartbeat(); // Blink the heartbeat LED
// Get incoming byte:
if (Serial.available() > 0) {
maincmd = toUpper(Serial.read());
// Process master controller commands
switch (maincmd) {
case 'D':
Serial.print("\nSensor Data Dump\n");
// Dump IR sensor data
for (sensorNr = 0; sensorNr < IR_MAX; sensorNr++) {
Serial.print("\nIR sensor #");
Serial.print(sensorNr, DEC);
Serial.print(": ");
Serial.print(ir[sensorNr], DEC);
Serial.print(" cm");
}
// Dump PING sensor data - Digital pins 4 through 11
for (sensorNr = 0; sensorNr < PING_MAX; sensorNr++) {
Serial.print("\nPING sensor #");
Serial.print(sensorNr, DEC);
Serial.print(": ");
Serial.print(ping[sensorNr], DEC);
Serial.print(" cm");
}
break;
case 'G':
// Get an immediate sensor reading
seccmd = toUpper(Serial.read());
sensorNr = Serial.read();
sensorNr = sensorNr - 48;
switch (seccmd) {
case 'I': // IR Sensor
ir[sensorNr] = read_gp2d12(sensorNr);
Serial.print(ir[sensorNr], BYTE);
break;
case 'U': // Ultrasonic (PING) Sensor
ping[sensorNr] = read_ping(sensorNr + PING_START);
Serial.print(ping[sensorNr], BYTE);
break;
default:
break;
}
break;
case 'R':
if (Serial.available() > 0) {
// Get the second character of the command
seccmd = toUpper(Serial.read());
switch (seccmd) {
case 'A': // RA command (Read Analog)
case 'P': // RP command (Read Pulse)
// Read an analog pin
inValue = Serial.read();
pin = inValue - 48;
switch (seccmd) {
case 'A':
inValue = analogRead(pin);
Serial.print("\nAnalog #");
break;
case 'P':
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
pinMode(pin, INPUT);
inValue = pulseIn(pin, HIGH);
Serial.print("\nPulse #");
default:
break;
}
Serial.print(pin, DEC);
Serial.print(" = ");
Serial.print(inValue, DEC);
break;
case 'R': // RR command
// Send all current sensor readings
// Send header
Serial.print(IR_MAX + PING_MAX, BYTE);
Serial.print(IR_MAX, BYTE);
Serial.print(PING_MAX, BYTE);
// Send IR sensor readings
for (sensorNr = 0; sensorNr < IR_MAX; sensorNr++)
Serial.print(ir[sensorNr], BYTE);
// Send PING sensor readings
for (sensorNr = 0; sensorNr < PING_MAX; sensorNr++)
Serial.print(ping[sensorNr], BYTE);
break;
case 'I': // RI command (Send last IR reading)
case 'U':
// Send single IR sensor reading
inValue = Serial.read(); // RU command (Send last PING reading)
sensorNr = inValue - 48;
switch (seccmd) {
case 'I':
Serial.print(ir[sensorNr], BYTE);
break;
case 'U':
Serial.print(ping[sensorNr], BYTE);
break;
default:
break;
}
break;
default:
break;
}
}
break;
case 'S': // S command (Scan area)
// Scan area using pan/tilt
scanarea = true;
break;
case 'T': // Test command
// Test command
Serial.println("\nTesting.. ");
break;
default:
break;
}
}
// Read IR sensors
for (sensorNr = 0; sensorNr < IR_MAX; sensorNr++)
ir[sensorNr] = read_gp2d12(sensorNr);
// Read PING sensors - Digital pins 4 through 11
for (sensorNr = 0; sensorNr < PING_MAX; sensorNr++)
ping[sensorNr] = read_ping(sensorNr + PING_START);
// Scan an area from -85 degrees to +85 degrees using a pan/tilt
if (scanarea) {
Serial.print("\nScanning..");
scanarea = false;
// Scan area using the Pan/Tilt sensors
}
}
BeagleCom.h:
Code:
#ifndef BeagleComm_h
#define BeagleComm_h
#include <inttypes.h>
#define IR_MAX 2
#define PING_MAX 2
#define PING_START 4
#define HEARTBEAT_PIN 13
#endif
For some reason I am getting weird JAVA errors when I try to upload the code to my Arduino or Sanguino. I'm using the Arduino 018 IDE upgraded with support for the Sanguino. As far as I can tell, my code looks good, but I am getting these weird errors when I try to upload it. The errors scroll to fast to read.
Edit: Updated the code listing for BeagleComm.pde after fixing some bugs. It all works now.

8-Dale