Sunday, December 5, 2010

Quadrature Encoder

One of the essential things an autonomous rover must have (which mine didn't had) is one or more quadrature encoders. In fact even some non-autonomous vehicles have these devices. Most regular cars these days feature this type of sensor as part of the ABS system (see Very reliable and high-resolution sensors can be found in these (featuring 90 steps or more).

For this autonomous rover I found that 16 steps would be the bare minimum, and easy to implement with common components.

As I didn't want to modify the RC car itself (drill holes, cut parts, etc), I looked for a solution that would minimize the impact on the car. As such I found that a good option would be to use the inner ring of the wheel as a surface for sticking an encoder band. This band has 16 steps, and looks like this:

Once glued to the wheel we had this:

On the other hand putting the sensors (two IR emmiter/sensor combos are necessary) would not be an easy task as well. As I have chosen the CNY70 (these are approximately 8 mm cubes), room for
the entire thing would be limited. Anyway I managed to fit the two sensors in one of the suspension ball link support holes. The result was this:

Another view with the wheel fitted in:

With a bit of effort, I managed to place the two sensors on a small PCB, and carefully aligned these with the encoder band and ensuring that a 90 degree displacement would be obtained (this is fundamental for proper detection).

There was obviously no room for more components or even for a conector to the main board. As such
I soldered thin wires from the sensor board to the analog interface board, which is the following:

The quadrature decoding board was mounted on the main fixture like most other electronics.

The role of this board is to receive the analog signal from the sensors, run it through an LM358 setup as a level comparator, clean the resulting square waves from impurities by passing it through a schmitt-trigger gate, and finally provide the signals to the decoding logic, taken care by an Atmel Attiny45. The contained firmware results from the work of Adriaan Swanepoel, which can be found here: This microcontroller counts the pulses from the encoder, and allows the count to be obtained through I2C, via its slave interface. This is a very handy solution, as it offloads any of the other computational modules of the robot from the quadrature decoding. The main logic only has to poll the count on a regular basis, and perform whatever calculations are necessary with the data (speed, odometry, etc).

A hand made schematic diagram describes the solution:

Like with any non-trivial design before the veroboard version of the hardware, I put together the entire circuit on breadboard, and tested against the remaining hardware (autonomous vehicle):

A few aspects are worth mentioning: First I had no trouble building the FW project with AVR Studio 4. To program the Attiny45 I used the simplest possible programmer:

To build it you just have to link the following pins:

Parallel Port Attiny45
1 (/STROBE) 7 (SCK)
2 (D0) 5 (MOSI)
3 (D1) 8 (VCC)
11 (BUSY) 6 (MISO)
16 (/INIT) 1 (RESET)
18 (GND) 4 (GND)

It is recommended to put a 1 KOhm resistor between the MOSI (Pin 5) and PPort pin 2, and another 1 KOhm resistor between SCK (Pin 7) and PPort pin 1. This will offer a certain degree of protection to both devices.

To actually flash the device I used "avrdude" under linux. It's a nifty little piece of software that allows programming with just about any type of hardware.

At first I could not communicate at all with the Attiny45. Using the I2C master routines from the PIC, I tried to issue the appropriate commands to the expected default address (0x3E). After googlig a bit and reading some forums, I found that certain I2C slaves expect the address shifted left by 1 bit. I tried this, and by analysing the SCL and SDA lines on the oscilloscope, I found that the device would react. Write commands such as reset (0x01) would apparently be successful. But the read command would fail most of the times. Without having deep knowledge about AVR architecture I started to consider all possible options. By looking at the fuse settings I found that the Attiny45 was running at 1 MHz:

avrdude: safemode: lfuse reads as 62
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as FF

Among other things lfuse maintains the clock divider bit (CKDIV8).This divides the 8 MHz clock by 8, slowing the device down to the speed I verified.

Well, given the fact that my I2C master was clocking out at 100 KHz, it was clear that a 1 MHz clock was not going to be enough to support a bit banging I2C slave device. Without hesitation I
put the device in the programmer and changed the fuse setting:

$ avrdude -v -p t45 -c dapa -P /dev/parport0 -U lfuse:w:0xE2:m

Put the Attiny45 back in the circuit and..Eureka! It was working flawlessly. Signals on the oscilloscope also looked more solid, without gaps in the clocks and responses.

After a few tests it was time to assemble everything in veroboard and add to the car. Final tests revealed the encoder to be pretty accurate, with Fonera software calibrated for measuring speed and distance in metric units. A very happy ending.

No comments: