W.A.L.T.E.R. Returns as a 2WD/4WD

More pictures of the new motor/wheel mounting scheme. You may recognize something here - an idea taken from a biped. :slight_smile: I expect this arrangement to provide the extra strength between the steering servo and motor mount. I can use either an ASB-09 or an ASB-10 in this setup. I ran out of ASB-09s in this case, so had to use ASB-10s.

8-Dale

After taking a closer look at the new wheel mounting scheme, Iā€™ve discovered I can not use the ASB-10 because it is too long to allow the wheel to mount onto the hub. So, Iā€™ll have to canibalize ASTRIDE to get the four ASB-09 ā€œCā€ brackets I need or wait until I can order more of them.

Edit: I was wrong. The ASB-10 or ASB-09 will point in the direction of backward travel for the rear wheels and the direction of forward travel for the front wheels. Iā€™ve also discovered a use for the ASB-07 45 degree bracket - I need one on each ASB-04 to bring that bracket in line with the center line of the robot. This will also provide better range of motion for the steering of each wheel.

8-Dale

Iā€™ve installed Python 2.6.6, flup 1.02, zLib 2.2.5, and pyserial-2.5 on my BeagleBoard. I built them natively because I could not get the right versions from OpenEmbedded to get dependencies to work out. I also have DJango 1.2.3 to install yet, for the web interface of W.A.L.T.E.R. and Phenny (IRC bot) for the IRC interactive interface. My BeagleBoard has been repurposed to run my AllStarLink/EchoLink node, so I will have to wait to add more to it until I can get a BeagleBoard-xM (the 1 GHz, 512 MB RAM version, 4 USB 2.0 Host, USB OTG, Ethernet, stereo audio, and much more).

In the meantime, I can still write and test my Python code on a PC, since Python is platform independent for the most part.

Below is the beginning of my Python main line. Iā€™ll be converting several things into objects, because it just makes sense to have Servo and Motor objects with their associated methods.

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Import the Serial module
import serial

EOL = "\r"
command = ""

# Set the Sanguino port - "COM1:" for Windows, "/dev/ttyS0 or /dev/ttyUSB0" for Linux
SANGUINO_PORT = "/dev/ttyUSB1"

#
# Left Front Motor
#
LFM_Speed_C = 0
LFM_Speed_Min = 500
LFM_Speed_Max = 2500
LFM_Stop = 1520
LFM_Dir = 0

#
# Left Front Steering
#
LFM_Steer_C = 1
LFM_Steer_Min = 600
LFM_Steer_Max = 2400
LFM_Steer_Ctr = 1500

#
# Right Front Motor
#
RFM_Speed_C = 16
RFM_Speed_Min = 500
RFM_Speed_Max = 2500
RFM_Stop = 1525
RFM_Dir = 0

#
# Right Front Steering
#
RFM_Steer_C = 17
RFM_Steer_Min = 500
RFM_Steer_Max = 2500
RFM_Steer_Ctr = 1500

#
# Left Rear Motor
#
LRM_Speed_C = 2
LRM_Speed_Min = 500
LRM_Speed_Max = 2500
LRM_Stop = 1520
LRM_Dir = 0

#
# Left Rear Steering
#
LRM_Steer_C = 3
LRM_Steer_Min = 600
LRM_Steer_Max = 2400
LRM_Steer_Ctr = 1500

#
# Right Rear Motor
#
RRM_Speed_C = 18
RRM_Speed_Min = 500
RRM_Speed_Max = 2500
RRM_Stop = 1525
RRM_Dir = 0

#
# Right Rear Steering
#
RRM_Steer_C = 19
RRM_Steer_Min = 0
RRM_Steer_Max = 0
RRM_Steer_Ctr = 1500

#
# Pan/Tilt
#
PanChan = 6
PanHome = 1530
PanREnd = 2150
PanLEnd = 900

TiltChan = 7
TiltHome = 1430
TiltUEnd = 500
TiltDEnd = 1550

# Reads single characters until a CR is read
def Response (port):
	ich = ""
	resp = ""

	while (port.inWaiting() and ich <> '\r'):
		ich = inAlpha(port)

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

	return resp

def inAlpha(port):
	ich = ""
	num = 0

	while (port.inWaiting() < 1):
		pass

	while ((num < 32) or (num > 125)):
		ich = port.read(1)
		num = ich
#		print "'",ich,", ", num

	return ich

# Establish communications with a serial slave
def establishComm(port):
	ich = port.read(1)

	while (ich != '!'):
		ich = inAlpha(port)

	print "Communication established.."

	port.write('*')

	return

# 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

# Wait for a servo move to be completed
def Wait_for_Servos (port):
	ich = ""

	while (ich <> "."):
		Send_Command (port, "Q", True)

		ich = port.read(1)

	return

# 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, 38400, timeout = 0, xonxoff = False, rtscts = False, dsrdtr = False)
inp = ''

establishComm(sanguino);

#   Send command to read ultrasonic sensor #0
command = "RI0"
Send_Command (sanguino, command, False)
#Send_EOL (sanguino)

#   Read the response
inp = InByte(sanguino)

#   Show what we got back
print inp

#while (1):
#	inp = inAlpha(sanguino)
#	print inp
#
#	if (inp == 'Q'):
#		exit
#
#   Close the port
sanguino.close()

#	Test the conversion functions
print "600 uS = ", to_Degrees(600), " degrees."
print "2400 uS = ", to_Degrees(2400), " degrees."
print "1500 uS = ", to_Degrees (1500), " degrees."

print "-90 degrees = ", to_uS(-90), " uS."
print "90 degrees = ", to_uS(90), " uS."
print "0 degrees = ", to_uS(0), " uS."

8-Dale

This is an awesome thread and I find myself wanted to find out more about this project. Is this project still in progress? Any video that shows it in motion?

I am new to the forums.

Yes, W.A.L.T.E.R. is still in progress, but development is stalled at present due to lack of funds. I am hoping to aquire a new RoboClaw 2x10 motor controller in a month or so, and next month is my birthday so Iā€™ll see what I can do then. :slight_smile: Iā€™ve decided to use the RoboClaw 2x10 because it is the same form factor as the SSC-32 and ARC-32 boards, while allowing for future upgrades of motors without changing the controller.

WELCOME to the forums!

8-Dale

With the excitement (for me, at least) of Lynxmotion bringing out an Arduino compatible shield and BotBoarduino, I am finding myself getting very excited about robotics again. Iā€™ve started thinking about where I want to go with W.A.L.T.E.R. again. :smiley:

Iā€™ve constructed what I believe will be a good leveling system to attach motors/wheels to. It has not got a lot of clearance from full retraction to full extension though. Itā€™s got about 2 inches total headroom, and I donā€™t know if that is going to be enough. However, I still want to build it and see how it works. The four wheels will still all have independent steering, but each wheel will also have a leveler that will allow for some interesting motion and hopefully self leveling with the help of readings from one or more accelerometers - right now, I am thinking that two, one center front and one center rear will do the job.

To test the leveling system, I am looking seriously at using a T-Hex chassis and creating a terrain adapting T-Rover. I am sure I have all the brackets I need to build six of these leveler wheel mounts, and they are perfect to attach to a T-Hex chassis. Then all I need will be 12 servos, and I am looking at the HS-5685MH servo, which I believe will do the job and maybe even be a bit overkill for what I want to do.

8-Dale

Here are a couple pictures of the levelers. These are the two front levelers.

Curled:
curled.jpg

Extended:


8-Dale

[quote="kurte"] Sounds like you are having some fun. Looking forward to seeing Walter up and running again. [/quote] Yes, indeed I am! I have gotten a bunch of I2C stuff from Adafruit over the last couple months. I need to get some sockets so I can populate the expansion connectors on my PandaBoard ES. [quote="kurte"] The UDOO looks interesting, but for a strict combination like board, I think I will wait for the Arduino Tre to come out. It will be an official Arduino board that has a BeagleBone Black merged with it. [/quote] The UDOO is less interesting to me after I saw the [ODROID-XU](http://www.hardkernel.com/main/products/prdt_info.php?g_code=G137510300620) and [64Gb eMMc](http://www.hardkernel.com/main/products/prdt_info.php?g_code=G137454809984) and [camera](http://www.hardkernel.com/main/products/prdt_info.php?g_code=G137517754892). I could couple an XU with my choice of secondary processor(s) to suit whatever computing and data gathering tasks I want to do with W.A.L.T.E.R. It should be possible to do some major data crunching on an XU. I'm going to be playing with I2C and serial with my BotBoarduino today to see how this would work out. I can also see the possibility of using one or more Raspberry Pi boards as secondary processing units, and support for it in Python is excellent from companies like Adafruit. [quote="kurte"] For my next Linux box to try, I have now on order a new Odriod U3 board ([hardkernel.com/main/products ... 8760240354](http://www.hardkernel.com/main/products/prdt_info.php?g_code=G138760240354)), which has an Atmega328 on it that you can use Arduino to program (20 IO pins), plus a Toshiba I2C GPIO expander chip which gives you 16 more digital pins. Will ship later in January. Their prices are pretty good, but you also have to factor in that they charge $30 for shipping. [/quote] I have not used the Toshiba or Maxim I2C expanders. I've always used the Microchip MCP23008 (8 I/Os) and MCP23017 (16 I/Os) because I can get free samples easily. :slight_smile: The U3 looks nice, but I'd still go for the XU with 64gb eMMC, just for the pure power. :slight_smile: I don't want to have to upgrade W.A.L.T.E.R.'s main processor any more than necessary. And, as I said, I can couple in any secondary processor(s) I might need as necessary.

$30.00 for shipping?? Thatā€™s quite a bit, so Iā€™d want to order as much as possible on a single order to make it not hurt quite so much. I wish Lynxmotion would come out with a super power robot board that is at least 1.9GHz and quad core - they just know how to do this sort of thing right and I really love my BotBoarduino because of that. I really like the ability to choose the language I want to program in, like Python or Go.

My Device Control System is all Python right now, and it will figure into my robotics stuff majorly at some point. My DCS can already authenticate between devices and exchange messages between devices. The DCS library is just over 2600 lines of Python right now, and device clients run about 700 lines of code on average. Iā€™m going to convert all of this into Go at some point. Devices can be anything from a Raspberry Pi running anything (such as a weather station, for instance) to a robot. They can be anywhere in the world and be able to communicate though the DCS as long as they have internet access.

Iā€™m working on W.A.L.T.E.R. today, and hope to get him moving. Most of what I need to do that is already wired up. I just have to find my 6.0v and 7.2v @ 2800mAH battery packs and get them charged up. My Sabertooth 2X5 motor controller is already mounted on the underside of the main deck and wired to the motors. I still need to add the tilt servo to the pan/tilt unit on the front and mount a couple more GP2D12 IR sensors on the front sides. Iā€™m also anxious to play with my sound detection circuit and create some behaviors based on that. Iā€™ve also got that cool 10DOF IMU with the temperature sensor, compass, 3-axis accelerometer, and 3-axis gyro to play with. :slight_smile: I have it connected to Chip (Raspberry Pi) now.

I just have to decide which of my processor boards I want to use as a main processor now for W.A.L.T.E.R. Iā€™d like to use my PandaBoard ES (Intrepid), since itā€™s the most powerful board I have right now, but I donā€™t have easy access to the expansion connectors right now - they donā€™t have connectors populated, but are 0.1" spaced. I really need some dual row sockets - two 14x2 pin. Iā€™m tempted to just solder in some wires temporarily, because I really only need access to I2C and a couple other things. I have 4 of those nice 4-channel bi-directional level shifter breakouts that are I2C safe. I donā€™t have a source that stocks the sockets that I order from regularly - not even Adafruit. :frowning: Iā€™ll have to check SparkFun. I have a Logitech 9000 webcam I could use for imaging. Iā€™ve already been experimenting with that and the Motion/FFMPEG packages. Right now, I have the webcam connected to Stargazer (BBBlack) running Motion as a webcam.

Iā€™ve got the rPi camera board (orginal, not the IR sensitive one) connected to Pod and have been tinkering with that, but it appears I am going to have to write my own software to do what I need. Motion keeps crashing on Pod. :frowning: I also need to wire up something easy to test I2C on Stargazer. I have so much I need to tinker with! Well, it keeps me off the streets and out of trouble (most of the time). :slight_smile:

8-Dale

Nice to see your still around 8-Daleā€¦!

Yes, I am still around. :slight_smile: In fact, I am working on W.A.L.T.E.R. today. I am finishing the front pan/tilt. I tested my sensors last night, and there are two bad ones - An IR and a PING. Iā€™ll have to replace the PING, because itā€™s on the pan/tilt with an IR ranger. After I do that, Iā€™ll have enough sensors to take care of the front.

Parallax has a cool laser range finder I want to mount centered on the top deck. Itā€™s only $99.00. :slight_smile:

I will be getting four new electret mic breakouts from Adafruit that will handle sound detection from four directions. I ready have a test circuit working with my BotBoarduino. I just need a bit more separation between them. Unfortunately, that requires four analog inputs, so Iā€™ll probably dedicate a small Arduino type board to that, and connect it as a peripheral via I2C. The same board can also handle some indicator lighting and sound, which shouldnā€™t be too much of a load.

I am pretty sure I am going to use my Panda Board ES as main brain, with my BotBoarduino, connected via I2C, to handle locomotion and main sensors. I may even put Pod (Raspberry Pi) on W.A.L.T.E.R., just as a peripheral handler, and he has the camera board too.

8-Dale

Yes, i donā€™t know how i have find it but did see it yesterday.
Itā€™s not just for product showing or anythingā€¦ lol

robotshop.com/en/parallax-15 ā€¦ inder.html

Yep! I can see some interesting possibilities with this laser range finder. Iā€™m going to get one after I have W.A.L.T.E.R. doing basic movement using the three IR sensors. Iā€™ll replace the front PING sensor when I get more money (soon!).

I have the front pan/tilt working now, and have all the limits set in a Python script. Iā€™ve also expanded my Arduino two channel sound detection code to four channels for front/left, front/right, back/left, and back/right detection directions. Iā€™ve broken the code into three routines and am storing the sound sample data in a struct. Iā€™m using an array of struct for data storage and am using loops to process everything. Itā€™s very fast! My Arduino navigation code (including the sound detection code) is now 478 lines and 38% of the Arduinoā€™s capacity. Itā€™s all running on my BotBoarduino now, and I am awaiting aquisition of four new electret mics to complete the sound detection circuit - this takes four of the BotBoarduinoā€™s analog inputs, still leaving A4 and A5 for I2C.

I have a two channel detection setup running on my true blue Arduino now, and it works great. I need 3 analog inputs for the IR sensors and 4 analog inputs for the sound detection circuit, so I am going to have to move the sound detection stuff to another board. Iā€™m also looking at the possibility of using an Arduino Nano with an expansion board I found on RobotShop yesterday, because it has 8 analog inputs. Even the Nano may not give me enough, but I need to look at its pinout to see where the I2C pins are located. Hopefully I2C wonā€™t conflict with the analog inputs.

Iā€™m also starting to play with the Wire library to set my BotBoarduino up as an I2C slave. Iā€™ll connect it to Pod (Raspberry Pi) for testing. Itā€™s quite possible that Pod may end up mounted on W.A.L.T.E.R. as soon as I work out the power connection setup and source I want to use. I got a BEC from Adafruit that takes in 6V to 20V and puts out a smooth 5V, so I just need to wire up a power connector for Pod. I still have to test I2C with Stargazer (BBBlack), and get some connectors soldered to Intrepid (PandaBoard ES) so I can make more use of it for stuff.

Iā€™ve also got initialization code in my navigation sketch for W.A.L.T.E.R. that sets up all the I2C and other sensors I have. That includes my 10DOF IMU, TCS34725 RGB color sensor, TMP006 heat sensor, and DS1307 real time clock. :slight_smile: Pod has the camera board too. :slight_smile: I got all these sensors from Adafruit. I also have their I2C 16 channel servo breakout board.

So, as you can see, Iā€™ve been quite busy! :slight_smile:

I am loving working with the BotBoarduino! Iā€™m planning on wiring up the Sabertooth 2x5 and SSC-32 to it today. Iā€™ll probably go with PWM control for the motor controller, for my first tests with W.A.L.T.E.R. moving around. I have a webcam setup and pointed at my work area now. It runs on Stargazer at present, with my Logitech Pro 9000 webcam.

I need a good solution for analog input expansion, but the best I have found so far are 4 channel breakouts that require I2C. I may have to look at using SPI for some stuff. Below is my current code for W.A.L.T.E.R. - FAR from complete, and the sound detection code remains untested until I can connect a full four channel mic circuit.

/*
  W.A.L.T.E.R. 2.0, main navigation and reactive behaviors
  
  Credit is given, where applicable, for code I did not write.
 
  Copyright (C) 2013 Dale Weber <[email protected]>.
*/

#include <Wire.h>

#include <Adafruit_Sensor.h>

#include <Adafruit_BMP180_Unified.h>
#include <Adafruit_LSM303DLHC_Unified.h>
#include <Adafruit_L3GD20.h>

#include <Adafruit_TCS34725.h>
#include <Adafruit_TMP006.h>
#include <RTClib.h>

#include "Walter_Navigation.h"

/*
    Initialize our sensors
    
    We have:
      A BMP180 temperature and pressure sensor
      An L3GD20 Gyro
      An LSM303 3-Axis accelerometer / magnetometer (compass)
      
      A TCS34725 Color sensor
      A TMP006 Heat sensor
      A DS1307 Real time clock
      
      GP2D12 IR Ranging sensors (3)
*/

/*
    These are all on a single small board from Adafruit
      http://www.adafruit.com/products/1604
*/
Adafruit_BMP180_Unified temperature = Adafruit_BMP180_Unified(10001);
Adafruit_L3GD20 gyro;
Adafruit_LSM303_Accel_Unified accelerometer = Adafruit_LSM303_Accel_Unified(10002);
Adafruit_LSM303_Mag_Unified magnetometer = Adafruit_LSM303_Mag_Unified(10003);

/*
    These are also from Adafruit, in order.
      http://www.adafruit.com/products/1334 (TCS34725)
      http://www.adafruit.com/products/1296 (TMP006)
      http://www.adafruit.com/products/264 (DS1307)
*/
Adafruit_TCS34725 color = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
Adafruit_TMP006 heat;
RTC_DS1307 ds1307;

/*
    Initialize global variables
*/
//  Storage for sound detection sample data
Sample samples[SAMPLE_MAX];

//  These are where the sensor readings are stored.
int ping[MAX_PING];
float gp2d12[MAX_GP2D12];

/* 
    Function that reads a value from GP2D12 infrared distance sensor and returns a
      value in centimeters.

    This sensor should be used with a refresh rate of 36ms or greater.

    Javier Valencia 2008

    float read_gp2d12(byte pin)

    It can return -1 if something gone wrong.
    
    TODO: Make several readings over a time period, and average them
      for the final reading.
*/
float read_gp2d12 (byte pin) {
  int tmp;

  tmp = analogRead(pin);

  if (tmp < 3)
    return -1;                                  // Invalid value
  else
    return (6787.0 /((float)tmp - 3.0)) - 4.0;  // Distance in cm
} 

/*
    Convert the PING pulse width in ms to inches
*/
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;
}

/*
    Convert the pulse width in ms to a distance in cm
*/
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;
}

/* Ping))) Sensor 
   This sketch reads a PING))) ultrasonic rangefinder and returns the
   distance to the closest object in range. To do this, it sends a pulse
   to the sensor to initiate a reading, then listens for a pulse
   to return.  The length of the returning pulse is proportional to
   the distance of the object from the sensor.
     
   The circuit:
    * +V connection of the PING))) attached to +5V
    * GND connection of the PING))) attached to ground
    * SIG connection of the PING))) attached to digital pin 7

   http://www.arduino.cc/en/Tutorial/Ping
   
   Created 3 Nov 2008
   by David A. Mellis
 
   Modified 30-Aug-2011
   by Tom Igoe

   Modified 09-Aug-2013
   by Dale Weber
 
   This example code is in the public domain.
*/

//  Set units = true for inches and false for cm
int readPing (byte pingPin, boolean units) {
  //  Establish variables for duration of the ping,
  //    and the distance result in inches and centimeters:
  long duration;
  int result;

  // 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(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, 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(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // Convert the time into a distance
  if (units) {
    // Return result in inches.
    result = microsecondsToInches(duration);
  } else {
    // Return result in cm
    result = microsecondsToCentimeters(duration);
  }
 
  delay(100);
  
  return result;
}

/*
    Pulses a digital pin for duration ms
*/
void pulseDigital(int pin, int duration) {
  digitalWrite(pin, HIGH);   // Turn the ON by making the voltage HIGH (5V)
  delay(duration);           // Wait for duration ms
  digitalWrite(pin, LOW);    // Turn the pin OFF by making the voltage LOW (0V)
  delay(duration);           // Wait for duration ms
}

bool displaySample (byte channel, Sample *sample) {
  String st;
  bool error = false;

  switch (channel) {
    case FRONT_LEFT_SIDE:
      st = "Front Left";
      break;
      
    case FRONT_RIGHT_SIDE:
      st = "Front Right";
      break;
      
    case BACK_LEFT_SIDE:
      st = "Back Left";
      break;
      
    case BACK_RIGHT_SIDE:
      st = "Back Right";
      break;
      
    default:
      st = "Invalid";
      error = true;
      break;
  }

  if (! error) {  
    Serial.print(st);
    Serial.print(" Sample = ");
    Serial.print(sample->value);
    Serial.print(", Voltage = ");
    Serial.print(sample->volts);
    Serial.println(" volts");
  }

  return error;
}

/*
    Get a sound sample from the given channel
*/
Sample soundSampleOf (byte channel) {
  Sample sample;
 
  sample.value = analogRead(channel);
  sample.volts = (sample.value * MAX_VOLTS) / MAX_STEPS;

  //  Initialize the rest of the sample
  sample.signalMin = 1024;
  sample.signalMax = 0;
  sample.signalMinVolts = 0.0;
  sample.signalMaxVolts = 0.0;
  sample.peakToPeakVolts = 0.0;

  return sample;
}

/*
    Get samples of sound from four microphones
*/
void getSoundSamples (Sample samples[SAMPLE_MAX]) {
  byte channel;
  Sample ts;

  //  Start of sample window
  unsigned long startMillis= millis();

  while ((millis() - startMillis) < sampleWindow) {
    /*
        Get and process raw samples from each microphone
    */
    for (channel = 0; channel < CHANNEL_MAX; channel++) {
      samples[channel] = soundSampleOf(channel);
      ts = samples[channel];

      if (ts.value < 1024) {
        //  Toss out spurious readings
        if (ts.value > ts.signalMax) {
          //  Save just the max levels
          ts.signalMax = ts.value;
          ts.signalMaxVolts = ts.volts;
        } else if (ts.value < ts.signalMin) {
          //  Save just the min levels
          ts.signalMin = ts.value;
          ts.signalMinVolts = ts.volts;
        }
        
        samples[channel] = ts;
      }
    }  
  } //  End of sample collection loop
  
  //  Calculate the peak to peak voltages
  for (channel = 0; channel < CHANNEL_MAX; channel++) {
    ts = samples[channel];
    ts.peakToPeakVolts = abs(ts.signalMaxVolts - ts.signalMinVolts); 

    samples[channel] = ts;
  }
}

/*
    Try to detect the loudest sound from one of four directions
*/
byte detectSound (void) {
  unsigned int sampleValue;
  Sample *ts;

  /*
      Variables for sound detection
  */
  double detectionFrontVolts = 0.0, detectionBackVolts = 0.0;
  byte detectionFront = 0;
  byte detectionBack = 0;
  byte detectionResult = 0;

  int displayPeakFrontLeft, displayPeakFrontRight;
  int displayPeakBackLeft, displayPeakBackRight; 
  
  /*
      Code starts here
  */

  /*
      Turn all the sound detection LEDs off
  */
  digitalWrite(FRONT_LEFT_LED, LOW);
  digitalWrite(FRONT_RIGHT_LED, LOW);
  digitalWrite(BACK_LEFT_LED, LOW);
  digitalWrite(BACK_RIGHT_LED, LOW);

  getSoundSamples(samples);

  /*
      Calculate the FRONT detection value
  */
  detectionFrontVolts = abs(samples[FRONT_LEFT_SIDE].peakToPeakVolts - samples[FRONT_RIGHT_SIDE].peakToPeakVolts);
  Serial.print("Front Detection value = ");
  Serial.println(detectionFrontVolts);

  /*
      Calculate the BACK detection value
  */
  detectionBackVolts = abs(samples[BACK_LEFT_SIDE].peakToPeakVolts - samples[BACK_RIGHT_SIDE].peakToPeakVolts);
  Serial.print("Back Detection value = ");
  Serial.println(detectionBackVolts);

  /*
      Get our final detection result
  */
  if ((detectionFrontVolts > detectionBackVolts) && (detectionFrontVolts > DETECTION_THRESHOLD)) {
    //  Check for sound detection
    if (samples[FRONT_LEFT_SIDE].peakToPeakVolts > samples[FRONT_RIGHT_SIDE].peakToPeakVolts) {
      digitalWrite(FRONT_LEFT_LED, HIGH);
      detectionFront = FRONT_LEFT_SIDE;
    } else if (samples[FRONT_RIGHT_SIDE].peakToPeakVolts > samples[FRONT_LEFT_SIDE].peakToPeakVolts) {
      digitalWrite(FRONT_RIGHT_LED, HIGH);
      detectionFront = FRONT_RIGHT_SIDE;
    } else {
      detectionFront = NO_SOUND_DETECTION;
    }
    
    detectionResult = detectionFront;
  } else if ((detectionBackVolts > detectionFrontVolts) && (detectionBackVolts > DETECTION_THRESHOLD)) {
    //  Check for sound detection
    if (samples[BACK_LEFT_SIDE].peakToPeakVolts > samples[BACK_RIGHT_SIDE].peakToPeakVolts) {
      digitalWrite(BACK_LEFT_LED, HIGH);
      detectionBack = BACK_LEFT_SIDE;
    } else if (samples[BACK_RIGHT_SIDE].peakToPeakVolts > samples[BACK_LEFT_SIDE].peakToPeakVolts) {
      digitalWrite(BACK_RIGHT_LED, HIGH);
      detectionBack = BACK_RIGHT_SIDE;
    } else {
      detectionBack = NO_SOUND_DETECTION;
    }

    detectionResult = detectionBack;
  }
  
  return detectionResult;
}

void setup() {
  //  Start up the Wire library as a slave device at address 0xE0
  Wire.begin(NAV_I2C_ADDRESS);

  //  Register event handler
  Wire.onRequest(wireRequestEvent);
  Wire.onReceive(wireReceiveData);

  //  Initialize the hardware serial port  
  Serial.begin(115200);
  
  //  Initialize the LED pin as an output.
  pinMode(HEARTBEAT_LED, OUTPUT);
  
  //  Set the LED pins to be outputs  
  pinMode(COLOR_SENSOR_LED, OUTPUT);
  pinMode(FRONT_LEFT_LED, OUTPUT);
  pinMode(FRONT_RIGHT_LED, OUTPUT);
  pinMode(BACK_LEFT_LED, OUTPUT);
  pinMode(BACK_RIGHT_LED, OUTPUT);
 
  //  Test the LEDs
  digitalWrite(FRONT_LEFT_LED, HIGH);
  digitalWrite(FRONT_RIGHT_LED, HIGH);
  digitalWrite(BACK_LEFT_LED, HIGH);
  digitalWrite(BACK_RIGHT_LED, HIGH);

  delay(1000);

  digitalWrite(FRONT_LEFT_LED, LOW);
  digitalWrite(FRONT_RIGHT_LED, LOW);
  digitalWrite(BACK_LEFT_LED, LOW);
  digitalWrite(BACK_RIGHT_LED, LOW);
  digitalWrite(COLOR_SENSOR_LED, LOW);
}

/*
    Called when a request from an I2C (Wire) Master comes in
*/
void wireRequestEvent (void) {
}

//  Called when the I2C (Wire) Slave receives data from an I2C (Wire) Master
void wireReceiveData (int nrBytesRead) {
}

// The loop routine runs forever:
void loop() {
  byte directionOfSound = 0;

  int analogPin = 0;
  int digitalPin = 0;
  
  // Pulse the heartbeat LED
  pulseDigital(HEARTBEAT_LED, 500);

  // Get distance readings from the GP2D12 Analog IR sensors and store the readings  
  for (analogPin = 0; analogPin < MAX_GP2D12; analogPin++) { 
    gp2d12[analogPin] = read_gp2d12(analogPin);
  }

  // Display the GP2D12 sensor readings (cm)
  for (analogPin = 0; analogPin < MAX_GP2D12; analogPin++) { 
    Serial.print("gp2d12 #");
    Serial.print(analogPin + 1);
    Serial.print(" range = ");
    Serial.print(gp2d12[analogPin]);
    Serial.println(" cm");
  }  
  
  Serial.println("");
/*  
  //  Get distance readings from PING Ultrasonic sensors in cm and store them
  for (digitalPin = 0; digitalPin < MAX_PING; digitalPin++) {
    ping[digitalPin] = readPing(digitalPin + DIGITAL_PIN_BASE, false);
  }
  
  // Display PING sensor readings (cm)
  for (digitalPin = 0; digitalPin < MAX_PING; digitalPin++) {
    Serial.print("Ping #");
    Serial.print(digitalPin + 1);
    Serial.print(" range = ");
    Serial.print(ping[digitalPin]);
    Serial.println(" cm");
  }
 
  Serial.println("");
*/

  //  Do sound detection
  directionOfSound = detectSound();

  if (directionOfSound == NO_SOUND_DETECTION) {
    Serial.println("No sound detection");
  } else {
    Serial.print("Sound detection from the ");
  
    switch (directionOfSound) {
      case FRONT_LEFT_SIDE:
        Serial.print("FRONT LEFT");
        break;
      
      case FRONT_RIGHT_SIDE:
        Serial.print("FRONT RIGHT");
        break;
      
      case BACK_LEFT_SIDE:
        Serial.print("BACK LEFT");
        break;
      
      case BACK_RIGHT_SIDE:
        Serial.print("BACK RIGHT");
        break;
    
      default:
        Serial.print("an INVALID");
        break;
    }
    
    Serial.println(" side");
  }
  
  Serial.println();
}

8-Dale

I have my BotBoarduino connected to an SSC-32, and they are communicating fine. I have the pan/tilt servos and motor controls connected to the SSC-32, but donā€™t have the Sabertooth 2x5 powered up yet. I also have Pod connected to the BotBoarduino via I2C, and Pod sees it on the I2C bus at address 0x50. I have a lot of code to write for the I2C stuff, so that wonā€™t be tested fully for awhile. I have to decide on a command structure and how those commands will be executed on the BotBoarduino. I also have to figure out how I am going to battery power Pod.

For W.A.L.T.E.R. 2.0ā€™s first voyage, I will not have Pod connected, so heā€™ll run just with the BotBoarduino and SSC-32. I have all the batteries I need to do that. Iā€™m in the process of retesting and mounting the remaining two GP2D12 IR sensors to each side of front center. They wonā€™t interfere with movement of the pan/tilt.

Iā€™ve decided to get an Arduino Mega 2560 ADK board with this shield, and try it out. The Mega has 16 analog inputs, 4 serial ports, and a lot of other goodies. The shield adds XBee headers and 3-pin headers for the signals.

Iā€™m also going to get the Parallax laser range finder. :smiley:

8-Dale

Go Walter!

Alan KM6VV

Ha ha ha!

Itā€™s going to take a bit longer to make W.A.L.T.E.R. go. I had hoped to get W.A.L.T.E.R. moving around a bit on his own tonight, but I, um, well, let all the magic smoke out of my Sabertooth 2x5 today, so I have to replace it. :frowning: Since it makes handling quadrature encoders much easier, Iā€™m going to replace the Sabertooth 2x5 with a RoboClaw (2x5 or 2x15).

Itā€™s too bad RobotShop doesnā€™t carry the RoboClaw 2x5, because thatā€™s all I really need. The smallest they stock is the RoboClaw 2x15, at a greatly inflated price. I could get the RoboClaw 2x15 for $20.00 LESS by going to either BasicMicro, or Orion Robotics direct. It looks like Iā€™ll have to go to Orion Robotics direct to get the RoboClaw 2x5 ($69.95), or the RoboClaw 2x15 ($89.95) if I want to have more headroom and room to upgrade motors. BasicMicro also has the RoboClaw 2x15 for $89.95. I can see I am going to have to be very careful when shopping at RobotShop, as far as prices go. RobotShopā€™s price for the RoboClaw 2x15 is $109.95, and I almost went for it. Iā€™ll buy a RoboClaw direct from Orion Robotics, instead of RobotShop.

I added the Parallax laser range finder back to my cart for my RobotShop order, in place of the RoboClaw controller, and they have it for the same price Parallax sells it for ($99.95). Iā€™ll mount this on top of W.A.L.T.E.R., mounted on a servo so I can scan a full 180 degree arc with it. The Laser range finder is a serial device, unfortunately. The front pan/tilt with IR and PING sensors, on the lower deck, can also scan a full 180 degree arc (left/right), as well as 90 degrees down and 50 degrees up. With another IR sensor mounted to each side of front center, and the laser range finder mounted on top, that should give W.A.L.T.E.R. pretty darn good coverage for ranging.

Now, I have to figure out why my new SSC-32 isnā€™t working. I have no idea whatā€™s wrong, and Iā€™ve checked all the jumpers, and compared the settings with an older SSC-32 that is working. All the jumpers look right, but it just doesnā€™t work.

Speaking of the SSC-32, I wrote a couple nice servo movement routines for the BotBoarduino that also allow use of the ā€œSā€ (per servo speed), and ā€œTā€ (affects entire group) parameters on a move, as well as combination moves. I have one routine for using pulse widths, and another for using degrees (+/- 90 or 0-180), settable per servo at initialization. Iā€™ll be testing these heavily tomorrow.

Iā€™ve defined a struct that holds data on a servo. I havenā€™t decided whether I want to wrap it all up into a proper class and create a library or not though. It probably wouldnā€™t be too difficult to do, since I already have the servo struct defined. I could start building a robotics library for the Arduino/BotBoarduino, or I could even make a BotBoarduino specific robotics library to take advantage of its special features. Iā€™ve written Arduino libraries before, so I know pretty much what I have to do. I could roll my four channel sound detection routines into a robotics library pretty easily, once Iā€™ve had a chance to test this fully. The two channel routine works great!

Pod (a Raspberry Pi, model B) sees my BotBoarduino on the I2C bus. :smiley: Now, I have to learn what I need to know to use Adafruitā€™s Python I2C library to communicate with the BotBoarduino and exchange data. I see the potential for creating at least a couple more libraries here, or maybe just rolling everything into one Arduino/SSC-32 library, a BotBoarduino specific library with its unique functionality, and a Python library. Since the BotBoarduino can also use Arduino libraries, and there isnā€™t anything that ties the SSC-32 to it specifically, I canā€™t see any reason to duplicate functionality. I see a lot of potential here.

This is really happening. :smiley: :smiley:

Iā€™m a software guy by choice, a hardware guy out of necessity.

8-Dale

Here are a few current pictures showing my progress with construction of W.A.L.T.E.R. 2.0 so far:

The front pan/tilt is complete, but I have to replace the PING sensor. I have an old HS-475 servo for the panning and an HS-645 for the tilt.


Now you can see how Iā€™ve chosen to mount the BotBoarduino and SSC-32 at the back of the top deck.

The motor controller and motor battery are on the underside of the bottom deck.

8-Dale

Looking nice.
Especially the nice color matched tie-wrap for the battery.

I think i will get my hands on a rover soon.
The DFRobotShop Rover is talking to meā€¦

I will of course use a botboarduino.

A Pololu motor driver? I thought you were using RoboClaw.

Looks good, 'tho.

Alan KM6VV

I also have some larger yellow tie wraps, but I canā€™t find them right now.

Iā€™ve been talking about, and dinking around with W.A.L.T.E.R. 2.0 since around 2007/2008. I am actually going to get him operational this time around! Except for my custom decks, all the parts for W.A.L.T.E.R. 2.0 are from Lynxmotion.

Those tires are not going to hold up for long though, but hopefully they will last long enough for me to design W.A.L.T.E.R. 3.0, which will have four wheels, using the same two deck setup. Itā€™s difficult to find good large tires for rovers. I am mounting the left and right side IR sensors today, and already have them plugged into the BotBoarduino. The sensor order is Left, Center (on pan/tilt), Right. I just have to mount the left and right IR sensors upside down on the underside of the bottom deck. The wires are already routed up to the top deck and connected to the BotBoarduino.

I still need to get expansion connectors soldered to Intrepid (my PandaBoard ES). I want to see how easy it is to use its features, especially I2C. It would be extremely nice to put Intrepid on W.A.L.T.E.R. as his main brain. I absolutely must have reliable I2C though.

Iā€™ve decided not to get the Laser Range Finder this month, and Iā€™ve cut several other things off my RobotShop order. I still have a fairly large Lynxmotion order, and there is still some stuff I still need to get from Adafruit. Iā€™m still getting the Arduino Mega 2560 ADK board with that shield that brings everything out to three pin headers, and also has 3 XBee connections. Iā€™m replacing the front PING on the pan/tilt, as well as replacing the motor controller.

This is going to make next month a real crunch month for me, but thatā€™s OK. 2014 will be the year of W.A.L.T.E.R. 2.0 and more! :smiley:

That BotBoarduino is one VERY sweet little board! :slight_smile:

8-Dale

The motor controller I just let all the magic smoke out of is a Sabertooth 2x5 (not the R/C version). Iā€™m replacing it with a RoboClaw 2x5 or maybe a RoboClaw 2x15.

Thanks! Now, you finally get to see ALL THOSE HOLES put to good use! :smiley: :wink:

8-Dale