Meet A.S.T.R.I.D

Here is a picture that will show about how big ASTRID will be. The right front and left rear legs will be built the same as will the left front and right rear legs. This should make for some interesting software development. :slight_smile: The top deck will become the bottom deck, the bottom deck will become the top deck, and there won’t be as much space between decks after I have all four legs built, aligned, and tested.


8-Dale

I’ve been doing a bit of electronics and software development for ASTRID, which will eventually include a RoboDuino connected via USB to a BeagleBoard as master controller. Below is the circuit I am testing software on with my Sanguino.

http://i853.photobucket.com/albums/ab97/robotguy_bucket/Robotics/sanguino_sensors.jpg

The current software under development is:

[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 [email protected]
Added commands to read sensors and send readings back through UART.
*/

#define IR_MAX 2
#define PING_MAX 2
#define PING_START 4

#define HEARTBEAT_PIN 2

int inValue = 0; // Incoming serial byte
byte ir[6], ping[8]; // Sensor data

// Establish contact with the master controller
void establishContact() {
while (Serial.available() <= 0) {
Serial.print(’!’, BYTE); // Send a ‘!’

delay(300);

}
}

// Read distance from a PING ultrasonic sensor
// Code taken from the Arduino Playground. Returns distance in cm.
byte read_ping (byte pin) {
unsigned long echo = 0;
unsigned long ultrasoundValue = 0;

pinMode(pin, OUTPUT); // Switch signalpin to output
digitalWrite(pin, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 uS
digitalWrite(pin, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 uS
digitalWrite(pin, LOW); // Hold off
pinMode(pin, INPUT); // Switch signal pin to input
digitalWrite(pin, HIGH); // Turn on pullup resistor

echo = pulseIn(pin, HIGH); // Listen for echo
ultrasoundValue = echo / 58.138; // Convert to cm

return ultrasoundValue;
}

// Read Sharp GP2D12 IR sensor.
// Code taken from the Arduino Playground. Returns distance in cm
byte read_gp2d12 (byte pin) {
int tmp;

tmp = analogRead(pin);

if (tmp < 3)
return -1; // Invalid value

return (6787.0 /((float)tmp - 3.0)) - 4.0;
}

// 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(9600);

// Initialize sensor arrays
for (i = 0; i < IR_MAX; i++)
ir* = 0;

for (i = 0; i < PING_MAX; i++)
ping* = 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());

Serial.print("\nMain: ");
Serial.write(maincmd);

// Process master controller commands
switch (maincmd) {
  case 'R':
    if (Serial.available() > 0) {
      // Get the second character of the command
      seccmd = toUpper(Serial.read());

      Serial.print(", Secondary: ");
      Serial.write(seccmd);
        
      switch (seccmd) {
        case 'A':                                            // RA command (Read Analog)
        case 'P':                                            // RP command (Read Pulse)
          // Read an analog pin
          pin = Serial.read();
          
          if (seccmd == 'A')
            inValue = analogRead(pin);
          else {
            pinMode(pin, OUTPUT);
            digitalWrite(pin, LOW);
            pinMode(pin, INPUT);
            inValue = pulseIn(pin, HIGH);
          }

          Serial.print(inValue, BYTE);
          break;
        case 'V':                                            // RV 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]);

          break;
        case 'I':                                          // RI command (Read IR)
          // Send single IR sensor reading
          sensorNr = Serial.read();
        
          Serial.print(ir[sensorNr], BYTE);
          break;
        case 'U':                                         // RP command (Read PING)
          // Send single PING ultrasonic reading
          sensorNr = Serial.read();  

          Serial.print(ping[sensorNr], BYTE);
          break;
        default:
          // Invalid command
          errorNr = 253;
          Serial.print("\nBad Secondary Command");
          break;
      }
    } else
      errorNr = 254;
    break;
  case 'S':                                            // S command (Scan area)
    // Scan area using pan/tilt
    scanarea = true;
    break;
  case 'T':                                            // Test command
    // Test command
    Serial.write('M');
    break;
  default:
    // Invalid command
    if (errorNr == 0)
      errorNr = 255;
    Serial.print("\nBad Main Command");
    break;
}

}

if (errorNr != 0) {
// Send error code back to master controller immediately
Serial.print(0xFF, BYTE);
Serial.print(errorNr, BYTE);
errorNr = 0;
} else {
// 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);  

delay(50);

}

// 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
}
}[/code]
I couldn’t attach a *.PDE (Arduino sketch) file.

8-Dale**

Hi Dale,

Looks like you are having fun! :smiley:

I have also had fun playing with the Atmegas again, like the one that is on the Axon2 (Atmega1280) and webbotlib. So how do you like working with the Arduino library/IDE versus working with Webbotlib? Do you have the roboduino yet?

Kurt

Yes, indeed I am! :smiley:

I don’t really have a preference, other than the editor for the two environments. I hate the Arduino IDE editor - it still does not deal with and preserve tabs like it should. Each environment has its purpose for the given task, and I use each for the required tasks.

Is the AXON2 really that different from the AXON? I was told the AXON2 would have jumperable power options for sets of pins, but it doesn’t appear this is the case.

Not yet. When I get it, I’ll get the kit ($34.00 + s/h) instead of already assembled. I will probably be using two RoboDuinos connected to my BeagleBoard.

Here is my latest code. All four sensors are being read and I can selectively read the stored value for each, as well as do a complete dump of all readings. I can also selectively take a raw reading from an analog pin.

[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 [email protected]
Added commands to read sensors and send readings back through UART.
*/

#define IR_MAX 2
#define PING_MAX 2
#define PING_START 4

#define HEARTBEAT_PIN 2

int inValue = 0; // Incoming serial byte
byte ir[6], ping[8]; // Sensor data

// 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.
int 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);

delay(50);

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
byte 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* = 0;

for (i = 0; i < PING_MAX; i++)
ping* = 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 '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
          pin = Serial.read();
          
          if (seccmd == 'A')
            inValue = analogRead(pin);
          else {
            pinMode(pin, OUTPUT);
            digitalWrite(pin, LOW);
            pinMode(pin, INPUT);
            inValue = pulseIn(pin, HIGH);
          }

          Serial.print(inValue, DEC);
          
          break;
        case 'V':                                            // RV 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 (Read IR)
        case 'U':
          // Send single IR sensor reading
          sensorNr = Serial.read();                        // Get sensor number
          
          if (seccmd == 'I')
            Serial.print(ir[sensorNr], DEC);
          else
            Serial.print(ping[sensorNr], DEC);
          break;
        default:
          // Invalid command
          errorNr = 253;
          break;
      }
    } else
      errorNr = 254;
    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:
    // Invalid command
    if (errorNr == 0)
      errorNr = 254;
    break;
}

}

if (errorNr != 0) {
// Send error code back to master controller immediately
Serial.print(0xFF, BYTE);
Serial.print(errorNr, BYTE);
errorNr = 0;
} else {
// 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);  

delay(50);

}

// 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
}
[/code]
Now it’s time to start working on the Python master control software.

8-Dale**

Here is the start of my Python master control software that will run on a BeagleBoard or Gumstix Overo.

[code]#!/usr/bin/python

Import the Serial module

import serial;

EOL = “\r”;
command = “”;

Set the SSC-32 port - “COM1:” for Windows, “/dev/ttyS0” for Linux

SANGUINO_PORT = “COM3:”;

Reads single characters until a CR is read

def Response (port):
ich = “”;
resp = “”;

while (ich <> ‘\r’):
ich = port.read(1);

  if (ich <> '\r'):
     resp = resp + ich;

return resp;

Reads a single byte

def getByte (port):
num = 0;

num = port.read(1);

return num;

Converts a servo position in degrees to uS for the SSC-32

def To_Degrees (uS):
result = 0;

result = (uS - 1500) / 10;

return result;

Converts an SSC-32 servo position in uS to degrees

def To_uS (degrees):
result = 0;

result = (degrees * 10) + 1500;

return result;

Send EOL to the SSC-32 to start a command executing

def Send_EOL (port):

result = port.write(EOL);

return result;

Send a command to the SSC-32 with or without an EOL

def Send_Command (port, cmd, sendeol):

result = port.write (cmd);

if (sendeol):
Send_EOL (port);

return result;

Open the port at 115200 Bps - defaults to 8N1

sanguino = serial.Serial(SANGUINO_PORT, 115200);

inp = “”;

Wait for a “!” to establish communication

while (inp <> “!”):
# Read the response
inp = Response(sanguino);

#	Show what we got back
print inp;

Now start processing data from the Sanguino

Read IR sensor #1

Send_Command (sanguino, “RI0”, FALSE);

Get data byte and show it.

data = getByte(sanguino);
print "Data = ", data;

Close the port

sanguino.close();[/code]
8-Dale

Here is my latest code for an Arduino compatible serial slave:

[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 31-May-2010, Version 0.50
Dale Weber [email protected]
Added commands to read sensors and send readings back through UART.
*/
#include <Servo.h>

#define IR_MAX 2
#define PING_MAX 2
#define PING_START 4

#define HEARTBEAT_PIN 2

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* = 0;

for (i = 0; i < PING_MAX; i++)
ping* = 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);
    }

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

    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
          pin = Serial.read();

          if (seccmd == 'A')
            inValue = analogRead(pin);
          else {
            pinMode(pin, OUTPUT);
            digitalWrite(pin, LOW);
            pinMode(pin, INPUT);
            inValue = pulseIn(pin, HIGH);
          }

          Serial.print(inValue, DEC);

          break;
        case 'V':                                            // RV 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 (Read IR)
        case 'U':
          // Send single IR sensor reading
          inValue = Serial.read();                        // Get sensor number
          sensorNr = inValue - 48;

          if (seccmd == 'I')
            Serial.print(ir[sensorNr], DEC);
          else
            Serial.print(ping[sensorNr], DEC);
          break;
        default:
          break;
      }
    } else
      errorNr = 254;
    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);

delay(50);

// 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
}
}
[/code]
I also want to make this all work as an I2C slave. I can easily add autonomous robot code to this to actually control a robot. The robot would still be able to receive and execute commands from a master controller while it is roaming around automomously.

8-Dale**

nice polish soundtrack in background :slight_smile: really like it