Poi aggiungi che lo faccio per imparare e per divertimento (altrimenti avrei usato il programma di mimoletti o quello di McMax che, seppur con cose che non mi piacciono, funzionano bene entrambi) quindi tutta conoscenza in piu' per imparare a scrivere un codice efficiente.
Ho fatto un po' di prove e sono riuscito a risolvere il problema. Ho rispolverato il buon vecchio analizzatore logico per testare su un arduino uno vero e non solo al simulatore.
Risolto il mio problema, ho voluto testare la mia isr e quella di McMax, le riporto qua sotto:
Codice: Seleziona tutto
ISR McMax:
{
static byte prev_encoder; // this variable stores the value of the input port register of the previous encoder state
byte port; // this variable stores the value of the input port register of the current encoder state
port = PIND & B00001100; //reads input pins 2 and 3 of the Arduino uno PORTD D and puts the binary image on the "port" byte variable
port |= prev_encoder; //makes the logic "OR" between the current "port" byte and the previous
steps = steps + encoder[port]; //increment/decrement the encoder couter according to the previous and current encoder values
absolute_encoder_steps = absolute_encoder_steps + encoder[port]; //increment the absolute encoder counter
port >>= 2; //shift the port image by 2 bits on right
prev_encoder = port; //assign the current port image to the "prev_encoder" byte by keeping just the bits n. 2 and 3
step_flag = true;
} //END of the Interrupt Service Routine
ISR io:
{
Enc_state=DREAD_ENCB;
if (!flag_menu)
{
Enc++; // incremento il contatore degli impulsi encoder
if (Enc==one_turn_mandrel_steps) // se il mandrino ha fatto un giro competo, 2000 impulsi encoder
{
Enc=0; // resetto il contatore degli impulsi
tacho++; //incremento la variabile per il calcolo degli rpm
}
/*****************************************************
valutare se portare fuori dall'interrupt
****************************************************/
if (RUN_feed)
{
Feed_Count++; // se l'avanzamento e' attivo conto gli impulsi di encoder per poter sparare lo step
if (Feed_Count >= Feed_Divisor) // se ho raggiunto il valore di impulsi da attendere
{
Feed_Count=0; // resetto il contatore
FireStep(); //sparo un impulso
}
}
/********************************************************
***********************************************************/
}
else
{
tick=1; // ho un impulso di encoder
if (Enc_state) // leggo il canale b, se basso il mandrino gira in senso antiorario
{
Enc_pos++; // incremento il conteggio degli impulsi
Spindle_dir=normale; // mandrino ruota antiorario
if (Enc_pos>=one_turn_mandrel_steps) // se ho fatto un giro completo
{
Enc_pos=0; // resetto il conteggio
if (passata) flag_step=1; // se sono in play (passata) parto con la filettatura.
}
}
else // mandrino gira in senso orario
{
Spindle_dir=contrario;
Enc_pos--; // diminuisco il conteggio degli impulsi
if (Enc_pos<0) // se il conteggio e' <0
{
Enc_pos=one_turn_mandrel_steps-1; // riparto col conteggio da 1999
if (passata) flag_step=1; // se sono in play parto
}
}
}
}
Guardando le due routine di interrupt, a prima vista, sembrerebbe che quella di McMax sia piu' efficiente (piu' snella e veloce). La mia inutilmente pesante (pur avendola snellita rispetto alla prima versione). Ma le apparenze, a volte, ingannano
La mia isr conta correttamente fino a 100KHz (oltre non ho provato), quella di McMax a 25KHz (la sua routine legge x4) conta sbagliato.
Sempre in allegato le immagini prese dall'analizzatore logico.
Faccio un po' il prezioso per stimolare la vostra curiosita' e magari insegnarvi qualcosa (visto che io ho imparato molto qua dentro cerco di restituire il piacere).
