Pages: [1] 2   Go Down
Author Topic: Port Manipulation Encoder  (Read 1427 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti. Devo controllare un rotary encoder per interfaccia utente e devo modificare il codice in "true C" per velocizzare le letture. Sto usando Arduino Uno (Atmega328).

Il codice di partenza é questo:

Code:
encoderLast=LOW;
n=LOW;
void setup(){
pinMode(2,INPUT);
pinMode(3,INPUT);
digitalWrite(2,HIGH);
digitalWrite(3,HIGH);
}
void loop(){
encoder();
}
void encoder(){
  n = digitalRead(2);
   if ((encoderLast == LOW) && (n == HIGH)) {
    if (digitalRead(3) == LOW) {
       encoderPos--;
     } else {
       encoderPos++;
     }
   }
   encoderLast = n;
}

Ora dovrei velocizzare la funzione encoder utilizzando la port manipulation:

Code:
void encoder(){
  n = PIND & _BV(PIND2);
   if ((encoderLast == LOW) && (n == HIGH)) {
    if ((PIND & _BV(PIND3)) == LOW) {
       encoderPos--;//antiorario
     } else {
       encoderPos++;//orario
     }
   }
   encoderLast = n;
}

Il risultato della modifica é che la variabile encoderPos non si incrementa ne si decrementa ed é come se nelle condizioni vi sia qualcosa che non va. Potete aiutarmi? Grazie
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 114
Posts: 7194
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Secondo me ti conviene usare un interrupt, così non perdi nessun impulso.
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Secondo me ti conviene usare un interrupt, così non perdi nessun impulso.
Quoto
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Purtroppo non posso usare gli interrupt perché mi da problemi con il display.
Inoltre vorrei imparare meglio la port manipulation. Secondo voi il codice é corretto?
Logged

Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
n = PIND & _BV(PIND2);
Se n viene dichiarato come intero 0000100 vale 4, e nel blocco if non viene riconosciuto come HIGH
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
n = PIND & _BV(PIND2);
Se n viene dichiarato come intero 0000100 vale 4, e nel blocco if non viene riconosciuto come HIGH
Perché HIGH è una costante predefinita che vale 1.
Come LOW è una costante che vale 0.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie, ora funziona!
Ho applicato la stessa funzione ad un encoder Hall di un motore che fa al massimo 80 giri/minuto (rapporto riduzione 131:1), con una risoluzione di 64 cpr, ma di cui utilizzo un solo canale, perché la direzione la prendo da una variabile impostata altrove. (non posso usare gli interrupt)
Dopo alcuni calcoli, ho fatto in modo che ad ogni 25 impulsi letti (solo sul fronte di salita) mi faccio aumentare una variabile per indicarmi i millimetri percorsi. Ora per distanze che vanno da 5mm fino ad 80 mm la precisione é buona. Oltre gli 80 mm inizio ad avere imprecisioni non uniformi.
Tengo a precisare che ho modificato gran parte delle funzioni presenti nel codice con quelle proprie della port manipulation ed ora tutto il funzionamento mi sembra molto piú fluido e senza ritardi.

Cosa posso fare per aumentare la precisione?
Logged

Offline Offline
Edison Member
*
Karma: 40
Posts: 1964
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Io ho appena costruito un oggetto vagamente simile al tuo, con display grafico abbastanza impegativo, e per variate alcuni parametri ho usato un encoder rotativo (a mò di Volume autoradio), usando gli interrupt sui pin 2 e 3.

Mi spieghi che problemi avresti con il display, visto che non usa alcun timer interno (unico motivo per cui un Interrupt ext non dovrebbe funzionare)?

Solo usando gli interrupt puoi avere una "fluidità" di utilizzo soddisfacente.

Tieni sempre a mente che l'ambizione e coronamento finale di un "Power user" di MCU, è quella di non scrivere NULLA nella funzione while(), nel caso di Arduino la funzione loop().
« Last Edit: March 12, 2013, 01:27:26 am by BaBBuino » Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 134
Posts: 9698
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tieni sempre a mente che l'ambizione e coronamento finale di un "Power user" di MCU, è quella di non scrivere NULLA nella funzione while(), nel caso di Arduino la funzione loop().


Direi che hai appena scritto una cosa che viola tutte le regole della buona programmazione.
E' esattamente l'opposto di quello che dici, nel main loop, tipicamente una while(1), viene fatto tutto, ovviamente chiamando funzioni esterne scritte appositamente, mentre nelle isr, che devono durare il minimo indispensabile, ci si deve limitare a resettare gli eventuali flag, svolgere solo le operazioni che richiedono attenzione immediata e settare un eventuale flag per informare il main loop che deve eseguire una certa azione.
Logged

Offline Offline
Edison Member
*
Karma: 40
Posts: 1964
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Guarda... mi stai mandando in depressione perchè ho giusto litigato la settimana scorsa con un Ingegnere che sosteneva quanto ho detto. Siccome sembrava sapesse il fatto suo, ho abbozzato e fatta mio questa osservazione.

Lui insisteva su una programmazione simil Windows, ovvero programmazione attivata da eventi. Funzioni che partono solo se si è innescato l'evento, un interrup. Naturalmente con una ben studiata gestione delle priorità degli int.

Io invece sostenevo che usare solo interrupt porta a un gran casino, e che una gestione sensata del loop fosse piú funzionale.

Se mi dici bene come sostenere la tesi contro il "tutto fuori", torno a litigarci di corsa!
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 134
Posts: 9698
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Lui insisteva su una programmazione simil Windows, ovvero programmazione attivata da eventi

Non è possibile fare paragoni tra un programma scritto per Windows tramite un compilatore ad oggetti, con relativo supporto, e un programma scritto per una mcu 8 bit, sono due cose totalmente diverse come approccio, funzionamento e stile di scrittura.
Il software event driven per Windows si basa sopratutto sugli interrupt software, che sono decisamente diversi da quelli hardware, anche perché il kernel di windows non consente di accedere direttamente all'hardware, poi ci sono i timer che permettono di far partire ogni tot ms (con largo margine di errore) un certo processo, inoltre anche rimanendo sul C++ per Windows non esiste proprio la main(), almeno in apparenza, in realtà c'è anche se non la vedi, più o meno come fa la loop() di Arduino.

Quote
Io invece sostenevo che usare solo interrupt porta a un gran casino, e che una gestione sensata del loop fosse piú funzionale.

L'approccio corretto, parlando di C, è avere un main loop, non importa se si chiama main() o loop(), dentro il quale gestisci il tutto in base ad una serie di flag e/o temporizzazioni.
Un buon modo di gestire il tutto è usare un timer come clock di sistema che ogni tot us, normalmente va bene una volta ogni ms (come fa la millis ) attiva la sua isr al cui interno vengono incrementate delle variabili che sono l'orologio di vari eventi, se ne usa più di una perché spesso fa comodo azzerarle ad ogni ciclo in modo da poter usare variabili al massimo di tipo int e non avere mai problemi di overflow.
Nella main/loop hai una cascata di if, o delle switch, che controllano i flag delle azioni, questi vengono settati all'interno delle isr o come risultanza di operazioni eseguite, in base ai quali vengono chiamate specifiche funzioni, idem con i timer che attivano ad intervalli regolari determinati processi.
Poi ci sarebbero da fare delle considerazioni sulle precedenze di alcuni processi su altri, sopratutto se è richiesto un preciso intervallo temporale di esecuzione con un jitter minimo, però qui stiamo entrando nel campo degli RTOS che è un discorso molto complesso, se serve realmente è meglio usarne uno già fatto e sicuramente funzionante.
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 134
Posts: 9698
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ho giusto litigato la settimana scorsa con un Ingegnere che sosteneva quanto ho detto.

Dimenticavo, ingegnere in cosa e che esperienza ha sulla programmazione di micro/mcu ?
Logged

Offline Offline
Edison Member
*
Karma: 40
Posts: 1964
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Purtroppo il personaggio è sopra le righe, è stato allievo di un certo Dott. Zener (!) alla Westinghouse e si occupa di robotica industriale (sistemi di azionamento motori brushless bracci robot). Uno di quelli che conosce a memoria ogni bit di Canbus, Modbus, Profibus ecc.
Non è uno di quei ingegneri da 1000 lire al kilo, quindi quando parla ha il suo fascino e ci litigo solo perchè è un caro amico.

Ma se ho modo ci litigo volentieri! smiley-grin
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 134
Posts: 9698
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma se ho modo ci litigo volentieri! smiley-grin

Dato che nemmeno io sono da 1000 lire al kg se vuoi ci litigo io per te  smiley-mr-green
Però non mi hai ancora detto in cosa è ingegnere, il fatto che si occupa di azionamenti non significa che li progetta lui, anzi è facile che utilizza sistemi che ho progettato io  smiley-grin smiley-mr-green smiley-grin
Logged

Genova
Offline Offline
Faraday Member
**
Karma: 40
Posts: 3431
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh perbacco qui la discussione si fa a .... "chi ce l'ha più lungo"  smiley-grin smiley-mr-green smiley-grin smiley-mr-green
Logged

no comment

Pages: [1] 2   Go Up
Jump to: