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

Messaggio da lucamoto »

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...
Avatar utente
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

Messaggio da ofranco »

Spero di mettere a punto lo sketch per Arduino. Ma vedo che qui tutto tace. :risatina:
Avatar utente
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

Messaggio da ofranco »

Ecco lo schema a blocchi del progetto. Vediamo se riesco a stimolare l'interesse di qualcuno. :mrgreen:
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

Messaggio da lucamoto »

io ho comprato ttutto questo ma mai messo in opera per questioni di tempo
prova se ti riesce ti copio :risatina:
Avatar utente
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

Messaggio da ofranco »

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.
Avatar utente
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

Messaggio da Davide Resca »

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



Immagine 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

Messaggio da MauroO »

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.
Avatar utente
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

Messaggio da renpag »

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.
Non hai i permessi necessari per visualizzare i file allegati in questo messaggio.
Avatar utente
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

Messaggio da ofranco »

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. :alcooli2:

P.S. Ho usato ARDUINO MEGA
Ultima modifica di ofranco il lun ago 24, 2026 16:14, modificato 1 volta in totale.
Avatar utente
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

Messaggio da ofranco »

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.
Avatar utente
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

Messaggio da ofranco »

PARTE III^

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.
Avatar utente
brunart
TORNITORE E FRESATORE
Messaggi: 1620
Iscritto il: dom dic 09, 2012 19:40
Località: messina

Re: Affilare le eliche delle frese con Arduino

Messaggio da brunart »

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!
Rispondi

Torna a “Software”