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

OSError 5 when doing i2c.readfrom_mem #3

Open
h3retek opened this issue Feb 18, 2021 · 2 comments
Open

OSError 5 when doing i2c.readfrom_mem #3

h3retek opened this issue Feb 18, 2021 · 2 comments
Labels

Comments

@h3retek
Copy link

h3retek commented Feb 18, 2021

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
@mcauser
Copy link
Owner

mcauser commented Feb 18, 2021

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
Copy link
Owner

mcauser commented Apr 16, 2021

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

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

No branches or pull requests

2 participants