Search This Blog

Monday, April 21, 2008

Using Basic Atom Pro with PING Ultrasonic Sensor

I've actually found a lot of information on using the PING ultrasonic sensor. There is even a forum topic in the Lynxmotion forums that goes through the whole process of developing code to get the Basic Atom Pro to work with the PING sensor located at http://www.lynxmotion.net/viewtopic.php?t=1819&postdays=0&postorder=asc&highlight=pro+ping+code&start=0

This code is posted here just to document what is used in the Midnight Prowlerbot. Here is the code that I used:

'Ultrasonic module - PING available from Lynxmotion or Parallax
Sonar_Pulse_Dat con P10


GetDistance

Low Sonar_Pulse_Dat
pulsout Sonar_Pulse_Dat, 10
RCTIME Sonar_Pulse_Dat, 1,rawDist
if rawDist > 65000 then
goto ErrorDist
endif
RCTIME Sonar_Pulse_Dat, 0, rawDist
PING_Scale.highword = 0
PING_Scale.lowword= 2260
cms = (rawDist */ PING_Scale ) / 2
goto GetDistanceExit
ErrorDist
cms = 0
GetDistanceExit
return

Please forgive the lack of proper indentation in the above code listing and previous code listings. I couldn't get the posting tool to cooperate enough to do proper indentations and I didn't want to take snapshots because I wanted people to be able to copy-and-paste the listings. The measurement result will be in the cms variable in centimeters.

The most significant difference between the code listed above for the PING and the code that is often listed on other websites for the Basic Atom non-Pro is the use of the rctime command instead of using pulsin. This is done because pulsin seems to be buggy on the Basic Atom Pro whereas rctime works fine. The pulsin bug is mentioned in several places on the Lynxmotion and Basic Micro forums.

The other difference in the above code and code that would be used on a non-Pro Basic Atom is that pulsout uses 10 for the time instead of 5. This is because the time is in 0.5 microsecond increments on the Basic Atom Pro compared to 1.0 microsecond increments on the Basic Atom.

This post is the last of three code listings for the different sensors currently used on the Midnight Prowlerbot. I still have a Memsic 2125 accelerometer that I could connect, but I can't see a real use for it at the moment on the Midnight Prowlerbot and I have my hands full with projects for the CMUCam2+. Posts from this point forward will be mostly about different projects with the CMUCam2+ and related code unless I decide to reconfigure the robot or add another sensor.

Using Basic Atom Pro with Sharp GP2D12 IR Sensor

Here is a listing of code used in the Midnight Prowlerbot for handling the Sharp GP2D12 infrared sensor readings.

'Infrared module - GP2D12 IR Sensor available from Lynxmotion
IR_LDat con P16 'AX2 (analog)
IR_RDat con P17 'AX3 (analog)


'Infrared reading conversion - this module is not linear and this compensates for it
IRconverttable bytetable 80,80,80,80,80,80,80,80,80,78,76,74,72,70,68,66,64,62,60, 59,58,57,55,53,52,51,50,49,48,47,45,43,42,41,40,39,38,37,35,33,
32,31,30,30,29,29,28,28,27,27,26,26,26,25,25,25,24,24,24,23,
23,22,22,21,21,20,20,20,19,19,18,18,18,17,17,16,16,16,15,15,
15,14,14,13,13,13,12,12,11,11,11,10,10,10,10,10,10,10,10,10

GetIRDistance
adin IR_RDat, IR_RRaw
IR_RFcms = tofloat(IR_RRaw) / 5.12
IR_Rcms = IRconverttable(toint IR_RFcms)
if IR_RRaw > 512 then
IR_Rcms = 99
endif

adin IR_LDat, IR_LRaw
IR_LFcms = tofloat(IR_LRaw) / 5.12
IR_Lcms = IRconverttable(toint IR_LFcms)
if IR_LRaw > 512 then
IR_Lcms = 99
endif
return

Notice that IR_RDat and IR_LDat do not use analog in pins that might be expected - they are using P16 and P17, not AX2 and AX3 as would be used on a Basic Atom. When I used AX2 and AX3, or even just 2 and 3 as in the manual, I couldn't get the sensors to work at all. Little did I realize that the adin command prefers a 'P' identified pin to work.

Since I rarely look for information on a device before using it, other than the manual or device sheet, I had no idea that the adin command had a quirk. It was after hours of frustration that I found a post on the Lynxmotion forums at http://www.lynxmotion.net/viewtopic.php?t=570&highlight=gp2d12 that described the pin identification problem.

Incidentally, the pin identifiers are mentioned in the Basic Atom Pro manual under the adin description, but what isn't mentioned is that if an 'AX#' identifier is used instead of a 'P#' identifier that the adin command will not work; however, the 'AX#' identifier works fine with the adin command on the Basic Atom non-Pro.

Oddly, I've had identifier issues with other commands also. It appears that using an assigned constant to identify a pin, such as using IR_RDat to identify P17, does not always work. For instance, serin does not seem to work with assigned constant identifiers, but works fine with 'P#' identifiers. Unfortunately, there is no indication that things aren't working as the code compiles and programs just fine.

I've even had a similar issue come up with 'if' statements only to find that not using an assigned constant identifier fixed the non-working code. This type of thing has happened on several occassions and failing to be aware of it caused frustration nearly to the point of forcible hair removal and uncontrollable mumbling. By the way, the identifier bug was on version 8.0.1.0 of the IDE. I'm not sure if it exists in the latest version.

Sunday, April 20, 2008

Using Basic Atom Pro with HM55B compass module

I've seen code for every sensor that the Midnight Prowlerbot is using available for Basic Stamp modules and most of it available for Basic Atom modules, but not Basic Atom Pro modules. Below is a listing of the HM55B code that I use in the Midnight Prowlerbot:

'Compass Module - HM55B available from Parallax
'Note: the module would not work accurately without the pause commands

'pin constants
Comp_En con P5
Comp_Clk con P6
Comp_DinDout con P7

'compass constants
Comp_Reset con 00
Comp_Measure con %1000
Comp_Report con %1100
Comp_Ready con %1100

'variables
Comp_x var sword
Comp_y var sword
Comp_status var Nib
fangle var float
Comp_angle var Word

GetCompass

'this routine gets the axes from the compass module for calculating direction.
'Note: software calibration may be needed
'clear variables first

Comp_status = 0
Comp_x = 0
Comp_y = 0

'send reset command to module
high Comp_En
pause 2
low Comp_En
shiftout Comp_DinDout,Comp_Clk,MSBFIRST,[Comp_Reset\4]
pause 2

'start measuring command
high Comp_En
pause 2
low Comp_En
shiftout Comp_DinDout,Comp_Clk,MSBFIRST,[Comp_Measure\4]
pause 2

'loop until the module tells us that it is ready with the data
repeat

high Comp_En
pause 2
low Comp_En

'measurement status command
shiftout Comp_DinDout,Comp_Clk,MSBFIRST,[Comp_Report\4]
'reply to status request
shiftin Comp_DinDout,Comp_Clk,MSBPOST,[Comp_status\4]

until Comp_status = Comp_Ready

'get the x and y values from the module
shiftin Comp_DinDout,Comp_Clk,MSBPOST,[Comp_x\11,Comp_y\11]

'disable the module
high Comp_En

'store 11 bits as a signed word (both axis)
if (Comp_y.bit10 = 1) then

Comp_y = Comp_y - %11111111111

endif


if (Comp_x.bit10 = 1) then

Comp_x = Comp_x - %11111111111

endif

fatan2 tofloat Comp_x\tofloat Comp_y + 0.1, fangle
Comp_angle = toint(fangle / 3.1416) * 180 + 179

return

I cannot take credit for originating the code for each of the modules used in the Midnight Prowlerbot, but I can take credit for developing code based on what I found, testing it, and modifying it and verifying that it works. Some of the code is based on what I was able to find in the Lynxmotion forums and some is based on information from a variety of other websites as well as of course based on original code for Basic Stamp modules.

When I was trying to integrate the related modules into the Midnight Prowlerbot, I just wish that I could have gone somewhere to get the necessary code and plug it in instead of spending hours debugging and trying different things; so, I've made the code available here, in one place, for anyone that is trying to get such modules to work with a Basic Atom Pro.

Friday, April 11, 2008

BlueSmirf and Basic Atom Pro

The BlueSmirf bluetooth modem available from Sparkfun (http://www.sparkfun.com/) provides an easy way to add wireless communications to a robot that doesn't need to communicate beyond about 30 feet. The current version of the Midnight Prowlerbot uses a BlueSmirf connected to the CMUCam2+ to allow wireless control of the camera from a laptop.

It seems that every module or device has some sort of gotcha and the gotcha with the BlueSmirf is that if it is not in fast data mode that the CMUCam2+ will overrun the buffer of the BlueSmirf and cause it to freeze when transferring an image. This is easily fixed by going into command mode and issuing ATMF to cause the BlueSmirf to use fast data transfer mode wherein it ignores BlueSmirf commands and simply transfers data. This applies to BlueSmirf v1 - I'm not sure if it applies to BlueSmirf v2.

I wanted more direct control of the Midnight Prowlerbot by communicating directly with the Atom Bot Board (ABB) instead of using the CMUCam2+ servo output to signal commands to the ABB. The goal was simply to split the receive line from the BlueSmirf to the CMUCam2+ and the ABB. Using a resistor to buffer between the ABB and the BlueSmirf while having a direct connection from the BlueSmirf to the CMUCam2+ achieved the goal. Any commands received through the BlueSmirf would be sent to both devices and each device would just ignore messages not intended for it.

The gotcha is that the Basic Atom Pro will not receive from the BlueSmirf any faster than 38400 baud. This was the limit using the hardware serial port. The max for the software serial port is 57600 baud anyway, so I didn't even bother with it. It did not matter if the BlueSmirf was in fast data mode or not, 38400 was the max for communicating with the Basic Atom Pro. It also didn't matter if the Basic Atom Pro was the only thing connected to the BlueSmirf or if the connection was being shared with the CMUCam2+, the limit was 38400. This appeared to be the true when using just a Basic Atom 28 instead of the Pro as well.

The 38400 baud limit would not be a problem if it was not for the desire to transfer images from the camera and have motion detection and color updates that would update as quickly as possible. So in the interest of not giving up these features, I just reconfigured the Midnight Prowlerbot back to the way it was using the servo output from the CMUCam2+ as the command pipeline.

The next revision of the bot is apparently going to need a second BlueSmirf since I can't seem to get both the CMUCam2+ and ABB/Basic Atom Pro to receive at the same speed without sacrificing more than I'm willing to tolerate. By not having to send commands through the CMUCam2+, it will no longer be necessary to interrupt color or motion tracking to update the robot position.

Thursday, April 10, 2008

Third Generation Bot and Netbeans


This is the most recent schematic for the Midnight Prowlerbot. I decided that it was best to simply control the CMUCam2+ using the Java GUI available from http://www.cs.cmu.edu/~cmucam2/downloads.html. Besides, it is interesting to be able to access video from the camera and actually see it - in some cases it has helped identify lighting issues that could never have been observed any other way. Incidentally, proper lighting is absolutely crucial for getting good results with the CMUCam 2+.

Instead of directly controlling the robot through bluetooth as was once done, now the robot is controlled indirectly through bluetooth to the CMUCam 2+ and eventually to the ABB. By sending servo settings for servo 2 on the CMUCam2+, it is possible to instruct the ABB. The ABB just polls the servo 2 output from the CMUCam 2+ for instruction. Of course the robot can also be controlled directly by wireless PS2 controller. However, the intent of controlling the robot through the servo 2 output is to allow the CMUCam 2+ GUI to make decisions for the robot based upon video processing feedback.

At first, an attempt to port the Java GUI to VB.Net was tried and failed. It didn't fail miserably, and it actually worked somewhat, but the serial port event handling in VB.Net seemed quirky and unreliable so I gave up on it. In some cases, an event would trigger when only a single character was in the buffer while in other cases an event would trigger only one time when there were multiple messages received. Apparently, carriage return (chr 13) does not necessarily indicate the end of a message even if every attempt is made to assure that it should.

I wanted the program to be in VB.Net simply because the GUI editing in VB.Net is far easier than it is in Java. After one too many frustrations with serial port control and VB.Net, I gave up and just started editing the Java program instead. However, trying to add any GUI object to an existing Java program can be a crapshoot if your Java is as rusty as mine. So, I decided to simplify the existing Java GUI for my benefit by converting it to a Netbeans (http://www.netbeans.org/) based program.

As I understand the Java community, and I'm no Java pro but more of a Java hack, Netbeans is loved or hated with no in between. Netbeans is a GUI answer for the difficult to use GUI functions of Java. Although there are GUI assistants available for other IDE's, such as Eclipse, I've come to prefer the GUI development in Netbeans. It may have something to do with the fact that I used to use Netbeans long ago when it was the only IDE with GUI support.

Unfortunately, to use the GUI assistant in Netbeans I had to first redo the CMUCam GUI program using the Netbeans GUI assistant - I couldn't just convert the existing program to use the GUI assistant. This went fairly smoothly, but the more that I used Netbeans the more it annoyed me because it seems to snag and just stop every so often, even with the autosave turned off.

I eventually got the CMUCam GUI converted to Netbeans anyway and found it very easy to add robot control to the GUI for sending the robot in a compass direction, and added functions for controlling the robot just as I was able to with the first generation control program that I wrote. I even added the ability to load an area layout, place the robot in a room of the layout, place the robot goal, and have the robot automatically navigate to the goal. Screenshots of the modified Java GUI and program explanations will be posted later.