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

pygame.error: No available video device #307

Open
Georodin opened this issue Aug 18, 2023 · 3 comments
Open

pygame.error: No available video device #307

Georodin opened this issue Aug 18, 2023 · 3 comments

Comments

@Georodin
Copy link

Georodin commented Aug 18, 2023

Hey guys,
I have the ST7796S running with fbcp-ili9341 < on my Raspi Zero W.
Now I wanted to print a lightweight GUI to the ST7796S using pygame.

But pygame cannot find the correct video driver. How can I link it correctly and use
pygame with fbcp-ili9341?
I can directly write images and stuff to the framebuffer fb0.

And I tried a ton of stuff from forums and ChatGPT but in the end it did not work.

But I always get the error like this when running my python:

python3 game.py
pygame 2.5.1 (SDL 2.0.14, Python 3.9.2)
Hello from the pygame community. https://www.pygame.org/contribute.html
The path /dev/dri/ cannot be opened or is not available
The path /dev/dri/ cannot be opened or is not available
The path /dev/dri/ cannot be opened or is not available
The path /dev/dri/ cannot be opened or is not available
Traceback (most recent call last):
  File "/home/pi/game.py", line 12, in <module>
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.error: No available video device

This script im using at the moment:

import pygame
import os

# Initialize pygame
pygame.init()

# Use fb0 for display
os.environ["SDL_FBDEV"] = "/dev/fb0"
os.environ["SDL_VIDEODRIVER"] = "rpi"

# Set up display dimensions
WIDTH, HEIGHT = 480, 320
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# Colors
WHITE = (255, 255, 255)
RED = (255, 0, 0)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill(WHITE)
    pygame.draw.circle(screen, RED, (WIDTH // 2, HEIGHT // 2), 50)
    pygame.display.flip()

pygame.quit()

When I activate this in the boot/config.txt, then the game.py does no longer throw errors, but the fbcp-ili9341 does not work any longer.

# Enable DRM VC4 V3D driver
#dtoverlay=vc4-kms-v3d

Any ideas or obvious mistakes on my side?
Much appreciated.

@Georodin
Copy link
Author

@juj if you read this I would love to tip you a coffee if you can provide some feedback :)

@userkazoo
Copy link

userkazoo commented Feb 5, 2024

Greetings!

I have the same situation and the same display.
I made the driver according to the instruction https://github.com/jobitjoseph/fbcp-ST7796.
It took a long time with pygame - as a result everything worked through framebuffer.
As an example of pygame work - the code below:

#!/usr/bin/python3

import pygame, time

# Very important: the exact pixel size of the TFT screen must be known so we can build graphics at this exact format
surfaceSize = (480, 320)

# Note that we don't instantiate any display!
pygame.init()

# The pygame surface we are going to draw onto. 
# /!\ It must be the exact same size of the target display /!\
lcd = pygame.Surface(surfaceSize)

# This is the important bit
def refresh():
    # We open the TFT screen's framebuffer as a binary file. Note that we will write bytes into it, hence the "wb" operator
    f = open("/dev/fb0","wb")
    # According to the TFT screen specs, it supports only 16bits pixels depth
    # Pygame surfaces use 24bits pixels depth by default, but the surface itself provides a very handy method to convert it.
    # once converted, we write the full byte buffer of the pygame surface into the TFT screen framebuffer like we would in a plain file:
    f.write(lcd.convert(16,0).get_buffer())
    # We can then close our access to the framebuffer
    f.close()
    time.sleep(0.1)

# Now we've got a function that can get the bytes from a pygame surface to the TFT framebuffer, 
# we can use the usual pygame primitives to draw on our surface before calling the refresh function.

# Here we just blink the screen background in a few colors with the "Hello World!" text
pygame.font.init()
defaultFont = pygame.font.SysFont(None,30)

lcd.fill((255,0,0))
lcd.blit(defaultFont.render("Hello World1!", False, (0, 0, 0)),(0, 0))
refresh()

lcd.fill((0, 255, 0))
lcd.blit(defaultFont.render("Hello World2!", False, (0, 0, 0)),(0, 0))
refresh()

lcd.fill((0,0,255))
lcd.blit(defaultFont.render("Hello World3!", False, (0, 0, 0)),(0, 0))
refresh()

lcd.fill((128, 128, 128))
lcd.blit(defaultFont.render("Hello World4!", False, (0, 0, 0)),(0, 0))
refresh()

pygame.draw.circle(lcd, (0,128,0), (200,200), 55)
# your picture
#image = pygame.image.load('guizero_flash.gif') # your picture
#lcd.blit(image, (0, 0))
refresh()

exit()

@Georodin
Copy link
Author

Georodin commented Feb 5, 2024

Thank you very much, I will try it as soon as I have a free Raspberry Pi again, my three are bound in projects atm

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

No branches or pull requests

2 participants