The Zumo 32U4 main board uses XOR gates to combine both channels of each encoder so that one interrupt is used instead of two. (For more information, see the Zumo 32U4 schematic diagram and the “Quadrature encoder” section of the Zumo 32U4 Robot User’s Guide. Both resources can be found under the “Resources” tab on any of the Zumo 32U4 product pages.) You could use the Zumo 32U4 encoder library (Zumo32U4Encoders) to read the encoder signals from the A-Star 32U4 SV Robot Controller, but you will need to add an XOR gate between pins 8 and 4 and pins 7 and 5.

In light of your response, the Zumo user guide is indeed very clear. However, as a complete beginner in electronics adding XOR gates looks a bit out of reach (probably need a special chip to do so???)

Instead of adding an XOR gate, I will look into using digital pins 15 and 16 (PCINT1 & PCINT2) as interrupts for pin B of the two encoders. I read a few very useful references on external interrupts and pin change interrupts (http://playground.arduino.cc/Main/PinChangeInterrupt & http://gammon.com.au/interrupts for instance). These indicate which PCINT vector corresponds to different ranges of pins as well as the corresponding PCMSK / PCIF / PCIE values as per table below. The issue is that these lists do not include digital pins 15 and 16 so I don’t know which PCINT_vect and PCMSK / PCIF / PCIE values to use. Is there somewhere I could look to find about those for digital pins 15 & 16?

Another issue I am facing is that while testing my encoders and code for handling interrupts, I noticed that pin B of one of my two encoders stays high permanently. Inverting the cables between the two motors/encoders allowed me to confirm that the problem is in the encoder itself. I checked the welds of the headers and they are clean so I could not locate any source of possible short to VCC. It seems I will have to replace this encoder with a new one.

Without a functional pin B, I can still count all changes on pin A. At 6 counts per motor rotations, one count equals to 0.5 degree rotation of the Romi wheels which is still quite accurate. Since without pin B I cannot determine the direction of rotation, I use the motor direction commands to infer the direction of rotation and change the sign of the delta counts between polls. This is not ideal but it will do the job until I get a new encoder.

Still a lot to do but considering where I start just a few days ago, I consider I made good progress!

In light of your response, the Zumo user guide is indeed very clear. However, as a complete beginner in electronics adding XOR gates looks a bit out of reach (probably need a special chip to do so???)

Yes, you would need to add an XOR chip like this one from Digi-Key to your setup, but it should not be too difficult to integrate that part. You can look at that chip’s datasheet (which is linked on that page) for details on how to connect the two output channels of each encoder to the chip and the respective XOR gate outputs to the interrupt pins (pins 7 and 8) on the A-Star 32U4 SV Robot Controller.

Is there somewhere I could look to find about those for digital pins 15 & 16?

Since you are planning to use two interrupts for each encoder, it would be easier to use a different encoder library (like this encoder library) instead of the Zumo 32U4 encoder library, which would require you to make modifications to the code.

I found what I was looking for in the ATmega31U4 datasheet. I finally went ahead making my own simple encoders library. As with the Zumo encoder library, I am using the Pololu FastGPIO library for performance. Everything works fine and I am now working on a python Odometer class to run on the Raspberry Pi using the encoder data received from the A Star microcontroller.

I finally got my encoders with both pins A & B working properly. I ended up using pins 8 & 16 (PCINT4 & PCINT2) for the left encoders A & B pins and pins 7 and 0 (INT6 & INT2) for the right encoder A & B pins. Setup code below (may be useful to someone else.)

The encoderLeftCount and encoderRightCount variables are transferred to the Raspberry Pi via the slave buffer in the main loop. I also have a boolean in the buffer that the Pi can write True to reset the encoder count variables.

I’m quite satisfied with the progress so far and I will post an update in the “share your project” section shortly.

I still have a small issue with the encoders where I noticed that when I increase the frequency at which I read the I2C struct data from the Raspberry Pi (say from 20/s to 50/s), I seem to be loosing some counts, i.e. the robot moves faster for the same speed command (the motor speeds are regulated with PID controllers using feedback from the encoders) and farther for the same number of counts.

I believe it has to do with the fact that, to avoid overflow of the encoders count variables on the A-Star, I reset these values every time the python code on the Raspberry Pi reads the encoder counts from the I2C struct data.

I plan on trying a few things to identify the cause of the issue:
1 - Remove the encoder reset (not a solution but can help to see if this is the cause)
2 - Disable interrupts around the portion of the A-Star code were I write the encoder count variables to the slave buffer and where I reset the encoder counts.

Any other idea? Thanks!

Below is the method of my Encoders class that reads the encoders (python, Raspberry Pi end):

I agree that the inaccuracy you are seeing is probably caused by this resetting of the encoder counts you are doing. Any counts that happen between the call to read_encoders and the call to reset_encoders will be lost. When you tried to read data from the A-Star more frequently, the percentage of time that your program spends between those two calls went up, so you ended up discarding more encoder counts.

The way I like to do it is to not reset the encoder counts on the A-Star and instead just let them overflow. If you want your Python program to have encoder count variables that do not overflow, then you could record the last count you read from each encoder. When you read a new count, you would compare it to the last count to see whether the counts increased or decreased, accounting for overflow. Then you would add or subtract the appropriate number of counts from a variable in your Python program (which would be a normal Python integer that does not overflow). The code for one encoder might look something like:

I did not think I could just let the encoder counts on the A-Star overflow.

I am not very fluent with hexadecimal numbers so it took me a moment to figure out your code example but it is very clear now. I’ll try it shortly.

Your response is very helpful and instructive at the same time. And I am starting to learn the power and simplicity of the modulo operator. I see it could simplify some of my odometer functions dealing with angles that loop from 359 to 0 degrees.

Would you also recommend disabling interrupts with cli() and sei() around the A-Start code lines reading the count variables? I noticed the Zumo encoders library does this.

Finally, as a curiosity, what are typical loop frequencies used for robots with encoders like the Zumo? Faster is better for responsiveness to inputs and movement accuracy but on the other hand if the number of counts per time step becomes too small, this can create scatter in speed and derivative calculations used by the PID controlling the motors. So far I was running my vision based line following at around 20-30 fps to match the rate at which I could capture and process frames from the camera but am considering accelerating it for other usages.

Would you also recommend disabling interrupts with cli() and sei() around the A-Star code lines reading the count variables?

Yes. The encoder count variables used by the ISRs have two bytes (they are 16-bit), but the AVR can only read one byte at a time from RAM. If you don’t disable interrupts, it is possible that you would get an invalid value for one of those variables because the interrupt could modify it after you read the first byte and before you read the second byte.

Finally, as a curiosity, what are typical loop frequencies used for robots with encoders like the Zumo?

I do not have any specific numbers to give you. You might consider reading about the robots we had at our last dead reckoning competition to see how they worked.