Implement working motor init command using limit-switch homing
Added `motor init [up|down] [timeout]` that homes the altitude axis by
slewing to a mechanical limit. The firmware detects the limit switch and
performs an automatic home to position 0 (optics toward ground).
Validated procedure:
1. Slew up briefly (90° 0.4 for 5s) to move away from the bottom limit
2. `motor init down 40` — slew 270° until bottom limit triggers auto-home
3. Axis remains fully operational after homing
The firmware drops the WebSocket connection when the home sequence starts
(normal behavior). After reconnecting, the axis works normally.
Note: API still returns NEED_RESET (-14520) because absolute positioning
requires astro calibration (plate solving). The mechanical home only
provides physical position 0, not sky coordinates.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@ -101,9 +101,19 @@ Le `motor stop` interrompt un slew en cours instantanément.
|
|||||||
**Découverte clé — Home par butée** : slewing en 270° (descente) à vitesse modérée jusqu'à ce que le limit switch se déclenche provoque un **home automatique du firmware**. Le télescope revient à la position 0 physique (optique vers le sol). C'est la méthode d'initialisation manuelle des moteurs — pas besoin de `motor reset` (qui ne fait que rebooter).
|
**Découverte clé — Home par butée** : slewing en 270° (descente) à vitesse modérée jusqu'à ce que le limit switch se déclenche provoque un **home automatique du firmware**. Le télescope revient à la position 0 physique (optique vers le sol). C'est la méthode d'initialisation manuelle des moteurs — pas besoin de `motor reset` (qui ne fait que rebooter).
|
||||||
|
|
||||||
Procédure d'initialisation manuelle :
|
Procédure d'initialisation manuelle :
|
||||||
1. `motor slew 270 0.5` jusqu'à la butée (le firmware home tout seul)
|
1. `motor slew 90 0.4` pendant 5s — monter ~45° pour décoller de la butée basse
|
||||||
2. Position 0 = optique vers le sol
|
2. `motor init down 40` — slew 270° jusqu'à la butée basse → home automatique
|
||||||
3. L'API reste en `NEED_RESET` tant que la calibration astro n'est pas faite (le home mécanique ne donne pas la position absolue, seulement la position physique)
|
3. Position 0 = optique vers le sol
|
||||||
|
4. L'axe altitude reste **pleinement opérationnel** après le home
|
||||||
|
5. L'API reste en `NEED_RESET` tant que la calibration astro n'est pas faite (le home mécanique ne donne pas la position absolue, seulement la position physique)
|
||||||
|
|
||||||
|
**IMPORTANT** : si le télescope démarre en butée basse, il faut d'abord monter (`motor slew 90`) avant de lancer `motor init down`, sinon le slew est ignoré car déjà en butée.
|
||||||
|
|
||||||
|
**Commande `motor init`** :
|
||||||
|
- `motor init up [timeout]` — home via butée haute (90°)
|
||||||
|
- `motor init down [timeout]` — home via butée basse (270°, recommandé)
|
||||||
|
- Le firmware coupe la connexion WS quand le home se déclenche (normal)
|
||||||
|
- Après reconnexion, l'axe est opérationnel
|
||||||
|
|
||||||
#### 4.5 Système de coordonnées joystick découvert (config alt-az, trépied vertical)
|
#### 4.5 Système de coordonnées joystick découvert (config alt-az, trépied vertical)
|
||||||
|
|
||||||
|
|||||||
@ -397,6 +397,28 @@ func cmdMotor() *cobra.Command {
|
|||||||
fmt.Printf("motor %d: id=%d code=%d position=%.2f\n", id, pos.GetId(), pos.GetCode(), pos.GetPosition())
|
fmt.Printf("motor %d: id=%d code=%d position=%.2f\n", id, pos.GetId(), pos.GetCode(), pos.GetPosition())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "init [up|down] [timeout]",
|
||||||
|
Short: "Home altitude axis by slewing to a mechanical limit (safe, daytime)",
|
||||||
|
Args: cobra.MaximumNArgs(2),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
dir := 90.0 // default: up
|
||||||
|
if len(args) > 0 && args[0] == "down" {
|
||||||
|
dir = 270.0
|
||||||
|
}
|
||||||
|
timeout := 30
|
||||||
|
if len(args) > 1 {
|
||||||
|
timeout = int(parseInt32(args[1]))
|
||||||
|
}
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
dirStr := "up (toward sky)"
|
||||||
|
if dir == 270 { dirStr = "down (toward ground)" }
|
||||||
|
fmt.Printf("Initializing: slewing %s at 0.5 until limit (max %ds)...\n", dirStr, timeout)
|
||||||
|
must(scope.MotorInit(dir, timeout))
|
||||||
|
fmt.Println("Init complete.")
|
||||||
|
},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|||||||
@ -210,6 +210,18 @@ func (t *Telescope) MotorGetPosition(id int32) (*pb.ResMotorPosition, error) {
|
|||||||
return resp, decodeResponse(pkt, resp)
|
return resp, decodeResponse(pkt, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MotorInit homes the altitude axis by slewing to a mechanical limit.
|
||||||
|
// The firmware detects the limit switch and resets position automatically.
|
||||||
|
// direction: 90 = up (toward sky), 270 = down (toward ground).
|
||||||
|
// timeoutSec is the maximum time to wait for the limit (typically 30-60s).
|
||||||
|
func (t *Telescope) MotorInit(direction float64, timeoutSec int) error {
|
||||||
|
if err := t.SlewJoystick(direction, 0.5); err != nil {
|
||||||
|
return fmt.Errorf("init slew: %w", err)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Duration(timeoutSec) * time.Second)
|
||||||
|
return t.SlewJoystick(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
// MotorReset resets a motor (finds home via limit switch).
|
// MotorReset resets a motor (finds home via limit switch).
|
||||||
// cmd 14003 is inferred. WARNING: causes telescope reboot — but may be
|
// cmd 14003 is inferred. WARNING: causes telescope reboot — but may be
|
||||||
// the only way to unblock an axis stuck at a mechanical limit.
|
// the only way to unblock an axis stuck at a mechanical limit.
|
||||||
|
|||||||
Reference in New Issue
Block a user