Tag Archives: Quadrature Decoder

BalanceBot – Quadrature Decoders

I’m old school when it comes to prototyping. I tend to test bits of the initial circuit on a breadboard, but quickly move to a prototype board using wire wrap. I’m a big fan of wire wrap prototyping over breadboard. It has lots of benefits;

The wires in Breadboards have a tendency to fall out if moved or quickly become a birds nest if the circuit is complicated.

Breadboards don’t stack neatly like shields, so they are difficult to mount in the chassis.

I knew my Robot was going to fall over a lot initially, so I wanted something sturdy that could take some knocks, without falling part, but could be changed easily if I got something wrong (you always get something wrong)

I found some great prototyping boards from FreeTronics.com (ProtoShield Pro for Arduino). These have a reset button, a general purpose button and general purpose LED mounted around the edge of a grid of holes. This is great for prototyping. The boards are well designed with easy access to power rails and they’re cheap.

I buy long pin through hole sockets for wire wrap and solder just two legs of the socket (at diagonal corners) on to the prototype board, just to hold the socket in place. You then use special thin wire wrap wire and a tool that twists the wire on to the pin, to wire your circuit. There’s no soldering to wire the circuit (just a dab to hold the socket on to the board) the friction of the wire wrapped around the pins holds it tight. You can cut the wire to roughly the right length for each connection, so the board stays tidy and does not resemble a birds nest.

Quadrature Counter Shield

Quadrature Counter Shield

If you make a mistake, you can use the tool to unwrap the wire and you just replace it with the correct connection. Once the circuit is complete, the board plugs in as a normal shield, and it’s robust enough not to fall apart in use.

The LS7366 Quadrature Decoders are chips made by LSI. There is a decoder IC for the quadrature encoder on each motor. The ICs have a 32 bit counter, so they can count about 4,294 million pulses before rolling over. They have an SPI interface so it’s just 5 wires to connect them both to the Arduino (three common SPI data lines and two slave select lines). The SPI interface uses common data and clock lines from every device (slave) to communicate to the Arduino (master). The master controls who can talk on the data lines, through a unique Slave Select (SS) line connected to each device. When the slave select line is held low that device talks to the master. When the slave select line is high, the slave ignores the data lines and puts the pins in a “high Z” state, i.e. they are isolated from other signals or devices connected to the common data lines.

  • MISO – Master In Slave Out (data from the chip to the Arduino)
  • MOSI – Master Out Slave In (data from the Arduino to the chip)
  • SCK – Clock

These three lines are all connected in parallel.

  • SS – Slave Select is unique to each slave and is connected back to a separate pin on the Arduino.

In this case, I used Arduino pins 3 & 5 for the two quadrature decoder slave select lines (one for each motor). The SPI data and clock pins are pins 11, 12 & 13 on the Arduino.

LS7366 Quadrature decoder shield schematic

LS7366 Quadrature decoder shield schematic

I had a few issues with the wire wrap prototype, misreading my own initial circuit diagram, but I soon got it working.

The code is simple, but understanding the data sheet took some time. To setup SPI on the Arduino, you have to set three parameters, the Mode, the Bit Order and the Clock Frequency. They are all defined in the data sheet for your device.

The mode sets the phase of the signals for valid data, i.e. does the device response on rising or trailing edges of the clock. Wikipedia has a very useful entry on SPI : http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

The Bit Order defines whether binary numbers are sent down the serial interface most significant bit first, or least significant bit first.

The Clock Frequency in the Arduino library is a multiple of the system clock. The maximum clock rate your device can handle will be in the data sheet. Then it’s just some simple maths to work out what multiple of the Arduino 16MHz clock you need to not exceed the maximum clock rate for your device. In this case I’m using “divide by 8” i.e. 2 MHz

There is an SPI library in the Arduino, which makes all this easy.


To send data to and from the device you call the “Transfer” function while holding the correct Slave Select line low :

SPI.transfer(byte val);

This sends a byte (8 bits) out of the SPI bus. You’ll notice all SPI communications are 8 bits. Our counter is 32 bits, so I wrote some helper functions to read the 4 byte counter values. You just need to read the multiple bytes sequentially.

Here’s the helper function that reads the 32 bit counter values, which takes the slave select line as a parameter, so I can use it for either quadrature counter. It sends the read command and then reads 4 bytes in sequence, building them in to a 32 bit unsigned long.

#define  RD_CNTR B01100000
unsigned long ReadCounter(byte CSx)
  unsigned long result;
  byte b;
  SPI.transfer(RD_CNTR);        // Read CNTR
  result = 0;
  b = SPI.transfer(0x00);
  result = result | b;
  result = result << 8;
  b = SPI.transfer(0x00);
  result = result | b;
  result = result << 8;
  b = SPI.transfer(0x00);
  result = result | b;
  result = result << 8;
  b = SPI.transfer(0x00);
  result = result | b;
  return result;

I don’t actually need the quadrature counters in phase one of the project to get the BalanceBot balancing. It will balance without them. However, it will probably drift from its original position as its balancing. The plan is to count the quadrature pulses as it drifts and then bring it back to its original position once it’s stable. This should mean if the robot gets knocked, it will move back to rebalance, and then slowly come back to where it was, maintaining its position.

Quadrature Counter Shield

Quadrature Counter Shield

Once I got the wire wrap version working, I converted the board to a custom PCB using Eagle PCB software and BatchPCB. More on that later…