Skip to content

Commit ccb5268

Browse files
authored
Initial code upload (#1)
1 parent 223d786 commit ccb5268

File tree

4 files changed

+340
-2
lines changed

4 files changed

+340
-2
lines changed

LICENSE.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 ams OSRAM
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,30 @@
1-
# tmf8806_app_circuitpython
2-
Circuitpython measurement implementation
1+
# TMF8806 (Time-of-flight) CircuitPython v8.0.5 calibration and measurement example
2+
3+
This folder provides simple examples to demonstrate factory calibration and basic device startup with calibration and continuous measurements
4+
5+
## Requirements
6+
7+
- An MCU device running Circuitpython v8.0.5, this code was developed using a TMF8806 connected to an RP2040 I2C interface
8+
- Code was developed using Thonny v4.1.6
9+
- CircuitPython Homepage : https://circuitpython.org/
10+
11+
## Files
12+
13+
The project consists of 2 files:
14+
- **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
16+
17+
## Factory calibration
18+
19+
Please refer to the TMF8806 datasheet(DS001097) section 6.9.1 and TMF8806 Host Driver Communication Application Note (AN001069) for full details
20+
21+
To achieve the performance described in the next sections, a calibration of the algorithm needs to be performed (command = 0x0A). The TMF8806 shall be embedded in the final application and the cover glass including the IR ink needs to be assembled. The calibration test shall be done in a housing with minimal ambient light and no target within 40 cm in field of view of the TMF8806.
22+
23+
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.
24+
25+
## Basic device configuration and continuous measurement example
26+
27+
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.
28+
29+
The script output consists of the Transaction ID (TID), a distance (mm) and a confidence (0-63).
30+

tmf8806_basic_example.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
"""
2+
*****************************************************************************
3+
* Copyright by ams OSRAM AG *
4+
* All rights are reserved. *
5+
* *
6+
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
7+
* THE SOFTWARE. *
8+
* *
9+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
10+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
11+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
12+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
13+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
14+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
15+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
16+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
17+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
18+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
19+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
20+
*****************************************************************************
21+
22+
TMF8806 CircuitPython v8.0.5 implementation specific to the RP2040 (Pin layout)
23+
24+
Configure device, load calibration data and start periodic measurements example
25+
26+
"""
27+
28+
import time
29+
import board
30+
import busio
31+
import digitalio
32+
33+
"""
34+
Constants
35+
"""
36+
SLAVE_ADDR = 0x41
37+
BSL_SLEEP = 0x00
38+
BSL_READY = 0x41
39+
PON = 0x01
40+
APP0 = 0xC0
41+
CLR_INT = 0x01
42+
EN_INT = 0x01
43+
RES_INT = 0x01
44+
I2C_FREQUENCY_1MHz = 1000000
45+
46+
"""
47+
TMF8806 register addresses
48+
"""
49+
app_req_id_reg = 0x02
50+
cmd_reg = 0x10
51+
stat_reg = 0x1D
52+
factory_cal_reg = 0x20
53+
enable_reg = 0xE0
54+
int_stat_reg = 0xE1
55+
int_en_reg = 0xE2
56+
result = bytearray(7)
57+
int_stat_result = bytearray(1)
58+
59+
"""
60+
Alternate command data strings, changes period & # of iterations
61+
62+
Command = [addr, cd9, cd8, cd7, cd6, cd5, cd4, cd3, cd2, cd1, cd0, cmd]
63+
Command = [addr, emc, ss, cal/st, alg, gpio,gpiot,thres,rep_ms,it_lsb,it_msb,start]
64+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0xFE, 0x0A, 0x00, 0x02] # 1Hz continuous sample rate, 10k iterations
65+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0xFE, 0xFF, 0x01, 0x02] # 1Hz continuous sample rate, 511k iterations
66+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x03, 0x01, 0x00, 0xC8, 0x01, 0x00, 0x02] # 10Hz continuous sample rate, 900k iterations
67+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0x1E, 0xA0, 0x0F, 0x02] # 10Hz continuous sample rate, 4000k iterations
68+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0x1E, 0x84, 0x03, 0x02] # 30Hz continuous sample rate, 900k iterations
69+
"""
70+
71+
start_measure = [0x06, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x06, 0x1E, 0x84, 0x03, 0x02] # 30Hz continuous sample rate, 900k iterations
72+
73+
"""
74+
Calibration data - individual to each device
75+
"""
76+
cal_data = [factory_cal_reg, 0x02,0x00,0x00,0xF9,0xCF,0xE0,0x3F,0x7F,0x03,0x00,0x40,0x20,0x00,0x04]
77+
78+
"""
79+
Configure TMF8806 Enable pin
80+
"""
81+
tmf8806_enablepin = digitalio.DigitalInOut(board.GP16)
82+
tmf8806_enablepin.direction = digitalio.Direction.OUTPUT
83+
84+
"""
85+
I2C setup
86+
"""
87+
tmf8806 = busio.I2C(scl=board.GP7, sda=board.GP6, frequency = I2C_FREQUENCY_1MHz)
88+
89+
"""
90+
Function definitions
91+
"""
92+
def enable_tmf8806():
93+
"""
94+
Function to enable TMF8806 device
95+
"""
96+
res = bytearray(1)
97+
tmf8806_enablepin.value = False # pull enable pin low for 3 milliseconds to allow cap to discharge
98+
time.sleep(0.003)
99+
tmf8806_enablepin.value = True
100+
time.sleep(0.002) # 2ms boot time
101+
102+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), res) # read state of device
103+
while (res[0] != BSL_SLEEP):
104+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), res)
105+
106+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg, PON]), res) # wake-up device
107+
while (res[0] != BSL_READY):
108+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), res)
109+
110+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg, APP0]), res)
111+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg]), res) # check the App Id here to make sure app is running
112+
while (res[0] != APP0):
113+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg]), res)
114+
115+
def load_cal():
116+
"""
117+
Load calibration data to device
118+
"""
119+
tmf8806.writeto(SLAVE_ADDR, bytes(cal_data))
120+
121+
def start_measurements():
122+
"""
123+
Write command data string to TMF8806 device
124+
"""
125+
tmf8806.writeto(SLAVE_ADDR, bytes([int_stat_reg, CLR_INT])) # clear any outdated (but still pending) interrupt (e.g. from previous run)
126+
tmf8806.writeto(SLAVE_ADDR, bytes([int_en_reg, EN_INT])) # enable interrupts before starting to measure, so to not miss the first one
127+
tmf8806.writeto(SLAVE_ADDR, bytes(start_measure)) # send command string
128+
129+
130+
"""
131+
Main code - Wait for result ready flag and print TID, Distance & Confidence
132+
"""
133+
134+
while not tmf8806.try_lock():
135+
pass
136+
137+
try:
138+
enable_tmf8806() # pull enable pin high and wait for CPU ready
139+
load_cal() # load factory calibration information
140+
start_measurements() # start continuous measurements as per start_measurement configuration
141+
142+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([int_stat_reg]), int_stat_result) # just read 1 byte
143+
144+
while(1):
145+
while (int_stat_result[0] != RES_INT): # poll interrupt flag for result ready indication
146+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([int_stat_reg]), int_stat_result)
147+
148+
tmf8806.writeto(SLAVE_ADDR, bytes([int_stat_reg, CLR_INT]))
149+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([stat_reg]), result) # read result block
150+
151+
print("TID: ", (result[2])) # print Transaction ID
152+
print("Distance:", (result[5] + 0xFF * result[6])) # print distance from lsb & msb distance bytes (mm)
153+
print("Confidence:", (result[4])) # print result confidence (0-63)
154+
print("")
155+
156+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([int_stat_reg]), int_stat_result) # reset interrupt for next measurement result
157+
158+
finally:
159+
tmf8806.unlock()

tmf8806_read_cal_data.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
"""
2+
*****************************************************************************
3+
* Copyright by ams OSRAM AG *
4+
* All rights are reserved. *
5+
* *
6+
* IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
7+
* THE SOFTWARE. *
8+
* *
9+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
10+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
11+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
12+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
13+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
14+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
15+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
16+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
17+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
18+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
19+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
20+
*****************************************************************************
21+
22+
TMF8806 CircuitPython v8.0.5 implementation specific to the RP2040 (Pin layout)
23+
24+
Device calibration and print calibration data example
25+
26+
"""
27+
28+
import time
29+
import board
30+
import busio
31+
import digitalio
32+
33+
"""
34+
Constants
35+
"""
36+
SLAVE_ADDR = 0x41
37+
BSL_SLEEP = 0x00
38+
BSL_READY = 0x41
39+
PON = 0x01
40+
APP0 = 0xC0
41+
I2C_FREQUENCY_1MHz = 1000000
42+
43+
"""
44+
TMF8806 register addresses
45+
"""
46+
app_req_id_reg = 0x02
47+
cmd_reg = 0x10
48+
stat_reg = 0x1D
49+
reg_contents_reg = 0x1E
50+
factory_cal_reg = 0x20
51+
enable_reg = 0xE0
52+
53+
"""
54+
Data array
55+
"""
56+
result = bytearray(14)
57+
58+
"""
59+
Command string to begin factory calibration routine
60+
"""
61+
start_cal = [ 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0xA0, 0x0A]
62+
63+
"""
64+
Configure TMF8806 Enable pin
65+
"""
66+
tmf8806_enablepin = digitalio.DigitalInOut(board.GP16)
67+
tmf8806_enablepin.direction = digitalio.Direction.OUTPUT
68+
69+
"""
70+
I2C setup
71+
"""
72+
tmf8806 = busio.I2C(scl=board.GP7, sda=board.GP6, frequency = I2C_FREQUENCY_1MHz)
73+
74+
"""
75+
Function definitions
76+
"""
77+
78+
def enable_tmf8806():
79+
"""
80+
Function to enable TMF8806 device
81+
"""
82+
result = bytearray(1)
83+
tmf8806_enablepin.value = False
84+
tmf8806_enablepin.value = True
85+
time.sleep(0.1)
86+
87+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), result)
88+
while (result[0] != BSL_SLEEP):
89+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), result)
90+
91+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg, PON]), result)
92+
while (result[0] != BSL_READY):
93+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([enable_reg]), result)
94+
95+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg, APP0]), result)
96+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg]), result)
97+
while (result[0] != APP0):
98+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([app_req_id_reg]), result)
99+
100+
def start_calibration():
101+
"""
102+
Write command data string to TMF8806 device
103+
"""
104+
105+
tmf8806.writeto(SLAVE_ADDR, bytes(start_cal))
106+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([reg_contents_reg]), result)
107+
108+
while (result[0] != 0x0A):
109+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([reg_contents_reg]), result)
110+
111+
"""
112+
Main code - enable device, start calibration and print calibration data
113+
"""
114+
115+
while not tmf8806.try_lock():
116+
pass
117+
118+
try:
119+
enable_tmf8806() # pull enable pin high and wait for CPU ready
120+
print("Gathering calibration data\n")
121+
start_calibration() # start factory calibration routine
122+
123+
tmf8806.writeto_then_readfrom(SLAVE_ADDR, bytes([factory_cal_reg]), result)
124+
125+
print (','.join(f'{byte:02X}' for byte in result))
126+
127+
print("\nCopy data to cal_data in tmf8806_basic_example.py\n")
128+
129+
finally:
130+
tmf8806.unlock()

0 commit comments

Comments
 (0)