Guzunty / Pi

This repository contains resources to support the Guzunty Pi IO expansion board
110 stars 32 forks source link

[New core request] Rotary shaft encoder #20

Open fschioler opened 10 years ago

fschioler commented 10 years ago

I have recently been struggling with interfacing a rotary shaft encoder to the Raspberry Pi.

The first attempt was based on Python interrupts where the falling edge of one pin causes an interrupt and I sample the "other" pin, interpreting a "high" value as CW movement an "low" as CCW. Although experimenting with debouncing, the result is an erratic behaviour.

The second attempt was based on http://guy.carpenter.id.au/gaugette/blog/2013/01/14/rotary-encoder-library-for-the-raspberry-pi/ This is a full quadrature decoder which works very well. The drawback being the pi always running on 100⅜ CPU.

In my youth I tinkered a bit with HW and made an implementation very similar to the bottom drawing at http://www.allaboutcircuits.com/vol_4/chpt_11/3.html I believe there is still room for improvement.

Now, it seems like the Xilinx lot has the perfect (FPGA?) solution to this classic problem described in http://www.xilinx.com/products/boards/s3estarter/files/s3esk_rotary_encoder_interface.pdf My only wish is that the output of the decoder is fed to an 8bit counter which the Pi can read at leisure. And, having the "event" signal available as an input pin is a bonus as this can provide interrupts.

Is such a CPLD core feasible?

campbellsan commented 10 years ago

Hi,

A quick look at the Xilinx document you linked suggests this functionality will fit comfortably into the Guzunty.

If you wish, we can have a go at it for you and post back here when we have something for you to try.

fschioler commented 10 years ago

Hi.

Thanks for a swift answer. And, yes please, a rotary shaft encoder coupled with a counter implemented in the Guzunty would be very appreciated :-)

campbellsan commented 10 years ago

Ok, may take a couple weeks. As for reading the value, do you want a parallel register, or can you read the value over SPI? I'd recommend the second one, it leaves more I/O for other things (on both the Pi and the Guzunty).

I expect there will be enough resources to handle multiple encoders. How many were you hoping to drive?

ptamike commented 10 years ago

A shaft encoder core would be a great idea. The ability to handle 2 or 3 encoders and read via SPI would be great. Thanks,

Mike

fschioler commented 10 years ago

SPI would be perfect.

My current "project" does not need more than one, but you never know... If you can fit in a couple of PWM outputs, I would be in heaven :-)

Best regards Fredrik

campbellsan commented 10 years ago

Ok, I'll take a look at this when I take delivery of some suitable encoders.

I was thinking that the erratic behaviour is due to interrupt latencies within the Raspberry Pi. I have seen widely varying reports of what this latency can be, from 75us up 500us.

Let's assume that the encoder is rotated manually, making a complete revolution in 1 second. For a typical 24 pulse per revolution encoder, this gives one pulse every 40ms or so. The leading/trailing pulse would be valid for half this time, so that the processor has 20ms to read the state of the other signal. Even at a 500us latency, the processor should easily win this race.

If your application is rotating the encoder much faster than this, say above 10 rps, you may start to get into trouble. Above 40 rps, you will almost certainly see issues and above 100 rps, the encoder will be unusable. On the other hand, 100 rps is 6000 rpm, i.e. turning like an internal combustion engine at full throttle. Not many applications require such a speed.

Can you confirm this is the symptom you are seeing? Does your code work at lower speeds? If so, then the Guzunty, with a gate delay of 10ns, will definitely work for much faster rotation rates.

If you are seeing something different, it may indeed be contact bounce that is causing the problem, in which case the Guzunty will see the same bouncing. Implementing debounce in hardware is possible of course, but will consume more CPLD resources; you might be as well off with a software solution after all.

Let me know.

campbellsan commented 10 years ago

I just looked the spec for a Bourne encoder. It specifies 5 ms contact de-bounce is required. This is most likely what is causing the problems. Comments on that topic are in the previous post. The Guzunty will need to be clocked to provide this behaviour. Not a problem, especially if you need PWM in the same core. It will require slightly increased resource usage.

fschioler commented 10 years ago

Hi. I'm going to turn the encoder by hand, thus there will be no need for high speed. I especially experienced the erratic behaviour when "hesitating", thus I believe that debouncing will be necessary. As advertised, the "Rotary Contact Filter" of the Xilinx document completely eliminate contact bounces, so if you can make room for this it will be of great advantage. I am totally ignorant of CPLD design, thus I cannot say whether such a design is self-clocked or need an external clock. The PWM requirement is not mandatory. It surfaced when I was considering alternate usages for an encoder: If using the encoder for positioning purposes, it may be nice to control the speed of a movement.

fschioler commented 10 years ago

Hmmmm. My ignorance: You really need an "oversampling clock" according to the description on http://www.fpga4fun.com/QuadratureDecoder.html I will not bring forward further suggestions before doing the research :-)