aboutsummaryrefslogtreecommitdiffstats
path: root/docs/guide.md
blob: 32ed2eb54b924ff87373601f67966db7d8436f2f (plain)
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
# Guide d'utilisation QtXpl2

Ce guide explique comment utiliser le module QML `Xpl2` pour piloter un Jetting Controller Alchemie depuis une interface Qt Quick.

## Import et connexion

```qml
import Xpl2

// Xpl2Client est un singleton — pas besoin de l'instancier.
// Configurer l'adresse du contrôleur :
Xpl2Client.host = "192.168.1.100"

// Se connecter / se déconnecter :
Xpl2Client.connectToServer()
Xpl2Client.disconnectFromServer()
```

### Propriétés de connexion

| Propriété | Type | Description |
|---|---|---|
| `host` | string | Adresse IP du Jetting Controller (défaut : `"127.0.0.1"`) |
| `connected` | bool | `true` quand les 3 ports TCP sont connectés |
| `controllerId` | int | ID du contrôleur (renseigné après `getJcVersion()`) |
| `firmwareVersion` | string | Version firmware du contrôleur |
| `hardwareVersion` | string | Version hardware du contrôleur |
| `printheadCount` | int | Nombre de têtes connectées |

### Signaux généraux

| Signal | Description |
|---|---|
| `errorOccurred(string error)` | Erreur de connexion ou de commande |
| `statusMessage(string message)` | Message de log pour chaque réponse reçue |
| `shuttingDown()` | Le serveur est en train de s'éteindre |

---

## Informations version

### Obtenir la version du contrôleur

```qml
Xpl2Client.getJcVersion()
```

La réponse met à jour les propriétés `controllerId`, `firmwareVersion`, `hardwareVersion` et `printheadCount`. Le signal `jcVersionReceived()` est émis.

### Obtenir la version d'une tête

```qml
Xpl2Client.getPhVersion(3)  // tête n°3
```

**Signal :** `phVersionReceived(controllerId, printheadId, mcuFirmwareVersion, mcuHardwareVersion, mcuFirmwareVariant, fpgaFirmwareVersion, fpgaHardwareVersion, bootloaderVersion)`

```qml
Connections {
    target: Xpl2Client
    function onPhVersionReceived(cid, phId, mcuFw, mcuHw, mcuVar, fpgaFw, fpgaHw, boot) {
        console.log("Tête", phId, "— MCU:", mcuFw, "FPGA:", fpgaFw)
    }
}
```

---

## Contrôle du jetting

### Activer / désactiver le jetting

```qml
// Toutes les têtes
Xpl2Client.jettingAllOn()       // → signal jettingAllOnResult(cid, success)
Xpl2Client.jettingOff()         // → signal jettingOffResult(cid, success)

// Avec un masque de buses (180 caractères, 12 par tête × 15 têtes)
// Chaque caractère : 'F' = jet actif, '0' = jet inactif
Xpl2Client.jettingOn("FFFF..." )  // → signal jettingOnResult(cid, success)

// Une seule tête avec masque (12 caractères)
Xpl2Client.phJettingOn(3, "FFFFFFFFFFFF")  // → signal phJettingOnResult(cid, phId, success)
Xpl2Client.phJettingOff(3)                 // → signal phJettingOffResult(cid, phId, success)
```

### LEDs d'identification

```qml
// LED du contrôleur
Xpl2Client.jcIdLedOn()    // → signal jcIdLedOnResult(cid, success)
Xpl2Client.jcIdLedOff()   // → signal jcIdLedOffResult(cid, success)

// LED d'une tête
Xpl2Client.phIdLedOn(3)   // → signal phIdLedOnResult(cid, phId, success)
Xpl2Client.phIdLedOff(3)  // → signal phIdLedOffResult(cid, phId, success)
```

### Calibration

```qml
// Calibrer toutes les têtes
Xpl2Client.jcCalibration()   // → signal jcCalibrationResult(cid, success)

// Calibrer une tête
Xpl2Client.phCalibration(3)  // → signal phCalibrationResult(cid, phId, success)

// Récupérer les données de calibration (48 fréquences par tête, -1 = non calibré)
Xpl2Client.phCalibrationData(3)     // → signal phCalibrationDataReceived(cid, phId, frequencies)
Xpl2Client.phCalibrationRawData(3)  // → signal phCalibrationRawDataReceived(cid, phId, frequencies)

// Fréquence de base calibrée
Xpl2Client.phCalibratedBaseFrequency(3)  // → signal phCalibratedBaseFrequencyReceived(cid, phId, baseFreq, activeBaseFreq)
```

### Codes de défaut

```qml
// Réinitialiser les codes de défaut
Xpl2Client.jcResetFaultCodes()       // → signal jcResetFaultCodesResult(cid, success)
Xpl2Client.phResetFaultCodes(3)      // → signal phResetFaultCodesResult(cid, phId, success)
```

### Désactivation de buses

```qml
// Masque de 12 caractères : '0' = buse active, autre = buse désactivée
// "000000000000" réactive toutes les buses
Xpl2Client.phNozzlesDisabled(3, "000000000000")  // → signal phNozzlesDisabledResult(cid, phId, success)
```

---

## Messages de statut

Le contrôleur peut envoyer périodiquement des messages de statut détaillés.

### Démarrer / arrêter les messages

```qml
// Niveau 1 = basique, niveau 2 = étendu
// Intervalle en millisecondes
Xpl2Client.jcStatusMessagingStart(1, 1000)  // JC, niveau 1, toutes les secondes
Xpl2Client.jcStatusMessagingStop()

Xpl2Client.phStatusMessagingStart(2, 500)   // Têtes, niveau 2, toutes les 500ms
Xpl2Client.phStatusMessagingStop()
```

**Signaux de confirmation :**
- `jcStatusMessagingStartResult(cid, statusLevel, sendIntervalMs, success)`
- `jcStatusMessagingStopResult(cid, success)`
- `phStatusMessagingStartResult(cid, statusLevel, sendIntervalMs, success)`
- `phStatusMessagingStopResult(cid, success)`

### Recevoir les statuts

Les messages de statut arrivent sous forme d'objets structurés avec des propriétés nommées.

```qml
Connections {
    target: Xpl2Client

    function onJcStatusReceived(status) {
        // status est un objet Xpl2JcStatus
        tempLabel.text = status.temperature.toFixed(1) + "°C"
        cpuLabel.text = status.cpuPercentageBusy.toFixed(1) + "%"
    }

    function onPhStatusReceived(status) {
        // status est un objet Xpl2PhStatus
        console.log("Tête", status.printheadId, "temp:", status.temperature)
    }
}
```

### Champs du statut JC (`Xpl2JcStatus`)

#### Niveau 1

| Propriété | Type | Description |
|---|---|---|
| `controllerId` | int | ID du contrôleur |
| `statusLevel` | int | Niveau de statut (1 ou 2) |
| `cpuPercentageBusy` | float | Charge CPU (%) |
| `rail5V` | float | Tension rail 5V |
| `railCanBus8V` | float | Tension bus CAN 8V |
| `temperature` | float | Température (°C) |
| `humidity` | float | Humidité (%) |
| `busCurrent` | float | Courant bus (A) |
| `onTimeSeconds` | int | Temps de fonctionnement (s) |

#### Niveau 2 (inclut le niveau 1 +)

| Propriété | Type | Description |
|---|---|---|
| `ipAddress` | string | Adresse IP |
| `eFuseVoltage` | float | Tension eFuse (V) |
| `eFuseBusEnabled` | bool | Bus eFuse activé |
| `busPowerEnabled` | bool | Alimentation bus activée |
| `busPowerOk` | bool | Alimentation bus OK |
| `switchValue` | int | Valeur du commutateur |
| `firmwareVersion` | string | Version firmware |
| `hardwareVersion` | string | Version hardware |
| `indicator0` .. `indicator5` | bool | Indicateurs 0 à 5 |

### Champs du statut PH (`Xpl2PhStatus`)

#### Niveau 1

| Propriété | Type | Description |
|---|---|---|
| `controllerId` | int | ID du contrôleur |
| `statusLevel` | int | Niveau de statut |
| `printheadId` | int | ID de la tête |
| `temperature` | float | Température (°C) |
| `humidity` | float | Humidité (%) |
| `mcuTemperature` | float | Température MCU (°C) |
| `pdsVoltage` | float | Tension PDS (V) |
| `mdsVoltage` | float | Tension MDS (V) |
| `systemVoltage` | float | Tension système (V) |
| `eFuseCurrent` | float | Courant eFuse (A) |
| `nozzleCurrent` | float | Courant buses (A) |
| `vdd` | float | Tension VDD (V) |
| `temperatureTrip` | bool | Seuil température dépassé |
| `pdsOverVoltageTrip` | bool | Surtension PDS |
| `pdsUnderVoltageTrip` | bool | Sous-tension PDS |
| `pdsSupplyErrorTrip` | bool | Erreur alimentation PDS |
| `mdsOverVoltageTrip` | bool | Surtension MDS |
| `mdsUnderVoltageTrip` | bool | Sous-tension MDS |
| `supplyOverVoltageTrip` | bool | Surtension alimentation |
| `supplyUnderVoltageTrip` | bool | Sous-tension alimentation |
| `eFuseOverCurrentTrip` | bool | Surintensité eFuse |
| `eFuseInputVoltageErrorTrip` | bool | Erreur tension entrée eFuse |
| `eFuseFaultTrip` | bool | Défaut eFuse |
| `flashFaultyTrip` | bool | Défaut flash |
| `flashChecksumErrorTrip` | bool | Erreur checksum flash |
| `dutyCycle` | float | Rapport cyclique (%) |
| `pwmFrequency` | float | Fréquence PWM (Hz) |
| `drive` | int | Drive |
| `nozzleDriveFrequency` | float | Fréquence drive buses (Hz) |
| `nozzleDriveDutyCycle` | float | Rapport cyclique drive buses (%) |
| `onTimeSeconds` | int | Temps de fonctionnement (s) |

#### Niveau 2 (inclut le niveau 1 +)

| Propriété | Type | Description |
|---|---|---|
| `accelerometerId` | int | ID accéléromètre |
| `mcuId` | string | ID MCU |
| `flashMemoryId` | string | ID mémoire flash |
| `temperatureSensorSerialNumber` | int | N° série capteur température |
| `mcuHardwareVersion` | string | Version hardware MCU |
| `mcuFirmwareVersion` | string | Version firmware MCU |
| `mcuFirmwareVariant` | string | Variante firmware MCU |
| `fpgaHardwareVersion` | string | Version hardware FPGA |
| `fpgaFirmwareVersion` | string | Version firmware FPGA |
| `bootloaderVersion` | string | Version bootloader |
| `maxAllowedTemperature` | float | Température max autorisée (°C) |
| `pdsVoltageMax` | float | Tension PDS max (V) |
| `pdsVoltageMin` | float | Tension PDS min (V) |
| `pdsVoltageSetting` | float | Réglage tension PDS (V) |
| `mdsVoltageMax` | float | Tension MDS max (V) |
| `mdsVoltageMin` | float | Tension MDS min (V) |
| `eFuseCurrentMax` | float | Courant eFuse max (A) |
| `measuredHardwareVersion` | string | Version hardware mesurée |
| `gyroX`, `gyroY`, `gyroZ` | int | Gyroscope X/Y/Z |
| `accelerationX`, `accelerationY`, `accelerationZ` | int | Accélération X/Y/Z |
| `purge`, `purgeState`, `purgeDelay`, `purgeCounter` | int | Paramètres de purge |
| `cleaningStartPeriod`, `cleaningEndPeriod`, `cleaningStepPeriod`, `cleaningPeriod` | int | Paramètres de nettoyage |

---

## Configuration

### ID des têtes

```qml
Xpl2Client.phSetId(3)       // → signal phSetIdResult(cid, phId, success)
Xpl2Client.phDeassignId()   // → signal phDeassignIdResult(cid, success)
```

### Paramètres de jetting

```qml
// Pour tout le contrôleur
Xpl2Client.jcSetJettingParams(dutyCycle, pwmFreq, drive, nozzleDriveFreq, nozzleDriveDutyCycle)
// → signal jcSetJettingParamsResult(cid, dutyCycle, pwmFreq, drive, nozzleDriveFreq, nozzleDriveDutyCycle, result)

// Pour une tête
Xpl2Client.phSetJettingParams(phId, dutyCycle, pwmFreq, drive, nozzleDriveFreq, nozzleDriveDutyCycle)
// → signal phSetJettingParamsResult(cid, phId, dutyCycle, pwmFreq, drive, nozzleDriveFreq, nozzleDriveDutyCycle, result)

// Lire les paramètres d'une tête
Xpl2Client.phGetJettingParams(3)
// → signal phGetJettingParamsResult(cid, phId, dutyCycle, pwmFreq, drive, nozzleDriveFreq, nozzleDriveDutyCycle, result)
```

Le paramètre `result` est un `JettingParamsResult` :

| Valeur | Signification |
|---|---|
| `1` (Ok) | Succès |
| `0` (Failed) | Échec |
| `-1` (DutyCycle) | Rapport cyclique invalide |
| `-2` (PwmFrequency) | Fréquence PWM invalide |
| `-3` (Drive) | Drive invalide |
| `-4` (NozzleDriveFrequency) | Fréquence drive buses invalide |
| `-5` (NozzleDriveDutyCycle) | Rapport cyclique drive buses invalide |

### Calibration

```qml
Xpl2Client.jcSaveCalibration()       // → jcSaveCalibrationResult(cid, success)
Xpl2Client.phSaveCalibration(3)      // → phSaveCalibrationResult(cid, phId, success)
Xpl2Client.jcResetCalibration()      // → jcResetCalibrationResult(cid, success)
Xpl2Client.phResetCalibration(3)     // → phResetCalibrationResult(cid, phId, success)
```

### Purge

```qml
// Configurer : intervalle (ms) et durée de jet (ms)
// La durée doit être inférieure à l'intervalle
Xpl2Client.jcSetPurgeSettings(5000, 200)  // → jcSetPurgeSettingsResult(cid, interval, time, success)
Xpl2Client.jcSwitchOffPurge()             // → jcSwitchOffPurgeResult(cid, success)
```

### Setter / Getter générique

Permet de lire ou écrire n'importe quel paramètre par son ID (voir Appendice D du protocole).

```qml
// Écrire un paramètre du contrôleur
// saveNewValue : true pour sauvegarder en mémoire permanente
Xpl2Client.jcSetter(true, 4, "35.0")   // setter ID 4 = température
// → signal jcSetterResult(cid, saveNewValue, setterId, newValue, result)

// Écrire un paramètre d'une tête
Xpl2Client.phSetter(3, false, 23, "50.0")  // tête 3, setter ID 23 = duty cycle
// → signal phSetterResult(cid, phId, saveNewValue, setterId, newValue, result)

// Lire un paramètre du contrôleur
// getSavedValue : true pour la valeur sauvegardée, false pour la valeur courante
Xpl2Client.jcGetter(false, 4)
// → signal jcGetterResult(cid, savedValue, getterId, currentValue, success)

// Lire un paramètre d'une tête
Xpl2Client.phGetter(3, false, 1)
// → signal phGetterResult(cid, phId, savedValue, getterId, currentValue, success)
```

Le `result` des setters est un `SetterResult` :

| Valeur | Signification |
|---|---|
| `1` (Ok) | Succès |
| `0` (Failed) | Échec |
| `-1` (IncorrectNewValue) | Valeur incorrecte |

### Sauvegarde et réinitialisation

```qml
// Sauvegarder tous les réglages
Xpl2Client.jcSaveAllPrintheadSettings()  // → jcSaveAllPrintheadSettingsResult(cid, success)
Xpl2Client.phSaveSettings(3)             // → phSaveSettingsResult(cid, phId, success)

// Réinitialiser les réglages
Xpl2Client.jcResetSettingsAllPrintheads()  // → jcResetSettingsAllPrintheadsResult(cid, success)
Xpl2Client.phResetAllSettings(3)           // → phResetAllSettingsResult(cid, phId, success)
```

### Redémarrage et arrêt

```qml
Xpl2Client.jcRebootAllPrintheads()      // → jcRebootAllPrintheadsResult(cid, success)
Xpl2Client.phReboot(3)                  // → phRebootResult(cid, phId, success)
Xpl2Client.jcResetControllerSoftware()  // → jcResetControllerSoftwareResult(cid, success)
Xpl2Client.jcRestart()                  // → jcRestartResult(cid, success)
Xpl2Client.jcShutdown()                 // → jcShutdownResult(cid, success)
```

---

## Imaging

Les commandes d'imaging sont envoyées sur le port 2 (9111).

### Démarrer / arrêter l'impression

```qml
Xpl2Client.imagingStart(1.0)  // vitesse d'impression
// → signal imagingReply(imageLines)  — nombre de lignes d'image à envoyer

Xpl2Client.imagingStop()
// → signal imagingStopResult(success)
```

### Masques d'image

Les masques définissent quelles buses sont actives pour chaque ligne d'image. Le masque fait 12 caractères par tête (180 caractères pour 15 têtes).

```qml
// Envoyer un masque : m0 démarre, m1 termine et déclenche l'envoi
Xpl2Client.imageMaskStart("FFFFFFFFFFFF...")   // 180 caractères
Xpl2Client.imageMaskEnd("fin_du_message")
// → signal imagingReply(imageLines)
```

### Masques de rapport cyclique

Même principe avec 2 caractères hexadécimaux par tête.

```qml
Xpl2Client.dutyCycleMaskStart("FF...")
Xpl2Client.dutyCycleMaskEnd("fin")
// → signal imagingReply(imageLines)
```

### Compteur d'images

Vérifie le nombre de lignes d'image restantes. Utilisé avant d'arrêter l'impression pour s'assurer que toutes les lignes ont été envoyées.

```qml
Xpl2Client.imageCount()
// → signal imagingReply(imageLines)  — 0 signifie que tout est envoyé
```

---

## Événements serveur

Ces signaux sont émis automatiquement quand le serveur envoie des événements.

### Erreurs

```qml
Connections {
    target: Xpl2Client

    // Erreur du contrôleur (codes 3000+)
    function onJcErrorCode(controllerId, errorCode, params) {
        console.log("Erreur JC:", errorCode, params)
    }

    // Erreur d'une tête (codes 4000+)
    function onPhErrorCode(controllerId, printheadId, errorCode, params) {
        console.log("Erreur tête", printheadId, ":", errorCode)
    }

    // Erreur d'imaging (codes 5000+)
    function onImgErrorCode(controllerId, errorCode, params) { }

    // Erreur de statut (codes 6000+)
    function onStatusErrorCode(controllerId, errorCode, params) { }
}
```

### Connexion des têtes

```qml
Connections {
    target: Xpl2Client

    function onPhConnectionChanged(controllerId, printheadId, connected) {
        console.log("Tête", printheadId, connected ? "connectée" : "déconnectée")
    }
}
```

### Arrêt du serveur

```qml
Connections {
    target: Xpl2Client
    function onShuttingDown() {
        console.log("Le serveur s'éteint")
    }
}
```