piface / pifacecad

PiFace Control and Display
GNU General Public License v3.0
47 stars 38 forks source link

SwitchEventListener doesnt work #16

Open Freaksed opened 9 years ago

Freaksed commented 9 years ago

I am trying to use the SwitchEventListener as shown in the documentation but it doesnt seem to do anything, the program just hangs.

tompreston commented 9 years ago

You mean the following code?

>>> import pifacecad
>>> cad = pifacecad.PiFaceCAD()
>>> listener = pifacecad.SwitchEventListener(chip=cad)
>>> listener.register(0, pifacecad.IODIR_RISING_EDGE, print)
>>> listener.activate()

I've just ran this on a fresh install of wheezy (after installing the python3-pifacecad package) and when I press switch 0 I get a print out of data.

Are you still having this issue? Are you running the latest version of Raspbian?

tompreston commented 9 years ago

Actually scratch that, I can't seem to get SwitchEventListener/interrupts to work either. There appears to be a problem with epoll. I'm going to dump what I have so far.

There is an MCP23S17 port expander on each PiFace product. For each port (A and B) there is an interrupt flag register and an interrupt capture register. The interrupt flag register is set to 0b1 whenever an interrupt occurs and the port's value is put in the capture register. Let's test this with PiFace CAD:

>>> import pifacecad
>>> cad = pifacecad.PiFaceCAD()
>>> bin(cad.intfa.value)
0b0
>>> bin(cad.intcapa.value)
0b11111111

And the results after pressing switch 0:

>>> bin(cad.intfa.value)
0b1
>>> bin(cad.intcapa.value)
0b11111110

And again:

>>> bin(cad.intfa.value)
0b0
>>> bin(cad.intcapa.value)
0b11111110

Notice how the flag has cleared after reading the INTCAPA register. So, interrupts are clearly working on the chip.

The MCP23S17 is configured such that the interrupt wire connected to GPIO25 (RPi pin 22) is active-low (0) when an interrupt has occurred (interrupt flag is high). In other words: GPIO25 is 0 when an interrupt has occurred, 1 otherwise. Let's see this in action:

Bring GPIO25 into userspace and check it's value:

$ echo 25 > /sys/class/gpio/export
$ more /sys/class/gpio/gpio25/value
1

Now check its value after pressing switch 0:

$ more /sys/class/gpio/gpio25/value
0

We use epoll to detect changes on this file, which signals that an interrupt has occurred:

>>> import select
>>> gpio25 = open('/sys/class/gpio/gpio25/value', 'r')
>>> epoll = select.epoll()
>>> epoll.register(gpio25, select.EPOLLIN | select.EPOLLET)
>>> epoll.poll()

The final command should hang until the interrupt occurs (and changes the /sys/class/gpio/gpio25/value file) after which it will return some file descriptor/event information.

The problem is that epoll is no longer returning and just hangs forever. I'm not sure why this is but am investigating. If anyone has anything to input then that would be great.

Also, the interrupt_example.c program doesn't work either. Further evidence to the problem being with epoll (or, at least, the way I'm using it). https://github.com/piface/libmcp23s17

Some more information:

SailingGreg commented 9 years ago

Thomas, noticed that init_epoll(void) in libmcp23s17.c, line 226 you open the file readonly and nonblocking

gpio_pin_fd = open(gpio_pin_filename, O_RDONLY | O_NONBLOCK);

In the above you do not specify not blocking on the open or change the file control

gpio25 = open('/sys/class/gpio/gpio25/value', 'r')
gibbo9000 commented 9 years ago

I have this issue as well on Pi 2 with PiFace CAD2. It seems to be just the listeners / interupts. Is there a way I can work around or fix this based on the above?

SailingGreg commented 9 years ago

My initial opinion was that the device tree config.txt changes addressed the interrupt issue so give them a go

Either disable the device tree in raspi-config (option 8/A5) or add dtoverlay=spi-bcm2708 to /boot/config.txt manually

gibbo9000 commented 9 years ago

It seems it may be the IDLE issue I picked up on the Element 14 site. I tried the various changes above in multiple combinations with no effect. But then I tried running it in a different environment than Raspbian IDLE and interupts worked perfectly (that was under Mavproxy / dronekit-python - part of the UAV technology the RPi will be art of). Then I tried running it from $ prompt and they worked sporadically. Need to do more experimenting around this later.

[Edit] Runs fine in Terminal if called as root. A bit brutal but allows me to code and test at least!

SailingGreg commented 9 years ago

If you find it works as root then check the file permissions in the /sys/class/gpio/gpio25 file system - I found that these changed between 3.x and 4.x and I added 'chmod 666 /sys/class/gpio/gpio17/value' to get my own code to work (in the case of the PiFaceCAD the interrupts use gpio25)

mduchateau commented 9 years ago

@SailingGreg Thanks ! 'chmod 666 /sys/class/gpio/gpio25/value' made the SwitchEventListener to work again with the PiFaceCAD

gibbo9000 commented 9 years ago

Also thanks! On Rpi 2 and CAD2 and my build it seems to be in /sys/class/gpio/gpiochip0/device/gpio/gpio25/value - does that make sense? I have changed its permissions and it now runs without root access on Terminal, but not through inbuilt IDLE.

SailingGreg commented 9 years ago

Not familiar with IDLE but another thing you can check is the user rights - 'id' will list the group memberships and see if 'gpio' is included as an alternative to chmod

BTW chmod 666 is a bit of a hack and chmod o+r woud be tidier

gibbo9000 commented 9 years ago

Will try the 'id' route and see what I learn. But not overly fussed - all good in Terminal and running in the environment it is meant for. Here are the comments on IDLE at Element 14: http://www.element14.com/community/thread/28282/l/piface-cad--eventinterrupt-for-keys?displayFullThread=true (which were from Tom in the first place!)

otrebski commented 8 years ago

Is anyone working on fix? It looks like there is no point in buying PiFace 😞