Search This Blog

Thursday, March 31, 2011

Forward with the Mouse and Bootloader

Java Bootloader
  I took quite a break from microcontrollers towards the end of winter.  I ended up working on a translator, using Antlr.  I ended up shelving it for now, but I learned quite a lot.  For instance, I am pretty good at parsing, but I am an horrible lexer!  Also, 4th generation languages based on Cobol are not a good place to start for language compilers/translators.  Moving on...

   I picked up the robotics itch again last weekend.  I completed the first version of my Java bootloader for the Pic 18F2455.  It looks pretty good.  Remember, the 18F series erases in aligned-only 64 byte blocks and writes in aligned-only 32 byte blocks.  For one thing, that means I have to waste 64 bytes of space at the end of the program space for the insertion of the user's first 8 bytes.

   I do this because I want the user code to be virtually ignorant of the presence of the bootloader.  They need to know ( and will be reminded by the bootloader if they goof ) that the last ~192 bytes are reserved by the bootloader.  I want the loader to be small and efficient.  I know it will not be very fast.  The erase procedure I insist on will always erase the entire program space but for the bootloader area.  My experience with the smaller 16F chips tells me that this will be slow ( but safe ).  I'll take it.

   Now, the asm  compiler creates lines in the hex file of arbitrary length and starting address.  The Pic wants to write blocks in 32 bit aligned blocks.  The Java code creates a Program Object that has a list of "Chunks."  Each chunk holds an array of 32 bytes.  The code has an HexFileParser that pulls out each line, determines if it is a data line, and the starting address.  It asks the program to place the line into the correct Chunks.  The program looks up the correct Chunk for each address and asks the Chunk to record the data byte String representation as a byte in its array.  Simple.  The Program can retrieve a List of all the Chunks that have real data to send to the Pic.

   Now the wrinkles.  First, we have to start the erase and write blocks at instruction zero.  This means it will overwrite the bootloader's instructions that send the program counter to the loader on reset.  So, I generated a test file and looked at the hex.  I have the Parser put the bootloaders first few instruction in the first 8 bytes of Chunk zero.  The Parser and Program do not allow the user's first eight bytes in this space.  Instead, they are diverted to a special Chunk called the RewriteChunk.  This has a calculated address at the end of the bootloader, 64 bytes before the end of the program space on the chip.  This Chunk is returned with the other writeable Chunks.

   Then it was a simple matter of creating a start sequence dialog with the chip and a write sequence for the bytes.  I hope to see if it works, soon.  All the JUnit test for parsing run fine.  I just don't know how the serial communication with the Pic will go.

Robot Design
   Saw a great preliminary design by Patrick McCabe on LMR for a line following type mousebot.  Two things I really liked about his approach.  He cut out his chassis from 2 pieces of acrylic.  His chips are little, single function modules.  I decided to blatantly steal both ideas.  I have zero experience working in plastic.  I bought a very thin sheet from the Domed Hippo ( Home Depot).  I'm hoping the ol' Dremel can get through it with good results.  I took a set of Radio Shack proto boards and sliced them up.  One is a regulator to take 6V and make it an evened 5V.  The next is for the dual H-Bridge motor driver.  That board was tough!  The pin out challenges you to get the breakout pins where you need them without making a mess.  The next board is for the microcontroller.  I like the idea of this board.  It is simple a breakout of the controller, with pins for input 5V and output of 5V and all the I/O.  And it has three pins to put in a resonator.  This way, I can swap out any resonator I like.  I plan to start with a 20 MHz one.  With this chip, I can replace it with a 4 MHz clock.  The cool thing is, with PLL, the chip turns this into 96 MHz!  The chip can run at 48 MHz with this.

   I haven't even designed anything around the mouse's sensors yet.  The current board will have a cut-out on the top layer for a servo body to hang down.  I'll put a Sharp IR array on that for the first build.  I want to work on continuous PID with PWM motor driving.  Once that works, I'll change the sensors to a line follower.  When that works, I'll start working on the mouse's sensors.  I want to get some rotary encoders, too.  I need odometery for this to even look like a real micromouse.

Rough sketch:

Mini Boards:


   That's all for now.  Better pics to come.

Sunday, February 13, 2011

Bootloader -- Again

    Quick recap of what's been going on.  Ordered a bunch of new stuff from Sparkfun with the fabulous gift certificate from my in-laws.  Yes, I am one of the few lucky ones who has outstanding in-laws.  One of the little gems I ordered was a Pic 18F2455.  This is a whole new ballgame in my world of microcontrollers.  I'll go on a rant about it later( like very little bank switching!!!! ya-hoo! ).  The big game changer for me is that my bootloader will not port easily.  I was going to just add on to my existing Python bootloader, but I decided to inflict some more pain on myself.  I decided I would bite the bullet and do it in Java.
  
    Ok. What could be so hard about that?  First, start with the fact that the standard Java SDK has no support for serial communication.  Luckily ( now that serial ports can't be found on computers ), they have added a serial and parallel library that actually works ( and is now, as of version 3.0, pretty portable ).  The javax.comm package was pretty straightforward to install.  I downloaded the version 3.0 package for linux.  I put the 2 .so libs in /usr/lib and made them executable with chmod a+x.  I put the comm.jar into my java libs dir along with the javax.comm.properties file.  I also installed it in my maven repo.  In my Eclipse project, I added the comm dependency to maven and put a copy of prop file in src/main/resources.  When I make the final jar executable, I'll add the comm.jar and prop file in the classpath in the Manifest.

    Now to solve the problem of doing this on my laptop with no serial ports.  I got a serial-USB converter and got it working with Python.  To do that, I had to set the sticky bit on my /usr/bin/python2.6 executable.  I've never been happy with that idea.  The other night, I started developing apps for Android on my HTC Evo.  To get that working, I had to learn about udev in Linux.  I got my phone connected and gave my user, tom, permissions with this udev rule in /etc/udev/rules.d/51-android.rules:

SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"
SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", OWNER="tom" GROUP="users"

For the USB-serial conveter, I created a rule for /etc/udev/rules.d/51-rs232.rules:
KERNEL=="ttyUSB*", ATTRS{idVendor}=="067b", MODE:="0666", SYMLINK+="ttyPIC"
KERNEL=="ttyUSB*", ATTRS{idVendor}=="067b", OWNER:="tom" GROUP:="users"

Now, any time I plug in the converter, no matter what ttyUSB name it gets, a symlink is created for ttyPIC and tom is given read and write permission to it.  Sweet.

    I tested all of this with my version of a null cable feeding back on itself.  I tried with old Python code and a test Java file.  All works.  On to the next hurdle.

    Java developers rarely have to think about lowly, menial tasks like byte operations.  In this case, it is the mainstay of the program.  The bootloader has to do a lot of conversion of hex represented strings ( sometimes doubled ) to integers.  It then needs to convert them to bytes for transmission over the serial line.  Enter the problems.  Java only offers a signed byte ( -128 to +127 ).  The end binary result is okay, but trying to print stuff for debug can be a real picnic.  I ended up with a lot of routines like this:

        /*
*  take a string representation of a data line from an Intel hex file
*  and convert it.  First, we get each byte( 2 characters from the string ).
*  Then we convert those from hex strings to integers and cast as a byte.
*/
public byte[] makePacket( String data )
{
// first, take 2 chars at a time and make bytes
System.out.println( "Start with: " + data );
int length = data.length()/2;
byte[] bites = new byte[length];
int counter = 0;
for(int i=0; i
String val = data.substring(i,i+2);
byte dataByte = (byte) (0x000000FF & (Integer.parseInt( val, 16 ) ) );
bites[counter++] = dataByte;
}
return bites;
}

    I worked out a lot of the basics tonight.  The next little challenge is the fact that the 18F2455 reads in single bytes, writes in blocks of aligned 32 bytes and erases in aligned blocks of 64.  Unfortunately, the gpasm compiler gives line of randomly long bytes ( up to 127 potentially ) and the addresses can start at any position.  Also, I now need to be aware of data type 04 lines.  These set the upper byte of the program counter address.  I'll write more about this next.  That's all for now.
    

Monday, January 31, 2011

Roadmap to Mouse

Just a quick post to set my goals going forward.  Ordered and received my latest set of parts.  Got 2 18F2455 Pics.  Gpsim doesn't fully support them yet.  That will make starting out with them tough.  In the meantime, I played around with PWM operation of motors with the 16F876a.  Got A/D reads working with the phototransistors.

My next goal is to create a wall following robot with the 16F876a, using one Sharp IR sensor and PID control of the motors with PWM.  Really, it will only be PD control.  I won't need the Integral component for flat surfaces.

Once I get that working, I'll move on to a line follower.  I'll use the 16F876a and 5 IR sensors.  I'm thinking I'll use all 5 A/D pins.  I don't want to try receiving all 5 on the same A/D pin and lighting up each IR LED in turn.  Michah Carrick seems to have made this work, but it seems too likely to create interference.  I'll take a read of one phototransistor dark and then light up all five IR LEDs and take a read.  Then jump to the next phototransistor.

If all goes well, I'll start the first prototype of the mouse.  I am still thinking of using 3 Sharp sensors for alignment.  I'd really like to get a compass module and use that for alignment as well.  Maybe someday.

The biggest question right now is what to use for the base of the robot.  I'd like to get some Sintra or other plastic to work with.  I'm not overly confident in my craftsmanship with plastics though.

Got some Pololu micrometal gear motors with 30:1 ratio and some 42mm diam. wheels.  440 RPMs at 6V.  Should be close to 1m/sec with no load.  What blew me away was how small the motor and gear were!  Take a look:

Wednesday, January 5, 2011

Maze Solver 1.2

    I made some changes to the maze solving simulator.  I found a maze from 2004 that the old one could not solve.  I tried to avoid the code, succeed, test, fail, code some more routine and come up with a new strategy.  This time, I turned off the explore counter.  The mouse is either exploring or speed running.  Each solve and return is either an explore run or a speed run. The speed run terminates the program with it gets back to the start.

Here is the latest simulator
Here is the new maze, maze 4

    Oh, I changed the text display, too.  The maze is now in red with white values.  The mouse is '800' in blue.  There is a variable called colors.  If you set it to false, it prints everything in monochrome.  I found this useful for step debugging in Pydev Eclipse.

Here is a screenshot of the mouse having explored, solved, and back solved once:


Here, you can see the most of the lower half is left unexplored.  A speed solve at this point will take a lot of side trips!  Let's explore some more:


That's better.  Now we have 217 cells of the maze explored.  Now we could do a reliable speed run.

    I'm thinking my mouse will capture the number of explored cells.  When it gets back to the start after an explore round, it will output the number of known cells on an LCD.  The operator ( me ) can elect to do another explore solve or a speed run by pressing a "speed run" button. This button could toggle between speed and explore modes.  The LCD should also display this value.  I'll want another button to vary the speed as I amp up to the best speed/time.  Perhaps the speed level should also be displayed...  We shall see.

Tuesday, December 21, 2010

Maze Solver With Explore - 3 for 3!

Ok, newest maze solver simulator.  I added an exploring routing that does up to 256 cells of exploring before using lowest value routines to get to its current target.  If the mouse explores on the way to the target and back for maze2, it uncovers enough of the maze to solve it well on the speed run.  It is still possible for the mouse to get stuck in a sequence of cells that are adjacent to accessible, unexplored cells when it is not in explore mode.  I need to look into a "back track" routine that will handle this.  In the meantime, here is the updated simulator:
Maze Sim With Explore
Maze File 2

I need to develop a "speed run" routine that doesn't flood, explore, etc.  On press of a button, it would compute a single, shortest know cell path to the target and put that in a queue.  It would then pull off turns from the queue ( only straight, right, and left ) to direct it to the target.

Sunday, December 19, 2010

Maze Solver - Not So Great...

    Ok, so I solved one maze from 1993.  It was a maze from a competition known to make hard mazes.  I created another maze from a 2004 competition.  It solved the maze.  It back solved by a different route.  It did its speed run on a totally new route and got stuck.  I'm just starting to work this out.  Here is the maze if you want to try it out:
Example Maze 2
  
    On the other hand, it does solve this maze from 2002 that I recreated.  It looks like I run into problems on two fronts.  First, if the first run and back solve don't reveal enough of the maze.  Second, if a run hits an unexplored region and the only open spaces available have cell values greater than the current cell.  I need to solve the "stuck" problem for sure.  I will also want to add more "exploration" to the back solve phase.

   Here is the other maze I was able to solve successfully ( if not optimally; I haven't checked ):
Example Maze 3

More Maze Simulation

    Okay, I made a slew of changes to the maze/mouse simulator.  The key to backsolving the maze from goal to start is to reflood the maze, using the start as the target.  I modified the flood method to take a target flag ( start or goal ) and a starting queue list ( either the start index or the goal indices ).  The program moves the mouse to the goal.  It then lets you back solve to the start.  It then lets you do a "speed run", solving the maze with all the wall data it collected in the initial solve and backsolve.  It was cool to see the mouse find a better back route than the initial solve route.  Along the way, it tried a few unexplored areas.  This led to the optimal 91 step route.
    I changed the display code, too.  The mouse is marked by the number 800.  I have code in there to make the mouse marker red, using ascii escape codes.  I commented these out, so everyone can run it ( and so it will display ok in the Eclipse console ).  Uncomment them if you like.  The maze file is unchanged.  I put it here, so no one has to go hunt for it.  Here is the new code:
Full Mouse Maze Simulator
Sample Maze File

    Oh, I didn't even think about this.  Windows users may have trouble seeing this maze file cleanly.  There are no carriage returns.  Don't let your editor add them.  It may cause problems when loading the maze.  I can't remember if I allowed for this or not.

New shots:
First Solve - Note the value at start cell

Back Solve Initial Flood Results

End Back Solve - Note New Values/Better Path

Speed Run - Note Better Path