Go Down

Topic: calcolo velocità con encoder ottico (Read 10977 times) previous topic - next topic

PaoloP

Si, l'uscita dell'encoder è differenziale, da quanto ho capito.
E' per quello che ho detto che potresti utilizzarlo ugualmente usando solo i segnali positivi (quelli senza il trattino sopra).
Però la gestione è molto critica perché con 500 impulsi a giro non hai tempo di fare altro se non contarli e a volte neanche quello.

Se il motore gira a 500 rpm, avrai 500*500*60 = 15'000'000 impulsi al secondo, ovvero uno ogni 0,06 microsecondi. Quindi Arduino, neanche con la funzione micros li conta.

francescoprisco

#16
Jul 30, 2013, 12:31 pm Last Edit: Jul 30, 2013, 01:22 pm by francescoprisco Reason: 1
io ho un motore che gira molto lento...oltre all'utilizzo di un encoder non ho trovato soluzione...ho visto in giro gente che usa gli encoder del mouse per calcolare gli rpm... come funziona con quelli?

tipo questo http://www.youtube.com/watch?v=KPv-s-e4HAA


edit:

Allora io ho una puleggia grande che gira molto lenta.Se collego vicino alla puleggia grande una puleggia molto + piccola con nelle prossimità del centro dei fori in modo circolare a ugual distanza e metterei su due sensori IR e utilizzerei questo codice
Code: [Select]

// read RPM

int rpmcount = 0;
int rpm = 0;
unsigned long lastmillis = 0;

void setup(){
Serial.begin(9600);
attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin two(2).
}

void loop(){

if (millis() - lastmillis == 1000){  //Uptade every one second, this will be equal to reading frecuency (Hz).

detachInterrupt(0);    //Disable interrupt when calculating


rpm = rpmcount * 60;  // Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.

Serial.print("RPM =\t"); //print the word "RPM" and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word "Hz".
Serial.println(rpmcount); //print revolutions per second or Hz. And print new line or enter.

rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Uptade lasmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
  }
}


void rpm_fan(){ // this code will be executed every time the interrupt 0 (pin2) gets low.
  rpmcount++;
}

poi faccio una proporzione tra la circonferenza di una puleggia e dell 'altra e gli rpm
in modo da trovarmi gli rpm del tipo  circA:rpmA=circB:rpmB    rpmA=(circA*rpmB)/circB e quindi mi trovo gli rpm della puleggia grande e poi da li mi trovo i m/s o i m/m o i cm/m a seconda di quello che mi serve. potrebbe funzionare?

francescoprisco

ecco la soluzione che avevo visto utilizzando un mouse https://docs.google.com/document/d/1TJYlWxdQgsCGO3YwdHaAeQjpceeQ9hpVJstuHzR1bWs/edit?pli=1

astrobeed


Se il motore gira a 500 rpm, avrai 500*500*60 = 15'000'000 impulsi al secondo,


Il calcolo corretto è 500  * 500/60 = 4166 impulsi al secondo.
Scientia potentia est

astrobeed


io ho un motore che gira molto lento...oltre all'utilizzo di un encoder non ho trovato soluzione..


Il tuo encoder ha i due canali su bus RS422, ovvero una linea differenziale e questo è il motivo per cui hai due fili per ogni canale, per collegarlo ad Arduino puoi usare due SN75176, o MAX485, in modo da trasformare le linee differenziali in segnali TTL, il vantaggio dui avere i canali su bus di questo tipo è che permette di usare cavi molto lunghi, anche 20 metri, per collegare l'encoder al circuito.
Per calcolare la velocità di rotazione non devi fare altro che misurare il tempo tra due scatti dell'encoder, va bene farlo sia sul fronte di salita che di discesa a piacere, e moltiplicarlo per 500 (risoluzione encoder), in questo modo ottieni il tempo per una rivoluzione completa, ne fai il reciproco e hai la frequenza di rotazione che moltiplicata per 60 ti da gli rpm.
Esempio pratico, ipotizziamo che il tempo tra due scatti dell'encoder è 2 ms pertanto il tempo per una rotazione è 2*500 = 1000 ms = 1s, 60 * 1/1s -> 60/1 = 60 rpm.
Scientia potentia est

PaoloP

#20
Jul 30, 2013, 05:49 pm Last Edit: Jul 30, 2013, 05:54 pm by PaoloP Reason: 1


Se il motore gira a 500 rpm, avrai 500*500*60 = 15'000'000 impulsi al secondo,

Il calcolo corretto è 500  * 500/60 = 4166 impulsi al secondo.


Sto andando a comprare il cilicio.  :smiley-sweat:

Comunque dopo pagine e pagine, topic su topic, non ho ancora capito di che motore si tratta, se ti serve visualizzare la velocità di rotazione del motore o la velocità lineare di un traslatore, se l'encoder lo vorresti acquistare o lo hai già, ma soprattutto se questo motore è già in funzione anche senza tutti questi controlli o lo stai progettando.  :~

francescoprisco

#21
Jul 30, 2013, 06:44 pm Last Edit: Jul 30, 2013, 06:46 pm by francescoprisco Reason: 1
PaoloP il motore è di una manovia che trasposta carrelli attraverso le varie fasi di produzione. Il sistema già è tutto in funzione ma mi serviva comandare appunto il motore tramite internet. Il sistema c'è, accende il motore spegne il motore ne aumenta la velocità e la diminuisce. mi occorre vedere la velocità del motore per sapere appunto di quanto aumentare o di quanto diminuire.L'encoder già lo tengo.Il sistema è fatto da un motore che gira sempre fisso alla stessa velocità con un riduttore con frizione che gestisce la velocità della puleggia che fa muovere tutto.Il tutto va ad esempio a 1 metro al minuto. La velocità mi servirebbe lineare ma se è più facile in rpm fa lo stesso.Sono mesi che non riesco a trovare una cavolo di soluzione.

icio

Il limk da cui hai preso spunto
http://www.alpha.triggerdog.com/blog/?p=17
mostra un' applicazione SIMILE ad un encoder , ma non è un encoder , gli serve solo per misurare gli RPM per un tornio e non la posizione del mandrino, infatti non usa il canale B che non c'è neppure , anche se l'ha dichiarato non usa nemmeno il canale A , usa solo lo Z che manda fuori 1 solo impulso al secondo,  come vedi la durata dell'impulso Z è molto lungo prendendo 90 gradi sulla rotazione,

tornando al tuo encoder puoi usare o il canale A (o B è indifferente )  oppure il canale Z,  se usi il canale A avrai grande precisione sul numero di giri usando un frequenzimentro,  invece se usi il canal Z avrai bassa precisione con un frequenzimetro , per avere alta precisione con il canale Z deve usare un periodometro

mettendo che tu voglia usare il canale A per fare un frequenzimetro è molto semplice, aprire un gate software che dura 1 secondo e contare tutti gli impulsi che arrivano nel tempo di gate in una variabile a 16bit o 32 bit uint32_t , puoi farlo semplicemente con la tecnica del polling senza usare un interrupt esterno sul canale A.
alla fine del secondo  calcoli gli rpm:   (numero_impulsi_contati  x 60)  / 500 .

riazzerri in contatore , riapri il gate per 1 secondo e ripeti

icio

L'applicazione del signore:  http://www.alpha.triggerdog.com/blog/?p=17   dice "build a encoder...." ma non è corrette , è invece "build a tachometer and  RPM meter"

invece la tua applicazione è "build a RPM meter using a encoder"

icio

mi sono dimenticato:

alla fine del gate di un secondo  calcoli gli rpm:   (numero_impulsi_contati  x 60)  / 500 .

visualizzi sull lcd

riazzerri in contatore , riapri il gate per 1 secondo e ripeti

icio

ti metto un codice che avevo fatto per un altro MC:
c'è un interrupt periodico da 16384usec generato da un timer in free running
ogni 61 interrupt fà un secondo ma io gli faccio raggiungere 63 interruzioni così 2 interruzioni (32msec) servono per il rinfresco del lcd
nel main si fà il conteggio per polling il calcolo e la visualizzazione

Code: [Select]

unsigned short tik, gate;
unsigned int Countgiri, Ngiri;  //int=16bit long=32bits

//-------------interrupt----------------------------------------------------------------------------------
void interrupt() {  // Interrupt  viene da TIMER0
//-----------rtc-----------------------------
   tik++;             //ogni 16,384 msec
   if (tik == 63) {   //61 tik =1 secondo    2 tik per il display
      tik=0;
      gate=0;
   }
   if (tik == 2) {
      gate=1;
   }
  INTCON.f2  = 0;  //cancella flag  timer0
} //fine interrupt

//----------------- Main procedure-----------------------
void main() {

        Init_Main();    // perform initialization
        scrivi_logo();  // scrivi logo su lcd
 
    while (1) {
   
        while (gate==0) {}         //aspetta gate
        while (gate==1) {          //ra4=pulsante coin rb5=in_coin
           if (!portb.f5) {        //fronte negativo
              Countgiri++;
           while (!portb.f5) {}    //aspetta fronte positivo
           }
        }
        Ngiri = (Countgiri * 60)  / 500;
        Countgiri=0;
        WordToStr(Ngiri, tnum6);
        LCD_Out(2,3,tnum6);       //visualizza valore giri su lcd

    }   //fine while
  }  //fine main



Go Up