Compare commits

...

2 Commits

Author SHA1 Message Date
c0c8cb91c7 dev 2026-03-10 16:46:46 +01:00
38b0853c32 dev 2026-03-10 16:46:17 +01:00
7 changed files with 107 additions and 74 deletions

View File

@ -14,14 +14,25 @@
#define ARM_REG_LEFT 0x0804 // position limite gauche (1/10 mm)
#define ARM_REG_RIGHT 0x0805 // position limite droite (1/10 mm)
// ─────────────────────────────────────────────
// Valeurs par défaut LEFT/RIGHT
// ─────────────────────────────────────────────
#define ARM_LEFT_DEFAULT 500U // 50.0 mm en dixièmes
#define ARM_RIGHT_DEFAULT 4500U // 450.0 mm en dixièmes
// ─────────────────────────────────────────────
// Mécanique
// 1 tour ARM = 40mm = 1600 micropas
// 1 micropas ARM = 25µm
// ─────────────────────────────────────────────
#define ARM_UM_PER_USTEP 25U // µm par micropas
#define ARM_USTEP_PER_REV 1600U // micropas par tour
// 8 microsteps
// #define ARM_UM_PER_USTEP 25U // µm par micropas
// #define ARM_USTEP_PER_REV 1600U // micropas par tour
// 4 microsteps
#define ARM_UM_PER_USTEP 50U // µm par micropas
#define ARM_USTEP_PER_REV 800U // micropas par tour
#define ARM_UM_PER_REV ((uint32_t)ARM_UM_PER_USTEP * ARM_USTEP_PER_REV) // 40000µm
// ─────────────────────────────────────────────
@ -31,19 +42,12 @@
#define ARM_GEAR_MIN 0 // µm (arrêt vgear)
#define ARM_GEAR_MAX 65535 // µm = 65.535mm par tour SPOOL
// ─────────────────────────────────────────────
// Valeurs par défaut positions (1/10 mm)
// ─────────────────────────────────────────────
#define ARM_LEFT_DEFAULT 500 // 50.0mm
#define ARM_RIGHT_DEFAULT 4500 // 450.0mm
// ─────────────────────────────────────────────
// API publique
// ─────────────────────────────────────────────
void ARM_Init(void);
void ARM_Step(void); // appelé depuis l'ISR SPOOL à chaque step
void ARM_UpdateTarget(void); // appelé depuis l'ISR SPOOL — met à jour arm_target_position
void ARM_Enable(uint8_t state); // ENABLE moteur ARM
void ARM_SetDir(uint8_t dir); // sens de rotation ARM
void ARM_SetFree(uint8_t state); // free ARM + désactive vgear (REG_CTRL bit1)
@ -53,6 +57,12 @@ void ARM_SetOffset(uint16_t um); // écriture registre 0x0803 + sauvegard
uint16_t ARM_GetOffset(void); // lecture offset courant
void ARM_SetLeft(uint16_t dmm); // écriture registre 0x0804 (1/10 mm)
void ARM_SetRight(uint16_t dmm); // écriture registre 0x0805 (1/10 mm)
void ARM_SetLeft(uint16_t pos); // écriture registre 0x0804 (1/10 mm)
void ARM_SetRight(uint16_t pos); // écriture registre 0x0805 (1/10 mm)
uint16_t ARM_GetLeft(void); // lecture position gauche courante
uint16_t ARM_GetRight(void); // lecture position droite courante
void ARM_SetLeft(uint16_t dmm); // écriture registre 0x0804 (1/10 mm)
void ARM_SetRight(uint16_t dmm); // écriture registre 0x0805 (1/10 mm)
uint16_t ARM_GetLeft(void);
uint16_t ARM_GetRight(void);

View File

@ -10,6 +10,8 @@
#define EE_ARM_OFFSET_H 0x10 // ARM offset high byte
#define EE_ARM_OFFSET_L 0x11 // ARM offset low byte
#define EE_SPOOL_RATIO_H 0x12
#define EE_SPOOL_RATIO_L 0x13
// ─────────────────────────────────────────────
// API publique

View File

@ -5,12 +5,14 @@
#include <stdint.h>
#include <macros.h>
// ─────────────────────────────────────────────
// Registres Modbus
// ─────────────────────────────────────────────
#define REG_CTRL 0x0800 // registre de contrôle commun
#define SPOOL_REG_FREQ 0x0801 // fréquence Step (Hz)
#define SPOOL_REG_RATIO 0x0806 // ratio démultiplication (millièmes, ex: 1000=1:1)
// bits REG_CTRL
#define CTRL_SPOOL_ENABLE ((uint16_t)(1U << 15)) // bit15 : SPOOL enable
@ -39,8 +41,11 @@
// ─────────────────────────────────────────────
void SPOOL_Init(void);
void SPOOL_TimerISR(void); // ISR Timer5 basse priorité
void SPOOL_TimerISR(void); // ISR Timer5 haute priorité
void SPOOL_SetCtrl(uint16_t ctrl); // écriture registre 0x0800
void SPOOL_SetFreq(uint16_t hz); // écriture registre 0x0801
void SPOOL_SetRatio(uint16_t milli); // écriture registre 0x0806 + sauvegarde EEPROM
extern volatile uint16_t arm_target_position; // position cible ARM (micropas)
#endif // SPOOL_H

View File

@ -1,5 +1,6 @@
#include <arm.h>
#include <eeprom.h>
#include <spool.h>
// ─────────────────────────────────────────────
// Machine d'état traverse
@ -18,7 +19,7 @@ typedef enum {
// Constantes
// ─────────────────────────────────────────────
#define ARM_WAIT_STEPS 1200U // 3/4 tour SPOOL (200pas × 8µstep × 3/4)
#define ARM_WAIT_STEPS 600U // 3/4 tour SPOOL (200pas × 4µstep × 3/4)
#define ARM_DIR_RIGHT 1
#define ARM_DIR_LEFT 0
@ -32,14 +33,12 @@ static uint16_t arm_offset; // distance capteur home → origine (µ
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 de la machine
static volatile uint16_t arm_pos; // position courante en micropas depuis LEFT
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
// (pos_right - pos_left) en 1/10mm → µm → micropas
// ─────────────────────────────────────────────
static uint16_t ARM_CalcTravelSteps(void)
@ -60,7 +59,6 @@ void ARM_Init(void)
pos_left = ARM_LEFT_DEFAULT;
pos_right = ARM_RIGHT_DEFAULT;
state = ARM_IDLE;
arm_pos = 0;
wait_ctr = 0;
travel_steps = ARM_CalcTravelSteps();
@ -71,7 +69,7 @@ void ARM_Init(void)
}
// ─────────────────────────────────────────────
// Enable / Dir — appelés depuis homing ou PLC
// Enable / Dir
// ─────────────────────────────────────────────
void ARM_Enable(uint8_t state_en)
@ -85,10 +83,12 @@ void ARM_SetDir(uint8_t dir)
}
// ─────────────────────────────────────────────
// Step — appelé depuis l'ISR SPOOL
// 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_Step(void)
void ARM_UpdateTarget(void)
{
if (free_arm || gear_um == 0)
return;
@ -99,19 +99,15 @@ void ARM_Step(void)
break;
case ARM_GO_TO_ZERO:
// Déplacement vers LEFT — on décrémente arm_pos
accumulator += gear_um;
while (accumulator >= ARM_UM_PER_REV) {
accumulator -= ARM_UM_PER_REV;
if (arm_pos > 0) {
ARM_HSTEP();
arm_pos--;
} else {
// Arrivée à LEFT
if (arm_target_position > 0)
arm_target_position--;
else {
accumulator = 0;
wait_ctr = 0;
state = ARM_WAIT_LEFT;
ARM_REV(ARM_DIR_RIGHT);
}
}
break;
@ -120,24 +116,22 @@ void ARM_Step(void)
wait_ctr++;
if (wait_ctr >= ARM_WAIT_STEPS) {
wait_ctr = 0;
ARM_REV(ARM_DIR_RIGHT);
state = ARM_TRAVERSE;
}
break;
case ARM_TRAVERSE:
// Déplacement vers RIGHT
accumulator += gear_um;
while (accumulator >= ARM_UM_PER_REV) {
accumulator -= ARM_UM_PER_REV;
if (arm_pos < travel_steps) {
ARM_HSTEP();
arm_pos++;
} else {
// Arrivée à RIGHT
if (arm_target_position < travel_steps)
arm_target_position++;
else {
accumulator = 0;
wait_ctr = 0;
state = ARM_WAIT_RIGHT;
ARM_REV(ARM_DIR_LEFT);
state = ARM_WAIT_RIGHT;
}
}
break;
@ -151,19 +145,16 @@ void ARM_Step(void)
break;
case ARM_RETURN:
// Déplacement vers LEFT
accumulator += gear_um;
while (accumulator >= ARM_UM_PER_REV) {
accumulator -= ARM_UM_PER_REV;
if (arm_pos > 0) {
ARM_HSTEP();
arm_pos--;
} else {
// Arrivée à LEFT
if (arm_target_position > 0)
arm_target_position--;
else {
accumulator = 0;
wait_ctr = 0;
state = ARM_WAIT_LEFT;
ARM_REV(ARM_DIR_RIGHT);
state = ARM_WAIT_LEFT;
}
}
break;
@ -172,7 +163,6 @@ void ARM_Step(void)
// ─────────────────────────────────────────────
// GO_TO_ZERO — retour à LEFT, nouvelle bobine
// appelé depuis REG_CTRL bit12
// ─────────────────────────────────────────────
void ARM_GoToZero(void)

View File

@ -10,7 +10,16 @@
void main(void) {
setup();
while(1) {
uint16_t arm_current_position = 0;
while (1) {
if (arm_current_position < arm_target_position) {
arm_current_position++;
ARM_HSTEP();
} else if (arm_current_position > arm_target_position) {
arm_current_position--;
ARM_HSTEP();
}
RTU_Task();
}
}
@ -18,13 +27,12 @@ void main(void) {
void __interrupt(low_priority) LOWprio_interrupt(void) {
if (PIR1bits.TMR2IF)
RTU_TimerISR();
if (PIR3bits.TMR5IF)
SPOOL_TimerISR();
}
void __interrupt(high_priority) HIGHprio_interrupt(void) {
if (PIR1bits.RCIF)
RTU_RxISR();
}
void __interrupt(high_priority) HIGHprio_interrupt(void) {
if (PIR3bits.TMR5IF)
SPOOL_TimerISR();
}

View File

@ -141,7 +141,7 @@ void RTU_Init(void)
PIE1bits.TMR2IE = 1;
// UART RX interrupt
IPR1bits.RCIP = 1; // haute priorité
IPR1bits.RCIP = 0; // RX basse priorité
PIE1bits.RCIE = 1;
}

View File

@ -1,5 +1,6 @@
#include <spool.h>
#include <arm.h>
#include <eeprom.h>
// ─────────────────────────────────────────────
// État interne
@ -7,6 +8,10 @@
static volatile uint16_t reload;
static volatile uint8_t running;
static uint16_t ratio;
static uint16_t current_freq;
volatile uint16_t arm_target_position; // position cible ARM en micropas, mise à jour par ISR
// ─────────────────────────────────────────────
// Calcul du reload Timer5
@ -16,7 +21,7 @@ static volatile uint8_t running;
static uint16_t SPOOL_CalcReload(uint16_t hz)
{
return (uint16_t)(65536UL - (8000000UL / ((uint32_t)hz * 2)));
return (uint16_t)(65536UL - (8000000UL / ((uint32_t)hz * 2UL)));
}
// ─────────────────────────────────────────────
@ -27,21 +32,24 @@ void SPOOL_Init(void)
{
reload = 0;
running = 0;
arm_target_position = 0;
ratio = EE_ReadWord(EE_SPOOL_RATIO_H, EE_SPOOL_RATIO_L);
if (ratio == 0) ratio = 1000;
MOTOR_EN(0);
MOTOR_REV(0);
// Timer5 off, prescaler 1:1, 16bit, Fosc/4
T5CON = 0b00000000;
TMR5H = 0;
TMR5L = 0;
PIR3bits.TMR5IF = 0;
IPR3bits.TMR5IP = 0; // basse priorité
IPR3bits.TMR5IP = 1; // haute priorité
PIE3bits.TMR5IE = 1;
}
// ─────────────────────────────────────────────
// ISR Timer5 — basse priorité
// ISR Timer5 — haute priorité
// Génère le step SPOOL, délègue ARM au main
// ─────────────────────────────────────────────
void SPOOL_TimerISR(void)
@ -51,12 +59,11 @@ void SPOOL_TimerISR(void)
TMR5L = reload & 0xFF;
MOTOR_HSTEP();
ARM_Step();
ARM_UpdateTarget(); // machine d'état ARM — met à jour arm_target_position
}
// ─────────────────────────────────────────────
// Écriture registre CTRL (0x0800)
// bit15 = ENABLE, bit14 = DIR
// ─────────────────────────────────────────────
void SPOOL_SetCtrl(uint16_t ctrl)
@ -64,8 +71,6 @@ void SPOOL_SetCtrl(uint16_t ctrl)
MOTOR_EN((ctrl & CTRL_SPOOL_ENABLE) ? 1 : 0);
MOTOR_REV((ctrl & CTRL_SPOOL_DIR) ? 1 : 0);
ARM_SetFree((ctrl & CTRL_ARM_FREE) ? 1 : 0);
// CTRL_ARM_HOMING : one-shot, traité dans RTU_Task
}
// ─────────────────────────────────────────────
@ -74,27 +79,40 @@ void SPOOL_SetCtrl(uint16_t ctrl)
void SPOOL_SetFreq(uint16_t hz)
{
if (hz == current_freq)
return;
current_freq = hz;
if (hz == 0) {
// Arrêt — timer off, position maintenue par ENABLE
T5CONbits.TMR5ON = 0;
running = 0;
return;
}
// Clamping
if (hz < SPOOL_FREQ_MIN) hz = SPOOL_FREQ_MIN;
if (hz > SPOOL_FREQ_MAX) hz = SPOOL_FREQ_MAX;
reload = SPOOL_CalcReload(hz);
if (!running) {
// Premier démarrage — charger le timer et démarrer
TMR5H = reload >> 8;
TMR5L = reload & 0xFF;
PIR3bits.TMR5IF = 0;
T5CONbits.TMR5ON = 1;
running = 1;
}
// Si déjà running, le nouveau reload sera pris en compte
// au prochain débordement dans l'ISR
}
// ─────────────────────────────────────────────
// Écriture registre RATIO (0x0806) + EEPROM
// ─────────────────────────────────────────────
void SPOOL_SetRatio(uint16_t milli)
{
if (milli == 0) milli = 1;
ratio = milli;
EE_WriteWord(EE_SPOOL_RATIO_H, EE_SPOOL_RATIO_L, milli);
if (running && current_freq > 0)
reload = SPOOL_CalcReload(current_freq);
}