calcolo velocità con encoder ottico

Il codice lo puoi prendere qui --> Arduino Playground - RotaryEncoders
Anzi, leggi tutta la pagina, ha decine di esempi per tutte le situazioni possibili.
Il tuo encoder ha 2 segnali più lo zero, mi pare di aver capito. controlla tra gli esempi, dovrebbe esserci qualcosa che fa al caso tuo.

Dallo sito del produttore ho visto che ci sono delle istruzioni --> http://www.tekel.it/PDF/Manuali/MU_EI_ITA_A3_R2.PDF
e delle spiegazioni interessanti --> TEKEL Instruments s.r.l. web site

Anche questo --> http://www.tekel.it/PDF/Appendice%20incrementali.pdf

non ho trovato nulla a riguardo il calcolo di rpm o velocità. già ho letto quella pagina

Quante connessioni ha in uscita l'encoder?

Per ottenere la velocità devi calcolare il numero di impulsi nell'intervallo di tempo oppure il tempo tra due impulsi.
Ma prima occorre, in base al modello dell'encoder, ottenere l'impulso.

Millis è troppo grande come unità di tempo, devi usare micros().
Con 500 impulsi al giro, bastano 2 giri al secondo, ovvero 120 al minuti che la millis non riesce più a calcolare il tempo.

allora in uscita io ho 6 fili... 2 out A 2 out B e 2 out z due fili per l'alimentazione e poi la schermatura del cavo

Allora in base al codice di ordinazione, siccome hai un "Line Driver" devi usare un integrato che fa da interfaccia tra l'encoder e l'arduino.
L'integrato è il 26LS32 (http://www.ti.com/lit/ds/symlink/am26ls32a.pdf) che dispone di 4 ingressi, tu ne userai tre.
Inoltre ti serviranno resistenze da 4.7K, condensatori da 10nF e impedenze da 150Ohm, secondo lo schema pubblicato qui, ultimo in basso a destra --> http://www.tekel.it/PDF/Appendice%20incrementali.pdf

Forse puoi utilizzare solo una delle 2 uscite per canale senza tutto l'ambaradan qui sopra. Ma non credo.

perchè ne userò tre? due di entrata a cui collegara i 6 fili e uno d'uscita?

Quell'integrato ha 4 coppie di ingressi, mentre il tuo encoder ha 3 coppie in uscita. Intendevo questo.
Dalle 3 coppie in ingresso al 26LS32 otterrai in uscita 3 singoli segnali ripuliti di eventuali disturbi.

quindi questo integrato serve solo a ripulire il segnale? serve un segnale sull'enable? l'altro schema a cosa serve in particolare? è possibile collegare direttamente l'encoder e l'arduino?

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 50050060 = 15'000'000 impulsi al secondo, ovvero uno ogni 0,06 microsecondi. Quindi Arduino, neanche con la funzione micros li conta.

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 ARDUINOtachometer.AVI - YouTube

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

// 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?

ecco la soluzione che avevo visto utilizzando un mouse Reading ps2 mouse output with an arduino Final - Google Docs

PaoloP:
Se il motore gira a 500 rpm, avrai 50050060 = 15'000'000 impulsi al secondo,

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

francescoprisco:
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.

astrobeed:

PaoloP:
Se il motore gira a 500 rpm, avrai 50050060 = 15'000'000 impulsi al secondo,

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

Sto andando a comprare il cilicio. :sweat_smile:

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. :~

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.

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

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"

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

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

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