Skip to content

Commit ce0cfa5

Browse files
author
Sebastian Goscik
committed
Copied accelerometer changes to pytrack
1 parent 89ab2be commit ce0cfa5

File tree

1 file changed

+45
-23
lines changed

1 file changed

+45
-23
lines changed

pytrack/lib/LIS2HH12.py

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
ACC_G_DIV = 1000 * 65536
2020

21+
2122
class LIS2HH12:
2223

2324
ACC_I2CADDR = const(30)
@@ -37,14 +38,16 @@ class LIS2HH12:
3738
ACT_THS = const(0x1E)
3839
ACT_DUR = const(0x1F)
3940

41+
SCALES = {FULL_SCALE_2G: 4000, FULL_SCALE_4G: 8000, FULL_SCALE_8G: 16000}
42+
ODRS = [0, 10, 50, 100, 200, 400, 800]
43+
4044
def __init__(self, pysense = None, sda = 'P22', scl = 'P21'):
4145
if pysense is not None:
4246
self.i2c = pysense.i2c
4347
else:
4448
from machine import I2C
4549
self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
4650

47-
self.reg = bytearray(1)
4851
self.odr = 0
4952
self.full_scale = 0
5053
self.x = 0
@@ -54,9 +57,6 @@ def __init__(self, pysense = None, sda = 'P22', scl = 'P21'):
5457
self.act_dur = 0
5558
self.debounced = False
5659

57-
self.scales = {FULL_SCALE_2G: 4000, FULL_SCALE_4G: 8000, FULL_SCALE_8G: 16000}
58-
self.odrs = [0, 10, 50, 100, 200, 400, 800]
59-
6060
whoami = self.i2c.readfrom_mem(ACC_I2CADDR , PRODUCTID_REG, 1)
6161
if (whoami[0] != 0x41):
6262
raise ValueError("LIS2HH12 not found")
@@ -68,9 +68,7 @@ def __init__(self, pysense = None, sda = 'P22', scl = 'P21'):
6868
self.set_full_scale(FULL_SCALE_4G)
6969

7070
# set the interrupt pin as active low and open drain
71-
self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL5_REG, self.reg)
72-
self.reg[0] |= 0b00000011
73-
self.i2c.writeto_mem(ACC_I2CADDR , CTRL5_REG, self.reg)
71+
self.set_register(CTRL5_REG, 3, 0, 3)
7472

7573
# make a first read
7674
self.acceleration()
@@ -82,7 +80,7 @@ def acceleration(self):
8280
self.y = struct.unpack('<h', y)
8381
z = self.i2c.readfrom_mem(ACC_I2CADDR , ACC_Z_L_REG, 2)
8482
self.z = struct.unpack('<h', z)
85-
_mult = self.scales[self.full_scale] / ACC_G_DIV
83+
_mult = self.SCALES[self.full_scale] / ACC_G_DIV
8684
return (self.x[0] * _mult, self.y[0] * _mult, self.z[0] * _mult)
8785

8886
def roll(self):
@@ -95,39 +93,63 @@ def pitch(self):
9593
rad = -math.atan2(y, (math.sqrt(x*x + z*z)))
9694
return (180 / math.pi) * rad
9795

96+
def set_register(self, register, value, offset, mask):
97+
reg = bytearray(self.i2c.readfrom_mem(ACC_I2CADDR, register, 1))
98+
reg[0] &= ~(mask << offset)
99+
reg[0] |= ((value & mask) << offset)
100+
self.i2c.writeto_mem(ACC_I2CADDR, register, reg)
101+
98102
def set_full_scale(self, scale):
99-
self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL4_REG, self.reg)
100-
self.reg[0] &= ~0b00110000
101-
self.reg[0] |= (scale & 3) << 4
102-
self.i2c.writeto_mem(ACC_I2CADDR , CTRL4_REG, self.reg)
103+
self.set_register(CTRL4_REG, scale, 4, 3)
103104
self.full_scale = scale
104105

105106
def set_odr(self, odr):
106-
self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL1_REG, self.reg)
107-
self.reg[0] &= ~0b01110000
108-
self.reg[0] |= (odr & 7) << 4
109-
self.i2c.writeto_mem(ACC_I2CADDR , CTRL1_REG, self.reg)
107+
self.set_register(CTRL1_REG, odr, 4, 7)
110108
self.odr = odr
111109

110+
def set_high_pass(self, hp):
111+
self.set_register(CTRL2_REG, 1 if hp else 0, 2, 1)
112+
112113
def enable_activity_interrupt(self, threshold, duration, handler=None):
113114
# Threshold is in mg, duration is ms
114115
self.act_dur = duration
115116

116-
_ths = int((threshold * self.scales[self.full_scale]) / 2000 / 128) & 0x7F
117-
_dur = int((duration * self.odrs[self.odr]) / 1000 / 8)
117+
if threshold > self.SCALES[self.full_scale]:
118+
error = "threshold %d exceeds full scale %d" % (thresold, self.SCALES[self.full_scale])
119+
print(error)
120+
raise ValueError(error)
118121

119-
self.i2c.writeto_mem(ACC_I2CADDR , ACT_THS, _ths)
120-
self.i2c.writeto_mem(ACC_I2CADDR , ACT_DUR, _dur)
122+
if threshold < self.SCALES[self.full_scale] / 128:
123+
error = "threshold %d below resolution %d" % (thresold, self.SCALES[self.full_scale]/128)
124+
print(error)
125+
raise ValueError(error)
126+
127+
if duration > 255 * 1000 * 8 / self.ODRS[self.odr]:
128+
error = "duration %d exceeds max possible value %d" % (duration, 255 * 1000 * 8 / self.ODRS[self.odr])
129+
print(error)
130+
raise ValueError(error)
131+
132+
if duration < 1000 * 8 / self.ODRS[self.odr]:
133+
error = "duration %d below resolution %d" % (duration, 1000 * 8 / self.ODRS[self.odr])
134+
print(error)
135+
raise ValueError(error)
136+
137+
_ths = int(127 * threshold / self.SCALES[self.full_scale]) & 0x7F
138+
_dur = int((duration * self.ODRS[self.odr]) / 1000 / 8)
139+
140+
self.i2c.writeto_mem(ACC_I2CADDR, ACT_THS, _ths)
141+
self.i2c.writeto_mem(ACC_I2CADDR, ACT_DUR, _dur)
121142

122143
# enable the activity/inactivity interrupt
123-
self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL3_REG, self.reg)
124-
self.reg[0] |= 0b00100000
125-
self.i2c.writeto_mem(ACC_I2CADDR , CTRL3_REG, self.reg)
144+
self.set_register(CTRL3_REG, 1, 5, 1)
126145

127146
self._user_handler = handler
128147
self.int_pin = Pin('P13', mode=Pin.IN)
129148
self.int_pin.callback(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._int_handler)
130149

150+
# return actual used thresold and duration
151+
return (_ths * self.SCALES[self.full_scale] / 128, _dur * 8 * 1000 / self.ODRS[self.odr])
152+
131153
def activity(self):
132154
if not self.debounced:
133155
time.sleep_ms(self.act_dur)

0 commit comments

Comments
 (0)