PiSupply / Flick

Resources for the Flick range of boards and cases
https://pisupp.ly/flick1
65 stars 26 forks source link

Flick large on Raspberry Pi 5 #69

Open jmeile opened 6 months ago

jmeile commented 6 months ago

Hi

I'm trying to run this on the Raspberry Pi 5, but as soon as I run the flick-demo, I get: RuntimeError: Cannot determine SOC peripheral base address

I found that this pi is really different than its predecesors and the main reason is that it isn't compatible with RPi.GPIO (I don't know what this means exactly).

Anyway, I also found that you could solve this by installing lgpio, so, I did it as follows:

sudo apt remove python3-rpi.gpio
pip3 install rpi-lgpio

The command line demos still doesn't work, so, I tried this code: https://news.sean.co.uk/2017/11/adding-gesture-control-to-raspberry-pi.html

It started to work, but at some point, an exception will be thrown:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "/home/admintv/.flick/lib/python3.11/site-packages/flicklib-0.0.3-py3.11.egg/flicklib.py", line 130, in run
  File "/home/admintv/.flick/lib/python3.11/site-packages/flicklib-0.0.3-py3.11.egg/flicklib.py", line 311, in _do_poll
AttributeError: 'NoneType' object has no attribute 'pop'

The program will keep running, but the coordinates won't be updated. Exiting with CTRL+C and trying to run it again, just shows: lgpio.error: 'GPIO busy'

I improve the code a little bit and that "busy" error disappeared, but the "AttributeError" exception still happens. In order to make the code work again, I need to exit from the python interpreter, come back and then run it again.

Is there anyway of getting this to be fixed for the Raspberry Pi 5?

Best regards Josef

Here the improved version of the code:

import RPi.GPIO as GPIO
import os
import flicklib
import time

x_pos, y_pos, z_pos = 0, 0, 0

@flicklib.move()
def move(x, y, z):
  global x_pos, y_pos, z_pos
  x_pos = x
  y_pos = y
  z_pos = z

def print_data():
  while True:
    #os.system('clear')
    print("X:", x_pos)
    print("Y:", y_pos)
    print("Z:", z_pos)
    #Even if the sleeping time is increased, the exception still happens
    time.sleep(0.25)

try:
  print_data()
except KeyboardInterrupt:
  print("Keyboard interrupt, exiting...")
except:
  print("Other error or exception occurred!")
finally:
  GPIO.cleanup()
  print("Cleaning GPIO")
jmeile commented 6 months ago

Ok, I found the source code of flick-demo, so, I copied it to a py file and run it. It runs better, but at some point the exception: AttributeError: 'NoneType' object has no attribute 'pop' comes.

The python script continues running, but then nothing will be refreshed on the screen.

So looks like: 20240426_22h33m28s_grim

I think it happens after doing the Air Wheel gesture

jmeile commented 6 months ago

Just for the records, now I understand a little bit the problem. From Raspberry Pi 5, they changed the way how the GPIOs are accessed; older Pis are using some library called RPI.GPIO, which is no longer compatible.

The flick-demo is somehow working, but an error will be raised from the flicklib code. It seems that at some point, no data will be read from the memory and thus the returned object is "None". Here I'm using a python library called: "rpi-lgpio", but you can also use other alternatives:

Currently, I found this link useful: https://pi-buch.info/gpio-reloaded-i-python

The author explains there how to install and use all those alternatives (only in german, so, you need to speak it or use the chromium based browsers translation).

Coming back to the problem, this is the exception:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "/home/admintv/.flick/lib/python3.11/site-packages/flicklib-0.0.3-py3.11.egg/flicklib.py", line 130, in run
  File "/home/admintv/.flick/lib/python3.11/site-packages/flicklib-0.0.3-py3.11.egg/flicklib.py", line 311, in _do_poll
AttributeError: 'NoneType' object has no attribute 'pop'

So, the error is after this line: https://github.com/PiSupply/Flick/blob/bada72a01cbec5c44d5635117d3e05736ccdc0a5/flick/flicklib.py#L309

It doesn't read anything and returns "None", so, the next line: d_size = data.pop(0)

Fails because "data" is "None", so it doesn't have any "pop" attribute. Now, I will try to work with only one gesture and see if the problem comes. My second option is to subclass the flicklib classes and then add a quick an dirty fix, for example:

if data != None:
  # Pop out the data from the poll and do whatever you have to do

I know it is not a clean solution and it could break something else, but given the fact that I don't know exactly how the code works, it is my fastest way of solving my problem.

jmeile commented 6 months ago

By looking at the code, you will see this line: https://github.com/PiSupply/Flick/blob/bada72a01cbec5c44d5635117d3e05736ccdc0a5/flick/flicklib.py#L308

It seems in deed that this small delay that is commented is really needed to avoid the "NoneType" exception. I added it and until now it hasn't crashed. It even detects the Wheel gesture, which without the pause doesn't. So, it seems to me that it is a latency problem with the Raspberry pi 5.

Anyway, I also did a test and added logging to the flicklib.py module. I put this lines at the beginning:

import logging
logger = logging.getLogger(__name__)
logging.basicConfig(filename='myapp.log', level=logging.INFO)
logger.info('Started')

Then I replaced the "_do_poll" function (Line 307) with this one:

def _do_poll():
    global logger

    #time.sleep(0.004)
    data = _read_msg(26)
    if data != None:
        d_size  = data.pop(0)
        if d_size == 0:
            # No msg from MGC3130
            return
        d_flags = data.pop(0)
        d_seq   = data.pop(0)
        d_ident = data.pop(0)

        if d_ident == 0x91:
            _handle_sensor_data(data)
        elif d_ident == 0x15:
            _handle_status_info(data)
        else:
            pass
    else:
        logger.info("_read_msg returned None")

Please note that I leave the "time.sleep(0.004)" line commented. Then I did: tail -f myapp.log

and discovered that "_read_msg" returned "None" several times and still the code continue working. So, I guess I will uncomment the "time.sleep(0.004)" line and leave my "if data != None:" in the code, just in case that no data is read again.

It would be great if the developers of this library could solve the problem. Their product is still on the mark and just downgrading to Raspberry Pi 4 or lower isn't a solution.

By the way, I think that somewhere on the code, you should do: GPIO.cleanup()

Just to free the GPIO and avoid the message lgpio.error: 'GPIO busy'

tvoverbeek commented 6 months ago

Remember flicklib was written when only Pi1 and Pi2 existed. Pi5 is so much faster. I am also trying to rewrite the lib using only gpiozero since that works on all models. rpi-lgpio just tries to implement rpi.gpio with the newer libraries. gpios are only used for the reset line and the transfer line (and the flick large 2-color led)

jmeile commented 6 months ago

Remember flicklib was written when only Pi1 and Pi2 existed. Pi5 is so much faster.

Yes, in deed, it seems to be a problem with the latency, I guess that the device hasn't finished sending all the information, when the next read request takes place.