Skip to content

Commit d9ba35e

Browse files
author
Aditya Jain
committed
Added code in pyscan to send light and accelerometer data to pybytes
1 parent 9e7d420 commit d9ba35e

File tree

3 files changed

+249
-0
lines changed

3 files changed

+249
-0
lines changed

pyscan/lib/LIS2HH12.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import math
2+
import time
3+
import struct
4+
from machine import Pin
5+
6+
7+
FULL_SCALE_2G = const(0)
8+
FULL_SCALE_4G = const(2)
9+
FULL_SCALE_8G = const(3)
10+
11+
ODR_POWER_DOWN = const(0)
12+
ODR_10_HZ = const(1)
13+
ODR_50_HZ = const(2)
14+
ODR_100_HZ = const(3)
15+
ODR_200_HZ = const(4)
16+
ODR_400_HZ = const(5)
17+
ODR_800_HZ = const(6)
18+
19+
ACC_G_DIV = 1000 * 65536
20+
21+
22+
class LIS2HH12:
23+
24+
ACC_I2CADDR = const(30)
25+
26+
PRODUCTID_REG = const(0x0F)
27+
CTRL1_REG = const(0x20)
28+
CTRL2_REG = const(0x21)
29+
CTRL3_REG = const(0x22)
30+
CTRL4_REG = const(0x23)
31+
CTRL5_REG = const(0x24)
32+
ACC_X_L_REG = const(0x28)
33+
ACC_X_H_REG = const(0x29)
34+
ACC_Y_L_REG = const(0x2A)
35+
ACC_Y_H_REG = const(0x2B)
36+
ACC_Z_L_REG = const(0x2C)
37+
ACC_Z_H_REG = const(0x2D)
38+
ACT_THS = const(0x1E)
39+
ACT_DUR = const(0x1F)
40+
41+
SCALES = {FULL_SCALE_2G: 4000, FULL_SCALE_4G: 8000, FULL_SCALE_8G: 16000}
42+
ODRS = [0, 10, 50, 100, 200, 400, 800]
43+
44+
def __init__(self, pysense = None, sda = 'P22', scl = 'P21'):
45+
if pysense is not None:
46+
self.i2c = pysense.i2c
47+
else:
48+
from machine import I2C
49+
self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
50+
51+
self.odr = 0
52+
self.full_scale = 0
53+
self.x = 0
54+
self.y = 0
55+
self.z = 0
56+
self.int_pin = None
57+
self.act_dur = 0
58+
self.debounced = False
59+
60+
whoami = self.i2c.readfrom_mem(ACC_I2CADDR , PRODUCTID_REG, 1)
61+
if (whoami[0] != 0x41):
62+
raise ValueError("LIS2HH12 not found")
63+
64+
# enable acceleration readings at 50Hz
65+
self.set_odr(ODR_50_HZ)
66+
67+
# change the full-scale to 4g
68+
self.set_full_scale(FULL_SCALE_4G)
69+
70+
# set the interrupt pin as active low and open drain
71+
self.set_register(CTRL5_REG, 3, 0, 3)
72+
73+
# make a first read
74+
self.acceleration()
75+
76+
def acceleration(self):
77+
x = self.i2c.readfrom_mem(ACC_I2CADDR , ACC_X_L_REG, 2)
78+
self.x = struct.unpack('<h', x)
79+
y = self.i2c.readfrom_mem(ACC_I2CADDR , ACC_Y_L_REG, 2)
80+
self.y = struct.unpack('<h', y)
81+
z = self.i2c.readfrom_mem(ACC_I2CADDR , ACC_Z_L_REG, 2)
82+
self.z = struct.unpack('<h', z)
83+
_mult = self.SCALES[self.full_scale] / ACC_G_DIV
84+
return (self.x[0] * _mult, self.y[0] * _mult, self.z[0] * _mult)
85+
86+
def roll(self):
87+
x,y,z = self.acceleration()
88+
rad = math.atan2(-x, z)
89+
return (180 / math.pi) * rad
90+
91+
def pitch(self):
92+
x,y,z = self.acceleration()
93+
rad = -math.atan2(y, (math.sqrt(x*x + z*z)))
94+
return (180 / math.pi) * rad
95+
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+
102+
def set_full_scale(self, scale):
103+
self.set_register(CTRL4_REG, scale, 4, 3)
104+
self.full_scale = scale
105+
106+
def set_odr(self, odr):
107+
self.set_register(CTRL1_REG, odr, 4, 7)
108+
self.odr = odr
109+
110+
def set_high_pass(self, hp):
111+
self.set_register(CTRL2_REG, 1 if hp else 0, 2, 1)
112+
113+
def enable_activity_interrupt(self, threshold, duration, handler=None):
114+
# Threshold is in mg, duration is ms
115+
self.act_dur = duration
116+
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)
121+
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)
142+
143+
# enable the activity/inactivity interrupt
144+
self.set_register(CTRL3_REG, 1, 5, 1)
145+
146+
self._user_handler = handler
147+
self.int_pin = Pin('P13', mode=Pin.IN)
148+
self.int_pin.callback(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._int_handler)
149+
150+
# return actual used thresold and duration
151+
return (_ths * self.SCALES[self.full_scale] / 128, _dur * 8 * 1000 / self.ODRS[self.odr])
152+
153+
def activity(self):
154+
if not self.debounced:
155+
time.sleep_ms(self.act_dur)
156+
self.debounced = True
157+
if self.int_pin():
158+
return True
159+
return False
160+
161+
def _int_handler(self, pin_o):
162+
if self._user_handler is not None:
163+
self._user_handler(pin_o)
164+
else:
165+
if pin_o():
166+
print('Activity interrupt')
167+
else:
168+
print('Inactivity interrupt')

pyscan/lib/LTR329ALS01.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import time
2+
from machine import I2C
3+
4+
class LTR329ALS01:
5+
ALS_I2CADDR = const(0x29) # The device's I2C address
6+
7+
ALS_CONTR_REG = const(0x80)
8+
ALS_MEAS_RATE_REG = const(0x85)
9+
10+
ALS_DATA_CH1_LOW = const(0x88)
11+
ALS_DATA_CH1_HIGH = const(0x89)
12+
ALS_DATA_CH0_LOW = const(0x8A)
13+
ALS_DATA_CH0_HIGH = const(0x8B)
14+
15+
ALS_GAIN_1X = const(0x00)
16+
ALS_GAIN_2X = const(0x01)
17+
ALS_GAIN_4X = const(0x02)
18+
ALS_GAIN_8X = const(0x03)
19+
ALS_GAIN_48X = const(0x06)
20+
ALS_GAIN_96X = const(0x07)
21+
22+
ALS_INT_50 = const(0x01)
23+
ALS_INT_100 = const(0x00)
24+
ALS_INT_150 = const(0x04)
25+
ALS_INT_200 = const(0x02)
26+
ALS_INT_250 = const(0x05)
27+
ALS_INT_300 = const(0x06)
28+
ALS_INT_350 = const(0x07)
29+
ALS_INT_400 = const(0x03)
30+
31+
ALS_RATE_50 = const(0x00)
32+
ALS_RATE_100 = const(0x01)
33+
ALS_RATE_200 = const(0x02)
34+
ALS_RATE_500 = const(0x03)
35+
ALS_RATE_1000 = const(0x04)
36+
ALS_RATE_2000 = const(0x05)
37+
38+
def __init__(self, pysense = None, sda = 'P22', scl = 'P21', gain = ALS_GAIN_1X, integration = ALS_INT_100, rate = ALS_RATE_500):
39+
if pysense is not None:
40+
self.i2c = pysense.i2c
41+
else:
42+
self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
43+
44+
contr = self._getContr(gain)
45+
self.i2c.writeto_mem(ALS_I2CADDR, ALS_CONTR_REG, bytearray([contr]))
46+
47+
measrate = self._getMeasRate(integration, rate)
48+
self.i2c.writeto_mem(ALS_I2CADDR, ALS_MEAS_RATE_REG, bytearray([measrate]))
49+
50+
time.sleep(0.01)
51+
52+
def _getContr(self, gain):
53+
return ((gain & 0x07) << 2) + 0x01
54+
55+
def _getMeasRate(self, integration, rate):
56+
return ((integration & 0x07) << 3) + (rate & 0x07)
57+
58+
def _getWord(self, high, low):
59+
return ((high & 0xFF) << 8) + (low & 0xFF)
60+
61+
def light(self):
62+
ch1low = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH1_LOW, 1)
63+
ch1high = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH1_HIGH, 1)
64+
data1 = int(self._getWord(ch1high[0], ch1low[0]))
65+
66+
ch0low = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH0_LOW, 1)
67+
ch0high = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH0_HIGH, 1)
68+
data0 = int(self._getWord(ch0high[0], ch0low[0]))
69+
70+
return (data0, data1)

pyscan/main.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
from pyscan import Pyscan
1414
from MFRC630 import MFRC630
15+
from LIS2HH12 import LIS2HH12
16+
from LTR329ALS01 import LTR329ALS01
1517
import binascii
1618
import time
1719
import pycom
@@ -22,6 +24,8 @@
2224

2325
py = Pyscan()
2426
nfc = MFRC630(py)
27+
lt = LTR329ALS01(py)
28+
li = LIS2HH12(py)
2529

2630
RGB_BRIGHTNESS = 0x8
2731

@@ -42,6 +46,12 @@ def print_debug(msg):
4246
if DEBUG:
4347
print(msg)
4448

49+
def send_sensor_data(name, timeout):
50+
while(pybytes):
51+
pybytes.send_virtual_pin_value(True, 2, lt.light())
52+
pybytes.send_virtual_pin_value(True, 3, li.acceleration())
53+
time.sleep(timeout)
54+
4555
def discovery_loop(nfc, id):
4656
while True:
4757
# Send REQA for ISO14443A card type
@@ -72,3 +82,4 @@ def discovery_loop(nfc, id):
7282

7383
# This is the start of our main execution... start the thread
7484
_thread.start_new_thread(discovery_loop, (nfc, 0))
85+
_thread.start_new_thread(send_sensor_data, ('Thread 2', 10))

0 commit comments

Comments
 (0)