-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy paththermo_test.py
More file actions
163 lines (125 loc) · 5.81 KB
/
thermo_test.py
File metadata and controls
163 lines (125 loc) · 5.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import time
from typing import List, Tuple
from sentio_prober_control.Sentio.ProberSentio import SentioProber
from sentio_prober_control.Sentio.Enumerations import *
from sentio_prober_control.Sentio.ProberBase import ProberException
def check_preconditions(prober : SentioProber) -> None:
if not prober.has_chuck_xyz():
raise Exception("This script requires a motorized chuck in order to run!")
has_ww : bool = prober.loader.has_station(LoaderStation.WaferWallet)
has_cas1 : bool = prober.loader.has_station(LoaderStation.Cassette1)
has_cas2 : bool = prober.loader.has_station(LoaderStation.Cassette2)
if not has_ww and not has_cas1 and not has_cas2:
raise Exception("The probe station needs a wafer wallet or cassette to execute this script.")
# Filter out non-existing wafers from a wafer list
def filter_nonexisting(prober : SentioProber, wafer_list : List[Tuple[LoaderStation, int]]) -> List[Tuple[LoaderStation, int]]:
out_list : List[Tuple[LoaderStation, int]] = []
for loc in wafer_list:
station, slot = loc
stat : Tuple[LoaderStation, int, int, int, float] | None = prober.loader.query_wafer_status(station, slot)
if stat is None:
print(f"Wafer at {station} {slot} does not exist and will be ignored!.")
continue
out_list.append(loc)
return out_list
def test_wafer(prober : SentioProber) -> None:
print("Testing wafer...")
prober.map.step_first_die()
try:
while True:
col, row, site = prober.map.step_next_die()
print(f'Testing cell {col}, {row} (Site: {site})')
except ProberException as e:
if e.error() != RemoteCommandError.EndOfRoute:
raise
def set_and_wait_for_temperature(prober : SentioProber, temp : float, soak_time_sec : float) -> None:
prober.status.set_chuck_temp(temp)
# wait for temperature to stabilize
while True:
current_temp = prober.status.get_chuck_temp()
setpoint = prober.status.get_chuck_temp_setpoint()
if abs(current_temp - setpoint) < 0.5:
break
print(f" - Waiting for temperature to reach set point: {current_temp} Setpoint: {setpoint}", end='\r')
time.sleep(1)
time_total = soak_time_sec
time_step_sec = 1
while time_total > 0:
print(f" - Waiting Soak time: {time_total} seconds remaining", end='\r')
time_total -= time_step_sec
time.sleep(time_step_sec)
print(" - Soak time completed.")
def main() -> None:
prober = SentioProber.create_prober("tcpip", "127.0.0.1:35555")
# Check whether a loader station exists
check_preconditions(prober)
# SENTIO demo mode starts with a wafer on the chuck remove this wafer to the cassette 1
#if prober.loader.query_wafer_status(LoaderStation.Chuck, 1) is not None:
# prober.loader.transfer_wafer(LoaderStation.Chuck, 1, LoaderStation.Cassette1, 13)
#
# ===> Select the type of cassette station or wafer wallet here
#
originStation : LoaderStation = LoaderStation.WaferWallet
if prober.loader.has_station(LoaderStation.WaferWallet):
originStation = LoaderStation.WaferWallet
elif prober.loader.has_station(LoaderStation.Cassette1):
originStation = LoaderStation.Cassette1
else:
raise(Exception("This script requires a cassette station or a wafer wallet to execute!"))
prober.loader.scan_station(originStation)
#
# ===> Select Wafers to test here!
#
wafer_list : List[Tuple[LoaderStation, int]] = []
wafer_list.append((originStation, 1))
wafer_list = filter_nonexisting(prober, wafer_list)
#
# ===> Select the project here
# Project Requirementes:
# - Fast Track must be set up in the project
# - AutoAlign, FindHome and PTPA (if enabled) must be trained
#
project_name : str = "PTPAOnAxis_Test"
print(f"Loading project {project_name}")
prober.open_project(project_name)
#
# ===> Common settings
#
prealigner_angle = 0
soak_time_sec = 60
temperatures = [25, 40]
try:
for temp in temperatures:
# Iterate over all wafers.
for wafer_origin in wafer_list:
station, slot = wafer_origin
print(f"Loading wafer from {station} {slot}")
prober.select_module(Module.Dashboard)
prober.loader.load_wafer(station, slot, prealigner_angle)
print(f"Setting and Waiting for temperature: {temp}")
set_and_wait_for_temperature(prober, temp, soak_time_sec)
# Here you could manually send commands to align the wafer, find home and so on. We won't do that here
# because we will use Fast Track instead.
# prober.vision.align_wafer(AutoAlignCmd.UpdateDieSize)
# prober.vision.find_home()
# Execute Fast Track. For this to work you must have set up Fast Track in the project.
# - Align Wafer
# - Find Home
# - Auto Focus
# - and possibly additional steps
# Once this command is done. The wafer must be aligned, in focus and the a home position must have been set.
prober.select_module(Module.Vision)
resp = prober.vision.start_fast_track()
prober.wait_complete(resp)
prober.select_module(Module.Wafermap)
test_wafer(prober)
prober.select_module(Module.Dashboard)
prober.loader.unload_wafer()
finally:
set_and_wait_for_temperature(prober, 25, 0)
if __name__ == "__main__":
try:
main()
except Exception as e:
print("\n#### Error ##################################")
print(f"{e}")