melexis-fir / mlx9064x-driver-py

MLX90640/41 python driver
Other
11 stars 4 forks source link

Error: 'NoneType' object is not subscriptable #6

Closed Kirei28 closed 3 years ago

Kirei28 commented 3 years ago

Hello, I'm trying to access the MLX90641 using the EVB9064x and there is always an error when taking the frame of the sensor.

My code is

import mlx.mlx90640 as mlx

dev = mlx.Mlx9064x('auto', i2c_addr=0x33, frame_rate=8.0) # establish communication between EVB90640 and
                                                          # PC, the I2C address of the MLX90640 sensor is
                                                          # 0x33 and change the frame rate to 8Hz
dev.init()                      # read EEPROM and pre-compute calibration parameters.
frame = dev.read_frame()        # Read a frame from MLX90640
                                # In case EVB90640 hw is used, the EVB will buffer up to 4 frames, so possibly you get a cached frame.
f = dev.do_compensation(frame)  # calculates the temperatures for each pixel

and I'm having this error

Traceback (most recent call last):
  File "/home/pi/Desktop/mlx90640.py", line 9, in <module>
    f = dev.do_compensation(frame)  # calculates the temperatures for each pixel
  File "/home/pi/.virtualenvs/cv/lib/python3.7/site-packages/mlx/mlx90640.py", line 163, in do_compensation
    info_data = raw_frame[np:]
TypeError: 'NoneType' object is not subscriptable

Can you help me with this?

mlx-kva commented 3 years ago

Hello Kirei,

Can you try to run this command:

mlx9064x-dump-frame auto

Now we have observed there is an error in other parts of this python code (calibration data is wrongly applied). We are working on a major update to fix the issue.

I'll keep you informed.

Kirei28 commented 3 years ago

Thanks for the reply!

Yes, I have tried that command before and it does send frame data. May I ask if you know other alternative drivers that works with the EVB90640 interface?. Thanks in advance.

mlx-kva commented 3 years ago

Please give this a try: https://github.com/melexis-fir/mlx90641-driver-py It is does not support yet the EVB... but using raspberry pi 4, should work. Start with running the script: https://github.com/melexis-fir/mlx90641-driver-py/blob/master/mlx90641_dump.py

mlx-kva commented 3 years ago

Alternatively, if you want EVB, there is a 'PSF' available: https://www.melexis.com/en/product/EVB90640-41/Evaluation-Board-MLX90640 See PSF implementation example for EVB90640-41 and Software library - PSF - EVB MLX90640 and MLX90641 in the tools/software section. (windows only)

Kirei28 commented 3 years ago

Thank you so much for the help, sorry for being so clueless about these devices. Can I connect the sensors directly to the raspberry pi pins? Or should I add anything like bypass capacitors first? Also, I'm using raspberry pi 3b+

Kirei28 commented 3 years ago

Please give this a try: https://github.com/melexis-fir/mlx90641-driver-py It is does not support yet the EVB... but using raspberry pi 4, should work. Start with running the script: https://github.com/melexis-fir/mlx90641-driver-py/blob/master/mlx90641_dump.py

Also, there's an error installing this library pi@raspberrypi:~ $ pip install mlx90641 Defaulting to user installation because normal site-packages is not writeable Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple ERROR: Could not find a version that satisfies the requirement mlx90641 ERROR: No matching distribution found for mlx90641

mlx-kva commented 3 years ago

Have a look at: https://github.com/melexis-fir/mlx90641-driver-py#installation

install with pip install mlx90641-driver!

Kirei28 commented 3 years ago

I tried this code "import mlx90641 as mlx

def main(): print("start") dev = mlx. print("dev", dev)

r = dev.i2c_init("/dev/i2c-1")

print("init", r)
r = dev.set_refresh_rate(1)
print("setRefreshRate", r)

refresh_rate = dev.get_refresh_rate()
print("refresh rate: {}".format(refresh_rate))

dev.dump_eeprom()
dev.extract_parameters()

for i in range(0, 10):
    dev.get_frame_data()
    ta = dev.get_ta() - 8.0
    emissivity = 1

    to = dev.calculate_to(emissivity, ta)

    print("{:02d}: {}".format(i, ','.join(format(x, ".2f") for x in to)))

if name == "main": main() " However, it returned this error "Python 3.7.3 (/home/pi/.virtualenvs/cv/bin/python3.7)

%Run mlx90641.py start Traceback (most recent call last): File "/home/pi/Desktop/mlx90641.py", line 32, in main() File "/home/pi/Desktop/mlx90641.py", line 5, in main dev = MLX90641() NameError: name 'MLX90641' is not defined"

mlx-kva commented 3 years ago

This goes back to python basics.

import mlx90641

will import the script itselfs, when your script is named mlx90641.py. Please name your script different than the module you want to import.

Just use the name as provided, mlx90641_dump.py for instance.

tinito commented 3 years ago

Hello,

I'm having the very same issue, I can grab frames with mlx9064x-dump-frame but with a simple python script I get:

Traceback (most recent call last):
  File "test.py", line 8, in <module>
    f = dev.do_compensation(frame)  # calculates the temperatures for each pixel
  File "/home/pi/.local/share/virtualenvs/melexis-7R3otVdu/lib/python3.7/site-packages/mlx/mlx90640.py", line 164, in do_compensation
    info_data = raw_frame[np:]
TypeError: 'NoneType' object is not subscriptable

Any news regarding the major update which should fix the issue?

mlx-kva commented 3 years ago

Hi Tinito,

It would be nice if you can share your test.py... Can you also tell which I2C hardware interface you are using?

tinito commented 3 years ago

I'm using the EVB, so I2C over USB.

My script was as simple as:

import mlx.mlx90640 as mlx

dev = mlx.Mlx9064x('/dev/ttyACM0', frame_rate=1.0)
dev.init() 

frame = dev.read_frame()
dev.do_compensation(frame)
print(frame)

The issue was caused by frame being None, and do_compensation() fails as a consequence.

The workaround is just to keep trying:

import mlx.mlx90640 as mlx

dev = mlx.Mlx9064x('/dev/ttyACM0', frame_rate=1.0)
dev.init() 

frame = None
while frame is None:
    frame = dev.read_frame()

dev.do_compensation(frame)
print(frame)
mlx-kva commented 3 years ago

Hi,

It is indeed a little bit like in the example: https://github.com/melexis-fir/mlx9064x-driver-py/blob/master/mlx/examples/mlx90640_dump_frame.py#L54

Now, I have to admit this version contains a little error in applying the calibration parameters. So your accuracy might be not at level using this driver. We have this driver: https://github.com/melexis-fir/mlx90640-driver-py https://github.com/melexis-fir/mlx90641-driver-py Where we use the same code as for MCU's (embedded C-code). However the EVB interface with that driver is not stable at the time of writing this comment. Should you want to use the I2C from MCP2221 or from the 40-pin header of a Raspberry Pi (devicetree), you might want to give that one a try.

tinito commented 3 years ago

Thank you for pointing this out.

Might I ask some additional details about what is wrong? If possible, I can try to port the C-code to the Python driver, so we get accurate results. I have to stay with the EVB over USB, unfortunately.

mlx-kva commented 3 years ago

Yesterday, I've made an update where the 'serial port' lib is replace by another one. Currently I have no access to a linux environment, so only the win 10 is checked. I expect issues with some timeout settings, so unlikely it will work as-is on linux. I guess those 3 lines needs to be updated: https://github.com/melexis-fir/mlx90640-driver-evb9064x-py/blob/master/evb9064x/c-code/src/rs232.c#L197 https://github.com/melexis-fir/mlx90640-driver-evb9064x-py/blob/master/evb9064x/c-code/src/rs232.c#L235-L236

mlx-kva commented 3 years ago

So I found a way to access a raspberry pi. Please check it out: https://github.com/melexis-fir/mlx90640-driver-evb9064x-py/#getting-started

tinito commented 3 years ago

Thank you! I'll give a try tomorrow.