Older blog entries for marcin (starting at number 12)

Hi everyone.

I've had a few days where I've either done nothing on the robot, or just watched it drive around the house (mostly) avoiding walls and furniture, but usually getting snagged on the rug (the robot has some clearance issues). I'm now in the 24-hour battery recharge cycle.

An interesting observation I've come away with, that will be analysed more thoroughly over the weekend, is the spotty performance of the SRF04 in 'hard' environments. By hard I don't mean outdoors, rough terrain. I mean in my passageway. My house is about 80 years old, with thick plaster covered walls, fairly tall, glossy, wooden skirting board, and polished wood floors. When the robot approaches the wall from an angle of 30deg or more away from the normal, it doesn't get a good range reading at all - it's like the wall isn't there. Then, all of a sudden it will get reflections when it is very close and execute the emergency reverse, then almost instantly get back to the invisible zone. It doesn't do this in my bedroom.

In general though, I like the SRF04 - I think it's very accurate - within 1 cm in the ranges of interest to me - and using the driver is a snap.

I'm going to integrate the Sharp IR ranger next .. hopefully that won't take 3 weeks!

Have a good w/e.

Cheers, Marcin.

I drew up an arbitration/subsumption architecture, on the train home, and then coded it tonight - so far is seems to work. I think it is more arbitration than subsumption though. The way it works is a bit of a publish and subscribe metaphor - in that each sensor has a supply vector, identifying what inputs it reports on (oublish: for example, the SRF reports range - theoretically, a sensor could report two or more measures), and it passes this supply vector to the arbiter () function during the ISR. The arbiter has a set of demand vectors that are associated with each action/behaviour (subscribe: for example, the avoid behaviour has a demand vector of range, but the general case would be that an action demands more than one input.)

So if the (supply_vector && demand_vector) == true, then the action is interested in the change in the environment reported by that sensor, and it gets called. If the action takes control of any outputs (eg motors, leds, etc) then it sets the corresponding bit in the output vector - but it first checks whether that output is available.

Then arbiter calls the next action on the list that is interested, etc. It sounds a bit convoluted, perhaps, but I'll type it up and put it on my new site once I've had some more time to tinker with it. But the nice thing about this is that the actions/behaviours can be programmed in isolation from each other.

This works with 3 behaviours (retreat, avoid, and roam), one sensor (the SRF04), and one output (the motors). We'll see how it scales in the coming weeks. I think that the arbiter my have to become a timed action queue manager once the number of inputs and outputs and behaviours increases.

Cheers for now, Marcin.

14 Aug 2005 (updated 14 Aug 2005 at 23:38 UTC) »

It's amazing how simple it was to use the SRF04 in my code, once the driver was working... I wrote some simple state machine based test code using the SRF04 for sensing... if range < 200mm or so, then reverse, if 200 < range < 400, then turn left, else drive forward. It has a bit of hysteresis to avoid getting trapped.

It works pretty much as expected - there are some deficiencies eg due to the beamwidth of the SRF04 not being wide enough close in for the width of the robot. The funniest one, though, is that the robot does a bit of a back-forward-back-forward-... shudder sometimes at close ranges, although it does normally work it out eventually.

The robot now has a new name - scaredyBOT - coined by my daughter because the robot was afraid of (backed up from) her teddy bear when she put it in front of the robot.

I feel so much happier now that I'm again moving forward, not backwards, upwards not forwards, and forever twirling...

I've got a highish-res movie of the robot being turned on with the sensor for the second time (about 2 minutes after the first time), but at 18MB, it's a bit too big to post at this stage, not to mention a bit boring for everyone except me.

Tonight's work will be that software subsumption/arbitration architecture I wrote about previously. We'll see how that goes.

Cheers, Marcin.

Finally, the SRF04 is now interfaced and working with my Renesas M16C SKP. As previously stated, I ended up needing to use one of the INT (interrupt) pins, along with one timer, and one GPIO. I really didn't want to use up that INT pin, hoping instead to use if for other things like kill switches,etc, but maybe losing one is ok. I think my previous design, that used one timer (including it's I/O pin) in both timer mode and pulse width measurement mode, was more elegant, and I may revisit it in the future. In the end, doing it this way turned out to be a bit simpler. I need to remember to learn to walk first...

I still have one issue with the state machine not behaving exactly as expected but it is of little importance as the additional state was really there for completeness and is not really currently required.

So, I now have a totally interrupt driven SRF04 interface - all you need to do is call srf_trigger(), and at some later stage call get_srf_reading_mm(). It's non-blocking, and pretty flexible.

Now to integrate it with the robot.

Cheers, Marcin

11 Aug 2005 (updated 11 Aug 2005 at 06:05 UTC) »

Interfacing the M16C SKP with the SRF04 is driving me crazy, and I don't know if it's the chip, the board, the sensor or me, although the odds are stacked pretty heavily against me as the single point of failure...

It turns out that pretty much all the B timers (except TB4, which I am using) have their external inputs used by the LCD, and the A timers can't be used in pulse width/period measurement mode!!!

I'm thinking of changing my code to use the INTx interrupt pins and 1 timer - it's not an elegant design, but maybe it is what is required.

Cheers, Marcin

My folks have gone on to see some other family in Perth, hence it's back to the mechatronic land of sleepless experimentation that we all love...

I've only done a little bit of work on the robot side of things in the last fortnight, but I have had some success. Firstly, I've figured out the (first) issue I've been having with my interrupt code - it turns out that it was that the compiler wasn't coding the isr as an isr but as a standard function.

From the M16C docs: By declaring the function as an interrupt handler, the compiled output ends in an "reit" (return from interrupt) instruction rather than the standard "rts" (return from subroutine). For hardware interrupts, use the declaration:

#pragma INTERRUPT function name.

When I was debugging the compiled code, I noticed that there was not REIT at the end of my srf_isr(). What actually needs to happen is that #pragma INTERRUPT directive needs to go in the same C file as the function it is referring to - I previously had it in main.c. Therefore, the ISR vector table quite happily invoked srf_isr() on the first timer interrupt, but then the thing crashed when trying to leave the isr for the first time.

I've also got rid of lots of debug code (LCD outputs), and now, for some reason, I can do sprintf(...) which previously didn't work. I really don't know why on that one.

Now my current problem lies with the fact that I dony appear to be getting any echo transitions back from the SRF04 - I seem to be getting a constant '1' back. I'm a bit concerned that the LCD output and control code actually interferes with my srf code. According to the SKP board schematic, the LCD only uses port 9_0 to 9_3 (4 lines) for data and port 6_0 and 6_1 for control. I use port 9_4 for ECHO_INPUT and 9_7 for TRIGGER_OUTPUT. So there shouldn't be a problem, but when I use the debugger on the supplied LCD code, it seems to change p9_5 occasionally - so I'm going to concentrate on that for a little while.

I've also been working on a new robot site.

Cheers, Marcin.

Haven't done much robot stuff this week, as I have family visting from overseas.

By not using a basic stamp, PIC or AVR, (I'm using a Renesas M16C) I realise that I'm actually making more work for myself as there isn't such a body of knowledge that can simply be plagarised from. For example, I'm trying to do this SRF04 interface for the M16C based on a single timer and a 5-state FSM. Basically, it should go:

state:      next state:      transition:      
INIT        READY            10ms timer IRQ
READY       TRIGGER          srf_trigger() function call
TRIGGER     TX               10us timer IRQ
TX          MEASURE          pulsewidth measure on falling 
                             edge on input or timer over/
MEASURE     READY            10ms timer IRQ

This is based on the expected behaviour shown at the srf04 main page. I'm finding it a bit difficult to get the thing to behave as expected.

Don't get me wrong though, I'm using the M16C starter kit plus (SKP) (it costs about $50 from memory and comes with a C compiler) and I really like it. The SKP board is fairly small (measures about 10x6 cm), has a 2x16 LCD, 3 buttons, 3 leds, and heaps of I/O (you attach the headers), and comes with a USB based programmer/debugger. The uC has 11 timers, 2 or 3 uarts, 3 or 4 INT pins, heaps of ADC. So it does have quite a bit going for it (not to mention about 16 or 32K RAM and a couple of hundred K flash. You can see the one I'm using here.

Cheers, Marcin. (marcincoles__at__yahoo.com)

29 Jul 2005 (updated 29 Jul 2005 at 06:57 UTC) »

Not too much excitement this week generated by success, as failure has certainly had the upper hand. I've started a resign of the electronic system by listing the peripherals that I'll want in a typical robot (not just the current one) and mapping that to the uC peripherals (timers, etc) that are available. For example, differential drive (independent PWM to each motor) will take 2xtimers(w/PWM) and three GPIO. Controlling the SRF04 currently looks like it needs 2 timers, etc. It's looking promising - contrary to a previous post, the M16C that I have has 11 timers, although the pins for these timers are shared with other peripherals (eg UART). So there is a bit there to be allocated, which is nice.

All that software subsumption architecture stuff is really application programming and more in my expertise, it's doing the device drivers that is making me insane. I'm trying to do the code for the SRF04 (pulse out, measure width of pulse coming back) and I can't get the thing to work - most of the control code is in interrupts, so it's a bit hard to debug, but from what I can see, the SRF state machine (INIT->READY->TRIGGER->TX- >MEASURE->READY) has some issues. Most notably, i check that the state is SRF_READY before doing the trigger, and the check is with a function call that simply returns 1 if the srf_state == SRF_READY. It never gets past that, even though I know that the interrupt that puts it into the ready state does fire. Very frustrating.

If anyone would like to teach me a lesson, and show me how it's done, you can find my code here . Help or hints would be appreciated.

Also, for some reason, I can't get sprintf to work in my code, which is really strange since I have previously used it in other projects. It compiles happily, but the runtime just does wierd things -> so that makes reporting the range of the SRF that much more difficult. (I use sprintf to generate the character string for display to the LCD).

Nothing worthwhile was every easy. I just have to keep telling myself that.

Have a good weekend. Marcin

So, it turns out the weekend wasn't productive at all - I was doing some tidying up and came across an old game (F1 Manager - circa 1996) which I propmptly whiled away all of Saturday and most of Sunday with.

That's not to say, though, that I didn't think robotic thoughts. I've come up with a four level behavioural hierarchy for my little robot. It sort of follows from what I've been reading regarding subsumption architecture, but also trying to make it a 'natural' behaviour model. I'm sure this model has been discredited by some people smarter than me in these things, but I haven't consulted the literature so I'm currently happily ignorant. And, having explained it to my wife, it seems plausible.

1. With the highest priority, we have direct device control - eg the ISR that controlls the operation of the rangefinder, the comms ports, etc. These have to be very much short and sweet ISRs. The analog for the real world to this level of the hierarchy is the involuntary muscle control we all do - eg breathing, hearing, etc. (Note that hearing is a basic function, understanding/listening is something totally different).

2. Next we have the 'self-preservation' reflexes - the ones that protect the robot. These are things like collision avoidance and recovery, low battery recovery, etc. The real world equivalents are pretty easy to imagine - I, personally, find it very difficult to walk into a wall on purpose.

4. I put this here (ie before 3) because it just makes sense in an explanation. The lowest priority is the default behaviour(s) of the robot. This may be simply to do nothing, follow the sun, hide in corners, or it could be to just roam. Think of a dog when it's left by itself.

3. Next is the level of task oriented activity - these are the high level tasks that are the reason for the robot being turned on. The sort of activities at this level are things like search and retrieve, map, navigate, etc. This is analogous to a sheep dog getting told to rustle up some sheep.

I think that 1,2 and 4 are fairly easily implemented in code because they can just be linear combinations of simple state machines. Level 1 is device drivers, level 2 is reactive code (ie if dist < threshold, do collision avoidance) and level 4 can be either random or fairly simple. If the robot has a sufficiently interesting level 4 behaviour (eg roam or follow motion) then it will be pretty cool without even having any level 3 actions programmed.

Cheers, Marcin (marcincoles__at__yahoo.com)

After getting all excited about the possibilities of software subsumption, I have made a very basic simulator using Borland C++ Builder (ie for windows) V1. You can find it on my geocities site under the news section.

While I wasn't able to achieve everything as easily as I hoped, I think there is heaps of potential here, without necessarily totally exhausting my ability to comprehend what's going on. The hardest part can be the arbiter on the outputs - currently it is a winner takes all arbiter - if a more cooperative approach to resources is desired. So now I'm going to try to stick this into my robot on the weekend - this will be a bit of a challenge since I still have to write the driver for the IR ranger and rewrite the motor control code, but it's all getting pretty exciting now, so I guess I'll just have to forgo sleep.

Cheers, Marcin

3 older entries...

Share this page