Go Down

Topic: Encoder quadratura e calcolo rpm (Read 830 times) previous topic - next topic

Augusto Picciani

Ciao, ho bisogno di un consiglio su come ottenere i giri di un motoriduttore 12Volt dotato di un encoder Hall a 64 CPR (http://arduino.cc/forum/index.php?PHPSESSID=9ce889364b858aa71b53f24042e5cf26&topic=36204.45).
Il motore ha una velocitá massima di 80 giri minuto con un rapporto di riduzione di 131:1.
Ho cercato di visualizzare gli rpm con questo codice:

Code: [Select]

byte pwm=255;
volatile int rpmcount;
unsigned int rpm;
unsigned long timeold;
float tempFloat = 0.0;
#define SHAFT_ENCODER_PPR 64.0
void setup() {
  //MOTORE DESTRO 
  Serial.begin(115200);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
digitalWrite(3,HIGH);
//attachInterrupt(0, rpm_fun, HIGH);
   rpmcount = 0;
   rpm = 0;
   timeold = 0;

avanti(pwm);      //chiama procedura avanti

}

void avanti(byte pwm) {
digitalWrite(4, HIGH); 
analogWrite(3, (255-pwm)); 

}

void indietro(byte pwm) {
digitalWrite(4, LOW);
analogWrite(3, pwm);   

}

void fermo() {            //ferma i motori
digitalWrite(4, LOW);   
digitalWrite(3, LOW);   



void loop() 
{

//Update RPM every second
   delay(1000);
   detachInterrupt(0);
 
   tempFloat = (rpmcount / SHAFT_ENCODER_PPR) * 600.0;
   rpmcount = 0;
   Serial.println(tempFloat,DEC);


   //Restart the interrupt processing
   attachInterrupt(0, rpm_fun, RISING);

}

void rpm_fun()
{
   rpmcount++;

}




Non sono sicuro, peró, se il numero di giri ottenuti sono quelli giusti, anche perché se divido poi per 131 non ottengo nulla che si avvicini ad 80. Potreste dirmi se sbaglio qualcosa e consigliarmi una formula adatta allo scopo?

Grazie

Augusto Picciani

ragazzi non c'é nessuno che mi aiuta?

Janos

E' difficile aiutarti, io l'avrei fatto in tutt'altro modo... Provo a darti delle dritte, poi vedi te...
Partiamo per step: togli il delay nel loop (lo dovrebbero togliere dalle funzioni di Arduino) e sostituiscilo con millis(), altrimenti prova a usare leOS o looper:

http://www.leonardomiliani.com/2012/leos-un-semplice-so-per-arduino/
http://www.leonardomiliani.com/2012/looper-uno-schedulatore-software-per-arduino/

Secondo: l'encoder non ti da un'informazione diretta sulla velocità ma sulla posizione, anzi, sugli spostamenti essendo un encoder incrementale. Intanto concentrati sul riuscire a leggere gli spostamenti dell'encoder, intesi come posizione, poi ogni tot tempo vai a vedere quandi impulsi sono passati e con una divisione trovi gli impulsi/sec.

Terzo: san google.....  ;)

http://playground.arduino.cc/Main/RotaryEncoders
http://www.mauroalfieri.it/elettronica/arduino-rotary-encoder.html

leo72


altrimenti prova a usare leOS o looper:

Guarda che non ti pago per la pubblicità, eh  ;)

Janos


uwefed


ragazzi non c'é nessuno che mi aiuta?

La mia proposta l' hai Tu stesso linkata. Cosa vuoi ancora?
Poi non fare fretta. Pensi ce tutti noi non hanno nient'altro da fare che aspettare a risponderti? C'é gente che di notte dorme, poi va al lavoro e ritorna la sera a casa per forse avere il tempo di mettersi al PC.

Ciao Uwe


Augusto Picciani

Grazie intanto per le risposte.

Questo é il mio codice modificato:
Code: [Select]

#define encoder0PinA  2
#define encoder0PinB  5
#define pinmotorPWM 3
#define pinmotor 4

volatile unsigned int encoder0Pos = 0;
byte pwm=255;
unsigned long timecamp;
unsigned long currentTime;
unsigned long timeold;
float rpm;
//float spost;
void setup() {
  Serial.begin (115200);


  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);       // turn on pullup resistor
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinB, HIGH);       // turn on pullup resistor

  attachInterrupt(0, doEncoder, RISING);  // encoder pin on interrupt 0 - pin 2
  Serial.println("start");                // a personal quirk
  timecamp=1000;
  rpm=0.0;
  spost=0.0;
}
void avanti() {
digitalWrite(4, HIGH); 
analogWrite(3, (255-pwm)); 

}
void indietro() {
      digitalWrite(4, LOW);
analogWrite(3,pwm);   
}

void ferma() {            //ferma i motori
digitalWrite(pinmotor, LOW);   
digitalWrite(pinmotorPWM, LOW);
 


void loop(){

currentTime=millis();

if(currentTime-timecamp > 1000){
  rpm=((encoder0Pos/16)/131.25)*60;
  encoder0Pos=0;
  Serial.println(rpm);
  timecamp=millis();

  }
}

void doEncoder() {
 
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
    encoder0Pos++;
  } else {
    encoder0Pos--;
  }


}


Ora riesco a vedere i giri/min e dividendo per il rapporto di riduzione ottengo i giri esatti.

L'altra domanda cruciale che vorrei porvi é come calcolare la distanza percorsa ad ogni giro (o anche meno di un giro) del motore. Ho pensato di usare la velocitá tangenziale: V=W x r dove ottengo lo spostamento in metri al secondo (o mm al secondo) attraverso il prodotto della velocitá angolare e del raggio della ruota.

Secondo voi sarebbe una buona soluzione? Avete delle alternative?
Grazie 

Go Up