ELS (Electronic Lead Screw) - progetto con ARDUINO
Moderatore: Junior Admin
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Ok concettualmente é chiaro ma ancora non ne vedo l'utilità. Se il passo da costruire é corto puoi comunque aumentare la velocità
visto che lo stepper andrà molto più lento rispetto al mandrino; se il passo é lungo di certo non puoi filettare a 2000rpm perché ti decolla il tornio.
Altra cosa: l'accelerazione va bene perché quando inizi la passata sei fuori dal pezzo quindi puoi anche stare fuori sincrono per qualche giro ma la decelerazione proprio no, a meno di fare uno scarico adeguato alla fine del filetto ma non é detto che sia sempre possibile. Questo vuol dire che si, fai partire lo stepper dolcemente ma poi sei comunque costretto a fermarlo bruscamente e anche in fermata puoi perdere dei passi se troppo repentina...
visto che lo stepper andrà molto più lento rispetto al mandrino; se il passo é lungo di certo non puoi filettare a 2000rpm perché ti decolla il tornio.
Altra cosa: l'accelerazione va bene perché quando inizi la passata sei fuori dal pezzo quindi puoi anche stare fuori sincrono per qualche giro ma la decelerazione proprio no, a meno di fare uno scarico adeguato alla fine del filetto ma non é detto che sia sempre possibile. Questo vuol dire che si, fai partire lo stepper dolcemente ma poi sei comunque costretto a fermarlo bruscamente e anche in fermata puoi perdere dei passi se troppo repentina...
McMax
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Certamente, se fermi lo stepper di botto rischi di perdere passi (per quello avevo previsto la decelerazione).
Che possa disturbare non saprei... a 3 decimi non vedo problemi (almeno per l'uso che ne faccio io). Poi vi aggiornero' appena monto il tutto. Magari basta una rampa piu' ripida oppure serve una rampa piu' dolce. Nel primo caso e' tutto di guadagnato, nel secondo caso potrebbe diventare un problema.
E' da provare nella realta' e aggiustare il tiro. Eventualmente si toglie la rampa e viviamo felici ugualmente (Mecha filetta a 3-400rpm usando il tuo programma, per me e' gia' sufficiente. Diciamo che la rampa l'ho messa perche' fa figo, l'ho vista nel programma del russo, l'ho capita, mi e' venuto semplice inserirla nel mio programma e l'ho usata. Se non ci fosse andrebbe ugualmente bene ma e' meno figo
)
Che possa disturbare non saprei... a 3 decimi non vedo problemi (almeno per l'uso che ne faccio io). Poi vi aggiornero' appena monto il tutto. Magari basta una rampa piu' ripida oppure serve una rampa piu' dolce. Nel primo caso e' tutto di guadagnato, nel secondo caso potrebbe diventare un problema.
E' da provare nella realta' e aggiustare il tiro. Eventualmente si toglie la rampa e viviamo felici ugualmente (Mecha filetta a 3-400rpm usando il tuo programma, per me e' gia' sufficiente. Diciamo che la rampa l'ho messa perche' fa figo, l'ho vista nel programma del russo, l'ho capita, mi e' venuto semplice inserirla nel mio programma e l'ho usata. Se non ci fosse andrebbe ugualmente bene ma e' meno figo
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Dico la mia, considerando che molti hanno un inverter montato o comunque un regolatore di velocità, non sarebbe più comodo far interfacciare l'els a quest'ultimo e far fare le accelerazioni decellerazioni direttamente al tornio?
-->I MIEI VIDEO<--
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Si potrebbe fare ma io non ho l'inverter e non ci ho pensato.
Gia' che siamo in argomento, qualcuno sa come funziona il protocollo di comunicazione degli inverter? E' standard o ogni casa usa il suo?
Gia' che siamo in argomento, qualcuno sa come funziona il protocollo di comunicazione degli inverter? E' standard o ogni casa usa il suo?
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Ogni costruttore ha il suo....
Sbinf il problema non é quando avvii il mandrino, li hai l'inerzia che anche con avvio diretto (senza inverter e accelerazione) comunque non causa strattoni alla vite. Il problema é quando esegui la filettatura a misura e fai partire la passata mentre il mandrino é già a regime....
Sbinf il problema non é quando avvii il mandrino, li hai l'inerzia che anche con avvio diretto (senza inverter e accelerazione) comunque non causa strattoni alla vite. Il problema é quando esegui la filettatura a misura e fai partire la passata mentre il mandrino é già a regime....
McMax
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Si Max era chiaro. Quelli che ho io li piloto tutti in tensione 0/10v penso sia sufficiente un DAC e un relè per avvio arresto Praticamente in filettatura parto a bassa velocità, aumento la rotazione del mandrino e in prossimità dell'arresto del carro decellero. A questo punto si aggiunge un motore per arretrare il carro e fa tutto in automatico :D
-->I MIEI VIDEO<--
-
mimoletti
- TORNITORE E FRESATORE
- Messaggi: 1140
- Iscritto il: dom dic 27, 2009 11:31
- Località: Torre del Greco (NA)
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Condivido le osservazioni fatte da Max, implementare le rampe di accelerazione non è banale dovendo mantenere il sincronismo, e probabilmente non serve filettare a velocità cosi alte. Ma provaci lo tesso non lasciare nulla di intentato anche solo per il gusto della sfida.
Ora tornando a noi e per fare in modo che chi legga possa comprendere, vorrei chiarire alcune cose:
Nel mio progetto ho definito tre fasi, Pausa, Play, e Reverse.
Per Paly intendo quando il carro, si sposta dalla contropunta alla mandrino, eseguendo la filettatura.
Per Reverse intendo quando il carro, si sposta dal mandrino verso la contropunta.
Per Pause quando e fermo a sinistra (lato mandrino) o destra (lato contropunta).
Quando si trova nella fase di Play avanza in modo sincronizzato, all'avanzamento scelto. Nella fase di Reverse si muove in modo asincrono, in questa fase è stata implementata una rampa di accelerazione e si muove alla massima velocità permessa dal sistema, che dipende da diversi fattori: Caratteristiche del motore, tensione di alimentazione, passo della madre vite ecc.
La massima velocità di rotazione del mandrino con il passo maggiore impostabile, in primis dipende essenzialmente, dalla presenza o meno di una rampa di accelerazione, ma come spiegato anche da altri fattori. Nei motori passo passo la coppia decresce con l'aumentare dei giri, il micro passo aiuta, perché anche se influisce lievemente sulla coppia statica, ti permette di aumentare la coppia dinamica.
Un secondo fattore che influisce sulla massima velocità è la durata delle rutine di interrupt e il modo in cui effettui la lettura degli impulsi. Nel tuo progetto immagino che avendo preso spunto dal firmware di Max, tu legga tutti i fronti di salita prodotti dal tuo encoder. Quindi la durata minima della tua rutine di interrupt dipenderà solo dalla massima velocità di rotazione, a cui ti sei prefissato che debba funzionare. Immaginiamo che in uscita al tuo encoder ci siano 120 Khz, avrai un un periodo di circa 8 microsecondi. Quindi la tua rutine di interrupt dovrà necessariamente avere una durata inferiore.
Per ovviare a questo problema nel mio progetto utilizzo il timer del micro, per la divisione degli impulsi.
Facciamo un esempio: Se voglio dividere gli impulsi per 5, carico il timer con il valore 251, dopo 5 impulsi avrò un overflow che mi genererà un interrupt.
Di conseguenza tra un interrupt e quello successivo avrò un tempo enormemente superiore. Perché avrò un interrupt ogni 5 impulsi.
Quindi il tempo che intercorre tra un interrupt e il successivo non dipende solo dalla velocita di rotazione ma anche dal valore di divisione.
Ora come funziona la mia rutine di interrupt:
In modo molto semplice, attraverso un If Then End If, passo continuamente dalla fase di Pause a quella di Divisione.
Durante la fase Pause abilito il prescaler e carico nel timer un valore tale che si verifichi, un interrupt esattamente dopo 2000 impulsi a giro. Successivamente nella fase di Play disabilito il prescaler e carico nel timer il valore di divisione. Passando quindi continuamente tra una fase e l'altra.
Credo anch'io che la cosa migliore per aggiungere delle rampe di accelerazioni e decelerazioni, e interfacciandosi direttamente con l'inverter. Credo che nei centri di lavoro avvenga esattamente questo. Uno dei miei amici che possiede la versione più piccola del Wabeco e che ha realizzato una sua versione su Arduino, semplicemente aggiunge o esclude delle resistenze in serie o in parallelo (ora non ricordo), al potenziometro che controlla i giri del motore.
Spero di essere stato chiaro.
Ora tornando a noi e per fare in modo che chi legga possa comprendere, vorrei chiarire alcune cose:
Nel mio progetto ho definito tre fasi, Pausa, Play, e Reverse.
Per Paly intendo quando il carro, si sposta dalla contropunta alla mandrino, eseguendo la filettatura.
Per Reverse intendo quando il carro, si sposta dal mandrino verso la contropunta.
Per Pause quando e fermo a sinistra (lato mandrino) o destra (lato contropunta).
Quando si trova nella fase di Play avanza in modo sincronizzato, all'avanzamento scelto. Nella fase di Reverse si muove in modo asincrono, in questa fase è stata implementata una rampa di accelerazione e si muove alla massima velocità permessa dal sistema, che dipende da diversi fattori: Caratteristiche del motore, tensione di alimentazione, passo della madre vite ecc.
La massima velocità di rotazione del mandrino con il passo maggiore impostabile, in primis dipende essenzialmente, dalla presenza o meno di una rampa di accelerazione, ma come spiegato anche da altri fattori. Nei motori passo passo la coppia decresce con l'aumentare dei giri, il micro passo aiuta, perché anche se influisce lievemente sulla coppia statica, ti permette di aumentare la coppia dinamica.
Un secondo fattore che influisce sulla massima velocità è la durata delle rutine di interrupt e il modo in cui effettui la lettura degli impulsi. Nel tuo progetto immagino che avendo preso spunto dal firmware di Max, tu legga tutti i fronti di salita prodotti dal tuo encoder. Quindi la durata minima della tua rutine di interrupt dipenderà solo dalla massima velocità di rotazione, a cui ti sei prefissato che debba funzionare. Immaginiamo che in uscita al tuo encoder ci siano 120 Khz, avrai un un periodo di circa 8 microsecondi. Quindi la tua rutine di interrupt dovrà necessariamente avere una durata inferiore.
Per ovviare a questo problema nel mio progetto utilizzo il timer del micro, per la divisione degli impulsi.
Facciamo un esempio: Se voglio dividere gli impulsi per 5, carico il timer con il valore 251, dopo 5 impulsi avrò un overflow che mi genererà un interrupt.
Di conseguenza tra un interrupt e quello successivo avrò un tempo enormemente superiore. Perché avrò un interrupt ogni 5 impulsi.
Quindi il tempo che intercorre tra un interrupt e il successivo non dipende solo dalla velocita di rotazione ma anche dal valore di divisione.
Ora come funziona la mia rutine di interrupt:
In modo molto semplice, attraverso un If Then End If, passo continuamente dalla fase di Pause a quella di Divisione.
Durante la fase Pause abilito il prescaler e carico nel timer un valore tale che si verifichi, un interrupt esattamente dopo 2000 impulsi a giro. Successivamente nella fase di Play disabilito il prescaler e carico nel timer il valore di divisione. Passando quindi continuamente tra una fase e l'altra.
Credo anch'io che la cosa migliore per aggiungere delle rampe di accelerazioni e decelerazioni, e interfacciandosi direttamente con l'inverter. Credo che nei centri di lavoro avvenga esattamente questo. Uno dei miei amici che possiede la versione più piccola del Wabeco e che ha realizzato una sua versione su Arduino, semplicemente aggiunge o esclude delle resistenze in serie o in parallelo (ora non ricordo), al potenziometro che controlla i giri del motore.
Spero di essere stato chiaro.
Solo gli stupidi non cambiano mai idea!
Tornio Wabeco D6000 con ELS; Fresa Wabeco F1210; Segatrice Nebes TM125 Inverter; Tavola a dividere Vertex HV-6,Morsa meccnica Allen MAP/78-N
https://www.youtube.com/watch?v=cobEZI8KvOk
Tornio Wabeco D6000 con ELS; Fresa Wabeco F1210; Segatrice Nebes TM125 Inverter; Tavola a dividere Vertex HV-6,Morsa meccnica Allen MAP/78-N
https://www.youtube.com/watch?v=cobEZI8KvOk
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
il russo l'ha fatto, il suo programma e' un capolavoro. Io mi sono limitato a capire alcune parti, non l'ho studiato tutto.
https://www.youtube.com/channel/UC4Mxjk ... GHw/videos
Usa un atmega2560 (arduino mega), piu' periferiche e memoria del atmega328p (arduino uno) ma praticamente stessa capacita' di calcolo.
Lui ha messo anche un carro sul trasversale e puo' filettare completamente in automatico ma anche tornire conicita', sfere e mi pare qualcos'altro che non ricordo.
@Mimoletti: grazie mille della spiegazione, ora mi e' chiaro come hai fatto funzionare il timer.
Il mio sistema replica i tuoi menu' e il tuo concetto di play-pause-reverse (mi sono abituato a quello e lo trovo comodo e immediato).
Visto che ho un encoder da 2000ppr e McMax consiglia un encoder da (attorno) 300ppr x4, ho pensato che bastasse leggere un fronte solo, quindi genero 2000 interrupt a giro (a 120KHz sono, come dici tu, 8uS). Per discernere il senso di rotazione, nella routine di interrupt vado a leggere lo stato dell'altro canale dell'encoder. Visto che l'interrupt e' sul fronte di discesa del canale A, se il canale B e' alto girero' da una parte, se e' basso girero' dall'altra.
Avevo gia' provato a misurare quanto ci mette la mia routine di interrupt ma non mi ricordo. Adesso faccio una prova al volo.
Fatta prova, la routine di interrupt impiega 4uS.
C'e' ancora tanto spazio di miglioramento e ottimizzazione del codice...
https://www.youtube.com/channel/UC4Mxjk ... GHw/videos
Usa un atmega2560 (arduino mega), piu' periferiche e memoria del atmega328p (arduino uno) ma praticamente stessa capacita' di calcolo.
Lui ha messo anche un carro sul trasversale e puo' filettare completamente in automatico ma anche tornire conicita', sfere e mi pare qualcos'altro che non ricordo.
@Mimoletti: grazie mille della spiegazione, ora mi e' chiaro come hai fatto funzionare il timer.
Il mio sistema replica i tuoi menu' e il tuo concetto di play-pause-reverse (mi sono abituato a quello e lo trovo comodo e immediato).
Visto che ho un encoder da 2000ppr e McMax consiglia un encoder da (attorno) 300ppr x4, ho pensato che bastasse leggere un fronte solo, quindi genero 2000 interrupt a giro (a 120KHz sono, come dici tu, 8uS). Per discernere il senso di rotazione, nella routine di interrupt vado a leggere lo stato dell'altro canale dell'encoder. Visto che l'interrupt e' sul fronte di discesa del canale A, se il canale B e' alto girero' da una parte, se e' basso girero' dall'altra.
Avevo gia' provato a misurare quanto ci mette la mia routine di interrupt ma non mi ricordo. Adesso faccio una prova al volo.
Fatta prova, la routine di interrupt impiega 4uS.
C'e' ancora tanto spazio di miglioramento e ottimizzazione del codice...
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Scusa Matteou come lo leggi l'encoder esattamente ? Non é molto chiaro. Quella é la parte più critica del codice, devi trovare un modo veloce altrimenti perdi troppo tempo. 4usec mi paiono troppi considerando il clock a 16Mhz....
McMax
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
-
mimoletti
- TORNITORE E FRESATORE
- Messaggi: 1140
- Iscritto il: dom dic 27, 2009 11:31
- Località: Torre del Greco (NA)
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Spiegami meglio come ha fatto, grazie.
Solo gli stupidi non cambiano mai idea!
Tornio Wabeco D6000 con ELS; Fresa Wabeco F1210; Segatrice Nebes TM125 Inverter; Tavola a dividere Vertex HV-6,Morsa meccnica Allen MAP/78-N
https://www.youtube.com/watch?v=cobEZI8KvOk
Tornio Wabeco D6000 con ELS; Fresa Wabeco F1210; Segatrice Nebes TM125 Inverter; Tavola a dividere Vertex HV-6,Morsa meccnica Allen MAP/78-N
https://www.youtube.com/watch?v=cobEZI8KvOk
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Codice: Seleziona tutto
volatile int Enc_pos = 0; //passi encoder filettatura
volatile bool flag_step=0;
volatile bool Spindle_dir=0;
volatile byte Ks_Count=0;
volatile int Km_Count=5000;
volatile long stepper_pos=0;
long near_end=100000;
volatile byte tmp_Accel = 25;
volatile byte tmp_Ks_Divisor = 25+7;
volatile byte Repeat_Count = 0;
#define REPEAt 4
bool sviluppo_filetto=false;
bool RUN_feed = false;
bool flag_libero=false;
byte Ks_Divisor=7;
int Km_Divisor=5000;
#define normale 1
#define contrario 0
volatile int Enc=0;
float tacho=0;
#define DREAD_ENCB (PIND&_BV(3))
#define STEP 9 //uscita segnale "STEP" per motore stepper
#define DIR 8 //uscita segnale "DIR" per motore stepper
#define ENABLE 7 //uscita segnale "ENABLE" per motore stepper
#define ENCA 2 //ingresso ancoder A - INTERRUPT 0
#define ENCB 3 //ingresso ancoder B - INTERRUPT 1
#define LR 11
bool passata=1;
// variabili relative ad encoder e motore stepper
#define one_turn_mandrel_steps 2000 //numero di step/giro dell'encoder mandrino (x4)
#define screw_pitch 3 //passo della vite madre in mm
#define one_turn_screw_steps 800 //numero di step/giro del motore stepper sulla vite
#define single_step_pitch 375 //valore in 10x nanometri (0,00375mm) di movimento del carro ad ogni step della vite madre
void SetOneShot()
{
ICR1 = 0; // Set ICR1 register to 0. ICR1 is the TOP of the timer counting which means the timer is stuck to 0
OCR1A = 65534; // Set OCR1A to 65534 in order to fire a pulse of 2 cycle clock (8us)
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11); //OC1A set for PWM with CLEAR at BOTTOM and SET at MATCH (inverted mode)
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11) | _BV(CS10); //WGM set for Fast PWM with ICR1 used as TOP value. Prescaler set to clk/64 (4uSec cycle)
// Timer1 start HERE
}
#define FireStep() TCNT1 = 65533
void ClearPWM() //Clear the PWM and stops Timer1
{
TCCR1B = 0; // halt Timer by setting clock bits (Prescaler) to 0. This will stop the timer until we get set up
TCCR1A = 0; // Reset the register to avoid misconfiguration issue
TCNT1 = 0; // start counting at 0 (BOTTOM)
TIMSK1 = 0; // Reset the interrupt mask register for Timer1
TCCR2A=0;
TCCR2B=0;
TIMSK2=0;
}
unsigned long lasttime=0;
void setup()
{
Serial.begin(9600);
pinMode(ENCA, INPUT_PULLUP); //Econder A input - INTERRUPT
pinMode(ENCB, INPUT_PULLUP); //Encoder B input - INTERRUPT
pinMode(STEP, OUTPUT); //STEP OUTPUT to stepper driver
ClearPWM();
SetOneShot();
lasttime=micros();
for (long w=0; w<=100000; w++)
{
if (DREAD_ENCB==0) // spindle normale
{
Enc_pos++;
Spindle_dir=normale;
if (Enc_pos==one_turn_mandrel_steps)
{
Enc_pos=0;
if (passata) flag_step=1;
}
}
else // spindle contrario
{
Spindle_dir=contrario;
Enc_pos--;
if (Enc_pos<0)
{
Enc_pos=one_turn_mandrel_steps-1;
if (passata) flag_step=1;
}
}
if (flag_step)
{
if ((stepper_pos>=near_end) && !flag_libero)
{
if (tmp_Ks_Divisor < tmp_Accel)
{
Ks_Count++;
if (Ks_Count > tmp_Ks_Divisor)
{
FireStep();
if (sviluppo_filetto) stepper_pos++;
if (!sviluppo_filetto) stepper_pos--;
Ks_Count = 0;
if (++Repeat_Count == REPEAt)
{
Repeat_Count = 0;
tmp_Ks_Divisor ++;
}
}
}
}
else
{
Ks_Count++;
if (Ks_Count > tmp_Ks_Divisor)
{
FireStep();
if (sviluppo_filetto) stepper_pos++;
if (!sviluppo_filetto) stepper_pos--;
if (tmp_Ks_Divisor > Ks_Divisor)
{
Ks_Count = 0;
if (++Repeat_Count == REPEAt)
{
Repeat_Count = 0;
tmp_Ks_Divisor --;
}
}
else
{
Km_Count = Km_Count + Km_Divisor;
if (Km_Count > Km_Divisor)
{
Km_Count = Km_Count - 10000;
Ks_Count = 0;
}
else {Ks_Count = 1;}
}
}
}
}
}
lasttime=micros()-lasttime;
Serial.println(lasttime);
}
void loop()
{
}
Normalmente l'interrupt viene attivato nel fronte di discesa del canale A dell'encoder. Ks_Divisor e' la parte intera della divisione. Km_Divisor e' la parte frazionaria.
Entrambe sono precalcolate e messe in una struct.
Se non e' chiaro chiedi.
Se ho fatto errori sii clemente
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
Matteou, non capisco bene dove sta l'interrupt, non lo vedo definito e attaccato a nessuno pin.
Da questo "if" intendo che stai leggendo il pin dell'encoder in polling:
Altra cosa, mi spieghi questa:
perché la funzione FireStep() è diventata un #define ???
Per curiosità ho provato a compilarla e non da errore ma son sincero, un #define usato in questo modo non l'avevo mai visto. Come funziona?
Da questo "if" intendo che stai leggendo il pin dell'encoder in polling:
Codice: Seleziona tutto
if (DREAD_ENCB==0) // spindle normaleCodice: Seleziona tutto
#define FireStep() TCNT1 = 65533Per curiosità ho provato a compilarla e non da errore ma son sincero, un #define usato in questo modo non l'avevo mai visto. Come funziona?
McMax
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
ah ok, mai usate così.
Perché lasciare il nome funzione con le parentesi ???
Perché lasciare il nome funzione con le parentesi ???
McMax
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson
fulminato in tenera età
-
umbez
- TORNITORE E FRESATORE
- Messaggi: 1886
- Iscritto il: lun set 29, 2008 23:19
- Località: Cologno Monzese
Re: ELS (Electronic Lead Screw) - progetto con ARDUINO
le macro si usano per funzioni semplici tipo il max fra due numeri ecc..
ti faccio un esempio e sono sicuro che ti sarà più familiare :
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
in genere non si usano per gli assegnamenti...
ps. mi ero dimenticato, le macro sono interpretate dal pre-processore del compilatore quindi prima di compilare sostituisce le chiamate alle macro nel codice.
Ciao!!
ti faccio un esempio e sono sicuro che ti sarà più familiare :
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
in genere non si usano per gli assegnamenti...
ps. mi ero dimenticato, le macro sono interpretate dal pre-processore del compilatore quindi prima di compilare sostituisce le chiamate alle macro nel codice.
Ciao!!
Ù.