Sono 8 per la tastiera, 4 per i motori, SDA e SCL. Puoi usare Uno o Nano (ATMega328P).
- SDA e SCL sono A4 e A5 (I/O 17 e 18).
- Per la tastiera puoi usare I/O 2...9.
- Per i motori puoi usare I/O 10...13 oppure A0...3 (I/O 14...17).
Sono 8 per la tastiera, 4 per i motori, SDA e SCL. Puoi usare Uno o Nano (ATMega328P).
Credo nulla
Semmai è previsto per una scheda diversa da quella che pensi tu
E questa è una rogna che si deve risolvere l'autore: è lui che sa le ragioni delle sue scelte
OK, ho capito.
C'é qualcuno di buona volontà che é in grado di buttare giù due righe di codice per far funzionare questo progetto?
'
La stessa ai che lo ha scritto non può finire il lavoro?
Altrimenti credo che, anche stando al regolamento, sia per te una buona occasione per imparare, non è quello che vuoi?
Se ho postato tutto quello che ho su questo forum é proprio per imparare qualcosa che mi manca, realizzando questo progetto. Dopo tanti post, solo due utenti hanno cercato di aiutarmi. per il resto non ho trovato ancora un buon maestro in grado di darmi una dritta costruttiva, purtroppo, solo tanti bla, bla.
Grazie
Mi sembra che adesso hai capito che aiuto lo hai avuto
O sbaglio?
Rileggi bene i messaggi e vedrai che di soluzioni te ne sono state indicate altre due
Poi c'è chi legge e capisce
E chi si lamenta e basta
Vedi tu da che parte vuoi stare…
Per esempio:
const int PIN_STEP_LINEARE = 10;
const int PIN_DIR_LINEARE = 11;
const int PIN_STEP_MANDRINO = 12;
const int PIN_DIR_MANDRINO = 13;
const int PIN_ENABLE_MOTORI = 14; // A0.
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] = {2, 3, 4, 5};
byte pinColonne[COLONNE] = {6, 7, 8, 9};
Adesso puoi partire in quarta! ![]()
Non mi serve rileggere i post perché di volta in volta ho ringraziato chi ha cercato di aiutarmi.
Colgo ancora l'occasione per ringraziare tutti gli utenti di questo treed che mi hanno dedicato il loro tempo con commenti costruttivi, secondo lo spirito del forum.
Perdona ma ... deve esserti sfuggito il punto 16.1 del ns. REGOLAMENTO ...
... quindi ... noi possiamo darti indicazioni, suggerimenti e correggere errori, ma il codice devi scriverlo tu ![]()
Guglielmo
Grazie Guglielmo é proprio quello che voglio. Fin'ora soltanto Tu e Datman avete scritto qualcosa di costruttivo, secondo lo spirito di questo forum.
Qui di seguito ho fatto le modifiche suggerite da Datman, così posso usare Arduino UNO.
/*
* 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 = 10;
const int PIN_DIR_LINEARE = 11;
const int PIN_STEP_MANDRINO = 12;
const int PIN_DIR_MANDRINO = 13;
const int PIN_ENABLE_MOTORI = 14;
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] = {2, 3, 4, 5};
byte pinColonne[COLONNE] = {6, 7, 8, 9};
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();
}
Pensate che il resto del codice sia giusto o dovrei fare delle modifiche?
Grazie ancora, Franco
Ci sei quasi... Alla fine lascia solo ``` prima della domanda finale.
Ottimo! ![]()
Prova a compilarlo per Uno o Nano, vedi se va a buon fine e poi carica il programma.
Ok, Grazie.
P.S. La compilazione è andata a buon fine. Appena posso faccio i collegamenti elettrici e lo carico su Arduino UNO.
Aggiorno appena possibile.
Io invece mi chiedo una cosa diversa … parli di un’apparecchio che dovrebbe afffilare i taglienti delle frese, come sei messo sul piano meccanico, sia come realizzazione che come esperienza specifica nel campo ?
Non te lo chiedo per sminuire il tuo progetto ne per scoraggiarti, solo che di frese ai miei tempi un po (di chili) ne ho dovute affilare, e la cosa e’ leggermente piu complicata di quanto possa apparire a prima vista.
Prima di tutto dipende dal materiale delle frese (HSS o widia, ad esempio, richiedono mole, velocita’ e profili differenti), poi serve vedere se le vuoi affilare “lato interno” oppure “lato esterno” del tagliente, per mantenere o meno i parametri dimensionali originali, se devi rifare anche i taglienti in testa (cosa non semplice), se l’affilatrice fa un controllo dimensionale della fresa affilata oppure si limita ad un’affilatura “brutale” senza controlo, se sono previsti diversi passaggi fino alla lappatura finale o se fai tutto in un solo passaggio senza rifinitura, ed alcuni altri parametri … relizzare da zero un meccanismo di questo tipo non e’ impossibile, ma va teuto presente che dovra’ lavorare “al centesimo di mm”, come minimo, quindi guide molto robuste, cuscinetti a ricircolo di sfere, movimenti a vite senza fine, sensori di posizione e di misura … e cosi via.
Ti rispondo in breve.
Per quanto attiene l'esperienza meccanica di costruzione, visita la mia pagina web sul gruppo MyFord Italia.
link ai miei progetti:
https://www.facebook.com/groups/461123799023896/my_posted_content porta utensile per filettare
UPGRADE ADFILATRICE | Franco Albatros affilatrice
Franco Albatros on Reels Pantografo per incidere i noni
Franco Albatros on Reels divisore meccanico.
Con Arduino ho realizzato anche un divisore meccanico digitale che uso per fare ingranaggi. Non l'ho postato perché il video pesa troppo.
Per quanto attiene, invece, il discorso affilatura frese, voglio affilare le eliche all'interno della gola, togliendo 3-4 centesimi per passata.
Non ho un’accesso a facebook (e’ bannato dal mio PC praticamente da quando esiste, come tutti gli altri asocial-networks), ma ho visto le realizzazioni sul PC di un’amico, e vedo con piacere che di esperienza in fatto di realizzazioni meccaniche ne hai, i miei complimenti.
Quindi di fatto vuoi affilare internamente, per non alterare i diametri esterni, se hai delle mordenti sferiche ti riesce anche meglio (compatibilmente con la dimensione delle cave, ovviamente), a condizione che le facce dei taglienti all’esterno siano integre (altrimenti servirebbe rifarle, e si perderebbe la dimensione esterna originale, ma ormai le CNC possono tranquillamente gestire queste “perdite” se inserite nei parametri dell’utensile).
Come Arduino, potrebbe forse bastare una UNO, ma come ti hanno gia consigliato (specie se il programma che ti hanno fornito e’ stato scritto per la Mega), di certo la Mega e’ migliore, piu ingressi ed uscite, piu memoria, piu “risorse” … posso solo consigliarti, se la tua macchina usasse potenziometri lineari di posizionamento, di usare ADC esterni (quelli interni hanno una risoluzione limitata”, mentre invece se usi encoder incrementali il problema non si pone.
Hai previsto anche un controllo in tempo reale delle dimensioni e della sagoma dell’utensile che andra’ ad affilare, oppure lo fai esternamente e lo inserisci a programma ?
Inserirò i dati manualmente e posizionerò la mola diamantata sulla fresa con l’utilizzo con l’asse Z.
Non ricordo se tra una passata e l’altra ho previsto di disimpegnare la mola. Se non è stato previsto occorrerà pensarci. Quindi chiedo a voi esperti come si può inserire questa opzione nello sketch di Arduino. Se sarà necessario acquisto Arduino mega per avere maggiore disponibilità di ingressi e output.
Grazie per avermi dedicato il tuo tempo.
AGGIORNAMENTO LAVORI: https://youtu.be/3Y62rc507mA
Come già spiegato nel video, analizzando le funzioni emerge la necessità di effettuare alcune migliorie: