Forum: Mikrocontroller und Digitale Elektronik Drehzahlmessung mit mikroC


von Remo (Gast)


Lesenswert?

Hallo Programmierer

Habe mir das Board easyPIC 5 gekauft, programmiere in mikroC und komme 
einigermassen zurecht damit.
Nun habe ich auch schon meine erste Aufgabe.
Ich möchte gerne über einen Hallsensor die Drehzahl Messen
(60 bis ca. 6000 U/min).
Pro Umdrehung habe ich einen Impuls vom Hallsensor am eingang RB0.

Nun mein Gedanke: Ich messe die Zeit zwichen den Impulsen des 
Hallsensors und rechne daraus die Drehzahl. Ich lasse den TMR0 1:2 
laufen und zähle die Überläufe.
Anhand der Überläufe und des aktuellen TMR0-Standes sollte man nun die 
Drehzahl rechnen können oder?

a = Überläufe
b = TMR0
c = Vorteiler (2)
d = 4*(1/(1000*Clock_Khz))

Die Formel:

1/ (((256 * a)+b)*c*d)

Nun mein Problem ich kenne mich in rechnen mit PIC's noch nicht aus.
Die Variabeln werden bestimmt komastellen haben.
Was muss ich da für Datentypen nehmen?
Am schluss möchte ich die Drehzahl an einer 4-Stelligen 7-Segmentanzeige 
darstellen (als gerundete Ganzzahl).

Oder gibt es da vielleicht ein ganz anderer Grundsatz?

freundliche Grüsse

Remo Hug

von Martin (Gast)


Lesenswert?

Stelle deine Formel so auf, das du ohne Kommastellen auskommst. Wenn man 
es vermeiden kann, verwendet man keine Fließkommazahlen.

von Remo (Gast)


Lesenswert?

Hallo Martin

Jetzt hab ich ein Knopf.
Wenn ich eine division habe, kann es doch immer eine komastelle geben.

von Karl H. (kbuchegg)


Lesenswert?

Remo wrote:
> Hallo Martin
>
> Jetzt hab ich ein Knopf.
> Wenn ich eine division habe, kann es doch immer eine komastelle geben.

Du willst zb. Preise addieren.
Das kannst du so machen:  2 Euro 20  plus  3 Euro 70
oder anders geschrieben: 2.20 + 3.70
ergibt 5.90, also 5 Euro 90

Du kannst aber auch so rechnen:
2 Euro 20, das sind 220 Cent   plus
3 Euro 70, das sind 370 Cent

 220 + 370 = 590

also ist das Ergebnis 590 Cent. Das wiederrum sind 5 Euro 90

Während der Berechnung hast du keine Kommastellen gebraucht.
Erst ganz zum Schluss, wenn es darum geht, das Ergebnis zu
begutachten und anzuzeigen, wurde bei der Ausgabe hinter
die Hunderterstelle ein Komma eingeschmuggelt um dem Benutzer
die 590 als 5.90 zu präsentieren.

Mann kann Formeln auch so umstellen, dass die Divisionen zum
Schluss erfolgen. Dadurch verliert man praktisch nichts wenn
vorher alles als ganze Zahlen gerechnet wird.

von Michael K. (Gast)


Lesenswert?

Bei sprut gibts da auch was dazu :

http://www.sprut.de/electronic/pic/projekte/dehzahl/dreh.htm

Sehr zu empfehlen !!!

Grüße
Michael

von Remo Hug (Gast)


Lesenswert?

Hallo Michael

Kenne die seite vom Googeln her.
Da der Code aber in Assembler ist sagt mir das relativ wenig aus.

Noch eine Frage: Was steht in c, wenn ich Folgendes Rechne?

a=5
b=2
c (integer)

c= a/b

von Gast (Gast)


Lesenswert?

c = 2

von Remo Hug (Gast)


Lesenswert?

Hallo

Könnte mir mal vielleicht jemand mein Programm anschauen?
Funktioniert dass?
Habe ich da keine Probleme mit Interrupt zeiten oder so?

#include "Display_utils.h"

unsigned short portd_array[4];
unsigned int i, X_high, y_low ,cntUberlauf, cntFlanke, digit, number;
unsigned long TMR1, Frequenz;

// Unterprogramme

void initialisieren(){
     //OPTION_REG = 0b01000000;
     TRISA = 0x00;
     TRISC = 0x00;
     TRISB = 0xFF;
     TRISC = 0x00;
     TRISD = 0x00;
     INTCON = 0b11010000;
     PIE1 = 0b00000001;
     T1CON = 0b00000001;

     PORTA = 0x00;
     PORTC = 0x00;
     PORTD = 0x00;

     TMR1H  = 0;
     TMR1L  = 0;
     cntUberlauf = 0;
     cntFlanke = 0;
     digit = 0;
     number = 0;

     Frequenz = 1000*Clock_Khz();

     digit = number / 1000u ;             // extract thousands digit
     portd_array[3] = mask(digit);        // and store it to PORTD array
     digit = (number / 100u) % 10u;       // extract hundreds digit
     portd_array[2] = mask(digit);        // and store it to PORTD array
     digit = (number / 10u) % 10u;        // extract tens digit
     portd_array[1] = mask(digit);        // and store it to PORTD array
     digit = number % 10u;                // extract ones digit
     portd_array[0] = mask(digit);
     }

unsigned float Drehzahl(unsigned int Uberlauf, unsigned int TMR){

         float a;
         const long Max_Zaehlerstand = 65535;
         const int TMR_Vorteiler = 1;
         const int Pulse_pro_Umdrehung = 1;

         a = 0;
         a = (Uberlauf*Max_Zaehlerstand)*TMR_Vorteiler;
         a = a+TMR;
         a = a*Pulse_pro_Umdrehung;
         a = a*4;
         a = a/Frequenz;
         a = 60/a;

         return a;
}

void interrupt() {
     INTCON.GIE = 0;

      if (INTCON.INTF == 1){
        if (cntFlanke = 0){
           TMR1H = 0x00;
           TMR1L = 0x00;
           cntUberlauf = 0;
           }

        INTCON.INTF = 0;
        cntFlanke++;
        }

      if (PIR1.TMR1IF == 1){
        PIR1.TMR1IF = 0;
        cntUberlauf++;
        PORTC = ~PORTC;
        }

     INTCON.GIE = 1;
}

// Hauptprogramm

void main() {

  initialisieren();

  while(1) {

     i=0;

     while(i<200){

         if (i==0 & cntFlanke==0){
             INTCON.GIE = 0;

             X_high = 0xAB;
             y_low = 0xCC;

             TMR1 = (X_high<<8)+y_low;

             //TMR1 = (TMR1H<<8)+TMR1L;
             number= Drehzahl(cntUberlauf,TMR1);
             digit = number / 1000u ;             // extract thousands 
digit
             portd_array[3] = mask(digit);        // and store it to 
PORTD array
             digit = (number / 100u) % 10u;       // extract hundreds 
digit
             portd_array[2] = mask(digit);        // and store it to 
PORTD array
             digit = (number / 10u) % 10u;        // extract tens digit
             portd_array[1] = mask(digit);        // and store it to 
PORTD array
             digit = number % 10u;                // extract ones digit
             portd_array[0] = mask(digit);

             cntUberlauf = 0;
             cntFlanke = 0;

             INTCON.GIE = 1;
         }

         PORTD = portd_array[0];
         PORTA = 0x01;
         Delay_us(500);
         PORTA = 0x00;

         if (number >= 10){
            PORTD = portd_array[1];
            PORTA = 0x02;
            Delay_us(500);
            PORTA = 0x00;
            }

         if (number >= 100){
            PORTD = portd_array[2];
            PORTA = 0x04;
            Delay_us(500);
            PORTA = 0x00;
            }

         if (number >= 1000){
            PORTD = portd_array[3];
            PORTA = 0x08;
            Delay_us(500);
            PORTA = 0x00;
            }

         i++;
     }
  }
}


freundliche Grüsse

Remo Hug

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.