Compare commits

..

No commits in common. "c0c8cb91c7484c3752a66289c32036fa4e69cb95" and "39cce4bbde717a9039c63c3c360af857ea61b308" have entirely different histories.

7 changed files with 75 additions and 108 deletions

View File

@ -14,25 +14,14 @@
#define ARM_REG_LEFT 0x0804 // position limite gauche (1/10 mm) #define ARM_REG_LEFT 0x0804 // position limite gauche (1/10 mm)
#define ARM_REG_RIGHT 0x0805 // position limite droite (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 // Mécanique
// 1 tour ARM = 40mm = 1600 micropas // 1 tour ARM = 40mm = 1600 micropas
// 1 micropas ARM = 25µm // 1 micropas ARM = 25µm
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 8 microsteps #define ARM_UM_PER_USTEP 25U // µm par micropas
// #define ARM_UM_PER_USTEP 25U // µm par micropas #define ARM_USTEP_PER_REV 1600U // micropas par tour
// #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 #define ARM_UM_PER_REV ((uint32_t)ARM_UM_PER_USTEP * ARM_USTEP_PER_REV) // 40000µm
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
@ -42,12 +31,19 @@
#define ARM_GEAR_MIN 0 // µm (arrêt vgear) #define ARM_GEAR_MIN 0 // µm (arrêt vgear)
#define ARM_GEAR_MAX 65535 // µm = 65.535mm par tour SPOOL #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 // API publique
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
void ARM_Init(void); void ARM_Init(void);
void ARM_UpdateTarget(void); // appelé depuis l'ISR SPOOL — met à jour arm_target_position void ARM_Step(void); // appelé depuis l'ISR SPOOL à chaque step
void ARM_Enable(uint8_t state); // ENABLE moteur ARM void ARM_Enable(uint8_t state); // ENABLE moteur ARM
void ARM_SetDir(uint8_t dir); // sens de rotation 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) void ARM_SetFree(uint8_t state); // free ARM + désactive vgear (REG_CTRL bit1)
@ -57,12 +53,6 @@ void ARM_SetOffset(uint16_t um); // écriture registre 0x0803 + sauvegard
uint16_t ARM_GetOffset(void); // lecture offset courant uint16_t ARM_GetOffset(void); // lecture offset courant
void ARM_SetLeft(uint16_t dmm); // écriture registre 0x0804 (1/10 mm) 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_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_GetLeft(void);
uint16_t ARM_GetRight(void); uint16_t ARM_GetRight(void);

View File

@ -10,8 +10,6 @@
#define EE_ARM_OFFSET_H 0x10 // ARM offset high byte #define EE_ARM_OFFSET_H 0x10 // ARM offset high byte
#define EE_ARM_OFFSET_L 0x11 // ARM offset low 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 // API publique

View File

@ -5,14 +5,12 @@
#include <stdint.h> #include <stdint.h>
#include <macros.h> #include <macros.h>
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// Registres Modbus // Registres Modbus
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
#define REG_CTRL 0x0800 // registre de contrôle commun #define REG_CTRL 0x0800 // registre de contrôle commun
#define SPOOL_REG_FREQ 0x0801 // fréquence Step (Hz) #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 // bits REG_CTRL
#define CTRL_SPOOL_ENABLE ((uint16_t)(1U << 15)) // bit15 : SPOOL enable #define CTRL_SPOOL_ENABLE ((uint16_t)(1U << 15)) // bit15 : SPOOL enable
@ -41,11 +39,8 @@
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
void SPOOL_Init(void); void SPOOL_Init(void);
void SPOOL_TimerISR(void); // ISR Timer5 haute priorité void SPOOL_TimerISR(void); // ISR Timer5 basse priorité
void SPOOL_SetCtrl(uint16_t ctrl); // écriture registre 0x0800 void SPOOL_SetCtrl(uint16_t ctrl); // écriture registre 0x0800
void SPOOL_SetFreq(uint16_t hz); // écriture registre 0x0801 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 #endif // SPOOL_H

View File

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

View File

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

View File

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

View File

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