Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to set line 4 to input #27

Open
seompark opened this issue Nov 27, 2019 · 46 comments
Open

Unable to set line 4 to input #27

seompark opened this issue Nov 27, 2019 · 46 comments
Labels

Comments

@seompark
Copy link

seompark commented Nov 27, 2019

I'm trying to make a Raspberry Pi 3 REST API that provides temperature and humidity with DHT22. The whole code:

from flask import Flask, jsonify, request
from sds011 import SDS011
from adafruit_dht import DHT22
import board
import os
import time

app = Flask(__name__)
dht = DHT22(board.D4)

def get_dht_data():
    while True:
        try:
            temperature, humidity = dht.temperature, dht.humidity
            print(temperature, humidity)
            if temperature is not None and humidity is not None:
                return temperature, humidity
            else:
                raise
        except:
            time.sleep(0.5)

@app.route('/', methods=['GET'])
def status():
    temperature, humidity = get_dht_data()

    return jsonify({
        'temperature': temperature,
        'humidity': humidity
    })

if __name__ == '__main__':
    app.run(debug=True)

However, when I start server, it shows message

Unable to set line 4 to input

and temperature and humidity is always None. If I don't run flask app but just DHT code, it works.

@ladyada
Copy link
Member

ladyada commented Nov 28, 2019

maybe you have to run as root? not sure - the code works as you said, just not in Flask

@monkeywire
Copy link

..it seems to work fine when I first boot up the raspberry pi and I can run the test code once and it works.... After that if I try to run to the test code a second time I get the same error....

@ladyada
Copy link
Member

ladyada commented Jan 24, 2020

try killing any 'libgpiod_pulsein' processes

@GratefulCoder
Copy link

GratefulCoder commented Jan 26, 2020

try killing any 'libgpiod_pulsein' processes

Same issue occurring here - not using Flask at all though. Worked on the first try when on fresh boot, but then subsequent executions would fail. Changing the pin and running the program had the same effect, worked the first time and subsequent attempts would fail with example:

Unable to set line 4 to input
Timed out waiting for PulseIn message
Timed out waiting for PulseIn message
Timed out waiting for PulseIn message
...

Locating the process libgpiod_pulsein ( pgrep libgpiod_pulsein for example ) and kill <PID found> did the trick.

Thanks!!!

@monkeywire
Copy link

Works, thank you!

@sczerwinski
Copy link

In my case, pgrep libgpiod_pulsein returned nothing. Reboot didn't change anything either.

Fortunately, changing the PIN to D18 worked.

Still no idea what is blocking GPIO4 though.

@jsubirat
Copy link

Short answer

Remove debug=True and enjoy. :-)

What was going on?

This problem drove me nuts but I think I found the root cause! In my case, I was encapsulating the DHT22 object in another object, like so:

...
class DHT22Custom:
    def __init__(self):
        print("**** BUILDING by {0}!".format(threading.currentThread().getName()))
        self.dht_device = adafruit_dht.DHT22(board.D17)
...

My main.py looked like:

import RPi.GPIO as GPIO
from sensor.config.app_config import create_app

if __name__ == '__main__':
    app = create_app()         # builds DHT22Custom inside
    app.run(debug=True)
    print("Cleaning up GPIO before exiting...")
    GPIO.cleanup()

And look what an interesting output I got:

root@05600e5:/app# python -m sensor.main
**** BUILDING by MainThread!
 * Serving Flask app "FlaskWS" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
**** BUILDING by MainThread!
Unable to set line 17 to input

The MainThread was initializing my object twice! How was that? Well, if you look at the documentation of Flask's run(), you'll see the following:

If the :attr:`debug` flag is set the server will automatically reload
 for code changes and show a debugger in case an exception happened.

So, it seems that Flask just relaunches the application or something like this. Not clear to me, to be honest. But well, if you just remove debug, you'll see something like:

root@05600e5:/app# python -m sensor.main
**** BUILDING by MainThread!
 * Serving Flask app "FlaskWS" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

I hope this helps. Happy coding!

@rashmendis
Copy link

try killing any 'libgpiod_pulsein' processes

This is a temporary solution right? It happens every time I stop the code and re-run it. Any solution?

@poisa
Copy link

poisa commented Apr 21, 2020

Fortunately, changing the PIN to D18 worked.

In my case, Pi 3 A+, only pin 11 (aka GPIO17/board.D17) worked. Neither of the other pins suggested here worked. ¯_(ツ)_/¯

@Saeven
Copy link

Saeven commented Apr 26, 2020

Also seeing the same problem!

@rashmendis
Copy link

Their old library worked for me. https://github.com/adafruit/Adafruit_Python_DHT

@SmackTO
Copy link

SmackTO commented May 2, 2020

I'm also seeing this problem on a RPi4. Also, the libgpio_pulsein task uses 25% of my CPU throughput!

The old library worked fine for me too. I'm going to revert and see what happens.

@jsubirat
Copy link

jsubirat commented May 2, 2020

Did you guys try to remove debug=True when initializing Flask? I think it's as simple as that...

@Saeven
Copy link

Saeven commented May 3, 2020

Not even using Flask - just this script, is enough to make the RPI4 hang:

import time
import board
import adafruit_dht

dhtDevice = adafruit_dht.DHT22(board.D4)

@RashmiMendis
Copy link

RashmiMendis commented May 3, 2020 via email

@Saeven
Copy link

Saeven commented May 3, 2020

Reverted to the old lib just now, that one's working a treat.

@kattni kattni added the bug label May 4, 2020
@kerel-fs
Copy link

kerel-fs commented Jun 9, 2020

First of all, if you don't have the pulseio module available (for whatever reason), adafruit_dht will use BitBanging and this bug will not appear.

I'm also affected by this bug as my temperature logger script (5min cronjob) suddenly stopped working after 23 hours, so I did some analysis:

Following the string

The output string Unable to set line X to input is generated by the executable libgpiod_pulsein at

  // set to an input
  if (gpiod_line_request_input(line, consumername) != 0) {
    printf("Unable to set line %d to input\n", offset);
    exit(1);
  }

adafruit/libgpiod_pulsein:/src/libgpiod_pulsein.c#L237-L241.

This executable is called in PulseIn.__init__() by self._process = subprocess.Popen(cmd)
adafruit/Adafruit_Blinka:/src/adafruit_blinka/microcontroller/bcm283x/pulseio/PulseIn.py#L65

PulseIn ?

A quick look into PulseIn.py reveals that PulseIn provides the __enter__() and __exit__() functions in order to be used as a context manager using the with statement.

    def deinit(self):
        """Deinitialises the PulseIn and releases any hardware and software
        resources for reuse."""
        # Clean up after ourselves
        self._process.terminate()
        procs.remove(self._process)
        self._mq.remove()
        queues.remove(self._mq)

    def __enter__(self):
        """No-op used by Context Managers."""
        return self

    def __exit__(self, exc_type, exc_value, tb):
        """Automatically deinitializes the hardware when exiting a context."""
        self.deinit()

PulseIn usage in adafruit_dht

As adafruit_dht is not using PulseIn as a context manager, I guess it should implement the functionality of __exit__() itself by calling PulseIn.deinit() at the approriate moment (e.g. in DHTBase.__exit__()? This would ensure that there is no long-running libgpiod_pulsein process left behind after the python script exited.

Best wishes,
kerel

PS:

# We don't use a context because linux-based systems are sluggish
# and we're better off having a running process
if _USE_PULSEIO:
    self.pulse_in = PulseIn(self._pin, 81, True)

adafruit/Adafruit_CircuitPython_DHT:adafruit_dht.py#L66-L67
Now I'm not sure if the running process was maybe intentional (but I can't see why this would be a good idea...)?

@rinty35
Copy link

rinty35 commented Jul 30, 2020

@kerel-fs thanks for your explain.
Could you push a sample to how to deinit the pulsein in the adafruit_dht context ?

I've a case with two call in the same py script. The First is OK and the second failed with "Unable to set line xxx to input"

My script like that :

_def lecture_temp_DHT (type_capteur, pin):
print ('Lecture de la temperature sur une sonde DHT' + str(pin))

    if type_capteur==22:
            #Initial the dht device, with data pin connected to:
            print ('capteur type DHT22')
            dhtDevice = adafruit_dht.DHT22(pin)
    else:
            dhtDevice = adafruit_dht.DHT11(pin)

    data = []
    for x in range(0,5):
            try :
                    temp = dhtDevice.temperature
                    if temp is not None:
                            print("Temp: {:.1f} C" .format(temp))
                            data.append(temp)
            except RuntimeError as error:
                    # Errors happen fairly often, DHT's are hard to read, just keep going
                    print(error.args[0])
            time.sleep (1)
    if len(data)==0:
            mesure=ERROR
    else:
            mesure = Decimal(sum(data)/float(len(data)))
            mesure = mesure.quantize(Decimal('.1'), rounding=ROUND_HALF_UP)
    return mesure_

And i wan't to be sure that the libgpiod_pulsein process will be kill before exiting this function

@rinty35
Copy link

rinty35 commented Jul 30, 2020

I find an unclean solution with this code to kill process
# recherche du process libgpio pour le tuer et pouvoir refaire une mesure dans la meme exec du script python
for proc in psutil.process_iter():
if proc.name() == 'libgpiod_pulsein' or proc.name() == 'libgpiod_pulsei':
proc.kill()

@guytas
Copy link

guytas commented Aug 4, 2020

I agree with you. Why not solving the problem instead of patching it?
The way i see this, is that we are using a 10 wheeler dump truck to move a tiny pail of sand.

I got fed up dealing with stack of problems just to read this device. I wrote a simple python program that sends the start signal via the GPIO output, and then reads the 40 bits from the dth22, and get the result in humidity and temperature. It is a very simple process that uses only the gpio and time libraries. What else should we really need?

@brocktucker
Copy link

brocktucker commented Aug 8, 2020

I got fed up dealing with stack of problems just to read this device. I wrote a simple python program that sends the start signal via the GPIO output, and then reads the 40 bits from the dth22, and get the result in humidity and temperature. It is a very simple process that uses only the gpio and time libraries. What else should we really need?

@guytas Would you mind sharing this script? I've been fighting multiple issues with libgpoid and would love to just leave it behind.

@guytas
Copy link

guytas commented Aug 8, 2020

Yes no problem. Let me figure out how to make it public on github. I hope you have a pi4. I do not check or validate the os.

I’ll probably do that tonight.

@ruaanmaraisklem
Copy link

ruaanmaraisklem commented Aug 11, 2020

So this is a super hacky work around to this problem, all I've done is force an ImportError when the adafruit_dht.py script attempts to import PulseIn. Once it fails to import PulseIn it will attempt to use bitbang instead, this works for me but I guess it depends on your specific use case whether or not it will work for you

Anyway, I modified line 37 in the adafruit_dht.py file located in dist-packages (remember to sudo here as this file is protected). I changed "from pulseio import PulseIn" to "from pulseio import PulseIn1" this then causes an ImportError and then PulseIo is not used which means the pin won't be blocked after exiting the code

As I said, it's hacky but for now it's a work around to this problem

I tried using the old repo but for some strange reason it wouldn't work on my RPi 4, it kept trying to run the BeagleBone code which obviously does not work.

Hopefully the Adafruit team can solve this properly in a future release

@guytas
Copy link

guytas commented Aug 14, 2020

@brocktucker , I have it ready for you to try amd let me know how it works for you.

How do we send personal message in here?

@goldyfruit
Copy link

goldyfruit commented Aug 14, 2020

Same issue here with fastapi, I got processes running in background.

ubuntu     23715  0.1  0.0  10420   704 pts/0    Sl+  01:45   0:00  |               |           |           \_ /home/ubuntu/.local/lib/python3.8/site-packages/adafruit_blinka/microcontroller/bcm283x/pulseio/libgpiod_pulsein --pulses 81 --
ubuntu     23718  0.0  0.0      0     0 pts/0    Z+   01:45   0:00  |               |           |           \_ [libgpiod_pulsei] <defunct>

@goldyfruit
Copy link

I revert back to the old library, everything works fine.

@kerel-fs
Copy link

This issue will be fixed by Pull Request #46 with implementing what is described in #27 (comment).

@goldyfruit
Copy link

This issue will be fixed by Pull Request #46 with implementing what is described in #27 (comment).

I didn't see the PR, thanks. The dhtDevice.exit() method solved the issue.

@engez7
Copy link

engez7 commented Sep 13, 2020

The dhtDevice.exit() method solved the issue.

Yes! Thank you!
I've two questions...

  1. Why del dhtDevice doesn't work ?
  2. Why the code below in a Flask app file doesn't release the pin after first execution, but after execution in a not Flask script (called by cron) the pin is available ?
import adafruit_dht
dhtDevice = adafruit_dht.DHT22(4)
temperature, humidity = dhtDevice.temperature, dhtDevice.humidity
print(temperature, humidity)

@WinBase
Copy link

WinBase commented Sep 27, 2020

I aint using flask, i dont even know what it is, just a basic board layout using the DHT11 as per many tutorials, i switched to circuit python and find it's quite rubbish giving me the input and pulse errors frequently documented elsewhere as well which i cant resolve via code. rebooting/killing process's every time to make buggy code run is just no solution at all, so i changed back to use the old library as per the link here:

https://stackoverflow.com/questions/63232072/cannot-import-name-beaglebone-black-driver-from-adafruit-dht/64090175#64090175

(i added the following to the file described)

elif match.group(1) == 'BCM2711':
return 3

c'mon adafruit developers, fix it or at least tell us how to reset everything when your script is launched

@ghost
Copy link

ghost commented Oct 27, 2020

In my case, pgrep libgpiod_pulsein returned nothing. Reboot didn't change anything either.

Fortunately, changing the PIN to D18 worked.

Still no idea what is blocking GPIO4 though.

Did you enabled 1-wire interface when using GPIO4?
Try disable 1-wire interface from raspi-config when using gpio4 with adafruit python lib.

@WinBase
Copy link

WinBase commented Dec 3, 2020

I thought i'd retry this today, i'm using D18 and 1-wire interface has never been enabled. i found that by killing the libgpiod process it all worked, but came back the next time the program was run (same as others found). i also tried using dht.exit() when my program closed, but no luck here either. I'm shocked at how bad the circuit python code is, with no support from the developers. i just cant see how anyone can run the published circuit python code using the standard instructions and sample code, as id consider my pi pretty standard, with the old deprecated code seemingly working fine (which i'm still forced to stick with). - anyone any new ideas?

thanks

@kheiakiyama
Copy link

kheiakiyama commented Jan 3, 2021

In my case, a program executes a python script parallels.
I got same error from this simple example.

time seq 1 5 | xargs -I ZZ -P 5 python3 /home/pi/dht_simpletest.py

dht_simpletest.py means below.
https://github.com/adafruit/Adafruit_CircuitPython_DHT/blob/master/examples/dht_simpletest.py

pulseio does not work for my situation.
So I changed code like below.

# dhtDevice = adafruit_dht.DHT22(board.YourPin)
dhtDevice = adafruit_dht.DHT22(board.YourPin, False)

It works for me.

@Amit2016-17
Copy link

Amit2016-17 commented Jan 18, 2021

I am getting this error , i am using raspi4b pin GPIO21 ( pin -40 )
pi@raspberrypi:/IOTstack/Adafruit_CircuitPython_DHT $ sudo python adafruit_dht.py
Traceback (most recent call last):
File "adafruit_dht.py", line 17, in
from digitalio import DigitalInOut, Pull, Direction
File "build/bdist.linux-armv7l/egg/digitalio.py", line 10, in
File "build/bdist.linux-armv7l/egg/adafruit_blinka/agnostic/init.py", line 8, in
ImportError: No module named adafruit_platformdetect
----------------again board is not imported --------------------------
pi@raspberrypi:
/IOTstack/Adafruit_CircuitPython_DHT $ sudo python dht_simpletest.py
Traceback (most recent call last):
File "dht_simpletest.py", line 5, in
import board
File "build/bdist.linux-armv7l/egg/board.py", line 32, in
ImportError: No module named adafruit_platformdetect.constants.boards

@z0rus26
Copy link

z0rus26 commented Apr 3, 2021

So this is a super hacky work around to this problem, all I've done is force an ImportError when the adafruit_dht.py script attempts to import PulseIn. Once it fails to import PulseIn it will attempt to use bitbang instead, this works for me but I guess it depends on your specific use case whether or not it will work for you

Anyway, I modified line 37 in the adafruit_dht.py file located in dist-packages (remember to sudo here as this file is protected). I changed "from pulseio import PulseIn" to "from pulseio import PulseIn1" this then causes an ImportError and then PulseIo is not used which means the pin won't be blocked after exiting the code

As I said, it's hacky but for now it's a work around to this problem

I tried using the old repo but for some strange reason it wouldn't work on my RPi 4, it kept trying to run the BeagleBone code which obviously does not work.

Hopefully the Adafruit team can solve this properly in a future release

Hello for everyone, im already using raspi w zero, my sensor works really good with old version, but with the new one, i am stock after this step, bc i get this response, when :

import time
import board
import adafruit_dht
dhtDevice = adafruit_dht.DHT11(board.D27)
temperature_c = dhtDevice.temperature

Traceback (most recent call last):
File "", line 1, in
File "/home/pi/ibee/py37-venv/lib/python3.7/site-packages/adafruit_dht.py", line 244, in temperature
self.measure()
File "/home/pi/ibee/py37-venv/lib/python3.7/site-packages/adafruit_dht.py", line 200, in measure
raise RuntimeError("A full buffer was not returned. Try again.")
RuntimeError: A full buffer was not returned. Try again.

apparently it fails for some buffer, but i dont know what should i do next. thanks for any help

@z0rus26
Copy link

z0rus26 commented Apr 3, 2021

I also tried to install on my venv "python 3.7" the oldest version, but it doesnt works, it says that this requirement is already satisfaid, so i check using pip list on venv , and i realize that i cant install correctly. i really apreciate any help.

@runnerbob
Copy link

runnerbob commented Jul 16, 2021

CONSIDERATION 1) 

I think the line that would prevent the 504 Error page is this:
slightly modified from @kheiakiyama solution
dhtDevice = adafruit_dht.DHT22(board.D18, use_pulseio=False)
Reference line 14 of Adafruit_CircuitPython_DHT/examples/dht_simpletest.py Commit 8d393f3 on Jan 14

CONSIDERATION 2)

For the 502 Bad Gateway Error, I discovered when running the above dht_simpletest.py and watching, that every few lines, the sensor would not be read and it would throw an Runtime Error...it would read like this:

...
Temp: 78.1 F / 25.6 C    Humidity: 53.5%
Temp: 78.1 F / 25.6 C    Humidity: 53.5%
Temp: 78.1 F / 25.6 C    Humidity: 53.6%
Checksum did not validate. Try again.
Temp: 78.1 F / 25.6 C    Humidity: 53.5%
...

The Checksum did not validate. Try again. was caught in the above linked dht_simpletest.py by running a while...try...except loop.

So, I implemented this same principal in my Flask python setup, and the HTML page has been running for 15 minutes without crashing :)

The try portion is the original code, but see in the except, I catch the RuntimeError, and then I just hard-coded 99 for both temperature and humidity. This could probably be setup better for the database just to ignore this reading...or to get really fancy, use linear interpolation and get a value of the prior and next :)

@app.route("/lab_temp2")
def lab_temp2():
    while True:
        try:
            dhtDevice = adafruit_dht.DHT22(board.D17, use_pulseio=False)
            temperature, humidity = dhtDevice.temperature, dhtDevice.humidity
            if humidity is not None and temperature is not None:
                return render_template("lab_temp2.html",temp=temperature,hum=humidity)
            else:
                return render_template("no_sensor.html")

        except RuntimeError as error:
            #This catches *RuntimeError* thrown if sensor value not read
            temperature, humidity = 99, 99
            return render_template("lab_temp2.html",temp=temperature,hum=humidity)

Hope this helps some of the Raspberry Pi / Flask users on this issue...and maybe give similar ideas to the rest.
@z0rus26 - hope this helps

@Kim-Hyeong-Seob
Copy link

In my case, a program executes a python script parallels.
I got same error from this simple example.

time seq 1 5 | xargs -I ZZ -P 5 python3 /home/pi/dht_simpletest.py

dht_simpletest.py means below.
https://github.com/adafruit/Adafruit_CircuitPython_DHT/blob/master/examples/dht_simpletest.py

pulseio does not work for my situation.
So I changed code like below.

# dhtDevice = adafruit_dht.DHT22(board.YourPin)
dhtDevice = adafruit_dht.DHT22(board.YourPin, False)

It works for me.

It works for me to. But I don't know why.

@ldiazcharris
Copy link

The solution that I found was:
dhtDevice = adafruit_dht.DHT22(board.D4, use_pulseio=False)

Acording to the group comments, this declaration use_pulseio=False disable the PulseIn functionality.

@axolotl190
Copy link

adding dhtDevice.exit() at the end of the code apparently kills the obstinate system process from within the program.

I just see that this has been pointed out before. I had to replace the While statement by a finite "range" loop, however, as the last line must be reached naturally, I guess.
This the only way it works here, but also: no idea why.

@axolotl190
Copy link

Everytime the programs stops without reaching ' dhtDevice.exit()', the offending process must be killed manually.
'os.system("pgrep libgpiod_pulse")' tells me the relevant process id. I don't know, however, how to import this number into "os.system("kill ....."). Anybody with an idea?
Thanks

@axolotl190
Copy link

resolved & closed.
Thank you

@ropering
Copy link

ropering commented Feb 6, 2022

for proc in psutil.process_iter():
        if proc.name() == 'libgpiod_pulsein' or proc.name() == 'libgpiod_pulsei':
            proc.kill()

it works for me

@axolotl190
Copy link

Thank you, ropering!
I cannot try it now, but will soon. In the meantime, I have found a workaround, which I will resort asap.

@Alistair-Kevan
Copy link

my problems mysteriously went away, could have just been loose jumper cables or something?

@onykage
Copy link

onykage commented Jun 24, 2022

so I too was having this issue. I found that if you set use_Pulseio=False when you declare the pin# then the issue clears up.

didnt see this anywhere commented above. Just wanting to help out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests