Machines de précision
La Bobineuse, la Chambre à vide, la Machine de photolithographie, l'Implanteur ionique, la Placeuse CMS et la Tireuse de cristaux : sur quoi elles travaillent, et pourquoi elles attendent.
Les machines de précision de Computing Ages fonctionnent comme une Presse mécanique de Create : elles sont suspendues au-dessus d'un tapis roulant ou d'un dépôt et descendent leur tête sur la pièce qui passe dessous, une étape de tube à vide ou de puce à la fois. Elles contiennent ce avec quoi elles travaillent (une bobine de fil, un dopant, un photomasque...) et demandent de la rotation, souvent rapide. Quand une machine attend, les Lunettes d'ingénieur disent pourquoi : trop lente, un ingrédient manquant... Un ordinateur lit la même chose, et peut agir : accélérer la ligne, réclamer du fil, vous prévenir.
local implanteur = peripheral.find("ion_implanter")
if implanteur.running() then
print("au travail : " .. math.floor(implanteur.progress() * 100) .. " %")
else
print("en attente : " .. (implanteur.problem() or "rien à corriger"))
endmachine.running() | Si la machine travaille : du moment où sa tête commence à descendre sur une pièce jusqu'à ce qu'elle soit remontée. |
machine.progress() | Où en est le cycle en cours, de 0 (la tête quitte le haut) à 1 (elle est remontée), arrondi au millième. 0 tant que la machine est au repos. Un arbre plus rapide raccourcit le cycle. |
machine.item() | La pièce qui attend sous la machine, sous forme de table d'objet : celle du tapis roulant ou du dépôt deux blocs plus bas, ou sinon celle posée au sol juste en dessous. nil quand il n'y a rien. count est la taille de cette pile. |
machine.recipe() | La recette que la machine lancerait sur la pièce du dessous : |
machine.problem() | Ce qui empêche la machine de travailler la pièce du dessous, comme le montrent les lunettes. nil quand il n'y a rien dessous, ou quand la pièce peut être traitée maintenant. |
machine.tier() | Le niveau de la source lumineuse chargée dans une Machine de photolithographie : 1 pour une Lampe UV, 2 pour un Laser excimère (DUV), 3 pour une Source de lumière EUV. 0 quand il n'y en a pas, et toujours 0 sur les quatre autres machines. |
tireuse.running() | Si un cristal est en cours de tirage. |
tireuse.progress() | Où en est le tirage du cristal, de 0 (le germe touche le bain) à 1 (la boule est sortie), arrondi au millième. Les lunettes le montrent en pourcentage. |
tireuse.max_speed() | La vitesse limite de la tireuse, en tr/min : la configuration serveur crystalPullerMaxSpeed, 32 par défaut. Le tirage est le plus rapide à exactement cette vitesse. |
tireuse.problem() | Ce qui empêche la tireuse de travailler : |
Installation
Cinq machines, les mêmes méthodes. Chaque machine a son propre type, celui que vous cherchez ; les cinq ont les méthodes de cette page, notées ici precision_machine.*.
| type | bloc | ce qu'elle contient (ses cases) |
|---|---|---|
coil_winder | Bobineuse | 1 : la bobine de fil ou de feuille |
vacuum_chamber | Chambre à vide | 1 : la cible de dépôt |
lithography_machine | Machine de photolithographie | 2 : le photomasque, puis la source lumineuse |
ion_implanter | Implanteur ionique | 1 : le dopant |
pick_and_place | Placeuse CMS | 8 : les chargeurs de composants |
precision_machine n'est pas un type : peripheral.find("precision_machine") renvoie nil. Demandez la machine que vous voulez, par exemple peripheral.find("coil_winder"). Sur un Câble de données (Mini-ordinateur et plus récents), une machine prend le nom de son type et de sa place : ion_implanter@120,64,-35.
Aussi cinétiques et inventaires. Une machine de précision tourne et contient des objets : c'est donc aussi un bloc cinétique et un inventaire, avec toutes leurs méthodes. machine.speed() lit sa vitesse en tr/min, machine.overstressed() dit si son réseau s'est arrêté, et machine.list() montre les cases du tableau ci-dessus (le fil qui reste sur une Bobineuse, par exemple). peripheral.find("inventory") les trouve aussi.
Où est la pièce. Une machine travaille sur la pièce posée sur le tapis roulant ou le dépôt deux blocs plus bas (avec un bloc d'air entre les deux, comme pour une Presse mécanique), ou, quand il n'y a là ni tapis ni dépôt, sur un objet posé au sol juste en dessous d'elle.
La Tireuse de cristaux travaille au-dessus d'un Bassin et a ses propres méthodes : voyez sa section à la fin de cette page.
Quand la machine a disparu, ses méthodes arrêtent le programme avec machine removed (crystal puller removed pour la Tireuse de cristaux) ; quand son chunk n'est pas chargé, avec peripheral is not loaded.
La tête
machine.running()
Si la machine travaille : du moment où sa tête commence à descendre sur une pièce jusqu'à ce qu'elle soit remontée.
- boolean
truetant que la tête est dans un cycle
Un voyant « occupée » sur le dessus de l'ordinateur :
local bobineuse = peripheral.find("coil_winder")
while true do
rs.set("top", bobineuse.running())
sleep(0.5)
endVoir aussi precision_machine.progress()
machine.progress()
Où en est le cycle en cours, de 0 (la tête quitte le haut) à 1 (elle est remontée), arrondi au millième. 0 tant que la machine est au repos. Un arbre plus rapide raccourcit le cycle.
- number
- l'avancement du cycle de la tête, de 0 à 1 ; 0 au repos
local chambre = peripheral.find("vacuum_chamber")
print("cycle sous vide : " .. math.floor(chambre.progress() * 100) .. " %")Voir aussi precision_machine.running()
La pièce en dessous
La pièce qui attend sous la machine, sous forme de table d'objet : celle du tapis roulant ou du dépôt deux blocs plus bas, ou sinon celle posée au sol juste en dessous. nil quand il n'y a rien. count est la taille de cette pile.
- table|nil
- la pièce sous la machine,
{name =, count =, display =}; nil quand il n'y en a pas
local litho = peripheral.find("lithography_machine")
local piece = litho.item()
if piece then
print("sous la machine : " .. piece.display)
else
print("pas de wafer dessous")
endVoir aussi precision_machine.recipe()
La recette que la machine lancerait sur la pièce du dessous :
- table|nil
{id =, output =, min_speed =, tier =}; nil sans pièce, ou quand on ne peut rien en faire
| champ | contenu |
|---|---|
id | l'identifiant de la recette |
output | l'identifiant de l'objet qu'elle fabrique |
min_speed | la rotation la plus lente qu'accepte la recette, en tr/min ; 0 pour n'importe quelle vitesse |
tier | la source lumineuse qu'elle demande sur une Machine de photolithographie, de 1 à 3 ; 0 sur les autres machines |
Plusieurs recettes peuvent partir de la même pièce : toute puce commence par le même wafer enduit sous la Machine de photolithographie. La machine prend celle pour laquelle elle est équipée : le photomasque, le dopant ou le fil que vous chargez décide donc du produit, et recipe() dit lequel ce sera. Dans un assemblage séquencé, output est la pièce inachevée que donne cette étape, jusqu'à la dernière.
local implanteur = peripheral.find("ion_implanter")
local r = implanteur.recipe()
if r then
print("fabrique " .. r.output .. ", à " .. r.min_speed .. " tr/min ou plus")
endVoir aussi precision_machine.item() precision_machine.problem()
Pourquoi elle attend
Ce qui empêche la machine de travailler la pièce du dessous, comme le montrent les lunettes. nil quand il n'y a rien dessous, ou quand la pièce peut être traitée maintenant.
- string|nil
"no_recipe","too_slow","tier_too_low"ou"missing_ingredient"; nil quand la pièce du dessous peut être traitée, ou quand il n'y a rien dessous
| problème | pourquoi | que faire |
|---|---|---|
"no_recipe" | cette machine ne fait rien de la pièce du dessous | envoyer la pièce à la bonne machine |
"too_slow" | la machine ne tourne pas, ou moins vite que le min_speed de la recette | l'accélérer, ou ajouter de la puissance si le réseau est surchargé |
"tier_too_low" | la source lumineuse de la Machine de photolithographie est trop faible pour le masque, ou absente | charger une source plus puissante |
"missing_ingredient" | la bobine, la cible, le dopant, le masque ou un composant que la recette prend dans la machine manque | recharger la machine |
Un problème à la fois, dans cet ordre : une fois la vitesse réglée, il peut encore manquer le dopant. Redemandez après chaque correction.
local bobineuse = peripheral.find("coil_winder")
local probleme = bobineuse.problem()
if probleme == "missing_ingredient" then
print("la Bobineuse a besoin d'une nouvelle bobine de fil")
elseif probleme == "too_slow" then
print("la Bobineuse ne tourne pas assez vite")
endVoir aussi precision_machine.recipe() precision_machine.tier()
machine.tier()
Le niveau de la source lumineuse chargée dans une Machine de photolithographie : 1 pour une Lampe UV, 2 pour un Laser excimère (DUV), 3 pour une Source de lumière EUV. 0 quand il n'y en a pas, et toujours 0 sur les quatre autres machines.
- number
- le niveau de la source lumineuse d'une Machine de photolithographie, de 1 à 3 ; 0 sans source, et sur les autres machines
Une recette tourne quand le niveau de la machine atteint au moins le tier de la recette : une lumière plus puissante sert aussi pour les masques plus anciens.
local litho = peripheral.find("lithography_machine")
local r = litho.recipe()
if r and litho.tier() < r.tier then
print("ce masque demande une source lumineuse de niveau " .. r.tier)
endVoir aussi precision_machine.recipe()
Tireuse de cristaux
La Tireuse de cristaux fait croître un monocristal dans le bain fondu du Bassin placé deux blocs plus bas, par le procédé Czochralski : une boule de silicium à partir de silicium fondu, ou du quartz synthétique. Son type est crystal_puller, et c'est aussi un bloc cinétique.
Elle veut un arbre lent. Au-delà de sa vitesse limite (32 tr/min par défaut), le cristal casserait : la tireuse ne démarre pas, et un tirage déjà commencé attend que l'arbre ralentisse. En dessous de la limite, plus elle tourne lentement, plus le tirage est long : deux fois plus long à la moitié de la limite, jusqu'à huit fois plus long. La durée est fixée au début du tirage : la meilleure vitesse est donc la limite elle-même, réglée avant que le tirage commence.
tireuse.running()
Si un cristal est en cours de tirage.
- boolean
truetant qu'elle tire un cristal
local tireuse = peripheral.find("crystal_puller")
print(tireuse.running())Voir aussi crystal_puller.progress()
tireuse.progress()
Où en est le tirage du cristal, de 0 (le germe touche le bain) à 1 (la boule est sortie), arrondi au millième. Les lunettes le montrent en pourcentage.
- number
- l'avancement du tirage, de 0 à 1 ; 0 quand elle ne tire pas
local tireuse = peripheral.find("crystal_puller")
if tireuse.running() then
print("boule tirée à " .. math.floor(tireuse.progress() * 100) .. " %")
endVoir aussi crystal_puller.running()
tireuse.max_speed()
La vitesse limite de la tireuse, en tr/min : la configuration serveur crystalPullerMaxSpeed, 32 par défaut. Le tirage est le plus rapide à exactement cette vitesse.
- number
- la rotation la plus rapide avant que le cristal casse, en tr/min
Avec la roue dentée d'un Contrôleur de vitesse de rotation qui entraîne directement la tireuse, ceci donne le tirage le plus rapide que permet le serveur (voir speed_controller.set_target_speed()) :
local tireuse = peripheral.find("crystal_puller")
local regulateur = peripheral.find("speed_controller")
regulateur.set_target_speed(tireuse.max_speed())Voir aussi crystal_puller.problem()
tireuse.problem()
Ce qui empêche la tireuse de travailler :
- string|nil
"too_fast","too_slow","no_basin", ou nil
| problème | pourquoi |
|---|---|
"too_fast" | elle tourne plus vite que max_speed() : le tirage attend |
"too_slow" | elle ne tourne pas |
"no_basin" | il n'y a pas de Bassin deux blocs plus bas |
nil veut dire qu'aucun de ces problèmes ne se pose, pas qu'un tirage va commencer : le Bassin doit encore contenir le bon bain et être assez chaud (un Brûleur à blaze surchauffé pour une boule de silicium).
local tireuse = peripheral.find("crystal_puller")
if tireuse.problem() == "too_fast" then
print("ralentissez : " .. tireuse.max_speed() .. " tr/min au plus")
endVoir aussi crystal_puller.max_speed()
Exemples
Jamais trop lent
Les recettes de l'Implanteur ionique demandent 128 tr/min. Un Contrôleur de vitesse de rotation l'entraîne, et ce programme monte le contrôleur pas à pas tant que l'implanteur est trop lent, jusqu'à la limite de Create. Quand le réseau est surchargé, plus de vitesse ne ferait qu'empirer les choses : le programme le dit plutôt.
local implanteur = peripheral.find("ion_implanter")
local regulateur = peripheral.find("speed_controller")
local PAS = 16 -- tr/min ajoutés à chaque fois
while true do
if implanteur.overstressed() then
print("surcharge : ajoutez de la puissance, plus de vitesse n'aiderait pas")
elseif implanteur.problem() == "too_slow" then
local cible = regulateur.target_speed()
if math.abs(cible) >= 256 then
print("le contrôleur est déjà à pleine vitesse")
else
local tours = math.min(256, math.abs(cible) + PAS)
if cible < 0 then
tours = -tours -- garde le sens de rotation
end
regulateur.set_target_speed(tours)
print("trop lent : contrôleur réglé à " .. tours .. " tr/min")
end
end
sleep(2)
endIl fonctionne quels que soient les engrenages entre le contrôleur et l'implanteur, puisqu'il ne surveille que le problème de l'implanteur lui-même. overstressed() vient des méthodes cinétiques qu'a chaque machine.
Un tableau d'état de la ligne
Un Mini-ordinateur sur le Câble de données qui longe une ligne de puces affiche une ligne par machine qu'il atteint : au travail avec son avancement, en attente avec son problème, ou au repos. La Tireuse de cristaux a elle aussi running, progress et problem : elle trouve sa place sur le même tableau.
local NOMS = {
coil_winder = "Bobineuse",
vacuum_chamber = "Chambre à vide",
lithography_machine = "Photolithographie",
ion_implanter = "Implanteur ionique",
pick_and_place = "Placeuse CMS",
crystal_puller = "Tireuse",
}
local function etat(machine)
if machine.running() then
return "au travail, " .. math.floor(machine.progress() * 100) .. " %"
end
return machine.problem() or "au repos"
end
while true do
term.clear()
term.set_cursor(1, 1)
for _, nom in ipairs(peripheral.list()) do
local libelle = NOMS[peripheral.type(nom)]
if libelle then
print(string.format("%-18s %s", libelle, etat(peripheral.wrap(nom))))
end
end
sleep(2)
endperipheral.type donne le premier type de chaque nom, qui pour ces blocs est le leur (coil_winder...), et non kinetic ou inventory.