micropython-mlx90614 icon indicating copy to clipboard operation
micropython-mlx90614 copied to clipboard

OSError 5 when doing i2c.readfrom_mem

Open h3retek opened this issue 4 years ago • 2 comments

Board: Raspberry Pi Pico

Code:

import uos
import machine
import time

print(uos.uname())
print("Freq: "  + str(machine.freq()) + " Hz")

i2c = machine.I2C(0, scl=machine.Pin(5), sda=machine.Pin(4))
print(i2c)

print("Available i2c devices: "+ str(hex(i2c.scan()[0])))

import ustruct

_REGISTER_TA = const(0x06)     # ambient
_REGISTER_TOBJ1 = const(0x07)  # object
_REGISTER_TOBJ2 = const(0x08)  # object2

class MLX90614:
	def __init__(self, i2c, address=0x5a):
		self.i2c = i2c
		self.address = address
		_config1 = i2c.readfrom_mem(address, 0x25, 2)
		_dz = ustruct.unpack('<H', _config1)[0] & (1<<6)
		self.dual_zone = True if _dz else False

	def read16(self, register):
		data = self.i2c.readfrom_mem(self.address, register, 2)
		return ustruct.unpack('<H', data)[0]

	def read_temp(self, register):
		temp = self.read16(register);
		# apply measurement resolution (0.02 degrees per LSB)
		temp *= .02;
		# Kelvin to Celcius
		temp -= 273.15;
		return temp;

	def read_ambient_temp(self):
		return self.read_temp(_REGISTER_TA)

	def read_object_temp(self):
		return self.read_temp(_REGISTER_TOBJ1)

	def read_object2_temp(self):
		if self.dual_zone:
			return self.read_temp(_REGISTER_TOBJ2)
		else:
			raise RuntimeError("Device only has one thermopile")

	@property
	def ambient_temp(self):
		return self.read_ambient_temp()

	@property
	def object_temp(self):
		return self.read_object_temp()

	@property
	def object2_temp(self):
		return self.read_object2_temp()
	
sensor = MLX90614(i2c)

while True:
    print(sensor.read_ambient_temp())
    time.sleep(1)

Output:

(sysname='rp2', nodename='rp2', release='1.14.0', version='v1.14 on 2021-02-09 (GNU 10.2.0 MinSizeRel)', machine='Raspberry Pi Pico with RP2040')
Freq: 125000000 Hz
I2C(0, freq=399361, scl=5, sda=4)
Available i2c devices: 0x5a
Traceback (most recent call last):
  File "<stdin>", line 63, in <module>
  File "<stdin>", line 23, in __init__
OSError: 5

h3retek avatar Feb 18 '21 05:02 h3retek

I've hit this OSError: 5 a few times now on different modules. Not sure exactly what is causing it. Try switching to SoftI2C. That fixes it for me on other boards.

Replace:

i2c = machine.I2C(0, scl=machine.Pin(5), sda=machine.Pin(4))

With:

i2c = machine.SoftI2C(scl=machine.Pin(5), sda=machine.Pin(4))

mcauser avatar Feb 18 '21 14:02 mcauser

After re-reading the datasheet, it looks like your I2C freq is too high. Drop your 399361 to > 100000 and it should start working.

The maximum frequency of the MLX90614 SMBus is 100 KHz and the minimum is 10 KHz. 8.4.7 Timing specification - Page 21

mcauser avatar Apr 16 '21 12:04 mcauser