periph / host

Go·Hardware·Lean - Host drivers
https://periph.io
Apache License 2.0
57 stars 32 forks source link

gpio Pin Read doesn't work as expected. #9

Closed gsexton closed 3 years ago

gsexton commented 3 years ago

Sorry for the length, but I'm trying to sort this out in my mind...

Description

Hardware: Raspberry Pi 4 OS: Raspbian w/ All Updates Go Version: 1.15.8 linux/arm

I'm running into a problem using the GPIO library. I'm using an Adafruit rotary switch and I can get the CCW turns working, but not the CW turns.

On the same device with the same switch, I can run a Java implementation using Pi4J, and both clockwise and counter-clockwise work as expected.

I'll explain how it works inline, but the best description is in the section labeled Quadrature Phase Shift Encoding here:

https://www.best-microcontroller-projects.com/rotary-encoder.html

I'm provisioning two pins:

statePin := gpioreg.ByName("GPIO20"),
dataPin  := gpioreg.ByName("GPIO21"),

statePin.In(gpio.PullUp, gpio.BothEdges)
// I tried BothEdges on dataPin with no effect.
dataPin.In(gpio.PullUp, gpio.NoEdge)

Counter-Clockwise Turn

On a Counter-Clockwise Turn, things work as expected. statePin unblocks with an edgeEvent and state=low. Reading the dataPin returns High. statePin then unblocks again, and dataPin returns Low. Here's some output on a switch turn.

2021/08/10 16:31:50 rotaryHandler() unblocked. State: Low  Last State: High Data: Low  Last Data: High time (Nanos):...29 879 957
2021/08/10 16:31:50 rotaryHandler() unblocked. State: High Last State: Low  Data: High Last Data: Low  time (Nanos):...96 961 395

Clockwise Turn

A clockwise turn starts with the state line transitioning to low, and the Data lines SHOULD be LOW. The second event is the state line transitioning to high, and the data line should be HIGH. However, what I'm seeing is the data pin is high on both edge events.

2021/08/10 16:30:36 rotaryHandler() unblocked. State: Low  Last State: High Data: High Last Data: High time (Nanos):...164 553 515
2021/08/10 16:30:36 rotaryHandler() unblocked. State: High Last State: Low  Data: High Last Data: High time (Nanos):...248 856 352

Additional Information

The only thing that I can see is that the time between the transitions is "slightly" longer for a CW turn. Here's a time sample for four turns in each direction. I think the time difference could be explained by the geometry of the switch contacts.

CW Turn

84.5ms 94.1ms 90.5ms 100ms

CCW Turn

66.8ms 62ms 73ms 69ms

I suppose one theory is that for CW turns, the latency to read the data pin exceeds the time that the data pin remains low. For CCW turns, slightly different geometry makes the system work. Unfortunately, I don't have a digital signal storage oscilloscope (yet) that I could use to measure the widths.

I measured the time to execute both .Read() commands and it's around 4-5 ms. Perhaps the issue is a mixture of the geometry and the time for .WaitForEdge() to unblock.

Do you have any ideas on how I could address this? If you'd like, I can post the source that I'm working on. For my use, doing only CCW turns is a work-around, but I would like to figure out how to make it work in both directions.

Thanks.

George

gsexton commented 3 years ago

Closing and opening on conn/gpio