joan2937 / pigpio

pigpio is a C library for the Raspberry which allows control of the General Purpose Input Outputs (GPIO).
The Unlicense
1.45k stars 407 forks source link

RPI4 - Hang while interrupt #482

Closed florian-guillemard closed 3 years ago

florian-guillemard commented 3 years ago

Hi everyone!

I am trying to count events with an interrupt on GPIO17 (or whatever) with pull-up internal and a high level of 90ms.

I am using a callback, it is working but there is no "real-time" in processing the interrupt function :( it is possible to wait 10 second before my callback is called!

Can someone explain that to me ?

Thanks a lot!

guymcswain commented 3 years ago

Please post a snippet of your code that demonstrates your issue.

florian-guillemard commented 3 years ago

Hi,

I have the problem in Python and C..

Maybe something wrong with the Pigpio Daemon ?!

#!/usr/bin/env python

# monitor.py
# 2016-09-17
# Public Domain

# monitor.py          # monitor all GPIO
# monitor.py 23 24 25 # monitor GPIO 23, 24, and 25

import sys
import time
import pigpio

last = [None]*32
cb = []

def cbf(GPIO, level, tick):
   if last[GPIO] is not None:
      diff = pigpio.tickDiff(last[GPIO], tick)
      if GPIO == 17:
        print("G={} l={} d={}".format(GPIO, level, diff))
   last[GPIO] = tick

pi = pigpio.pi()

if not pi.connected:
   exit()

if len(sys.argv) == 1:
   G = range(0, 32)
else:
   G = []
   for a in sys.argv[1:]:
      G.append(int(a))

for g in G:
   cb.append(pi.callback(g, pigpio.EITHER_EDGE, cbf))

try:
   while True:
      time.sleep(60)
except KeyboardInterrupt:
   print("\nTidying up")
   for c in cb:
      c.cancel()

pi.stop()
guymcswain commented 3 years ago

This code seems reasonable. What is the stimulus on gpio 17? By default, gpio 17 will be an input with a pull down.

florian-guillemard commented 3 years ago

The stimulus is an open-circuit with a S0 impulse output from a power counter.

90ms activated for 1Wh.

guymcswain commented 3 years ago

Have you verified that you are receiving valid levels on that input?

To verify pigpio is behaving properly I suggest disconnecting the external stimulus then making the pin an output and write to it during the while loop.

florian-guillemard commented 3 years ago

Yes, the pigpio is working but it is like hanging during the stimulus.

When I do the contact at the hand, it is working but heracticly (many, too much times).

I tested this program too :

#!/usr/bin/env python

import struct
import time

control = open("/dev/pigpio", "w")
result  = open("/dev/pigout", "r")

control.write("no\n")      # All pipe commands must be ended with a line feed.
control.flush()            # Force message through the pipe.
h = int(result.readline()) # Read result (handle).

if h >= 0: # Valid notification handle received.

   notify = open("/dev/pigpio{}".format(h)) # Read notifications from here.

   # Specify gpios for which notifications are required.
   control.write("nb {} {}\n".format(h, -1)) # -1 is all gpios.
   control.flush()                           # Force message through the pipe.
   result.readline()                         # Discard result.

   start = time.time()

   while (time.time() - start) < 30: # Run for a few seconds.

      msg = notify.read(12) # Read next notification.

      if len(msg) == 12:

         S, fl, t, v = struct.unpack("HHII", msg)

         # Ignore sequence number and flags for quick test.

         print("Tick={:010d} gpios={:032b}".format(t, v))

   control.write("nc {}\n".format(h)) # Close notification.
   control.flush()                    # Force message through the pipe.
   result.readline()                  # Discard result.

   notify.close()

result.close()
control.close()
guymcswain commented 3 years ago

When I do the contact at the hand, it is working but heracticly (many, too much times).

This is normal and called “contact bounce”. It can bounce for tens if not hundreds of times and never the same way.

joan2937 commented 3 years ago

If you get more level changes than can be handled by Python they will all be queued up by the daemon. It can take seconds for the changes to arrive at Python once the system becomes less busy.

Are you expecting tens of thousands of level changes per second?

florian-guillemard commented 3 years ago

I think I will be far from 10k!

With this datasheet : https://www.cartelectronic.fr/documentation/DRS155-B.pdf

1 impulse = 1 Wh = 1 blink led

And I can count the led blinkink, like 1 per second!

guymcswain commented 3 years ago

What is the SO device in the diagram? Is it something to convert the 60v to 3.3v?

felixkasza commented 3 years ago

ETA: Link to English Wikipedia and current-loop details

What is the SO device in the diagram? Is it something to convert the 60v to 3.3v?

S0-outputs are a simple interface that is fairly common in Germany. I could not find an English-language data sheet for S0 in general or the DRS155-B inparticular, but the principle is simple: while the signal is being asserted, a switch or equivalent connects the two pins via a 1k resistor. The whole thing is free of potential as the switch must be electrically separate from the rest of the device (e.g., via an optocoupler).

The S0-interface must be driven by the remote (RPi in this case) and can handle up to 27 V at 27 mA. The intent, btw, is to use this as a current-loop interface, with <2 mA being a LOW signal and >10 mA being HIGH. With the Pi's 3.3V, I doubt one will get much of anything out of it. On the other hand, there are cheap TTL-to-current loop converters.

Oh, and the S0 output has to be free of bouncing.

Found it: S0 does not have a special name in English, but Wikipedia describes exactly this interface, minus the exact numbers provided by the German S0 standard.

guymcswain commented 3 years ago

Thanks @felixkasza.

But it seems to me that a bit more signal conditioning is required. As I understand it, the RPi is the input, not the controller. A 4-20mA current loop would over-voltage the internal pull up/down resistor with an impedance of approximately 50K ohms. Maybe I'm still not getting it.

Oh, and the S0 output has to be free of bouncing.

@alternadom, you will need to debounce the input. Edit: This could prove to be difficult if the signal pulse is only 90 msec. I think contact bounce period can be greater than that.

guymcswain commented 3 years ago

Actually, an optocoupler by itself would be an ideal interface element: Direct conversion to 3.3V with no mechanical switch bounce.

felixkasza commented 3 years ago

I apologise for having been unclear.

According to the EN 62053-31 standard, the S0 interface requires the external side, in this case, the RPi, to produce enough voltage (up to the max of 27 V) to maintain a current loop at all times. The sensor just determines, assuming the external side is able to source enough juice, whether to let flow a current of less than 2 mA (LOW) or more than 10 mA (high). A current so low as to be undetectable is considered a failure indicator, like broken wires and such.

In "classical" applications the loop was controlled on the sensor side by an opto-transistor that allowed more or less current to flow depending on whether a pre-existing LED was on or off; the current would travel to the external side and if there was enoug current (HIGH), it would turn on a LED which turned on an opto-transistor. A discrete opto-coupler pair, if you will.

@alternadom – Regarding debouncing, the DRS155-B doesn't need that, but the mechanical switch you used to simulate the DRS certainly does.

More to the point: Your RPi is (a) not a constant-current source, much less a controllable one. On a good day, a GPIO pin on the RPi might source 50 mA at 3.3 V, but the S0 current-loop interface is comparable to a series-equivalent resistor of 7.5k (assuming 15 V input and 2 mA) in the LOW/OFF state respectively 1.5k in the HIGH/ON state (assuming 15 V and 10 mA).

Your poor little Pi would, using these series-equivalent resistances, produce 0.4 mA (LOW) resp.  2 mA (HIGH), not nearly good enough. Buy a current-loop-to-TTL (also called current-loop to voltage) converter, or hack one together. It should only take a double op-amp (and maybe even just one? It's been a while since the TTY33KSR.)

felixkasza commented 3 years ago

Actually, an optocoupler by itself would be an ideal interface element: Direct conversion to 3.3V with no mechanical switch bounce.

But we would still need the driver for the current loop. :(

guymcswain commented 3 years ago

This is S0 complicated, lol.

felixkasza commented 3 years ago

It gets worse. There are umpteen 20mA-to-RS232 converters on the market, more than there are stars in the sky, more than there are grains of sand at the beach. Because why? Because RS232 comes with a power supply! ±9 V minimum, ±15 V ideally, ±24 V if someone was generous. :)

In this case we would need:

That begins to sound like a bit of a project. Maybe go with the RS232 converter? No, the Pi cannot (directly) handle RS232 signal levels :(

felixkasza commented 3 years ago

@alternadom – here, this is what you want: Your counter has a little LED in a round hole near the display. Depending on the model, this is a visible-light LED or an infrared LED.

Note: 0.2 seconds debounce time is fine. In a home, you are unlikely to have more than 40 A @ 240 V max. That gives us 9600 VA, which means an impulse every 0.375 seconds. If you want something better, condition the signal from the optotransistor with a Schmitt-trigger.

Summary: One optotransistor, a few yards of cheap wire, a strip of Sellotape (sticky tape). No current-limiting current source, no weird supply voltages, nothing. And you are not annoying the GPIO pads in your RPi's 2711.

florian-guillemard commented 3 years ago

Hi,

At the beginning, I started working on this : https://electrorun.blogspot.com/2016/10/monitorer-la-consommation-denergie-avec.html

Very simple, i thought it would be easy but the behavior of the interrupt function was not really nice. All the interrupt calls was treated at the same time!

And I wanted to monitor my power usage with precision..

I will be damn to use the LED and not the S0 output (which is made for that kind of usage!).

Is the debounce can be configured on the pigpiod ? The service is working correctly but if i stop it and try a manual run like : sudo pigpiod -s 2 -b 200 -f My RPi is frozen and I need to cut the power 😢

Any advice to configure pigpiod better than in my link above ?

felixkasza commented 3 years ago

I saw plenty of articles that just connect the S0 lines to the Pi and claim that it works. And for every one of those articles, I found three forum discussions because it didn't work.

You cannot connect an S0 interface to a Pi GPIO (3.3 V, 16 mA in theory) and expect it to work.

What you are seeing on the meter output is not bouncing; it is because the Pi does not deliver enough power to make a clear distinction betwen HIGH and LOW. The signal current goes into the forbidden area between 2 mA and 10 mA. The solutions that work, like the Volkszaehler, all use dedicated interface hardware co convert between current loop signals and 3.3 V levels.

Hook up a scope, check for yourself!

guymcswain commented 3 years ago

@alternadom, the blog you linked shows a different part number - DDS5188. Let's assume the output of this device is a dry contact, ie, not the current loop mentioned above, and that you have wired it as described in the blog. What is missing from your code is setting the pull-up resistor on GPIO 17. You would need to add the following:

pi.set_mode(17, pigpio.INPUT)  # don't rely on default pin mode.
pi.set_pull_up_down(17, pigpio.PUD_UP) # set the pull up resistor

If there is noise (bounce) coming from the dry contact you can experiment with

pi.set_glitch_filter(17, steady)  # steady is microseconds to filter

The service is working correctly but if i stop it and try a manual run like : sudo pigpiod -s 2 -b 200 -f My RPi is frozen and I need to cut the power

This is not expected. Can you provide some detail about how your service is configured and how you stopped it?

florian-guillemard commented 3 years ago

No change with the 3 lines..

For the pigpiod, this is my /etc/init.d/pigpiod file :

#!/bin/sh
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and sourcing.
if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
    set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
fi
### BEGIN INIT INFO
# Provides:          pigpiod
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.  This example start a
#                    single forking daemon capable of writing a pid
#                    file.  To get other behavoirs, implemend
#                    do_start(), do_stop() or other functions to
#                    override the defaults in /lib/init/init-d-script.
### END INIT INFO

# Author: NikoRun ( nikorun @ airtune . info )

DESC="Start PiGpiod Daemon"
DAEMON=/usr/local/bin/pigpiod
guymcswain commented 3 years ago

What OS are you running? What version is pigpio? What is return value of ‘pigs hwver’ Where did this service script come from?

guymcswain commented 3 years ago

I did a bit more research. There are two types of SO interfaces: The type you are using requires an external DC voltage be supplied - usually 5 - 27VDC. The other type, as used in the blog, is a "potential free contact" type. You should consider the advise offered by @felixkasza.

I will continue to assist you with the service shutdown hang that you mention.

Sineos commented 3 years ago

https://wiki.volkszaehler.org/hardware/controllers/raspberry_pi_erweiterung_klein https://wiki.volkszaehler.org/hardware/controllers/raspberry_pi_erweiterung_mit_schaltausgaengen_rev.1

I have two of the second up and running. Working like a charm. Sorry, links only available in German.

Also a ready to buy product is available: https://busware.de/tiki-index.php?page=SD0

Edit: Simple solution for S0 to USB https://wiki.volkszaehler.org/hardware/controllers/s0-an-usb

guymcswain commented 3 years ago

Issue is not related to pigpio.