Affilare le eliche delle frese con Arduino
Moderatore: Junior Admin
-
lucamoto
- TORNITORE E FRESATORE
- Messaggi: 2432
- Iscritto il: lun ott 08, 2012 22:27
- Località: caltanissetta(san cataldo)
Re: Affilare le eliche delle frese con Arduino
tempo fa volevo farlo sulla mia velocetta ho acquistato il materiale e mi sono fermato per fare altre cose piu urgenti...
prima o poi spero di completarla...
prima o poi spero di completarla...
- ofranco
- FINALMENTE USO IL TORNIO
- Messaggi: 338
- Iscritto il: dom gen 12, 2020 00:00
- Località: Martina Franca
Re: Affilare le eliche delle frese con Arduino
Spero di mettere a punto lo sketch per Arduino. Ma vedo che qui tutto tace. 
- ofranco
- FINALMENTE USO IL TORNIO
- Messaggi: 338
- Iscritto il: dom gen 12, 2020 00:00
- Località: Martina Franca
Re: Affilare le eliche delle frese con Arduino
Ecco lo schema a blocchi del progetto. Vediamo se riesco a stimolare l'interesse di qualcuno. 
Non hai i permessi necessari per visualizzare i file allegati in questo messaggio.
-
lucamoto
- TORNITORE E FRESATORE
- Messaggi: 2432
- Iscritto il: lun ott 08, 2012 22:27
- Località: caltanissetta(san cataldo)
Re: Affilare le eliche delle frese con Arduino
io ho comprato ttutto questo ma mai messo in opera per questioni di tempo
prova se ti riesce ti copio
prova se ti riesce ti copio
- ofranco
- FINALMENTE USO IL TORNIO
- Messaggi: 338
- Iscritto il: dom gen 12, 2020 00:00
- Località: Martina Franca
Re: Affilare le eliche delle frese con Arduino
Come dice Arnold Schwarzenegger: "La forza non viene dal vincere. Le tue lotte sviluppano la tua forza. Quando passi attraverso delle avversità e decidi di non arrenderti, quella è la forza". Ce la possiamo fare.
- Davide Resca
- CAPO OFFICINA
- Messaggi: 13862
- Iscritto il: lun feb 29, 2016 11:29
- Località: Ustica & Dintorni saltuariamente Bologna o Pesaro
- Contatta:
Re: Affilare le eliche delle frese con Arduino
Sembra un buon progetto, ma io preferisco andare a mano...credo che si abbia più sensibilità, ma forse sbaglio ...
Gli errori sono per i principianti, noi esperti puntiamo al disastro !!!
Le conoscenze acquisite, sono proporzionali al DANNO PRODOTTO !!! ( esperienza personale...)
youtube
2°socio TIRATOSAURO CLUB ITALIAN
Le conoscenze acquisite, sono proporzionali al DANNO PRODOTTO !!! ( esperienza personale...)
youtube
2°socio TIRATOSAURO CLUB ITALIAN-
MauroO
- TORNITORE E FRESATORE
- Messaggi: 1327
- Iscritto il: mer giu 18, 2014 14:55
- Località: Alessandria
Re: Affilare le eliche delle frese con Arduino
L'idea è buona, però questo significa mettere in pista un'altra macchinetta oppure motorizzare una vecchia affilatrice, per me sempre di un'altra macchina si tratta e non ho posto; inoltre non sono un patito di Arduino che deve per forza risolvere tutto con esso, ho un sistema di tornio e fresatrice che ho trasformato a cnc e utilizzo le due macchine per fare praticamente tutto, quindi perchè ammattire con tante macchinette dedicate quando è sufficiente caricare un altro programma per cambiare lavorazione?
Vi spiego come affilo le frese, ho costruito una specie di rettifica tangenziale per tornio (nulla di trascendentale o di complicato, ho semplicemente fatto un supporto da posizionare al posto della torretta porta cartelle, per fissare la moletta veloce Parkside) e utilizzo quella.
Eseguo i seguenti passi:
- 1) determino il passo dell'elica: posiziono la fresa nel mandrino e un comparatore fissato al carro col tastatore a toccare l'elica, sposto il carro di una certa quantità (possibilmente una misura intera, tipo 10 mm), faccio ruotare il mandrino molto lentamente (usando l'avanzamento a step) fino a chè il comparatore è ritornato alla lettura iniziale; sui contatori vado a leggere l'angolo, ora disponendo di angolo e spostamento è banale determinare il passo;
- 2) posiziono la moletta sulla torretta e copro le guide del tornio per preservarle dallo spolverio di abrasivo e metallo;
- 3) carico un mio programmino Gcode in Mach3, imposto in esso il numero di eliche della fresa e il passo prima calcolato, azzero tutto sulla posizione iniziale della prima elica, avvio la moletta e lancio il programma;
fine.
Devo precisare che il tornio l'ho motorizzato sui 3 assi (longitudinale, trasversale e mandrino); ho affrontato la spesa della motorizzazione del mandrino con un motore a passi di una certa coppia per ottenere una macchina molto versatile, di fatto è utilizzabile persino come una fresatrice col 4^ asse orizzontale.
Vi spiego come affilo le frese, ho costruito una specie di rettifica tangenziale per tornio (nulla di trascendentale o di complicato, ho semplicemente fatto un supporto da posizionare al posto della torretta porta cartelle, per fissare la moletta veloce Parkside) e utilizzo quella.
Eseguo i seguenti passi:
- 1) determino il passo dell'elica: posiziono la fresa nel mandrino e un comparatore fissato al carro col tastatore a toccare l'elica, sposto il carro di una certa quantità (possibilmente una misura intera, tipo 10 mm), faccio ruotare il mandrino molto lentamente (usando l'avanzamento a step) fino a chè il comparatore è ritornato alla lettura iniziale; sui contatori vado a leggere l'angolo, ora disponendo di angolo e spostamento è banale determinare il passo;
- 2) posiziono la moletta sulla torretta e copro le guide del tornio per preservarle dallo spolverio di abrasivo e metallo;
- 3) carico un mio programmino Gcode in Mach3, imposto in esso il numero di eliche della fresa e il passo prima calcolato, azzero tutto sulla posizione iniziale della prima elica, avvio la moletta e lancio il programma;
fine.
Devo precisare che il tornio l'ho motorizzato sui 3 assi (longitudinale, trasversale e mandrino); ho affrontato la spesa della motorizzazione del mandrino con un motore a passi di una certa coppia per ottenere una macchina molto versatile, di fatto è utilizzabile persino come una fresatrice col 4^ asse orizzontale.
- renpag
- FINALMENTE USO IL TORNIO
- Messaggi: 790
- Iscritto il: mar dic 18, 2018 16:09
- Località: Casarza Ligure (GE)
Re: Affilare le eliche delle frese con Arduino
Io per le eliche uso la Rapidofil....
Certo un sistemino come quello che sta progettando ofranco sarebbe una bellezza ma non ho le capacità per realizzarlo quindi mi devo arrangiare con altro.
Certo un sistemino come quello che sta progettando ofranco sarebbe una bellezza ma non ho le capacità per realizzarlo quindi mi devo arrangiare con altro.
Non hai i permessi necessari per visualizzare i file allegati in questo messaggio.
- ofranco
- FINALMENTE USO IL TORNIO
- Messaggi: 338
- Iscritto il: dom gen 12, 2020 00:00
- Località: Martina Franca
Re: Affilare le eliche delle frese con Arduino
AGGIORNAMENTO LAVORI !...
Dopo tanto tempo, rieccomi.
Durante questo tempo ho progettato e realizzato il carrello per automatizzare l'affilatura delle frese. Allo stato attuale ha soltanto due assi. In futuro ho intenzione di aggiungerne altri due, uno per alzare e scendere la mola e uno per muoversi di fianco.
Mi sono fermato ai due assi principali per affilare le eliche perchè questo era il progetto originario e, per il momento, lo porterò avanti così. Tanto, se lo piazzo sulla tavola a croce della mia affilatrice farà tutte le funzioni di affilatura: eliche, taglienti e gole.
Il video della macchinetta è questo: https://youtube.com/shorts/VUZ1eKIsam4? ... Csw1VfXtV6 .
Qui ho fatto la simulazione con una fresa cinese e un comparatore piazzato sull'elica: https://youtube.com/shorts/R2b5JXr58J8? ... VZWQFBcih2
Le fasi dell'affilatrice sono le seguenti: DISIMPEGNO → POSIZIONAMENTO PUNTO DI PARTENZA → ANDATA → RITORNO → DISIMPEGNO → ROTAZIONE Y → REIMPEGNO → prossima elica
Nel menù "IMPUT DATI":
- diametro della fresa;
- lunghezza della fresa con valore decimale (mm);
- numero delle eliche;
- angolo dell'elica.
Nel menù "INPUT IMPOSTAZIONI":
- valore della riduzione meccanica asse X, giri/mm
- valore della riduzione meccanica asse Y, giri/mm
- valore del Backslash dell'asse X, decimi di mm
- valore del Backslash dell'asse Y, decimi di mm
- microstep asse X
- microstep asse Y
Per le foto mi sto attrezzando, al momento non ho un programmino per farlo.
P.S. Ho usato ARDUINO MEGA
Dopo tanto tempo, rieccomi.
Durante questo tempo ho progettato e realizzato il carrello per automatizzare l'affilatura delle frese. Allo stato attuale ha soltanto due assi. In futuro ho intenzione di aggiungerne altri due, uno per alzare e scendere la mola e uno per muoversi di fianco.
Mi sono fermato ai due assi principali per affilare le eliche perchè questo era il progetto originario e, per il momento, lo porterò avanti così. Tanto, se lo piazzo sulla tavola a croce della mia affilatrice farà tutte le funzioni di affilatura: eliche, taglienti e gole.
Il video della macchinetta è questo: https://youtube.com/shorts/VUZ1eKIsam4? ... Csw1VfXtV6 .
Qui ho fatto la simulazione con una fresa cinese e un comparatore piazzato sull'elica: https://youtube.com/shorts/R2b5JXr58J8? ... VZWQFBcih2
Le fasi dell'affilatrice sono le seguenti: DISIMPEGNO → POSIZIONAMENTO PUNTO DI PARTENZA → ANDATA → RITORNO → DISIMPEGNO → ROTAZIONE Y → REIMPEGNO → prossima elica
Nel menù "IMPUT DATI":
- diametro della fresa;
- lunghezza della fresa con valore decimale (mm);
- numero delle eliche;
- angolo dell'elica.
Nel menù "INPUT IMPOSTAZIONI":
- valore della riduzione meccanica asse X, giri/mm
- valore della riduzione meccanica asse Y, giri/mm
- valore del Backslash dell'asse X, decimi di mm
- valore del Backslash dell'asse Y, decimi di mm
- microstep asse X
- microstep asse Y
Per le foto mi sto attrezzando, al momento non ho un programmino per farlo.
P.S. Ho usato ARDUINO MEGA
Ultima modifica di ofranco il lun ago 24, 2026 16:14, modificato 1 volta in totale.
- ofranco
- FINALMENTE USO IL TORNIO
- Messaggi: 338
- Iscritto il: dom gen 12, 2020 00:00
- Località: Martina Franca
Re: Affilare le eliche delle frese con Arduino
II° PARTE









Mappatura dei pin:
Joystick Shield – Pulsanti digitali
BTN_UP — pin 2
BTN_RIGHT — pin 3
BTN_DOWN — pin 4
BTN_LEFT — pin 5
BTN_JOY — pin 8 (correzione fondamentale: il centrale NON è sul 6)
Tutti configurati come INPUT_PULLUP.
Joystick analogico
JOY_X — A1
JOY_Y — A0
Usati per il movimento manuale degli assi X/Y.
Driver stepper CNC
Asse X
X_STEP — pin 45
X_DIR — pin 43
Asse Y
Y_STEP — pin 41
Y_DIR — pin 39
Riduzione Y impostata dal menù impostazioni (valore salvato in EEPROM).
Keypad 4×4
Keypad_R1 — 22
Keypad_R2 — 24
Keypad_R3 — 26
Keypad_R4 — 28
Keypad_C1 — 30
Keypad_C2 — 32
Keypad_C3 — 34
Keypad_C4 — 36
Configurazione standard Keypad.h.
LCD I2C
LCD_I2C — indirizzo 0x27
Ciclo automatico – Sequenza comandi
Il ciclo parte SOLO con:
BTN_JOY – START
E segue questa sequenza:
DISIMPEGNO INIZIALE
POSIZIONAMENTO PUNTO DI PARTENZA
ANDATA
RITORNO
DISIMPEGNO FINE ELICA
ROT_AZIONE Y (360° / numero_eliche)
REIMPEGNO
PROSSIMA ELICA
FINE CICLO
Interrompibile in qualsiasi momento con:
BTN_LEFT – STOP
Keypad 4×4 – Inserimento dati
Tasto * → Virgola decimale (.)
Tasto C → Cancella ultimo carattere
Tasto # → Conferma valore inserito
Tasto D → Annulla / esci dal campo
Usato nei menù DATI e IMPOSTAZIONI.
Joystick analogico (movimento manuale)
Movimento X avanti/indietro → Joystick asse X (A1)
Movimento Y orario/antiorario → Joystick asse Y (A0)
Usato SOLO quando la macchina è in STATO_IDLE.
Joystick Shield – Pulsanti digitali
Comando A – BTN_UP → Apre il menù DATI (inserimento: diametro elica, lunghezza fresa, numero eliche, angolo di rampa elica)
Comando C – BTN_RIGHT → Apre il menù IMPOSTAZIONI (riduzioni, backlash, microstep, ecc.)
Comando D – BTN_LEFT → STOP / EMERGENZA (interrompe immediatamente il ciclo automatico e torna a IDLE)
Comando B – BTN_JOY → START ciclo automatico (avvia la sequenza: disimpegno → posizionamento → andata → ritorno → rotazione Y → reimpegno → prossima elica)
BTN_DOWN → Non assegnato (libero per future funzioni)
Hardware: motore stepper NEMA 23, 200 passi; driver TB6560
Riduzioni: L'asse Y 10T+50T - L'asse X motore stepper con ingranaggi 1:1 su vite da 16mm con passo 2
Come avrete notato il passo dell'elica viene calcolato dallo sketch. Io inserisco soltanto il diametro e l'angolo dell'elica.
Mappatura dei pin:
Joystick Shield – Pulsanti digitali
BTN_UP — pin 2
BTN_RIGHT — pin 3
BTN_DOWN — pin 4
BTN_LEFT — pin 5
BTN_JOY — pin 8 (correzione fondamentale: il centrale NON è sul 6)
JOY_X — A1
JOY_Y — A0
Asse X
X_STEP — pin 45
X_DIR — pin 43
Asse Y
Y_STEP — pin 41
Y_DIR — pin 39
Keypad_R1 — 22
Keypad_R2 — 24
Keypad_R3 — 26
Keypad_R4 — 28
Keypad_C1 — 30
Keypad_C2 — 32
Keypad_C3 — 34
Keypad_C4 — 36
LCD_I2C — indirizzo 0x27
Il ciclo parte SOLO con:
BTN_JOY – START
E segue questa sequenza:
DISIMPEGNO INIZIALE
POSIZIONAMENTO PUNTO DI PARTENZA
ANDATA
RITORNO
DISIMPEGNO FINE ELICA
ROT_AZIONE Y (360° / numero_eliche)
REIMPEGNO
PROSSIMA ELICA
FINE CICLO
Interrompibile in qualsiasi momento con:
BTN_LEFT – STOP
Tasto * → Virgola decimale (.)
Tasto C → Cancella ultimo carattere
Tasto # → Conferma valore inserito
Tasto D → Annulla / esci dal campo
Movimento X avanti/indietro → Joystick asse X (A1)
Movimento Y orario/antiorario → Joystick asse Y (A0)
Comando A – BTN_UP → Apre il menù DATI (inserimento: diametro elica, lunghezza fresa, numero eliche, angolo di rampa elica)
Comando C – BTN_RIGHT → Apre il menù IMPOSTAZIONI (riduzioni, backlash, microstep, ecc.)
Comando D – BTN_LEFT → STOP / EMERGENZA (interrompe immediatamente il ciclo automatico e torna a IDLE)
Comando B – BTN_JOY → START ciclo automatico (avvia la sequenza: disimpegno → posizionamento → andata → ritorno → rotazione Y → reimpegno → prossima elica)
BTN_DOWN → Non assegnato (libero per future funzioni)
Hardware: motore stepper NEMA 23, 200 passi; driver TB6560
Riduzioni: L'asse Y 10T+50T - L'asse X motore stepper con ingranaggi 1:1 su vite da 16mm con passo 2
Come avrete notato il passo dell'elica viene calcolato dallo sketch. Io inserisco soltanto il diametro e l'angolo dell'elica.
- ofranco
- FINALMENTE USO IL TORNIO
- Messaggi: 338
- Iscritto il: dom gen 12, 2020 00:00
- Località: Martina Franca
Re: Affilare le eliche delle frese con Arduino
PARTE III^
Codice:
Codice:
Codice: Seleziona tutto
#include <AccelStepper.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <EEPROM.h>
#include <math.h>
// ============================================================================
// CONFIGURAZIONE DIREZIONE ASSI
// ============================================================================
#define INVERTI_DIR_X true // Inversione rotazione asse X
#define INVERTI_DIR_Y false // Mantenuto false per Y
// ============================================================================
// HARDWARE PINOUT
// ============================================================================
#define BTN_UP 2 // Comando A -> Menu DATI
#define BTN_RIGHT 3 // Comando B -> Menu IMPOSTAZIONI
#define BTN_DOWN 4 // Comando C -> Ritorno Posizione Iniziale (0,0)
#define BTN_LEFT 5 // Comando D -> STOP / EMERGENZA
#define BTN_JOY 8 // Pulsante Centrale Joystick -> START Ciclo Automatico
#define JOY_X A1 // Analogico X Joystick
#define JOY_Y A0 // Analogico Y Joystick
// Driver Stepper
#define X_STEP 45
#define X_DIR 43
#define Y_STEP 41
#define Y_DIR 39
AccelStepper stepperX(AccelStepper::DRIVER, X_STEP, X_DIR);
AccelStepper stepperY(AccelStepper::DRIVER, Y_STEP, Y_DIR);
// Keypad 4x4
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {22, 24, 26, 28};
byte colPins[COLS] = {30, 32, 34, 36};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// LCD 20x4 I2C
LiquidCrystal_I2C lcd(0x27, 20, 4);
// ============================================================================
// STRUTTURE DATI
// ============================================================================
struct Impostazioni {
float riduzione_X_giri_per_mm;
float riduzione_Y;
int backlash_X_decimi_mm;
int backlash_Y_decimi_mm;
int microstep_X;
int microstep_Y;
} setupData;
struct DatiLavoro {
float diametro_fresa_mm;
float lunghezza_fresa_mm;
int numero_eliche;
float angolo_eliche_gradi;
} jobData;
enum StatoMacchina {
STATO_IDLE,
MENU_DATI,
MENU_IMPOSTAZIONI,
AUTO_INIT,
AUTO_DISIMPEGNO_1,
AUTO_POSIZIONAMENTO,
AUTO_ANDATA,
AUTO_BACKLASH_RITORNO, // Stato per recupero gioco a fine andata
AUTO_RITORNO,
AUTO_DISIMPEGNO_2,
AUTO_ROTAZIONE_Y,
AUTO_REIMPEGNO,
EMERGENCY_STOP
};
StatoMacchina statoAttuale = STATO_IDLE;
int elicaAttuale = 0;
long targetPassiX = 0;
long targetPassiY = 0;
long quotaBaseY = 0;
long disimpegnoPassiX = 0;
long backlashPassiX = 0; // Variabile per i passi reali di backlash X
// Variabili per la gestione del Joystick
float currentSpeedX = 0.0;
float currentSpeedY = 0.0;
const float maxJoystickSpeed = 500.0;
unsigned long lastJoystickUpdate = 0;
// ============================================================================
// PROTOTIPI FUNZIONI
// ============================================================================
void gestisciPulsantiShield();
void gestisciComandiTastiera();
void gestisciJoystickManuale();
void eseguiCicloAutomatico();
void apriMenuDati();
void apriMenuImpostazioni();
void ritornaPosizioneIniziale();
bool leggiValoreKeypad(const char* titolo, float &valore, const char* unita);
void mostraMessaggio(String r1, String r2);
void aggiornaDisplayIdle();
float calcolaPassiPerMM_X();
float calcolaPassiPerGrado_Y();
void calcolaInterpolazioneSincronizzata();
// ============================================================================
// SETUP
// ============================================================================
void setup() {
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_RIGHT, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_LEFT, INPUT_PULLUP);
pinMode(BTN_JOY, INPUT_PULLUP);
stepperX.setPinsInverted(INVERTI_DIR_X, false, false);
stepperY.setPinsInverted(INVERTI_DIR_Y, false, false);
stepperX.setMaxSpeed(1000.0);
stepperY.setMaxSpeed(1000.0);
stepperX.setMinPulseWidth(10);
stepperY.setMinPulseWidth(10);
lcd.init();
lcd.backlight();
mostraMessaggio("CNC AFFILATRICE", "Inizializzazione...");
EEPROM.get(0, setupData);
if (isnan(setupData.riduzione_X_giri_per_mm) || setupData.riduzione_X_giri_per_mm <= 0) {
setupData.riduzione_X_giri_per_mm = 0.5;
setupData.riduzione_Y = 5.0;
setupData.backlash_X_decimi_mm = 0;
setupData.backlash_Y_decimi_mm = 0;
setupData.microstep_X = 8;
setupData.microstep_Y = 8;
EEPROM.put(0, setupData);
}
EEPROM.get(sizeof(Impostazioni), jobData);
if (isnan(jobData.diametro_fresa_mm) || jobData.diametro_fresa_mm <= 0) {
jobData.diametro_fresa_mm = 16.0;
jobData.lunghezza_fresa_mm = 30.0;
jobData.numero_eliche = 4;
jobData.angolo_eliche_gradi = 30.0;
EEPROM.put(sizeof(Impostazioni), jobData);
}
delay(800);
aggiornaDisplayIdle();
}
// ============================================================================
// LOOP PRINCIPALE
// ============================================================================
void loop() {
if (digitalRead(BTN_LEFT) == LOW) {
statoAttuale = EMERGENCY_STOP;
}
switch (statoAttuale) {
case STATO_IDLE:
gestisciJoystickManuale();
gestisciPulsantiShield();
gestisciComandiTastiera();
break;
case AUTO_INIT:
case AUTO_DISIMPEGNO_1:
case AUTO_POSIZIONAMENTO:
case AUTO_ANDATA:
case AUTO_BACKLASH_RITORNO:
case AUTO_RITORNO:
case AUTO_DISIMPEGNO_2:
case AUTO_ROTAZIONE_Y:
case AUTO_REIMPEGNO:
eseguiCicloAutomatico();
break;
case EMERGENCY_STOP:
stepperX.stop();
stepperY.stop();
mostraMessaggio("! ARRESTO EMERGENZA !", "Premere Reset HW");
while (1);
break;
default:
break;
}
}
// ============================================================================
// CALCOLI CINEMATICI
// ============================================================================
float calcolaPassiPerMM_X() {
return setupData.riduzione_X_giri_per_mm * setupData.microstep_X * 200.0;
}
float calcolaPassiPerGrado_Y() {
return (setupData.riduzione_Y * setupData.microstep_Y * 200.0) / 360.0;
}
void calcolaInterpolazioneSincronizzata() {
float passiMM_X = calcolaPassiPerMM_X();
float passiGrado_Y = calcolaPassiPerGrado_Y();
targetPassiX = lround(jobData.lunghezza_fresa_mm * passiMM_X);
disimpegnoPassiX = lround(10.0 * passiMM_X);
// Calcolo dei passi di backlash basato sui decimi di mm inseriti nel menu
float mmBacklash = (float)setupData.backlash_X_decimi_mm / 10.0;
backlashPassiX = lround(mmBacklash * passiMM_X);
// Calcolo passo con angolo rispetto all'asse longitudinale: P = (pi * D) / tan(angolo)
float angoloRadianti = jobData.angolo_eliche_gradi * (M_PI / 180.0);
float passo_elica_mm_giro = (M_PI * jobData.diametro_fresa_mm) / tan(angoloRadianti);
float gradiRapportoY = (jobData.lunghezza_fresa_mm / passo_elica_mm_giro) * 360.0;
targetPassiY = lround(gradiRapportoY * passiGrado_Y);
float vMaxBase = 800.0;
float accelBase = 500.0;
if (abs(targetPassiX) > 0) {
float rapporto = (float)abs(targetPassiY) / (float)abs(targetPassiX);
stepperX.setMaxSpeed(vMaxBase);
stepperX.setAcceleration(accelBase);
stepperY.setMaxSpeed(fmax(100.0, vMaxBase * rapporto));
stepperY.setAcceleration(fmax(100.0, accelBase * rapporto));
}
}
// ============================================================================
// LOGICA CICLO AUTOMATICO
// ============================================================================
void eseguiCicloAutomatico() {
stepperX.run();
stepperY.run();
switch (statoAttuale) {
case AUTO_INIT:
stepperX.setCurrentPosition(0);
stepperY.setCurrentPosition(0);
quotaBaseY = 0;
elicaAttuale = 0;
calcolaInterpolazioneSincronizzata();
mostraMessaggio("AUTO - DISIMPEGNO", "Elica 1/" + String(jobData.numero_eliche));
stepperX.setMaxSpeed(800.0);
stepperX.setAcceleration(500.0);
stepperX.moveTo(-disimpegnoPassiX);
stepperY.moveTo(quotaBaseY);
statoAttuale = AUTO_DISIMPEGNO_1;
break;
case AUTO_DISIMPEGNO_1:
if (stepperX.distanceToGo() == 0 && stepperY.distanceToGo() == 0) {
mostraMessaggio("AUTO - POSIZIONA", "Punto di Partenza");
stepperX.moveTo(0);
stepperY.moveTo(quotaBaseY);
statoAttuale = AUTO_POSIZIONAMENTO;
}
break;
case AUTO_POSIZIONAMENTO:
if (stepperX.distanceToGo() == 0 && stepperY.distanceToGo() == 0) {
mostraMessaggio("AUTO - ANDATA", "Elica " + String(elicaAttuale + 1) + "/" + String(jobData.numero_eliche));
stepperX.moveTo(targetPassiX);
stepperY.moveTo(quotaBaseY + targetPassiY);
statoAttuale = AUTO_ANDATA;
}
break;
case AUTO_ANDATA:
if (stepperX.distanceToGo() == 0 && stepperY.distanceToGo() == 0) {
if (backlashPassiX > 0) {
mostraMessaggio("AUTO - BACKLASH", "Recupero Gioco X");
stepperX.moveTo(targetPassiX + backlashPassiX);
statoAttuale = AUTO_BACKLASH_RITORNO;
} else {
mostraMessaggio("AUTO - RITORNO", "Ritorno Carrello");
stepperX.moveTo(0);
stepperY.moveTo(quotaBaseY);
statoAttuale = AUTO_RITORNO;
}
}
break;
case AUTO_BACKLASH_RITORNO:
if (stepperX.distanceToGo() == 0) {
mostraMessaggio("AUTO - RITORNO", "Ritorno Carrello");
stepperX.moveTo(0);
stepperY.moveTo(quotaBaseY);
statoAttuale = AUTO_RITORNO;
}
break;
case AUTO_RITORNO:
if (stepperX.distanceToGo() == 0 && stepperY.distanceToGo() == 0) {
mostraMessaggio("AUTO - DISIMPEGNO", "Disimpegno Sicurezza");
stepperX.moveTo(-disimpegnoPassiX);
stepperY.moveTo(quotaBaseY);
statoAttuale = AUTO_DISIMPEGNO_2;
}
break;
case AUTO_DISIMPEGNO_2:
if (stepperX.distanceToGo() == 0 && stepperY.distanceToGo() == 0) {
elicaAttuale++;
if (elicaAttuale < jobData.numero_eliche) {
mostraMessaggio("AUTO - ROTAZIONE Y", "Indice Elica " + String(elicaAttuale + 1));
float gradiDivisione = 360.0 / jobData.numero_eliche;
quotaBaseY += lround(gradiDivisione * calcolaPassiPerGrado_Y());
stepperY.moveTo(quotaBaseY);
statoAttuale = AUTO_ROTAZIONE_Y;
} else {
mostraMessaggio("LAVORAZIONE OK", "Ciclo Completato!");
delay(2000);
statoAttuale = STATO_IDLE;
aggiornaDisplayIdle();
}
}
break;
case AUTO_ROTAZIONE_Y:
if (stepperY.distanceToGo() == 0) {
mostraMessaggio("AUTO - REIMPEGNO", "Reimpegno X");
stepperX.moveTo(0);
statoAttuale = AUTO_REIMPEGNO;
}
break;
case AUTO_REIMPEGNO:
if (stepperX.distanceToGo() == 0) {
calcolaInterpolazioneSincronizzata();
mostraMessaggio("AUTO - POSIZIONA", "Elica " + String(elicaAttuale + 1) + "/" + String(jobData.numero_eliche));
stepperX.moveTo(0);
stepperY.moveTo(quotaBaseY);
statoAttuale = AUTO_POSIZIONAMENTO;
}
break;
default:
break;
}
}
// ============================================================================
// MANOVRABILITÀ E COMANDI MANUALI
// ============================================================================
void gestisciPulsantiShield() {
if (digitalRead(BTN_UP) == LOW) {
apriMenuDati();
} else if (digitalRead(BTN_RIGHT) == LOW) {
apriMenuImpostazioni();
} else if (digitalRead(BTN_DOWN) == LOW) {
ritornaPosizioneIniziale();
} else if (digitalRead(BTN_JOY) == LOW) {
statoAttuale = AUTO_INIT;
delay(200);
}
}
void gestisciComandiTastiera() {
char key = keypad.getKey();
if (key == 'A') {
apriMenuDati();
} else if (key == 'B') {
apriMenuImpostazioni();
} else if (key == 'C') {
ritornaPosizioneIniziale();
}
}
void ritornaPosizioneIniziale() {
mostraMessaggio("RITORNO HOME", "Spostamento...");
stepperX.setMaxSpeed(800.0);
stepperX.setAcceleration(500.0);
stepperY.setMaxSpeed(1000.0);
stepperY.setAcceleration(600.0);
stepperX.moveTo(0);
stepperY.moveTo(0);
while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0) {
if (digitalRead(BTN_LEFT) == LOW) {
statoAttuale = EMERGENCY_STOP;
return;
}
stepperX.run();
stepperY.run();
}
mostraMessaggio("RITORNO HOME", "Quota 0 Raggiunta!");
delay(1000);
aggiornaDisplayIdle();
}
void gestisciJoystickManuale() {
if (millis() - lastJoystickUpdate >= 10) {
lastJoystickUpdate = millis();
int valX = analogRead(JOY_X);
int valY = analogRead(JOY_Y);
float targetSpeedX = 0.0;
if (valX < 400) {
targetSpeedX = -maxJoystickSpeed;
} else if (valX > 620) {
targetSpeedX = maxJoystickSpeed;
}
float targetSpeedY = 0.0;
if (valY < 400) {
targetSpeedY = -maxJoystickSpeed;
} else if (valY > 620) {
targetSpeedY = maxJoystickSpeed;
}
float stepRampa = 4.0;
if (targetSpeedX == 0.0) {
currentSpeedX = 0.0;
} else {
if (currentSpeedX < targetSpeedX) {
currentSpeedX += stepRampa;
if (currentSpeedX > targetSpeedX) currentSpeedX = targetSpeedX;
} else if (currentSpeedX > targetSpeedX) {
currentSpeedX -= stepRampa;
if (currentSpeedX < targetSpeedX) currentSpeedX = targetSpeedX;
}
}
if (targetSpeedY == 0.0) {
currentSpeedY = 0.0;
} else {
if (currentSpeedY < targetSpeedY) {
currentSpeedY += stepRampa;
if (currentSpeedY > targetSpeedY) currentSpeedY = targetSpeedY;
} else if (currentSpeedY > targetSpeedY) {
currentSpeedY -= stepRampa;
if (currentSpeedY < targetSpeedY) currentSpeedY = targetSpeedY;
}
}
stepperX.setSpeed(currentSpeedX);
stepperY.setSpeed(currentSpeedY);
}
stepperX.runSpeed();
stepperY.runSpeed();
}
// ============================================================================
// MENÙ CONFIGURAZIONE KEYPAD (con riga 4 a 20 caratteri)
// ============================================================================
bool leggiValoreKeypad(const char* titolo, float &valore, const char* unita) {
String buffer = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(titolo);
lcd.setCursor(0, 1);
lcd.print("Attuale: ");
lcd.print(valore, 1);
lcd.print(" ");
lcd.print(unita);
lcd.setCursor(0, 2);
lcd.print("Nuovo: ");
lcd.setCursor(0, 3);
lcd.print("OK:# C:Del *=. D:Esc");
while (true) {
if (digitalRead(BTN_LEFT) == LOW) {
statoAttuale = EMERGENCY_STOP;
return false;
}
char key = keypad.getKey();
if (key != NO_KEY) {
if (key == 'D') {
return false;
} else if (key >= '0' && key <= '9') {
if (buffer.length() < 8) {
buffer += key;
lcd.setCursor(7, 2);
lcd.print(buffer);
}
} else if (key == '*') {
if (buffer.indexOf('.') == -1) {
if (buffer.length() == 0) buffer += "0";
buffer += ".";
lcd.setCursor(7, 2);
lcd.print(buffer);
}
} else if (key == 'C') {
if (buffer.length() > 0) {
buffer.remove(buffer.length() - 1);
lcd.setCursor(7, 2);
lcd.print(" ");
lcd.setCursor(7, 2);
lcd.print(buffer);
}
} else if (key == '#') {
if (buffer.length() > 0) {
valore = buffer.toFloat();
}
return true;
}
}
}
}
void apriMenuDati() {
statoAttuale = MENU_DATI;
if (!leggiValoreKeypad("1/4 DIAMETRO FRESA", jobData.diametro_fresa_mm, "mm")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
if (!leggiValoreKeypad("2/4 LUNGH. FRESA", jobData.lunghezza_fresa_mm, "mm")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
float tempEliche = jobData.numero_eliche;
if (!leggiValoreKeypad("3/4 NUMERO ELICHE", tempEliche, "nr")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
jobData.numero_eliche = (int)tempEliche;
if (!leggiValoreKeypad("4/4 ANGOLO ELICA", jobData.angolo_eliche_gradi, "deg")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
EEPROM.put(sizeof(Impostazioni), jobData);
mostraMessaggio("DATI SALVATI!", "Salvato in EEPROM");
delay(1000);
statoAttuale = STATO_IDLE;
aggiornaDisplayIdle();
}
void apriMenuImpostazioni() {
statoAttuale = MENU_IMPOSTAZIONI;
if (!leggiValoreKeypad("1/6 RIDUZIONE X", setupData.riduzione_X_giri_per_mm, "g/mm")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
if (!leggiValoreKeypad("2/6 RIDUZIONE Y", setupData.riduzione_Y, "ratio")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
float tempBlX = setupData.backlash_X_decimi_mm;
if (!leggiValoreKeypad("3/6 BACKLASH X", tempBlX, "0.1mm")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
setupData.backlash_X_decimi_mm = (int)tempBlX;
float tempBlY = setupData.backlash_Y_decimi_mm;
if (!leggiValoreKeypad("4/6 BACKLASH Y", tempBlY, "0.1mm")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
setupData.backlash_Y_decimi_mm = (int)tempBlY;
float tempMsX = setupData.microstep_X;
if (!leggiValoreKeypad("5/6 MICROSTEP X", tempMsX, "step")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
setupData.microstep_X = (int)tempMsX;
float tempMsY = setupData.microstep_Y;
if (!leggiValoreKeypad("6/6 MICROSTEP Y", tempMsY, "step")) { statoAttuale = STATO_IDLE; aggiornaDisplayIdle(); return; }
setupData.microstep_Y = (int)tempMsY;
EEPROM.put(0, setupData);
mostraMessaggio("SETUP SALVATO!", "Salvato in EEPROM");
delay(1000);
statoAttuale = STATO_IDLE;
aggiornaDisplayIdle();
}
// ============================================================================
// INTERFACCIA LCD
// ============================================================================
void mostraMessaggio(String r1, String r2) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(r1);
lcd.setCursor(0, 1);
lcd.print(r2);
}
void aggiornaDisplayIdle() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Stato: PRONTO (IDLE)");
lcd.setCursor(0, 1);
lcd.print("A:Dati B:Setup C:Hom");
lcd.setCursor(0, 2);
lcd.print("JOYSTICK: START");
lcd.setCursor(0, 3);
lcd.print("Pulsante SX: STOP");
}
Ultima modifica di ofranco il lun ago 24, 2026 22:16, modificato 1 volta in totale.
Re: Affilare le eliche delle frese con Arduino
mooooolto interessante, vi seguo
e ricordati che se vuoi volare devi battere le ali.
Tieni sempre a mente! ..... Quando tutto sembra andare contro, ricorda che gli aeroplani decollano contro vento, non con lui!
Tieni sempre a mente! ..... Quando tutto sembra andare contro, ricorda che gli aeroplani decollano contro vento, non con lui!