forked from deshipu/micropython-bno055
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bno055.py
175 lines (143 loc) · 5.2 KB
/
bno055.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
from micropython import const
import ustruct
from functools import partial
from time import sleep_ms
_CHIP_ID = const(0xa0)
CONFIG_MODE = const(0x00)
ACCONLY_MODE = const(0x01)
MAGONLY_MODE = const(0x02)
GYRONLY_MODE = const(0x03)
ACCMAG_MODE = const(0x04)
ACCGYRO_MODE = const(0x05)
MAGGYRO_MODE = const(0x06)
AMG_MODE = const(0x07)
IMUPLUS_MODE = const(0x08)
COMPASS_MODE = const(0x09)
M4G_MODE = const(0x0a)
NDOF_FMC_OFF_MODE = const(0x0b)
NDOF_MODE = const(0x0c)
_POWER_NORMAL = const(0x00)
_POWER_LOW = const(0x01)
_POWER_SUSPEND = const(0x02)
class BNO055:
"""
Driver for the BNO055 9DOF IMU sensor.
Example::
import bno055
from machine import I2C, Pin
i2c = I2C(-1, Pin(5), Pin(4))
s = bno055.BNO055(i2c)
print(s.temperature())
print(s.euler())
"""
def __init__(self, i2c, address=0x28):
self.i2c = i2c
self.address = address
self.init()
def _registers(self, register, struct, value=None, scale=1):
if value is None:
size = ustruct.calcsize(struct)
data = self.i2c.readfrom_mem(self.address, register, size)
value = ustruct.unpack(struct, data)
if scale != 1:
value = tuple(v * scale for v in value)
return value
if scale != 1:
value = tuple(v / scale for v in value)
data = ustruct.pack(struct, *value)
self.i2c.writeto_mem(self.address, register, data)
def _register(self, register, value=None, struct='B'):
if value is None:
return self._registers(register, struct=struct)[0]
self._registers(register, struct=struct, value=(value,))
_chip_id = partial(_register,
register=0x00,
value=None)
_power_mode = partial(_register,
register=0x3e)
_system_trigger = partial(_register,
register=0x3f)
_page_id = partial(_register,
register=0x07)
operation_mode = partial(_register,
register=0x3d)
errorcode = partial(_register,
register=0x3a,
value=None)
systemstatus = partial(_register,
register=0x39,
value=None)
temperature = partial(_register,
register=0x34,
value=None)
accelerometer = partial(_registers,
register=0x08,
struct='<hhh',
value=None,
scale=1/100)
magnetometer = partial(_registers,
register=0x0e,
struct='<hhh',
value=None,
scale=1/16)
gyroscope = partial(_registers,
register=0x14,
struct='<hhh',
value=None,
scale=1/900)
euler = partial(_registers,
register=0x1a,
struct='<hhh',
value=None,
scale=1/16)
quaternion = partial(_registers,
register=0x20,
struct='<hhhh',
value=None,
scale=1/(1<<14))
linear_acceleration = partial(_registers,
register=0x28,
struct='<hhh',
value=None,
scale=1/100)
gravity = partial(_registers,
register=0x2e,
struct='<hhh',
value=None,
scale=1/100)
def init(self, mode=NDOF_MODE):
chip_id = self._chip_id()
if chip_id != _CHIP_ID:
raise RuntimeError("bad chip id (%x != %x)" % (chip_id, _CHIP_ID))
self.reset()
self._power_mode(value=_POWER_NORMAL)
self._page_id(value=0)
self._system_trigger(value=0x00)
self.operation_mode(value=mode)
def reset(self):
self.operation_mode(value=CONFIG_MODE)
self._system_trigger(value=0x20)
while True:
try:
chip_id = self._chip_id()
except OSError as e:
if e.args[0] != 19: # errno 19 ENODEV
raise
chip_id = 0
if chip_id == _CHIP_ID:
return
def use_external_crystal(self, value):
last_mode = self.operation_mode()
self.operation_mode(value=config_mode)
self._page_id(value=0)
self._system_trigger(value=0x80 if value else 0x00)
self.operation_mode(value=last_mode)
def fix_bno(self):
rval = [-1, -1, -1]
while ((rval[0] != NDOF_MODE) and (rval[1] != 5) and (rval[2] != 0)):
self.operation_mode(value=NDOF_MODE)
for i in range(4):
sleep_ms(50)
rval = self.operation_mode(), self.systemstatus(), self.errorcode(), self.temperature(), self.euler()
return rval
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 syn=python