I just started with MicroPython. I have a NodeMCU board (with CP2102), and I installed latest MicroPython firmware into it. Using UPyCraft as an IDE and uploader. I already did some rudimentary things, and now I'm trying to get a HMC5883L digital compass (on a GY-273 board) to work. It uses i2c protocol for data transfer.
I hooked up the HMC5883L like so: VCC to NodeMCU 3.3V pin, GND to GND, DRDY unhooked, SDA to D2 (GPIO4), SCL to D1 (GPIO5). I also added 4.7K resistors to SDA and SCL, pulling them up to 3.3V.
Now, to get it to work, I am running this library. Here is the code from hmc5883l.py:
Code: Select all
import math
import machine
from ustruct import pack
from array import array
class HMC5883L:
__gain__ = {
'0.88': (0 << 5, 0.73),
'1.3': (1 << 5, 0.92),
'1.9': (2 << 5, 1.22),
'2.5': (3 << 5, 1.52),
'4.0': (4 << 5, 2.27),
'4.7': (5 << 5, 2.56),
'5.6': (6 << 5, 3.03),
'8.1': (7 << 5, 4.35)
}
def __init__(self, scl=4, sda=5, address=30, gauss='1.3', declination=(0, 0)):
self.i2c = i2c = machine.I2C(scl=machine.Pin(scl), sda=machine.Pin(sda), freq=100000)
# Initialize sensor.
i2c.start()
# Configuration register A:
# 0bx11xxxxx -> 8 samples averaged per measurement
# 0bxxx100xx -> 15 Hz, rate at which data is written to output registers
# 0bxxxxxx00 -> Normal measurement mode
i2c.writeto_mem(30, 0x00, pack('B', 0b111000))
# Configuration register B:
reg_value, self.gain = self.__gain__[gauss]
i2c.writeto_mem(30, 0x01, pack('B', reg_value))
# Set mode register to continuous mode.
i2c.writeto_mem(30, 0x02, pack('B', 0x00))
i2c.stop()
# Convert declination (tuple of degrees and minutes) to radians.
self.declination = (declination[0] + declination[1] / 60) * math.pi / 180
# Reserve some memory for the raw xyz measurements.
self.data = array('B', [0] * 6)
def read(self):
data = self.data
gain = self.gain
self.i2c.readfrom_mem_into(30, 0x03, data)
x = (data[0] << 8) | data[1]
z = (data[2] << 8) | data[3]
y = (data[4] << 8) | data[5]
x = x - (1 << 16) if x & (1 << 15) else x
y = y - (1 << 16) if y & (1 << 15) else y
z = z - (1 << 16) if z & (1 << 15) else z
x = round(x * gain, 4)
y = round(y * gain, 4)
z = round(z * gain, 4)
return x, y, z
def heading(self, x, y):
heading_rad = math.atan2(y, x)
heading_rad += self.declination
# Correct reverse heading.
if heading_rad < 0:
heading_rad += 2 * math.pi
# Compensate for wrapping.
elif heading_rad > 2 * math.pi:
heading_rad -= 2 * math.pi
# Convert from radians to degrees.
heading = heading_rad * 180 / math.pi
degrees = math.floor(heading)
minutes = round((heading - degrees) * 60)
return degrees, minutes
def format_result(self, x, y, z):
degrees, minutes = self.heading(x, y)
return 'X: {:.4f}, Y: {:.4f}, Z: {:.4f}, Heading: {}° {}′ '.format(x, y, z, degrees, minutes)
Code: Select all
from hmc5883l import HMC5883L
sensor = HMC5883L(scl=5, sda=4)
Line 30 isTraceback (most recent call last):
File "<stdin>", line 1, in <module>
File "hmc5883l.py", line 30, in __init__
OSError: [Errno 19] ENODEV
Code: Select all
i2c.writeto_mem(30, 0x00, pack('B', 0b111000))
Code: Select all
import machine
i2c = machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))
devices = i2c.scan()
for device in devices:
print("Decimal address: ",device," | Hexa address: ",hex(device))
It appears that it sees a device, but the hex address seems wrong.Decimal address: 13 | Hexa address: 0xd
I already tried swapping the SDA and SCL lines, but I get the exact same error.
Can somebody please share any suggestions? Where is my mistake?
Thank you!
EDIT:
I forgot to mention that I already found two topics relating to this issue on this forum:
viewtopic.php?f=16&t=7158&p=40718&hilit=enodev#p40718
viewtopic.php?f=6&t=6371&hilit=enodev
First one suggested reconnecting the device, while the second one suggested lowering pbs rate to 1000. I tried both, but it didn't work.