Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 1579

Python • "lgpio.error: 'GPIO busy'" when running flask server and updating e-ink display via python script

$
0
0
Hi there, long-time lurker, first-time poster.

I have built a Pi e-ink dashboard using a Waveshare 7.5 e-paper screen and a Raspberry Pi 3b+. I am using Python for the script that renders and displays the image on the screen. I also built a Flask web app to remotely control the dashboard from other devices on my home network. The app uses buttons to send POST requests that trigger the Python scripts. The problem is, whenever the Flask server is running on the Pi and I try to run the image display script, either from the web app or via the Terminal, I get a "lgpio.error: 'GPIO busy'" error. When the server is off, the script runs fine from the Terminal, but I would like to manage the dashboard without having to SSH to it all the time.

I don't know why running the server would require interacting with the GPIO pins at all. My photo display script sleeps the display as recommended, and I have used both the Flask development server and Waitress to run the web app, with the same error popping up when running the script. Is there something I am missing? I have posted the error below, along with my Flask app and the photo display script, for reference. Any help would be greatly appreciated.

Thanks!

GPIO Error

Code:

Traceback (most recent call last):  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 411, in pin    pin = self.pins[info]          ~~~~~~~~~^^^^^^KeyError: PinInfo(number=11, name='GPIO17', names=frozenset({'BOARD11', 17, 'WPI0', 'GPIO17', '17', 'J8:11', 'BCM17'}), pull='', row=6, col=1, interfaces=frozenset({'', 'spi', 'dpi', 'gpio', 'uart'}))During handling of the above exception, another exception occurred:Traceback (most recent call last):  File "/home/tempus/tempus-db/manage/../photodisplay.py", line 8, in <module>    from waveshare_epd import epd7in5_V2  File "/home/tempus/tempus-db/waveshare_epd/epd7in5_V2.py", line 32, in <module>    from . import epdconfig  File "/home/tempus/tempus-db/waveshare_epd/epdconfig.py", line 313, in <module>    implementation = RaspberryPi()                     ^^^^^^^^^^^^^  File "/home/tempus/tempus-db/waveshare_epd/epdconfig.py", line 56, in __init__    self.GPIO_RST_PIN    = gpiozero.LED(self.RST_PIN)                           ^^^^^^^^^^^^^^^^^^^^^^^^^^  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 108, in __call__    self = super().__call__(*args, **kwargs)           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  File "/usr/lib/python3/dist-packages/gpiozero/output_devices.py", line 192, in __init__    super().__init__(pin, active_high=active_high,  File "/usr/lib/python3/dist-packages/gpiozero/output_devices.py", line 74, in __init__    super().__init__(pin, pin_factory=pin_factory)  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 75, in __init__    super().__init__(*args, **kwargs)  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 553, in __init__    pin = self.pin_factory.pin(pin)          ^^^^^^^^^^^^^^^^^^^^^^^^^  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 413, in pin    pin = self.pin_class(self, info)          ^^^^^^^^^^^^^^^^^^^^^^^^^^  File "/usr/lib/python3/dist-packages/gpiozero/pins/lgpio.py", line 126, in __init__    lgpio.gpio_claim_input(  File "/usr/lib/python3/dist-packages/lgpio.py", line 755, in gpio_claim_input    return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  File "/usr/lib/python3/dist-packages/lgpio.py", line 458, in _u2i    raise error(error_text(v))lgpio.error: 'GPIO busy'

Flask App

Code:

import subprocessfrom flask import Flask, url_for, render_template, request, jsonifyfrom markupsafe import escapefrom manager import *app = Flask(__name__)@app.route('/')def index():  # define dashboard buttons  button_list = [    {"id": "dashboard", "text": "Start Dashboard", "icon": "layout-dashboard.svg", "route":""},     {"id": "photo", "text": "Display Image", "icon": "image.svg", "route":"/showimage"},     {"id": "clear", "text": "Clear Dashboard", "icon": "brush-cleaning.svg", "route":"/clear"},     {"id": "pause", "text": "Pause Dashboard", "icon": "circle-pause.svg", "route":"/dashstop"}  ]  return render_template('index.html', buttons=button_list)# start dashboard route@app.route('/dashstart', methods=['POST'])def dashstart():  if request.is_json:    data = request.get_json()    timer = data["timing"]    hasjob = set_tempus_job(timer)    if hasjob:      subprocess.run(['python3', '../main.py'])      result = f"Dashboard started successfully. Refresh time interval is {timer} minutes."      print(result)      return jsonify({'message': result})    else:      return jsonify({'error': 'Dashboard not started'}), 400  else:    return jsonify({'error': 'Request must be JSON'}), 400# display photo route@app.route('/showimage', methods=['POST'])def showimage():  stopped = clear_tempus_jobs()  if stopped:    subprocess.run(['python3', '../photodisplay.py'])    result = "Switched to photo display mode"    print(result)    return jsonify({'message': result})  else:     return jsonify({'error': 'Photo display failed'}), 400# clear screen route@app.route('/clear', methods=['POST'])def cleardash():  clear_display()  result = "Dashboard Cleared Successfully"  print(result)  return jsonify({'message': result})# stop dashboard cron job route@app.route('/dashstop', methods=['POST'])def dashstop():  stopped = clear_tempus_jobs()  if stopped:    result = "Dashboard Paused Successfully"    print(result)    return jsonify({'message': result})  else:    return jsonify({'error': 'Dashboard not paused'}), 400

Photo Display script

Code:

import loggingimport sysimport pathlibimport timefrom PIL import Imagefrom waveshare_epd import epd7in5_V2if __name__ == '__main__':logger = logging.getLogger('tempusdash')config = {"imgW": 800,"imgH": 480,"angle": 0,"photo_path": "photo-display/photo.png","error_photo": "photo-display/error.png"}# load configuration for photo displaycurrPath = str(pathlib.Path(__file__).parent.absolute())# initialize displayepd = epd7in5_V2.EPD()img_wid = config["imgW"]img_ht = config["imgH"]angle = config["angle"]photo_path = currPath + "/" + config["photo_path"]error_photo = currPath + "/" + config["error_photo"]# create and configure loggerlogging.basicConfig(filename="logfile.log", format='%(asctime)s %(levelname)s - %(message)s', filemode='a')logger = logging.getLogger('tempusdash')logger.addHandler(logging.StreamHandler(sys.stdout))  # print logger to stdoutlogger.setLevel(logging.INFO)logger.info("Starting photo display")# get pictureif pathlib.Path(photo_path).exists():dashimage = Image.open(photo_path)log_msg = "Photo suscessfully displayed on screen"else:dashimage = Image.open(error_photo)log_msg = "Photo not found"dashimage = dashimage.convert("1")epd.init()epd.Clear()epd.display(epd.getbuffer(dashimage))logger.info(log_msg)time.sleep(2)epd.sleep()logger.info("Completed photo display update")

Statistics: Posted by cealpha — Thu Aug 28, 2025 8:08 pm



Viewing all articles
Browse latest Browse all 1579

Trending Articles