fdr1-modbus-slave/src/arm.c
2026-03-10 16:46:46 +01:00

225 lines
8.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <arm.h>
#include <eeprom.h>
#include <spool.h>
// ─────────────────────────────────────────────
// Machine d'état traverse
// ─────────────────────────────────────────────
typedef enum {
ARM_IDLE,
ARM_GO_TO_ZERO, // retour vers LEFT
ARM_WAIT_LEFT, // attente 3/4 tour à LEFT
ARM_TRAVERSE, // déplacement vers RIGHT
ARM_WAIT_RIGHT, // attente 3/4 tour à RIGHT
ARM_RETURN // déplacement vers LEFT
} arm_state_t;
// ─────────────────────────────────────────────
// Constantes
// ─────────────────────────────────────────────
#define ARM_WAIT_STEPS 600U // 3/4 tour SPOOL (200pas × 4µstep × 3/4)
#define ARM_DIR_RIGHT 1
#define ARM_DIR_LEFT 0
// ─────────────────────────────────────────────
// État interne
// ─────────────────────────────────────────────
static volatile uint16_t gear_um; // déplacement µm par tour SPOOL
static volatile uint32_t accumulator; // accumulateur µm
static uint16_t arm_offset; // distance capteur home → origine (µm)
static volatile uint8_t free_arm; // 1 = vgear désactivé, moteur libre
static uint16_t pos_left; // limite gauche (1/10 mm)
static uint16_t pos_right; // limite droite (1/10 mm)
static volatile arm_state_t state; // état courant
static volatile uint16_t wait_ctr; // compteur steps SPOOL pour les pauses
static uint16_t travel_steps; // micropas pour aller de LEFT à RIGHT
// ─────────────────────────────────────────────
// Calcul du trajet LEFT→RIGHT en micropas
// ─────────────────────────────────────────────
static uint16_t ARM_CalcTravelSteps(void)
{
uint32_t um = (uint32_t)(pos_right - pos_left) * 100UL; // 1/10mm → µm
return (uint16_t)(um / ARM_UM_PER_USTEP);
}
// ─────────────────────────────────────────────
// Init — lecture offset EEPROM au démarrage
// ─────────────────────────────────────────────
void ARM_Init(void)
{
gear_um = 0;
accumulator = 0;
free_arm = 0;
pos_left = ARM_LEFT_DEFAULT;
pos_right = ARM_RIGHT_DEFAULT;
state = ARM_IDLE;
wait_ctr = 0;
travel_steps = ARM_CalcTravelSteps();
ARM_EN(0);
ARM_REV(0);
arm_offset = EE_ReadWord(EE_ARM_OFFSET_H, EE_ARM_OFFSET_L);
}
// ─────────────────────────────────────────────
// Enable / Dir
// ─────────────────────────────────────────────
void ARM_Enable(uint8_t state_en)
{
ARM_EN(state_en);
}
void ARM_SetDir(uint8_t dir)
{
ARM_REV(dir);
}
// ─────────────────────────────────────────────
// UpdateTarget — appelée depuis l'ISR SPOOL
// Machine d'état légère : accumule µm et met
// à jour arm_target_position (pas de steps ici)
// ─────────────────────────────────────────────
void ARM_UpdateTarget(void)
{
if (free_arm || gear_um == 0)
return;
switch (state) {
case ARM_IDLE:
break;
case ARM_GO_TO_ZERO:
accumulator += gear_um;
while (accumulator >= ARM_UM_PER_REV) {
accumulator -= ARM_UM_PER_REV;
if (arm_target_position > 0)
arm_target_position--;
else {
accumulator = 0;
wait_ctr = 0;
state = ARM_WAIT_LEFT;
}
}
break;
case ARM_WAIT_LEFT:
wait_ctr++;
if (wait_ctr >= ARM_WAIT_STEPS) {
wait_ctr = 0;
ARM_REV(ARM_DIR_RIGHT);
state = ARM_TRAVERSE;
}
break;
case ARM_TRAVERSE:
accumulator += gear_um;
while (accumulator >= ARM_UM_PER_REV) {
accumulator -= ARM_UM_PER_REV;
if (arm_target_position < travel_steps)
arm_target_position++;
else {
accumulator = 0;
wait_ctr = 0;
ARM_REV(ARM_DIR_LEFT);
state = ARM_WAIT_RIGHT;
}
}
break;
case ARM_WAIT_RIGHT:
wait_ctr++;
if (wait_ctr >= ARM_WAIT_STEPS) {
wait_ctr = 0;
state = ARM_RETURN;
}
break;
case ARM_RETURN:
accumulator += gear_um;
while (accumulator >= ARM_UM_PER_REV) {
accumulator -= ARM_UM_PER_REV;
if (arm_target_position > 0)
arm_target_position--;
else {
accumulator = 0;
wait_ctr = 0;
ARM_REV(ARM_DIR_RIGHT);
state = ARM_WAIT_LEFT;
}
}
break;
}
}
// ─────────────────────────────────────────────
// GO_TO_ZERO — retour à LEFT, nouvelle bobine
// ─────────────────────────────────────────────
void ARM_GoToZero(void)
{
accumulator = 0;
wait_ctr = 0;
ARM_REV(ARM_DIR_LEFT);
state = ARM_GO_TO_ZERO;
}
// ─────────────────────────────────────────────
// Écriture registre GEAR (0x0802)
// ─────────────────────────────────────────────
void ARM_SetGear(uint16_t um)
{
gear_um = um;
accumulator = 0;
}
// ─────────────────────────────────────────────
// Écriture registre OFFSET (0x0803) + EEPROM
// ─────────────────────────────────────────────
void ARM_SetOffset(uint16_t um)
{
arm_offset = um;
EE_WriteWord(EE_ARM_OFFSET_H, EE_ARM_OFFSET_L, um);
}
uint16_t ARM_GetOffset(void)
{
return arm_offset;
}
// ─────────────────────────────────────────────
// Free ARM — appelé depuis REG_CTRL bit1
// ─────────────────────────────────────────────
void ARM_SetFree(uint8_t s)
{
free_arm = s;
ARM_EN(s ? 0 : 1);
}
// ─────────────────────────────────────────────
// Positions limites gauche/droite (1/10 mm)
// ─────────────────────────────────────────────
void ARM_SetLeft(uint16_t dmm)
{
pos_left = dmm;
travel_steps = ARM_CalcTravelSteps();
}
void ARM_SetRight(uint16_t dmm)
{
pos_right = dmm;
travel_steps = ARM_CalcTravelSteps();
}