Skip to content

Commit fcc8c16

Browse files
committed
add pixel and mpu9250 etc.
1 parent fcff786 commit fcc8c16

5 files changed

Lines changed: 500 additions & 11 deletions

File tree

01.leds/pixel.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from machine import Pin
2+
from neopixel import NeoPixel
3+
4+
def PixelPower(bool):
5+
Pin(2, Pin.OUT).value(bool)
6+
7+
class Pixel(NeoPixel):
8+
9+
def __init__(self):
10+
self.Min, self.Max, self.Sum = 0, 5, 25
11+
NeoPixel.__init__(self, Pin(4), self.Sum, 3, 1)
12+
13+
def LoadXY(self, X, Y, RGB, isSoftWare = True):
14+
if self.Min <= X and X < self.Max and self.Min <= Y and Y < self.Max:
15+
if isSoftWare: # SoftWare coordinate system
16+
self[int(Y) + ((self.Max - 1) - int(X)) * self.Max] = RGB # left and top is (0, 0)
17+
else: # Hardware coordinate system
18+
self[(int(X)) + int(Y) * self.Max] = RGB # right and top is (0, 0)
19+
else:
20+
pass
21+
# print('Pixel Load Over Limit')
22+
23+
def LoadPos(self, Pos, RGB):
24+
if self.Min <= Pos and Pos < self.Sum:
25+
self[Pos] = RGB
26+
else:
27+
pass
28+
# print('Pixel Load Over Limit')
29+
30+
def Show(self):
31+
self.write()
32+
33+
34+
PixelPower(True)
35+
View = Pixel()
36+
37+
View.LoadXY(0, 0, (10, 0, 0))
38+
View.LoadXY(0, 4, (0, 10, 0))
39+
View.LoadXY(4, 0, (0, 0, 10))
40+
View.LoadXY(4, 4, (10, 10, 10))
41+
View.Show()
42+
43+
# default SoftWare coordinate system

07.sensors/mpu9250/Mpu9250.py

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,70 @@
1-
import utime
2-
from machine import I2C, Pin
3-
from mpu9250 import MPU9250
4-
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=200000)
5-
sensor = MPU9250(i2c)
6-
print("MPU9250 id: " + hex(sensor.whoami))
7-
while True:
8-
print('acceleration:', str(sensor.acceleration))
9-
print('gyro:', str(sensor.gyro))
10-
print('magnetic:', str(sensor.magnetic))
11-
1+
#
2+
# This file is part of MicroPython MPU9250 driver
3+
# Copyright (c) 2018 Mika Tuupola
4+
#
5+
# Licensed under the MIT license:
6+
# http://www.opensource.org/licenses/mit-license.php
7+
#
8+
# Project home:
9+
# https://github.com/tuupola/micropython-mpu9250
10+
#
11+
12+
"""
13+
MicroPython I2C driver for MPU9250 9-axis motion tracking device
14+
"""
15+
16+
# pylint: disable=import-error
17+
from micropython import const
18+
from mpu6500 import MPU6500
19+
from ak8963 import AK8963
20+
# pylint: enable=import-error
21+
22+
__version__ = "0.2.0"
23+
24+
class MPU9250:
25+
"""Class which provides interface to MPU9250 9-axis motion tracking device."""
26+
def __init__(self, i2c, mpu6500 = None, ak8963 = None):
27+
if mpu6500 is None:
28+
self.mpu6500 = MPU6500(i2c)
29+
else:
30+
self.mpu6500 = mpu6500
31+
# '''
32+
if ak8963 is None:
33+
self.ak8963 = AK8963(i2c)
34+
else:
35+
self.ak8963 = ak8963
36+
# '''
37+
@property
38+
def acceleration(self):
39+
"""
40+
Acceleration measured by the sensor. By default will return a
41+
3-tuple of X, Y, Z axis values in m/s^2 as floats. To get values in g
42+
pass `accel_fs=SF_G` parameter to the MPU6500 constructor.
43+
"""
44+
return self.mpu6500.acceleration
45+
46+
@property
47+
def gyro(self):
48+
"""
49+
Gyro measured by the sensor. By default will return a 3-tuple of
50+
X, Y, Z axis values in rad/s as floats. To get values in deg/s pass
51+
`gyro_sf=SF_DEG_S` parameter to the MPU6500 constructor.
52+
"""
53+
return self.mpu6500.gyro
54+
55+
@property
56+
def magnetic(self):
57+
"""
58+
X, Y, Z axis micro-Tesla (uT) as floats.
59+
"""
60+
return self.ak8963.magnetic
61+
62+
@property
63+
def whoami(self):
64+
return self.mpu6500.whoami
65+
66+
def __enter__(self):
67+
return self
68+
69+
def __exit__(self, exception_type, exception_value, traceback):
70+
pass

07.sensors/mpu9250/ak8963.py

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#
2+
# This file is part of MicroPython MPU9250 driver
3+
# Copyright (c) 2018 Mika Tuupola
4+
#
5+
# Licensed under the MIT license:
6+
# http://www.opensource.org/licenses/mit-license.php
7+
#
8+
# See:
9+
# https://github.com/tuupola/micropython-mpu9250
10+
# https://www.akm.com/akm/en/file/datasheet/AK8963C.pdf
11+
#
12+
13+
"""
14+
MicroPython I2C driver for AK8963 magnetometer
15+
"""
16+
17+
__version__ = "0.2.0"
18+
19+
# pylint: disable=import-error
20+
import ustruct
21+
import utime
22+
from machine import I2C, Pin
23+
from micropython import const
24+
# pylint: enable=import-error
25+
26+
_WIA = const(0x00)
27+
_HXL = const(0x03)
28+
_HXH = const(0x04)
29+
_HYL = const(0x05)
30+
_HYH = const(0x06)
31+
_HZL = const(0x07)
32+
_HZH = const(0x08)
33+
_ST2 = const(0x09)
34+
_CNTL1 = const(0x0a)
35+
_ASAX = const(0x10)
36+
_ASAY = const(0x11)
37+
_ASAZ = const(0x12)
38+
39+
_MODE_POWER_DOWN = 0b00000000
40+
MODE_SINGLE_MEASURE = 0b00000001
41+
MODE_CONTINOUS_MEASURE_1 = 0b00000010 # 8Hz
42+
MODE_CONTINOUS_MEASURE_2 = 0b00000110 # 100Hz
43+
MODE_EXTERNAL_TRIGGER_MEASURE = 0b00000100
44+
_MODE_SELF_TEST = 0b00001000
45+
_MODE_FUSE_ROM_ACCESS = 0b00001111
46+
47+
OUTPUT_14_BIT = 0b00000000
48+
OUTPUT_16_BIT = 0b00010000
49+
50+
_SO_14BIT = 0.6 # μT per digit when 14bit mode
51+
_SO_16BIT = 0.15 # μT per digit when 16bit mode
52+
53+
class AK8963:
54+
"""Class which provides interface to AK8963 magnetometer."""
55+
def __init__(
56+
self, i2c, address=0x0c,
57+
mode=MODE_CONTINOUS_MEASURE_1, output=OUTPUT_16_BIT,
58+
offset=(0, 0, 0), scale=(1, 1, 1)
59+
):
60+
self.i2c = i2c
61+
self.address = address
62+
self._offset = offset
63+
self._scale = scale
64+
65+
if 0x48 != self.whoami:
66+
raise RuntimeError("AK8963 not found in I2C bus.")
67+
68+
# Sensitivity adjustement values
69+
self._register_char(_CNTL1, _MODE_FUSE_ROM_ACCESS)
70+
asax = self._register_char(_ASAX)
71+
asay = self._register_char(_ASAY)
72+
asaz = self._register_char(_ASAZ)
73+
self._register_char(_CNTL1, _MODE_POWER_DOWN)
74+
75+
# Should wait atleast 100us before next mode
76+
self._adjustement = (
77+
(0.5 * (asax - 128)) / 128 + 1,
78+
(0.5 * (asay - 128)) / 128 + 1,
79+
(0.5 * (asaz - 128)) / 128 + 1
80+
)
81+
82+
# Power on
83+
self._register_char(_CNTL1, (mode | output))
84+
85+
if output is OUTPUT_16_BIT:
86+
self._so = _SO_16BIT
87+
else:
88+
self._so = _SO_14BIT
89+
90+
@property
91+
def magnetic(self):
92+
"""
93+
X, Y, Z axis micro-Tesla (uT) as floats.
94+
"""
95+
xyz = list(self._register_three_shorts(_HXL))
96+
self._register_char(_ST2) # Enable updating readings again
97+
98+
# Apply factory axial sensitivy adjustements
99+
xyz[0] *= self._adjustement[0]
100+
xyz[1] *= self._adjustement[1]
101+
xyz[2] *= self._adjustement[2]
102+
103+
# Apply output scale determined in constructor
104+
so = self._so
105+
xyz[0] *= so
106+
xyz[1] *= so
107+
xyz[2] *= so
108+
109+
# Apply hard iron ie. offset bias from calibration
110+
xyz[0] -= self._offset[0]
111+
xyz[1] -= self._offset[1]
112+
xyz[2] -= self._offset[2]
113+
114+
# Apply soft iron ie. scale bias from calibration
115+
xyz[0] *= self._scale[0]
116+
xyz[1] *= self._scale[1]
117+
xyz[2] *= self._scale[2]
118+
119+
return tuple(xyz)
120+
121+
@property
122+
def adjustement(self):
123+
return self._adjustement
124+
125+
@property
126+
def whoami(self):
127+
""" Value of the whoami register. """
128+
return self._register_char(_WIA)
129+
130+
def calibrate(self, count=256, delay=200):
131+
self._offset = (0, 0, 0)
132+
self._scale = (1, 1, 1)
133+
134+
reading = self.magnetic
135+
minx = maxx = reading[0]
136+
miny = maxy = reading[1]
137+
minz = maxz = reading[2]
138+
139+
while count:
140+
utime.sleep_ms(delay)
141+
reading = self.magnetic
142+
minx = min(minx, reading[0])
143+
maxx = max(maxx, reading[0])
144+
miny = min(miny, reading[1])
145+
maxy = max(maxy, reading[1])
146+
minz = min(minz, reading[2])
147+
maxz = max(maxz, reading[2])
148+
count -= 1
149+
150+
# Hard iron correction
151+
offset_x = (maxx + minx) / 2
152+
offset_y = (maxy + miny) / 2
153+
offset_z = (maxz + minz) / 2
154+
155+
self._offset = (offset_x, offset_y, offset_z)
156+
157+
# Soft iron correction
158+
avg_delta_x = (maxx - minx) / 2
159+
avg_delta_y = (maxy - miny) / 2
160+
avg_delta_z = (maxz - minz) / 2
161+
162+
avg_delta = (avg_delta_x + avg_delta_y + avg_delta_z) / 3
163+
164+
scale_x = avg_delta / avg_delta_x
165+
scale_y = avg_delta / avg_delta_y
166+
scale_z = avg_delta / avg_delta_z
167+
168+
self._scale = (scale_x, scale_y, scale_z)
169+
170+
return self._offset, self._scale
171+
172+
def _register_short(self, register, value=None, buf=bytearray(2)):
173+
if value is None:
174+
self.i2c.readfrom_mem_into(self.address, register, buf)
175+
return ustruct.unpack("<h", buf)[0]
176+
177+
ustruct.pack_into("<h", buf, 0, value)
178+
return self.i2c.writeto_mem(self.address, register, buf)
179+
180+
def _register_three_shorts(self, register, buf=bytearray(6)):
181+
self.i2c.readfrom_mem_into(self.address, register, buf)
182+
return ustruct.unpack("<hhh", buf)
183+
184+
def _register_char(self, register, value=None, buf=bytearray(1)):
185+
if value is None:
186+
self.i2c.readfrom_mem_into(self.address, register, buf)
187+
return buf[0]
188+
189+
ustruct.pack_into("<b", buf, 0, value)
190+
return self.i2c.writeto_mem(self.address, register, buf)
191+
192+
def __enter__(self):
193+
return self
194+
195+
def __exit__(self, exception_type, exception_value, traceback):
196+
pass

07.sensors/mpu9250/exmaple.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import utime
2+
from machine import I2C, Pin
3+
from mpu9250 import MPU9250
4+
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=200000)
5+
sensor = MPU9250(i2c)
6+
print("MPU9250 id: " + hex(sensor.whoami))
7+
while True:
8+
print('acceleration:', str(sensor.acceleration))
9+
print('gyro:', str(sensor.gyro))
10+
print('magnetic:', str(sensor.magnetic))
11+

0 commit comments

Comments
 (0)