Buongiorno, ho intenzione di affilare le eliche delle frese con un sistema motorizzato a due assi. Uno che fa l'avanzamento longitudinale lungo la fresa e l'altro rotativo. In particolare inserendo i valori di avanzamento (passo) sui due assi l'utensile (mola) dovrebbe scorrere lungo la scanalatura dell'elica per affilarla. Come si vede nel video https://www.youtube.com/watch?v=VNDwdyo1ioI
Con l'aiuto di amici abbiamo realizzato questo sketch:
/*
* SISTEMA AUTOMATICO AFFILATURA FRESE - CONTROLLO CNC ARDUINO (VERSIONE SEQUENZIALE)
*
* Questo programma automatizza l'affilatura di frese a candela eseguendo una passata
* per ogni tagliente della fresa. Dopo ogni passata, il mandrino ruota automaticamente
* per posizionare il tagliente successivo.
*
* ===================================================================================
* GUIDA ALL'USO DEL TASTIERINO (4x4)
* ===================================================================================
* [A] - SU: Sposta il cursore verso l'alto nel menu.
* [B] - GIU: Sposta il cursore verso il basso nel menu.
* [C] - INVIO/CONFERMA:
* - Nel Menu: Entra in modalità modifica o avvia l'azione selezionata.
* - Durante l'inserimento: Salva il valore digitato.
* - A fine lavoro: Riavvia il ciclo completo di affilatura.
* [D] - STOP/ANNULLA:
* - Durante la lavorazione: Ferma immediatamente i motori e torna al menu.
* - Durante l'inserimento: Annulla l'operazione e torna al menu.
* [*] - RESET: Cancella il numero che stai scrivendo se hai fatto un errore.
* [0-9] - NUMERI: Usati per inserire i valori dei parametri.
*
* ===================================================================================
* PARAMETRI DI LAVORO
* ===================================================================================
* 1. PASSO ELICA (mm/giro): La distanza lineare che la fresa percorrerebbe in un giro.
* 2. LUNGHEZZA (mm): Quanto è lungo il tratto del tagliente da affilare.
* 3. NUM. TAGLIENTI: Quanti taglienti ha la fresa (es. 2, 3, 4).
* 4. GRADI DIVIS.: L'angolo esatto tra un tagliente e l'altro (es. 90° per 4 taglienti).
*
* HARDWARE: Arduino, LCD I2C, Keypad 4x4, 2x Driver Stepper.
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <AccelStepper.h>
// ===================================================================================
// CONFIGURAZIONE HARDWARE
// ===================================================================================
const float PASSI_PER_MM_LINEARE = 320.0;
const float PASSI_PER_GIRO_MANDRINO = 1600.0;
const float VELOCITA_MAX = 1000.0;
const float ACCELERAZIONE = 500.0;
const int PIN_STEP_LINEARE = 2;
const int PIN_DIR_LINEARE = 3;
const int PIN_STEP_MANDRINO = 4;
const int PIN_DIR_MANDRINO = 5;
const int PIN_ENABLE_MOTORI = 8;
const byte RIGHE = 4;
const byte COLONNE = 4;
char keys[RIGHE][COLONNE] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte pinRighe[RIGHE] = {22, 24, 26, 28};
byte pinColonne[COLONNE] = {30, 32, 34, 36};
LiquidCrystal_I2C lcd(0x27, 20, 4);
Keypad tastierino = Keypad(makeKeymap(keys), pinRighe, pinColonne, RIGHE, COLONNE);
AccelStepper motoreLineare(AccelStepper::DRIVER, PIN_STEP_LINEARE, PIN_DIR_LINEARE);
AccelStepper motoreMandrino(AccelStepper::DRIVER, PIN_STEP_MANDRINO, PIN_DIR_MANDRINO);
// ===================================================================================
// STATI E VARIABILI
// ===================================================================================
enum StatoSistema {
MENU_PRINCIPALE,
EDIT_VALORE,
LAVORO_ANDATA,
LAVORO_RITORNO,
LAVORO_ROTAZIONE,
LAVORO_COMPLETATO
};
StatoSistema stato = MENU_PRINCIPALE;
int voceSelezionata = 0;
// Parametri Utente
float passoElica = 50.0;
float lunghezzaAffilatura = 150.0;
int numTaglienti = 4;
float gradiDivisione = 90.0;
// Variabili di controllo ciclo
int taglienteCorrente = 0;
String inputBuffer = "";
void setup() {
lcd.init();
lcd.backlight();
lcd.print("AFFILATRICE FRESE");
lcd.setCursor(0,1);
lcd.print("Ver. Sequenziale");
delay(2000);
pinMode(PIN_ENABLE_MOTORI, OUTPUT);
digitalWrite(PIN_ENABLE_MOTORI, LOW);
motoreLineare.setMaxSpeed(VELOCITA_MAX);
motoreLineare.setAcceleration(ACCELERAZIONE);
motoreMandrino.setMaxSpeed(VELOCITA_MAX);
motoreMandrino.setAcceleration(ACCELERAZIONE);
mostraMenu();
}
void loop() {
motoreLineare.run();
motoreMandrino.run();
char tasto = tastierino.getKey();
switch (stato) {
case MENU_PRINCIPALE:
gestisciNavigazione(tasto);
break;
case EDIT_VALORE:
gestisciInserimento(tasto);
break;
case LAVORO_ANDATA:
if (tasto == 'D') fermaTutto();
if (motoreLineare.distanceToGo() == 0 && motoreMandrino.distanceToGo() == 0) {
delay(500);
lcd.setCursor(0, 3);
lcd.print("Stato: RITORNO ");
motoreLineare.moveTo(0);
motoreMandrino.moveTo(0);
stato = LAVORO_RITORNO;
}
break;
case LAVORO_RITORNO:
if (tasto == 'D') fermaTutto();
if (motoreLineare.distanceToGo() == 0 && motoreMandrino.distanceToGo() == 0) {
taglienteCorrente++;
if (taglienteCorrente < numTaglienti) {
delay(500);
lcd.setCursor(0, 3);
lcd.print("Stato: PROSSIMO ");
// Ruota il mandrino per il prossimo tagliente
long passiRotazione = (gradiDivisione / 360.0) * PASSI_PER_GIRO_MANDRINO;
motoreMandrino.move(passiRotazione);
stato = LAVORO_ROTAZIONE;
} else {
stato = LAVORO_COMPLETATO;
mostraFineLavoro();
}
}
break;
case LAVORO_ROTAZIONE:
if (tasto == 'D') fermaTutto();
if (motoreMandrino.distanceToGo() == 0) {
delay(500);
// Reset coordinate relative per la nuova passata
motoreLineare.setCurrentPosition(0);
motoreMandrino.setCurrentPosition(0);
avviaPassataSincronizzata();
aggiornaDisplayLavoro();
stato = LAVORO_ANDATA;
}
break;
case LAVORO_COMPLETATO:
if (tasto == 'C') { // Ripeti ciclo
avviaCicloCompleto();
} else if (tasto == 'D') {
stato = MENU_PRINCIPALE;
mostraMenu();
}
break;
}
}
// ===================================================================================
// INTERFACCIA E MENU
// ===================================================================================
void mostraMenu() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("--- IMPOSTAZIONI ---");
lcd.setCursor(0,1);
lcd.print(voceSelezionata == 0 ? ">Elica: " : " Elica: ");
lcd.print(passoElica, 1);
lcd.setCursor(0,2);
lcd.print(voceSelezionata == 1 ? ">Lung.: " : " Lung.: ");
lcd.print(lunghezzaAffilatura, 1);
lcd.setCursor(0,3);
if (voceSelezionata == 2) lcd.print(">Taglienti: " + String(numTaglienti));
else if (voceSelezionata == 3) lcd.print(">Gradi: " + String(gradiDivisione, 1));
else if (voceSelezionata == 4) lcd.print("> [AVVIA AFFILATURA]");
}
void gestisciNavigazione(char tasto) {
if (!tasto) return;
if (tasto == 'A') { voceSelezionata = (voceSelezionata > 0) ? voceSelezionata - 1 : 4; mostraMenu(); }
else if (tasto == 'B') { voceSelezionata = (voceSelezionata < 4) ? voceSelezionata + 1 : 0; mostraMenu(); }
else if (tasto == 'C') {
if (voceSelezionata == 4) avviaCicloCompleto();
else { stato = EDIT_VALORE; inputBuffer = ""; lcd.setCursor(0,3); lcd.print("Valore: "); lcd.setCursor(8,3); }
}
}
void gestisciInserimento(char tasto) {
if (!tasto) return;
if (tasto >= '0' && tasto <= '9') { inputBuffer += tasto; lcd.print(tasto); }
else if (tasto == '*') { inputBuffer = ""; lcd.setCursor(8,3); lcd.print(" "); lcd.setCursor(8,3); }
else if (tasto == 'C') {
if (inputBuffer.length() > 0) {
float val = inputBuffer.toFloat();
if (voceSelezionata == 0) passoElica = val;
if (voceSelezionata == 1) lunghezzaAffilatura = val;
if (voceSelezionata == 2) numTaglienti = (int)val;
if (voceSelezionata == 3) gradiDivisione = val;
}
stato = MENU_PRINCIPALE; mostraMenu();
} else if (tasto == 'D') { stato = MENU_PRINCIPALE; mostraMenu(); }
}
// ===================================================================================
// LOGICA DI LAVORAZIONE
// ===================================================================================
void avviaCicloCompleto() {
taglienteCorrente = 0;
lcd.clear();
lcd.print("AVVIO AFFILATURA...");
delay(1000);
motoreLineare.setCurrentPosition(0);
motoreMandrino.setCurrentPosition(0);
avviaPassataSincronizzata();
aggiornaDisplayLavoro();
stato = LAVORO_ANDATA;
}
void avviaPassataSincronizzata() {
long targetLineare = lunghezzaAffilatura * PASSI_PER_MM_LINEARE;
float gradiRotazione = (lunghezzaAffilatura / passoElica) * 360.0;
long targetMandrino = (gradiRotazione / 360.0) * PASSI_PER_GIRO_MANDRINO;
motoreLineare.moveTo(targetLineare);
motoreMandrino.moveTo(targetMandrino);
// Calcolo velocità sincronizzata
float velBase = 400.0;
float tempo = abs(targetLineare) / velBase;
float velMandrino = abs(targetMandrino) / tempo;
motoreLineare.setMaxSpeed(velBase);
motoreMandrino.setMaxSpeed(velMandrino);
}
void aggiornaDisplayLavoro() {
lcd.clear();
lcd.print("AFFILATURA IN CORSO");
lcd.setCursor(0,1);
lcd.print("Tagliente: ");
lcd.print(taglienteCorrente + 1);
lcd.print("/");
lcd.print(numTaglienti);
lcd.setCursor(0,2);
lcd.print("D: STOP");
lcd.setCursor(0,3);
lcd.print("Stato: ANDATA ");
}
void mostraFineLavoro() {
lcd.clear();
lcd.print("LAVORO FINITO!");
lcd.setCursor(0,1);
lcd.print("Taglienti fatti: ");
lcd.print(numTaglienti);
lcd.setCursor(0,2);
lcd.print("C: RIPETI CICLO");
lcd.setCursor(0,3);
lcd.print("D: ESCI AL MENU");
}
void fermaTutto() {
motoreLineare.stop();
motoreMandrino.stop();
stato = MENU_PRINCIPALE;
mostraMenu();
}
Dovendo utilizzare il tastierino alfanumerico cosa mi consigliate di utilizzare per collegarlo ai piedini 22, 24, 26, 28 e 30, 32, 34, 36.
Ringrazio anticipatamente per l'aiuto che vorrete darmi.
Saluti a tutti, Franco


