pendante WHB04B-6
XHC WHB04B-6 6 axes, sans fil LinuxCNC 2.9.10 en service sur la PrintNC

La pendante, et ses touches qui mentent

Seize touches, deux sélecteurs, une molette — et un mode d'emploi d'origine qui ne parle que de Mach3. Voici ce que fait réellement chaque commande sous LinuxCNC, y compris les trois endroits où l'inscription sur le bouton dit le contraire de ce qu'il fait.

antenne · pile X: +1234.4561 Y: −1470.9632 CON:10% RESET STOP Start ⏻ Feed+ Feed− Spin+ Spin− M-HOME Safe-Z W-HOME S-ON/OFF Probe-Z Fn axe OFF X Y Z A B C vitesse pas · % · Lead Macro-10 molette
À lire en premier

Trois inscriptions qui disent le contraire du vrai

Les développeurs du composant LinuxCNC le disent sans détour : la sérigraphie et la notice du fabricant sont mal traduites. Trois pièges en découlent, et ils suffisent à croire l'appareil en panne.

MPG et Step sont inversés

Le bouton marqué MPG met la pendante en mode continu, et le bouton marqué Step/Continuous la met en mode pas à pas. En continu, chaque cran de molette veut dire « déplace l'axe à la vitesse choisie » ; en pas à pas, « déplace-le d'un pas ».

« CON: 10% » n'est pas un indicateur de connexion

C'est le mode Continuous à 10 % de la vitesse maximale. Selon le firmware, le même état s'écrit CONT 30%, CON:30% ou STEP: 1.0. La liaison radio, elle, a son propre pictogramme d'antenne, en haut à gauche de l'écran, à côté de la pile.

Sélecteur d'axe sur OFF : l'écran se fige

Ce n'est pas seulement que rien ne bouge — la pendante cesse de rafraîchir les coordonnées. Un écran qui affiche des chiffres figés avec le sélecteur sur OFF est un écran qui fonctionne normalement.

Les deux molettes crantées

Le sélecteur de vitesse se lit de deux façons

Une seule couronne, deux graduations imprimées l'une sous l'autre. Celle qui compte dépend du mode : les millimètres en pas à pas, les pourcentages en continu.

Positionen pas à pasen continuce que fait la molette
1re0.001 mm2 %un cran = un pas, ou 2 % de la vitesse maxi
2e0.01 mm5 %idem
3e0.1 mm10 %idem
4e1 mm30 %idem
5e—60 %pourcentage seulement
6e—100 %pourcentage seulement
Lead——la molette règle la correction de broche
MPG——la molette règle la correction d'avance
Pourquoi la molette ne déplace rien en MPG ni en Lead

Parce que le composant est lancé avec les options -s et -f, qui donnent précisément ce rôle à ces deux positions. Pour déplacer un axe, il faut une position de pas ou de pourcentage. L'option -B ajoute par ailleurs les pas de 5 mm et 10 mm.

Le sélecteur d'axe, lui, est plus simple : OFF, X, Y, Z, A, B, C. Sur la PrintNC, qui est une machine XYZY (le Y est en tandem sur deux moteurs), les positions A, B et C ne font rien : ces axes n'existent pas. Ce n'est pas un défaut.

La touche modificatrice

Fn transforme n'importe quelle touche en macro

Fn maintenue, puis la touche — dans cet ordre. La combinaison fonctionne avec les seize touches, y compris celles où aucun numéro de macro n'est sérigraphié.

Toucheseuleavec Fn
RESETarrêt d'urgence / réarmementMacro-11
STOParrête le programmeMacro-12
Start/Pauselance, met en pause, reprendMacro-13
Feed +augmente la correction d'avanceMacro-1
Feed −diminue la correction d'avanceMacro-2
Spindle +augmente la correction de brocheMacro-3
Spindle −diminue la correction de brocheMacro-4
M-HOMEprise d'origine machineMacro-5
Safe-Zdégagement en ZMacro-6
W-HOMEorigine pièceMacro-7
S-ON/OFFbroche en marche / à l'arrêtMacro-8
Probe-Zpalpage en ZMacro-9
Macro-10bascule l'affichage machine / pièceMacro-14
MPG (= continu)passe en mode continuMacro-15
Step (= pas à pas)passe en mode pas à pasMacro-16
Fnmodificateur — ne fait rien seule

Sur cette machine, huit gestes sont câblés — et chaque touche garde sa famille : seule elle fait le geste courant, avec Fn elle fait le réglage correspondant.

ToucheSeuleAvec Fn
M-HOMEprise d'originealler au zéro machine
Safe-Zdégager en haut de coursemode Z sur le martyre
W-HOMEaller au zéro pièce, Z d'abordmode Z sur la pièce
Probe-Zpalper l'outil courantremettre la référence à zéro
halui n'exécute qu'une seule commande par bouton

Les MDI_COMMAND se déclarent dans [HALUI], et halui exporte une pin halui.mdi-command-XX par ligne — XX suivant l'ordre des lignes, à partir de 00. Déplacer une ligne déplace le bouton qui l'appelle, sans que rien ne proteste.

Attention, ce n'est pas la section [MDI_COMMAND_LIST] des boutons de l'écran, et le ; n'y sépare rien : en G-code il ouvre un commentaire. Une ligne comme G0 Z25;X0 Y0;Z0 monterait le Z et ne rejoindrait jamais X Y — un demi-geste, silencieux. Les gestes en plusieurs temps passent donc par un sous-programme.

RESET réarme, il ne déclenche pas

Il est câblé sur halui.estop.reset. La différence est le sens de la panne : déclencher un arrêt d'urgence depuis une pendante sans fil est une fausse sécurité — liaison tombée, le bouton ne fait plus rien, et le réflexe s'est pris sur un objet mort. Réarmer tombe du bon côté : sans liaison on ne réarme pas, la machine reste à l'arrêt. Le champignon câblé demeure le seul organe pour arrêter.

Et surtout pas la remise à zéro des références sur cette touche, malgré le nom : RESET est le bouton du réflexe, celui que la main trouve sans regarder quand ça part de travers. Il effacerait la référence de longueur d'outil en plein travail. Ce geste-là est derrière Fn + Probe-Z, la touche qui a posé cette référence.

La pendante arrête et regarde, elle ne lance pas

halui.program.{run, pause, resume, is-idle} ne sont pas câblées : sur la machine réelle elles sont déjà portées par les boutons physiques FEED_HOLD et CYCLE_START, et deux sources sur un même signal font refuser HAL — la config ne chargerait plus. En simulation ces pins sont libres, donc la faute ne se serait vue qu'à l'établi.

Ce n'est pas qu'un contournement : lancer un cycle au bout d'une liaison radio qui tombe est le geste à ne pas offrir. STOP, lui, fonctionne — c'est le sens sûr.

L'écran

Deux jeux de coordonnées, et lequel vous regardez

La pendante reçoit deux positions par axe et n'en affiche qu'une à la fois. X: donne la coordonnée machine, X1: la coordonnée pièce. Le bouton Macro-10 bascule de l'une à l'autre. Un écart entre l'écran de la pendante et celui du pupitre vient presque toujours de là : les deux valeurs sont justes, elles ne parlent simplement pas du même repère.

L'écran affiche aussi le niveau de pile, la force du signal, le mode et le pas ou le pourcentage en cours. Il ne peut rien montrer d'autre : le firmware n'accepte aucune donnée libre.

Au réveil, la pendante ne dit pas où sont ses sélecteurs

C'est un défaut connu, reconnu dans le README du composant : à l'allumage, l'appareil n'annonce pas spontanément la position de ses deux couronnes. Tant qu'on n'a rien bougé, LinuxCNC croit qu'aucun axe n'est choisi. Tourner un sélecteur d'un cran suffit à le faire parler.

Installation

La règle udev d'abord — tout le reste en dépend

Le composant xhc-whb04b-6 est livré avec LinuxCNC : il n'y a rien à compiler. Mais sans droit d'accès au dongle, il démarre quand même, et fait croire que tout va bien.

Le piège qui coûte une après-midi

Sans la règle udev, le composant se lance, crée ses 137 pins HAL et transmet même les positions vers l'écran de la pendante — mais il n'ouvre jamais le dongle. Rien ne remonte, et le dongle se réinitialise en boucle toutes les 20 secondes faute d'être interrogé. Un loadusr -W qui réussit ne prouve donc rien sur les permissions : il réussit aussi quand le composant n'a aucun accès.

Le paquet Arch ne pose pas cette règle, et celle fournie en amont vise le groupe plugdev, qui n'existe pas sur Arch — d'où TAG+="uaccess" à la place.

Poser la règle :

echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="10ce", ATTR{idProduct}=="eb93", MODE="0666", TAG+="uaccess"' \
  | sudo tee /etc/udev/rules.d/99-xhc-whb04b-6.rules
sudo udevadm control --reload && sudo udevadm trigger

Puis débrancher et rebrancher le dongle : une règle udev ne s'applique qu'à l'énumération suivante. Le contrôle qui ne ment pas — s'il ne renvoie rien, le composant n'a pas le dongle :

ls -l /proc/$(pgrep -x xhc-whb04b-6)/fd | grep /dev/bus/usb

Côté .ini, la section [HAL] doit déclarer HALUI = halui — c'est halui qui expose la moitié des signaux utilisés.

Le câblage se charge depuis le post-GUI, et la ligne y est laissée commentée exprès. Pour l'activer, retirer le # devant source pendant-whb04b6.hal :

ConfigFichier où décommenter
Machine réellepostgui_call_list.hal
Simulationpostgui_call_list_sim.hal
Une fois cette ligne active, LinuxCNC exige la pendante

loadusr -W attend que le composant soit prêt : pendante éteinte ou dongle absent, LinuxCNC ne démarre plus. Sur la machine de production, c'est un vrai risque d'atelier — il faut l'accepter en connaissance de cause. La ligne est active dans la config publiée depuis que la pendante est en service ; remettre le # suffit à retrouver un démarrage sans elle.

Et dans cet ordre : la règle udev d'abord, la ligne ensuite.

Le dongle qui clignote n'est pas en panne

Au repos, quand aucun logiciel ne l'interroge, le dongle se réinitialise toutes les 20 secondes : c'est son comportement normal. Il se stabilise de lui-même dès que le composant l'a ouvert. Et si l'on a besoin de le forcer à rester présent — pour lui laisser le temps d'être attrapé au démarrage — il suffit de maintenir une touche de la pendante enfoncée : la liaison tient alors plus d'une minute au lieu de dix secondes.

Le câblage HAL

81 liaisons, vérifiées pin par pin

Ce fichier vit dans le dépôt printnc-config. Il a été écrit contre la configuration de simulation, mais rien n'y était propre à la simulation : la machine réelle a les mêmes axes et les mêmes joints, et le même câblage a été repris tel quel sur la PrintNC.

Trois corrections sur l'exemple livré avec LinuxCNC

Un. La pin whb.halui.home-all est décrite dans la page de manuel mais n'existe pas dans le binaire 2.9.10 ; c'est whb.button.m-home qui pilote halui.home-all. La liste des pins réelles s'obtient en chargeant le composant seul : halrun puis show pin whb.

Deux. halui.program.is-paused et spindle.0.on portent déjà des signaux dans la configuration PrintNC : il faut s'y raccrocher, HAL refusant qu'une pin appartienne à deux signaux.

Trois. Quatre pins de l'exemple ont été retirées après contrôle contre la config réelle, et non contre la simulation : halui.program.{run, pause, resume, is-idle} y sont déjà portées par les boutons physiques de la carte. La simulation les laisse libres — la faute n'aurait éclaté qu'au moment de démarrer la machine.

La molette exige une machine prise d'origine

Elle pilote axis.<lettre>.jog-*, ce qui suppose le mode teleop. Avant la prise d'origine, LinuxCNC est en mode joint et la molette reste sans effet. Ce n'est pas une panne.

# pendant-whb04b6.hal
# Pendante sans fil XHC WHB04B-6 -- cablage HAL pour la SIMULATION.
#
# CE FICHIER N'EST PAS CHARGE PAR DEFAUT. Pour l'activer, decommenter la
# ligne "source pendant-whb04b6.hal" dans postgui_call_list_sim.hal.
#
# ATTENTION -- loadusr -W ATTEND que le composant soit pret. Dongle USB
# debranche ou pendante eteinte => LinuxCNC NE DEMARRE PAS, et c'est voulu :
# sans le composant les pins whb.* n'existent pas et tous les net ci-dessous
# echoueraient un par un. Pour lancer la sim sans la pendante, recommenter
# la ligne dans postgui_call_list_sim.hal.
#
# Machine simulee : XYZY, Y en tandem. Joints 0=X, 1=Y, 2=Z, 3=Y2.
# Le selecteur rotatif de la pendante porte aussi A, B et C : ces axes
# n'existent pas ici, ces trois positions ne feront rien. Normal.
#
# PREALABLE INDISPENSABLE -- LA REGLE UDEV.
# Sans elle le composant demarre, cree toutes ses pins, et n'ouvre JAMAIS le
# dongle : LinuxCNC a l'air correct, mais rien ne remonte de la pendante et le
# dongle se reinitialise en boucle toutes les 20 s (personne ne l'interroge).
# Un loadusr -W qui reussit ne prouve donc RIEN sur les permissions -- verifier
# plutot que le composant tient le peripherique :
#     ls -l /proc/$(pgrep -x xhc-whb04b-6)/fd | grep /dev/bus/usb
# Poser la regle (le groupe plugdev de la regle amont n'existe pas sur Arch) :
#     echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="10ce", ATTR{idProduct}=="eb93", MODE="0666", TAG+="uaccess"' \
#       | sudo tee /etc/udev/rules.d/99-xhc-whb04b-6.rules
#     sudo udevadm control --reload && sudo udevadm trigger
# Puis DEBRANCHER et REBRANCHER le dongle : la regle ne s'applique qu'a
# l'enumeration suivante.

# La molette pilote axis.<lettre>.jog-*, ce qui exige le mode TELEOP, donc
# une machine HOMEE. Avant homing LinuxCNC est en mode joint et la molette
# reste sans effet -- ce n'est pas une panne.

# ######################################################################
# chargement du composant
# ######################################################################
#   -H  mode HAL (sans lui le composant tourne en mode interactif console)
#   -s  Lead + molette = correction de broche
#   -f  MPG  + molette = correction d'avance
#   -B  ajoute les pas 5 mm et 10 mm au selecteur
	loadusr -W xhc-whb04b-6 -HsfB

# ######################################################################
# marche / arret machine
# ######################################################################
	net pdnt.machine.is-on      halui.machine.is-on         => whb.halui.machine.is-on
	net pdnt.machine.on         whb.halui.machine.on        => halui.machine.on
	net pdnt.machine.off        whb.halui.machine.off       => halui.machine.off

# ######################################################################
# programme
# ######################################################################
# LA PENDANTE ARRETE ET REGARDE, ELLE NE LANCE PAS.
#
# halui.program.{run,pause,resume,is-idle} sont DEJA PORTES sur la vraie
# machine (remora-flexi.hal 399-407) par les boutons physiques FEED_HOLD
# et CYCLE_START. Les cabler ici ferait DEUX SOURCES sur un meme signal :
# HAL refuse, et la config de l'atelier ne chargerait plus. En simulation
# ces pins sont libres -- la faute ne se serait vue qu'a l'etabli, parce
# que ces boutons-la n'existent que sur la FlexiHAL.
#
# Les retirer n'est pas qu'un contournement, c'est le bon choix : lancer
# un programme au bout d'une liaison radio qui tombe est le geste a ne
# pas offrir. Arreter, si -- le sens sur. Le cycle se lance depuis
# l'ecran ou le bouton CYCLE_START, comme avant.
#
# Si un jour la pause depuis la pendante devient necessaire, elle passe
# par un or2 en amont de hold_toggle, PAS par un second net -- et se
# mesure a l'etabli : cette logique-la porte deja un bug paye (le
# programme qui redemarrait en boucle, remora-flexi.hal 408-419).
	net pdnt.program.is-running halui.program.is-running    => whb.halui.program.is-running
	net pdnt.program.stop       whb.halui.program.stop      => halui.program.stop
# halui.program.is-paused porte deja le signal program-is-paused
# (remora-flexi-sim.hal, vers hold_toggle.is-on) : on s'y raccroche au lieu
# de creer un second signal, ce que HAL refuserait.
	net program-is-paused       => whb.halui.program.is-paused

# ######################################################################
# modes machine
# ######################################################################
	net pdnt.mode.auto          whb.halui.mode.auto         => halui.mode.auto
	net pdnt.mode.manual        whb.halui.mode.manual       => halui.mode.manual
	net pdnt.mode.mdi           whb.halui.mode.mdi          => halui.mode.mdi
	net pdnt.mode.joint         whb.halui.mode.joint        => halui.mode.joint
	net pdnt.mode.teleop        whb.halui.mode.teleop       => halui.mode.teleop
	net pdnt.mode.is-auto       halui.mode.is-auto          => whb.halui.mode.is-auto
	net pdnt.mode.is-manual     halui.mode.is-manual        => whb.halui.mode.is-manual
	net pdnt.mode.is-mdi        halui.mode.is-mdi           => whb.halui.mode.is-mdi
	net pdnt.mode.is-joint      halui.mode.is-joint         => whb.halui.mode.is-joint
	net pdnt.mode.is-teleop     halui.mode.is-teleop        => whb.halui.mode.is-teleop

# ######################################################################
# prise d'origine
# ######################################################################
# whb.halui.home-all est documente dans le man mais N'EXISTE PAS dans le
# binaire 2.9.10 (verifie par halcmd show pin) : c'est le bouton M-Home
# qui pilote la prise d'origine.
	net pdnt.home-all           whb.button.m-home           => halui.home-all
# Y en tandem : le joint 3 se prend en meme temps que le joint 1, la
# pendante n'a pas de voyant pour lui.
	net pdnt.joint.x.is-homed   halui.joint.0.is-homed      => whb.halui.joint.x.is-homed
	net pdnt.joint.y.is-homed   halui.joint.1.is-homed      => whb.halui.joint.y.is-homed
	net pdnt.joint.z.is-homed   halui.joint.2.is-homed      => whb.halui.joint.z.is-homed

# ######################################################################
# selection d'axe et molette
# ######################################################################
	net pdnt.axis.x.select      whb.halui.axis.x.select     => halui.axis.x.select
	net pdnt.axis.y.select      whb.halui.axis.y.select     => halui.axis.y.select
	net pdnt.axis.z.select      whb.halui.axis.z.select     => halui.axis.z.select

	net pdnt.axis.x.jog-counts  whb.axis.x.jog-counts       => axis.x.jog-counts
	net pdnt.axis.y.jog-counts  whb.axis.y.jog-counts       => axis.y.jog-counts
	net pdnt.axis.z.jog-counts  whb.axis.z.jog-counts       => axis.z.jog-counts

	net pdnt.axis.x.jog-enable  whb.axis.x.jog-enable       => axis.x.jog-enable
	net pdnt.axis.y.jog-enable  whb.axis.y.jog-enable       => axis.y.jog-enable
	net pdnt.axis.z.jog-enable  whb.axis.z.jog-enable       => axis.z.jog-enable

	net pdnt.axis.x.jog-scale   whb.axis.x.jog-scale        => axis.x.jog-scale
	net pdnt.axis.y.jog-scale   whb.axis.y.jog-scale        => axis.y.jog-scale
	net pdnt.axis.z.jog-scale   whb.axis.z.jog-scale        => axis.z.jog-scale

	net pdnt.axis.x.jog-vel-mode whb.axis.x.jog-vel-mode    => axis.x.jog-vel-mode
	net pdnt.axis.y.jog-vel-mode whb.axis.y.jog-vel-mode    => axis.y.jog-vel-mode
	net pdnt.axis.z.jog-vel-mode whb.axis.z.jog-vel-mode    => axis.z.jog-vel-mode

# ######################################################################
# affichage des positions sur l'ecran de la pendante
# ######################################################################
	net pdnt.axis.x.pos-feedback halui.axis.x.pos-feedback  => whb.halui.axis.x.pos-feedback
	net pdnt.axis.y.pos-feedback halui.axis.y.pos-feedback  => whb.halui.axis.y.pos-feedback
	net pdnt.axis.z.pos-feedback halui.axis.z.pos-feedback  => whb.halui.axis.z.pos-feedback

	net pdnt.axis.x.pos-relative halui.axis.x.pos-relative  => whb.halui.axis.x.pos-relative
	net pdnt.axis.y.pos-relative halui.axis.y.pos-relative  => whb.halui.axis.y.pos-relative
	net pdnt.axis.z.pos-relative halui.axis.z.pos-relative  => whb.halui.axis.z.pos-relative

# ######################################################################
# correction d'avance (molette en position MPG)
# ######################################################################
	net pdnt.feed-override.scale    whb.halui.feed-override.scale    => halui.feed-override.scale
	net pdnt.feed-override.value    halui.feed-override.value        => whb.halui.feed-override.value
	net pdnt.feed-override.increase whb.halui.feed-override.increase => halui.feed-override.increase
	net pdnt.feed-override.decrease whb.halui.feed-override.decrease => halui.feed-override.decrease
# Position "continu" du selecteur : vitesse = % * max-velocity.
	net pdnt.max-velocity.value     whb.halui.max-velocity.value     => halui.max-velocity.value

# ######################################################################
# broche (molette en position Lead)
# ######################################################################
	net pdnt.spindle.is-on      halui.spindle.0.is-on       => whb.halui.spindle.is-on
	net pdnt.spindle.start      whb.halui.spindle.start     => halui.spindle.0.start
	net pdnt.spindle.stop       whb.halui.spindle.stop      => halui.spindle.0.stop
	net pdnt.spindle.forward    whb.halui.spindle.forward   => halui.spindle.0.forward
	net pdnt.spindle.reverse    whb.halui.spindle.reverse   => halui.spindle.0.reverse
	net pdnt.spindle.increase   whb.halui.spindle.increase  => halui.spindle.0.increase
	net pdnt.spindle.decrease   whb.halui.spindle.decrease  => halui.spindle.0.decrease
	net pdnt.spindle.speed-cmd  spindle.0.speed-out-abs     => whb.halui.spindle-speed-cmd

	net pdnt.so.scale           whb.halui.spindle-override.scale    => halui.spindle.0.override.scale
	net pdnt.so.value           halui.spindle.0.override.value      => whb.halui.spindle-override.value
	net pdnt.so.increase        whb.halui.spindle-override.increase => halui.spindle.0.override.increase
	net pdnt.so.decrease        whb.halui.spindle-override.decrease => halui.spindle.0.override.decrease

# ######################################################################
# arrosage
# ######################################################################
	net pdnt.flood.is-on        halui.flood.is-on           => whb.halui.flood.is-on
	net pdnt.flood.on           whb.halui.flood.on          => halui.flood.on
	net pdnt.flood.off          whb.halui.flood.off         => halui.flood.off
	net pdnt.mist.is-on         halui.mist.is-on            => whb.halui.mist.is-on
	net pdnt.mist.on            whb.halui.mist.on           => halui.mist.on
	net pdnt.mist.off           whb.halui.mist.off          => halui.mist.off

# ######################################################################
# les gestes des boutons
# ######################################################################
# Chaque touche garde sa famille : seule elle fait le geste courant, avec
# Fn elle fait le reglage correspondant. L'INDEX SUIT L'ORDRE DES LIGNES
# MDI_COMMAND de [HALUI] dans le .ini -- deplacer une ligne la-bas
# deplace le bouton ici, sans que rien ne proteste.
#
#   Safe-Z          degage en haut de course        Fn+  mode martyre
#   W-HOME          zero piece (Z d'abord)          Fn+  mode piece
#   Probe-Z         palpe l'outil courant           Fn+  reset ref
#   M-HOME          prise d'origine (halui.home-all) Fn+ zero machine
	net pdnt.button.safe-z      whb.button.safe-z   => halui.mdi-command-00
	net pdnt.button.w-home      whb.button.w-home   => halui.mdi-command-01
	net pdnt.button.probe-z     whb.button.probe-z  => halui.mdi-command-02
	net pdnt.macro-5            whb.button.macro-5  => halui.mdi-command-03
	net pdnt.macro-6            whb.button.macro-6  => halui.mdi-command-04
	net pdnt.macro-7            whb.button.macro-7  => halui.mdi-command-05
	net pdnt.macro-9            whb.button.macro-9  => halui.mdi-command-06

# ######################################################################
# boutons laisses en signaux libres -- observables dans halshow
# ######################################################################
# RESET REARME, il ne declenche PAS. La difference est le sens de la
# panne. Declencher l'arret d'urgence depuis une pendante SANS FIL est
# une fausse securite : liaison tombee -- elle tombe --, le bouton ne
# fait plus rien sans le dire, et le reflexe s'est pris sur un objet
# mort. Rearmer, au contraire, tombe du bon cote : sans liaison on ne
# rearme pas, la machine reste a l'arret. Le champignon cable demeure le
# seul organe pour ARRETER.
#
# Et surtout PAS O<reset_ref> ici, meme si le nom appelle : RESET est le
# bouton du reflexe, celui que la main trouve sans regarder quand ca part
# de travers. Il effacerait #1000, la reference de longueur d'outil de la
# session, en plein job -- sans rien dire d'autre qu'un message qui
# passe. Ce geste-la est derriere Fn + Probe-Z, la touche qui a pose
# cette reference.
	net pdnt.button.reset       whb.button.reset    => halui.estop.reset

# Les autres restent nus faute d'emploi : les charger tous, sur un
# boitier tenu d'une main au-dessus d'une fraise qui tourne, fabrique la
# fausse manoeuvre. Feed+/- et Spindle+/- agissent deja nativement.
	net pdnt.button.fn          whb.button.fn
	net pdnt.button.stop        whb.button.stop
	net pdnt.button.start-pause whb.button.start-pause
	net pdnt.button.feed-plus   whb.button.feed-plus
	net pdnt.button.feed-minus  whb.button.feed-minus
	net pdnt.button.spindle-plus  whb.button.spindle-plus
	net pdnt.button.spindle-minus whb.button.spindle-minus
	net pdnt.button.mode-step   whb.button.mode-step
	net pdnt.button.mode-continuous whb.button.mode-continuous
Quand rien ne bouge

Couper le problème en deux, en une commande

La chaîne va de la pendante à LinuxCNC en passant par la radio, le dongle, le composant et HAL. Une seule lecture dit de quel côté chercher.

Ce qu'on litCe que ça veut dire
halcmd show pin whb.halui.axis — les pos-feedback portent de vraies coordonnées Le sens LinuxCNC → pendante fonctionne : le câblage HAL est bon.
… mais tous les .select et selected-* sont à FALSE Le sens pendante → LinuxCNC ne passe pas. Chercher du côté des droits d'accès, pas du câblage.
ls -l /proc/$(pgrep -x xhc-whb04b-6)/fd ne montre aucun /dev/bus/usb Le composant n'a jamais ouvert le dongle : la règle udev manque.
journalctl -k montre un cycle de connexion / déconnexion régulier Personne n'interroge le dongle. C'est un symptôme, jamais une cause : ni panne, ni appairage, ni hub.
La molette compte (whb.axis.x.jog-counts augmente) mais l'axe ne bouge pas Machine non prise d'origine, ou sélecteur de vitesse sur MPG ou Lead.
L'écran de la pendante ne se rafraîchit plus Sélecteur d'axe sur OFF.
Ce que le fabricant documente, et ce qu'il ne documente pas

La page constructeur ne couvre que Mach3 sous Windows ; le pilote qu'elle propose est inutile ici. Tout le support LinuxCNC vient du composant xhc-whb04b-6, écrit par rétro-ingénierie du protocole USB — le fabricant ayant refusé de publier la moindre spécification. C'est aussi pourquoi certaines bizarreries d'affichage sont signalées comme des bugs de firmware dans son README, et non corrigées.