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

More pictures! :smiley:

These are all bottom views of WALTER, which also shows the independent steering of the wheels and the range of steering that’s available.




8-Dale

And, yet MORE pictures! :smiley:

Here you can see a better view of one wheel with range of motion of steering.




8-Dale

Last of the pictures! :smiley:

One more view of the independent steering of the wheels


One of the legs, side view. I wish I had a longer offset bracket for the legs.

Same leg, top view

8-Dale

looks really cool. Interesting SES config!

Thanks! :smiley:

I don’t have the wheels properly secured to the motors yet. I really don’t like the Banebot wheel securement method. The wheel is kept on the hub with a snap ring. I just found out today that allen wrenches are NOT the same as hex wrenches, and I only have allen wrenches. There seems to be some confusion with retailers on the difference also. I do like the Banebot wheels, but don’t care for the set screws used in the hubs. I wonder if I might be able to find a compatible 1/16" set screw for allen style head for these hubs.

I took a trip to my local hobby shop yesterday and they carry some nice wheels in various sizes that mount onto a 12mm hex hub, which should be compatible with the HUB-12 as far as I can tell. I will probably end up going this route for WALTER because I have a much wider selection of wheels and it will be much easier to deal with them. I found three one piece (wheel + tire) sets in three different sizes at the hobby shop, and they have larger sizes for the 12mm hex hub also, all the way up to almost 7" diameter. :slight_smile: The wheels I looked at seem quite light also, and have the type of tread pattern I am looking for.

On the SES leg design, my goal is to keep the retracted leg as close to the body as possible and still get a good range of movement for my application. I’d rather have a longer offset bracket though, but I think this is a decent compromise. The only problem is I think I am going to have to go with 5980 or 5990 servos for at least one joint, and probably two joints, in order to be able to lift the full weight of the motor and wheel at the end. I have already proven that using all HS-645 servos will not do the job in the main lifting joint. I’m going to experiment with another possibility of using two 645’s in a double jointed lifting arrangement, but I would rather not add another joint if possible. Using two 645’s would be the same price as a single 5980 and not far from the price of a 5990.

8-Dale

I’ve been working on some code for WALTER and the AXON controller. I’ve got the initialization code in and am starting to write code to actually do things. :slight_smile: I’m using the Webbot avr framework, which makes it pretty easy to get things done. There is already good support for a lot of different sensors.

Anyway, attached are the .C and .H files of what I have right now. I’ll be using this same basic code for A.S.T.R.I.D., but will be handling many more servos there.

8-Dale
walter.h (3.88 KB)
walter.c (6.74 KB)

I’ve designed a small 3DOF arm for the front point which will have two sensors (PING and Sharp IR) and a camera. I want to use the BlackFin camera here, so will have to see how easy it will be to mount on the top of the ASB-18. The sensors will be mounted on the underside of the ASB-18 to allow the camera to be mounted on top of it.

Here are a few pictures:


8-Dale

Mount the Blackfin camera on the ASB-18? (I’m currently working on a tilt/pan for the Blackfin). The Blackfin has 4 holes in the PCB, two on one end match up (pretty close) with two of the holes of an ASB-04. the other two holes of the Blackfin kinda hang over A plate with matching holes to the Blackfin camera (actually, the servo/radio board that the camera board mounts on) could be used on an ASB-04 to “pick up” the other two holes (via spacers) of the package. I like aluminum, but PCB stock should work fine for this, and allow the Blackfin to be mounted down close on the ASB-04.

Would that work for you?

Although looking at your camera bracket again, I see that the ASB-04 might be 90 out of the orientation you would need. I need to see my current experimental setup to know for sure…

Edit:

Current available Blackfin tilt/pan:

http://www.surveyor.com/images/bpt-kt500.jpg

breakout board:

http://www.surveyor.com/blackfin/bfin-breakout-v1.png

You can see the four mounting holes, and correlate a pair of holes to the holes on the ASB-04. Hole pattern might be 1.872" x 2.173" (not verified).

Alan KM6VV

I don’t think this would work for what I want to do. Remember, I want to have two sensors on the arm also. My idea is to secure the camera to the top of the ASB-18 with some insulator between and mount the two sensors on the underside.

I won’t be able to mount the camera direct to an ASB-04. I think once I mount the two sensors and take some more pictures, it will be much more clear what I have in mind. :smiley:

8-Dale

As I work on leg designs for ASTRID, I am also working on the eventual self leveling system for WALTER. In fact, part of the new leg design for ASTRID will be used for WALTER - just the second and third joints to make a 2DOF leveler. Even if this leg style isn’t used for ASTRID at all, I will use this part of it for the levelers on WALTER because it is simple and will just work. It will be strong and not have any problem lifting WALTER’s body.

Here is what I will use on WALTER:


I won’t be installing these right away because there is still quite a lot to do before this. I want to have plenty of time to work out the steering patterns for the 2WD and 4WD styles before I add the leveling system, which will also require an accelerometer.

8-Dale

I finished building the new leg and took a few pictures.

Walking mode:


8-Dale

Here are a few more picures of the new leg attached to ASTRID. I have several macros made in LynxTerm to send the leg to various positions, as it might be controlled by a micro. I wish I could share this as a video, but my PC is apparently not quite fast enough to capture smooth video from my webcam (Logitec 9000).

Home position:


Medium extension:

Full extension:

This leg design looks way better than the previous design, and these servos have quite a bit of slop due to much use in experimenting with stuff. I’m wondering if going to the digital (5485 and 5645) would be worth the extra cost. I’m using just regular analog 475 and 645 servos at present.

Would going to the digital versions of my current servos make enough difference to warrent spending the extra money?

8-Dale

Well, I must be coming full circle or something. I connected up my Basic Atom Pro and checked all the pins. Everything seems to be working so far, which is good. Now that Basic Micro has released build #30 of Basic Micro Studio, hservo compiles and links properly. :slight_smile: I’m going to put the BAP/Bot Board II on WALTER and see what I can do with it. My previous software for WALTER was written for the Basic Atom (not Pro), but I lost it when I lost everything on my hard drives and will be starting from scratch (not necessarily a bad thing) now. So, I have a clean slate, which can often be a really good thing. :smiley: I’m preparing for getting an Arc32 board when they are available.

I’m also going to experiment with programming the BAP/Arc32 in C, which is my preference for writing code. I’m starting to look at Kurte’s C code for the Phoenix and see what I might be able to use from that, and build from there. If Basic Micro adds solid support for building and using libraries to Basic Micro Studio, I think there is a lot of potential for development in C for both Atom Pro and Arc32. I have several ideas I’d like to work towards in C development for the Atom Pro/Arc32.

We’ll see how fast I can fill up 32K of flash on the Atom Pro. I ran out of flash pretty quick on the Basic Atom when I started working with Subsumption. At some point, I want to add a BeagleBoard or Gumstix into the mix for WALTER, and can make pretty much any micro into a serial slave. I’ve already worked out how to power my BeagleBoard and USB hub from a standard NMiH battery pack using a slightly modified breadboard power supply from SparkFun.

8-Dale

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 [email protected]

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* = 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);
  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
}
}
[/code]
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[/code]
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. :slight_smile:

8-Dale**

I’ve mounted my AtomPro/BotBoard II on to WALTER and have the rear steering servos connected, and I’ve got some initial code I have been working on. It’s like I haven’t even been away from programming an AtomPro! :smiley:

Right now, all the code does is send the steering servos to their home position, which is for standard forward/reverse motion. With this position, I should be able to use standard two wheel steering by using the motor speed and direction for turning. I still have to do some fine tuning of the home position to be sure the wheels are positioned correctly for this mode of control and properly center the servos mechanically, which I will do when I get the am able to get the new HS-485 servos. For now, my current setup is good enough for testing.

Below is my current code:

[code]’
’ Program: Control Software for W.A.L.T.E.R. - the Wheeled Autonomous Learning Terrain Exploring Rover
’ Author: Dale Weber [email protected]
’ Date: 04-Jun-2010
’ Version: 2.10
’ Purpos: Original

’ Processor: Basic Atom Pro on a BotBoard II
’ Hardware: Dimension Engineering Sabertooth 2X5 Motor Controller
’ GHM-04 Motors with QME-01 Shaft Encoders (2)
’ HS-485HB Servos (4 Steering, 1 Arm Pan)
’ HS-645MG Servos (2)
’ 7.2V @ 2800 mAH NiMH Battery Pack (Motors)
’ 7.2V @ 2800 mAH Battery Pack (Electronics)
’ 6.0V @ 2800 mAH Battery Pack (Servos)


’ Constants

StepsPerDegree con 133.3 ’ Counts per degree of servo movement.

TRUE con 1
FALSE con 0

’ Steering servo pins

RightFront con 0
LeftFront con 1
RightRear con 2
LeftRear con 3

’ Steering servo direction addustments

RFDir con 0
LFDir con 0
RRDir con 1
LRDir con -1

’ Steering positions in degrees

CurrRFPos var sword
CurrLFPos var sword
CurrRRPos var sword
CurrLRPos var sword

CurrSpeed var sword

’ Initialize variables

CurrRFPos = 0
CurrLFPos = 0
CurrRRPos = 55
CurrLRPos = -55

CurrSpeed = 0

enablehservo

’ Tell everyone we are here
sound 9, [150\5000, 150\4400, 150\5000]
’ Send servos to starting position
hservo [RightFront\0, LeftFront\0, RightRear\0, LeftRear\0]


’ Main Line

gosub Steering [CurrRFPos, CurrLFPos, CurrRRPos, CurrLRPos, 100]
goto ShutDown

'Set speed for the four motors - SaberTooth 2x5 motor controller, packet serial

speed var sword
SetSpeed [speed]
return


’ Steer the four wheels

rfangle var sword
lfangle var sword
rrangle var sword
lrangle var sword
spd var sword
Steering [rfangle, lfangle, rrangle, lrangle, spd]
hservo [RightFront\rfangle * StepsPerDegree\spd, LeftFront\lfangle * StepsPerDegree\spd, RightRear\rrangle * StepsPerDegree\spd, LeftRear\lrangle * StepsPerDegree\spd]
return

ShutDown
End[/code]
8-Dale

I’ve added a PS2 wireless controller to WALTER now, and am getting data from the controller. I have the controller on P0 - P3 and used Kurte’s init code to get started with that configuration. After I changed the power jumper for those pins to +5V instead of VS (thanks to a nudge from Kurte), everything started to come together nicely. I took the rest of the PS2 controller code from one of the A4WD1 PS2 tutorial.

The purpose of having PS2 control available is I want to be able to take manual control of WALTER if he gets into a problem area he can’t get out of on his own. After I correct his course, I can then return control to him and he can continue to roam around autonomously. :smiley:

Now, I am getting anxious to get a RoboClaw 2X5A motor controller, so I can hook the rear motors and encoders up and start tinkering with that. I could connect up my SaberTooth 2X5, but I’d rather just start out with the RoboClaw. :slight_smile:

8-Dale

I’ve mapped out the I/Os on my Atom Pro. To get everything I want connected to WALTER right now, I will be using every single I/O, and there is still stuff I want to connect beyond this. I’ll be using the hardware serial port for the motor controllers. I’ve decided to use motors with encoders on the front wheels as well as the rear wheels, which means using two motor controllers.

It looks like I will be needing an Arc32 board for WALTER at some point in the not too distant future. I’m anxiously awaiting the Arc32 and RoboClaw 2X5A coming into stock here, but unfortunately I don’t think I will be able to order both at the same time as I would like to do. At this point, it actually makes more sense to get the RoboClaw first, since I can use it right on WALTER immediately, but I could also use my SaberTooth 2X5 for awhile as long as I don’t want to use the encoders right away. Getting the Arc32 now pretty much depends on whether I have the possibility of building my own DIY Robot Remote Controller with XBee, but I am not at all sure I can pull a project like this off.

8-Dale

I’ve been working with my BeagleBoard and Sanguino. I’ve already got code written and debugged that allows a Sanguino/Arduino to read sensors and send those results out the UART. This happens based on ASCII commands sent from a host, such as a PC or BeagleBoard. Now I am working on Python code for my BeagleBoard that will send commands to the Sanguino and have it take sensor readings and send those results back to the BeagleBoard for action. This will get me one step closer to being able to use a BeagleBoard for the main brain on W.A.L.T.E.R. When this is working, I’ll be able to use RoboDuinos for sensor handlers, a pan/tilt sensor handler (always scanning).

I’ve decided to use an SSC-32 for servo control rather than getting an ARC-32 for this purpose right now. I’m not sure I’d be able to use the ARC-32 as a serial slave, due to various things I have been reading. Of course, I might be able to have it communicate via HSERIAL2, which is a possibility. I just don’t have the funds available right now for purchasing new boards, so have to experiment with and use what I already have, until I perfect my hardware configuration for W.A.L.T.E.R. So far, using one or more Arduino compatible boards seems to be the best way to go for me, with the BeagleBoard as the main brain. I’ve already verified that my BeagleBoard will detect and setup the serial port when I plug my Sanguino into it, which is positive. I’ve also got WiFi b/g working on my BeagleBoard (LinkSys WUSB54GC dongle) and will also be adding XBee via USB.

Using the BeagleBoard will also allow me to do some much more processing intense tasks such as onboard video processing, etc. I’m anxious to get a BeagleBoard-xM board at some point when it is released, because it operates at 1 GHz, has a four port USB Hub and 10/100 Ethernet on board. Right now, I have my C3 BeagleBoard setup to boot Android 2.1 from NAND if there is no SD Card in the SD slot, or from the SD Card if one is present. I’m also looking forward to getting a TinCanTools Trainer Board at some point, to add to my BeagleBoard, which will break out and level shift many of the pins to 3.3V and/or 5V to make it easier to interface additional hardware to it.

8-Dale

Yes, I know my work on W.A.L.T.E.R. is not progressing very fast.

Things like health issues and a severe anxiety/panic attack on a public bus (still have health issues from this) last month keep me from doing the things I enjoy most. However, I can get a bit of work done on him here and there as I am able, and have started actually putting together the new motor/wheel mounting system. Yes, I have been taking pictures along the way and have a set of 16 (and growing) new pictures coming together now. I just have to decide which mounting position I want to try for the wheels first, more forward or more rearward with respect to WALTER’s most forward point. This new mounting scheme is more flexible, and will allow at least four (three usable) different schemes for mounting the motors and wheels, unlike the old setup which had to be completely rebuilt just to change the mounting scheme. Right now, I want to try the more forward short “C” bracket scheme.

This new mounting scheme also allows for the possibility of mounting sensors that would point out over the wheel in the direction the wheel is moving. The impact of having this capability has not fully hit me yet, and my head is already hurting. Knowing how far each wheel is from an obstacle could be very valuable information, considering that each wheel is independently steerable.

Hopefully, I will have the two new motor/wheel mounts assembled this week, if I can find the short “C” (ASB-09) brackets I need. I also have the option of using long “C” (ASB-10) brackets.

8-Dale

OK, here are some pictures of the latest revisions to W.A.L.T.E.R. These pictures show the start of the assembly of the new motor mounts for the rear wheels. The basic mount is just an ASB-06 attached to an ASB-04. I will have to clip a bit off one corner of the deck to provide for full range of motion, but I can take care of that with my Dremel tool.

8-Dale