Skip to content

Commit c84d0ce

Browse files
authored
Added script to measure optical crosstalk (#3)
Authored-by: David Smith
1 parent 9e58fd4 commit c84d0ce

File tree

2 files changed

+172
-2
lines changed

2 files changed

+172
-2
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ This folder provides simple examples to demonstrate factory calibration and basi
1010

1111
## Files
1212

13-
The project consists of 2 files:
13+
The project consists of 3 files:
1414
- **tmf8806_read_cal_data.py** - CircuitPython script to configure TMF8806, start factory calibration and print out calibration data
15-
- **tmf8806_basic_example.py** - CurcuitPython script to configure TMF8806, load factory calibration, start measurements and print out TID, Distance and confidence
15+
- **tmf8806_read_xtalk.py** � CircuitPython script to perform a series of crosstalk measurements. The minimum, maximum and average crosstalk values are printed to the shell window
16+
- **tmf8806_basic_example.py** - CircuitPython script to configure TMF8806, load factory calibration, start measurements and print out TID, Distance and confidence
1617

1718
## Factory calibration
1819

@@ -22,6 +23,10 @@ To achieve the performance described in the next sections, a calibration of the
2223

2324
The tmf8806_read_cal_data.py script outputs a string of 14 bytes that should be copied to the tmf8806_basic_example.py script cal_data variable.
2425

26+
## Measure optical stack crosstalk
27+
28+
It is important that the crosstalk generated by the optical stack is within the limits stated within the TMF8806 Optical Design Guide (PD001060). The script will run a set number of measurements and print out the minimum, maximum and average crosstalk values.
29+
2530
## Basic device configuration and continuous measurement example
2631

2732
The tmf8806_basic_example.py will configure the sensor with the defualt settings as described in the TMF8806 datasheet(DS001097) and TMF8806 Host Driver Communication Application Note (AN001069) section 8.8. The script includes several other configuration examples which can be used to change the basic device configuration.

tmf8806_read_xtalk.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# /*****************************************************************************
2+
# * Copyright (c) [2024] ams-OSRAM AG *
3+
# * All rights are reserved. *
4+
# * *
5+
# * FOR FULL LICENSE TEXT SEE LICENSE.TXT *
6+
# ******************************************************************************/
7+
8+
"""
9+
TMF8806 Circuitpython v8.0.5 implementation specific to the RP2040 (Pin layout)
10+
11+
Configure device, read xtalk
12+
13+
"""
14+
15+
import time
16+
import board
17+
import busio
18+
import digitalio
19+
20+
"""
21+
Constants
22+
"""
23+
SLAVE_ADDR = 0x41
24+
BSL_SLEEP = 0x00
25+
BSL_READY = 0x41
26+
PON = 0x01
27+
APP0 = 0xC0
28+
CLR_INT = 0x01
29+
EN_INT = 0x01
30+
RES_INT = 0x01
31+
I2C_FREQUENCY_1MHz = 1000000
32+
NUMBER_OF_MEASUREMENTS = 100
33+
34+
"""
35+
TMF8806 register addresses
36+
"""
37+
app_req_id_reg = 0x02
38+
cmd_reg = 0x10
39+
stat_reg = 0x1D
40+
factory_cal_reg = 0x20
41+
enable_reg = 0xE0
42+
int_stat_reg = 0xE1
43+
int_en_reg = 0xE2
44+
45+
"""
46+
Variables
47+
"""
48+
result = bytearray(7)
49+
int_stat_result = bytearray(1)
50+
number_of_measurements = 100
51+
xtalk_min = 1000000
52+
xtalk_max = 0
53+
xtalk_avg = 0
54+
55+
"""
56+
Alternate command data strings, changes period & # of iterations
57+
58+
Command = [addr, cd9, cd8, cd7, cd6, cd5, cd4, cd3, cd2, cd1, cd0, cmd]
59+
Command = [addr, emc, ss, cal/st, alg, gpio,gpiot,thres,rep_ms,it_lsb,it_msb,start]
60+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0xFE, 0x0A, 0x00, 0x02] # 1Hz continuous sample rate, 10k iterations
61+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0xFE, 0xFF, 0x01, 0x02] # 1Hz continuous sample rate, 511k iterations
62+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x03, 0x01, 0x00, 0xC8, 0x01, 0x00, 0x02] # 10Hz continuous sample rate, 900k iterations
63+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0x1E, 0xA0, 0x0F, 0x02] # 10Hz continuous sample rate, 4000k iterations
64+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0x1E, 0x84, 0x03, 0x02] # 30Hz continuous sample rate, 900k iterations
65+
"""
66+
67+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0x1E, 0x84, 0x03, 0x02] # 30Hz continuous sample rate, 900k iterations
68+
69+
"""
70+
Calibration data - individual to each device
71+
"""
72+
cal_data = [factory_cal_reg, 0x02,0x00,0x00,0xF9,0xCF,0xE0,0x3F,0x7F,0x03,0x00,0x40,0x20,0x00,0x04]
73+
74+
"""
75+
Configure TMF8806 Enable pin
76+
"""
77+
tmf8806_enablepin = digitalio.DigitalInOut(board.GP16)
78+
tmf8806_enablepin.direction = digitalio.Direction.OUTPUT
79+
80+
"""
81+
I2C setup
82+
"""
83+
tmf8806 = busio.I2C(scl=board.GP7, sda=board.GP6, frequency = I2C_FREQUENCY_1MHz)
84+
85+
"""
86+
Function definitions
87+
"""
88+
def enable_tmf8806():
89+
"""
90+
Function to enable TMF8806 device
91+
"""
92+
res = bytearray(1)
93+
tmf8806_enablepin.value = False # pull enable pin low for 3 milliseconds to allow cap to discharge
94+
time.sleep(0.003)
95+
tmf8806_enablepin.value = True
96+
time.sleep(0.002) # 2ms boot time
97+
98+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), res) # read state of device
99+
while (res[0] != BSL_SLEEP):
100+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), res)
101+
102+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg, PON]), res) # wake-up device
103+
while (res[0] != BSL_READY):
104+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), res)
105+
106+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg, APP0]), res)
107+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg]), res) # check the App Id here to make sure app is running
108+
while (res[0] != APP0):
109+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg]), res)
110+
111+
def load_cal():
112+
"""
113+
Load calibration data to device
114+
"""
115+
tmf8806.writeto(SLAVE_ADDR, bytes(cal_data))
116+
117+
def start_measurements():
118+
"""
119+
Write command data string to TMF8806 device
120+
"""
121+
tmf8806.writeto(SLAVE_ADDR, bytes([int_stat_reg, CLR_INT])) # clear any outdated (but still pending) interrupt (e.g. from previous run)
122+
tmf8806.writeto(SLAVE_ADDR, bytes([int_en_reg, EN_INT])) # enable interrupts before starting to measure, so to not miss the first one
123+
tmf8806.writeto(SLAVE_ADDR, bytes(start_measure)) # send command string
124+
125+
"""
126+
Main code - Wait for result ready flag and measure crosstalk levels, print min, max and average value for 100 measurements
127+
"""
128+
129+
while not tmf8806.try_lock():
130+
pass
131+
132+
try:
133+
enable_tmf8806() # pull enable pin high and wait for CPU ready
134+
load_cal() # load factory calibration information
135+
start_measurements() # start continuous measurements as per start_measurement configuration
136+
137+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([int_stat_reg]), int_stat_result) # just read 1 byte
138+
139+
print("Measuring crosstalk, please wait...\n")
140+
141+
for loop in range(NUMBER_OF_MEASUREMENTS): # loop for "number_of_measurements" measurements
142+
while (int_stat_result[0] != RES_INT): # poll interrupt flag for result ready indication
143+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([int_stat_reg]), int_stat_result)
144+
145+
tmf8806.writeto(SLAVE_ADDR, bytes([int_stat_reg, CLR_INT]))
146+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([0x3C]), result) # read result block
147+
148+
if (result[0] + 0xFF * result[1]) < xtalk_min: # is this the lowest crosstalk measurement?
149+
xtalk_min = (result[0] + 0xFF * result[1])
150+
151+
if (result[0] + 0xFF * result[1]) > xtalk_max: # is this the highest crosstalk measurement?
152+
xtalk_max = (result[0] + 0xFF * result[1])
153+
154+
xtalk_avg = xtalk_avg + (result[0] + 0xFF * result[1]) # sum xtalk for average calculation
155+
156+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([int_stat_reg]), int_stat_result) # reset interrupt for next measurement result
157+
158+
print("Crosstalk minimum value:", xtalk_min) # print min, max and average results
159+
print("Crosstalk maximum value:", xtalk_max)
160+
print("Average of 100 measurements:",round(xtalk_avg/NUMBER_OF_MEASUREMENTS))
161+
162+
163+
finally:
164+
tmf8806.unlock()
165+

0 commit comments

Comments
 (0)