mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik C167 Drehzahlmessung mit Timer 3


Autor: Ciek S. (cierish)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte die Drehzahl von einem Förderband mit Hilfe einem
Optoelektronischen Sensor (Schaltfreq = 500 HZ, Ansprechzeit = 1ms)
messen.
Der Sensor ist mit dem Mikrocontroller c167 verbunden.

Erstmal möchte die Zahl der steigenden Flanke in einer bestimmten Zeit
zählen und danach die Drehzahl berechnen.
Wie funktioniert es?

sbit lauf  = P3^6;

void main () {

DP2 = 0xffff;
P2  = 0;
T3CON          =  0x0249;      // load timer 3 control register
T3             =  0x0000;      // load timer 3 register

while(lauf){
   P2 = T3;
}

T3R = 0;
set_cursor(20,5);
printf("Counter = %4u", P2);

//Wie kann ich die Zahl vonm Zähöer auf Terminal ausgeben?
}


Vielen Dank.

MfG,
Ciek

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Mikrocontroller-Programm hört niemals auf.
void main () {

  DP2 = 0xffff; 
  P2  = 0;
  T3CON =  0x0249;      // load timer 3 control register
  T3    =  0x0000;      // reset timer 3 register
  while (1) { // endlose Schleife
    while(lauf)
      ;
    T3R = 1;
    while(lauf) 
      P2 = T3;
    T3R = 0;

    set_cursor(20,5);
    printf("Counter = %4u", P2);
  }
}

> Wie kann ich die Zahl vonm Zähöer auf Terminal ausgeben?
Lies nach, wie du printf() auf die serielle Schnittstelle umbiegen 
kannst. Üblicherweise geht das über putchar();
Allerdings habe ich den Verdacht, du steuerst mit dieser Funktion schon 
ein Display an ( wegen set_cursor(); ).

Autor: Ciek S. (cierish)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller wrote:
> Ein Mikrocontroller-Programm hört niemals auf.
Sorry, ich habe nur ein Teil geschnitten.

Welche ist besser, nur ein Timer zählt, wieviele steigende Flanke gibt,
oder mit 2 Timer, ein anderer Timer als Counter.
Ich meinte T3 funktioniert als Timer, und T4(od. T2) funktioniert als 
Counter und zählt die Flanke (Bit T3OTL als Zähltakt).

Vielen Dank.

MfG,
Ciek

Autor: Ciek S. (cierish)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe das Programm folgendes geändert, aber die Zahl erhöht sich 
immer, obwohl ich das Band noch nicht laufend lasse. Was mache ich 
falsch?
WORD T3IMAGE; 

void main(){ 

   T3CON = 0x0401; 
   T3    = 0; 
   T3IE  = 1; 
   T3IC  = 0x61; 
   T2CON = 0x000D; 
   T2    = 0; 
   T2IC  = 0x44; 
   T2R   = T3R =1; 
   IEN   = 1; 

   while(1){ 

      T3IMAGE = T2; 
      set_cursor(20,5); 
      printf("Counter = %5u", T2); 
   }

   T3IE = 0;
   IEN = 0;
   T3R = 0;
   T2R = 0; 
}

Vielen Dank.

MfG,
Ciek

Autor: TManiac (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ciek,

Du setzt
T2CON = 0x000D; 

0x000D ist in binär 00001101 (die letzten acht bit)

Ich gehe mal davon aus du hast irgendwo T2CON auf das GPT12E_T2CON 
Register gemappt.

Aber:
Im Manual steht auch die letzten drei Bit sind T2I (Timer Tx Input 
Parameter Selection).
Und im Countermode steht das für: "1XX Reserved. Do not use this 
combination"

kann dein Fehler daher kommen.

Autor: Ciek S. (cierish)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Danke für die Antwort.
T2CON = 0x000D bedeutet:
Timer T2 funktioniert als Ereigniszähler (T2M = 001)
T2 wird inkrementiert, wenn steigende Flanke von T3OTL auftauchen (T2I =
101)
Es ist richtig so oder?
void main(){ 

   T3CON = 0x0401;  // 0 010|0 0 0|001 T3OTL=1 Teiler 8*2=16
   T2CON = 0x000D;  // 0 0 0 1|101 Counter, steigende Flanke von T30TL
   T2IC = 0x44;    // T2IE=1 ILVL=1 GLVL=0
   T3 = 0;
   T2 = 0;
   T3R=1;
   IEN=1;

   while(1) {

        set_cursor(13,5);
        printf("Counter = %5u", T3);
        set_cursor(14,5);
        printf("Counter = %5u", T2);
   }
}
 

Im Terminal sehe ich jetzt, dass T3 von 65536 bis 0 dekrementiert wird.
Wenn ich T2 starte (durch einen Tastendruck im Steuerungsrechner,
T2R=1),
wird der Wert von T2 immer gestiegen.

Wie kann man eigentlich genau mit dem Counter in 65536 Takt zählen?

Vielen Dank für die Hilfe.

MfG,
Ciek

Autor: TManiac (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh mir ist gerade aufgefallen, dass ich beim letzten mal das falsche 
Derivat zugrunde gelegt hatte (habe beim XC167 geschaut). Dann ist mein 
zu letzt gegebener Hinweis natürlich Quatsch gewesen.

Ich verstehe nun aber noch weniger was du vorhast. Durch deine 
Einstellung, dass T2 incrementiert wenn das T3OTL toggelt, hast du dir 
einen schönen 32bit großen Timer gebaut. Mit dem Format T2.T3 Ist auch 
prima im Kapitel "Timer Concatenation" im C167 UM beschrieben.

Was willst du genau ermitteln? Die Drehzahl?
Wenn du weißt wieviele Zähne deine Sensorscheibe hat, brauchst du die 
nicht zählen. Also benötigst du keinen Counter. Es sei denn du willst 
wissen, wie weit sich das Rad/Band gedreht hat.

Zur Drehzahlermittlung benötigst du ein Capture-Interrupt. Das kannst du 
beim C167 entweder über die GPT oder über die CapCom machen.
Die Zeit wird je nach Konfiguration automatisch gespeichert. Du brauchst 
dann nur noch in der Interruptroutine den Zähler zurück setzen oder 
jedesmal die Differenz ausrechnen (Überlauf beachten).

Wenn du T2 als richtigen Zähler benutzen willst, musst du als input die 
T2IN auswählen, mit der gewünschten Flanke (T2I = 001, 010 oder 011). 
Den Pin als Eingang schalten.

Autor: Ciek S. (cierish)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für die Antwort.
Ich habe auch den alten Thread gelesen und der Link, den Du gegeben 
hast, hilft mir auch.

Die Bandscheibe hat insgesamt 16 Zähne (8 schwarz und 8 weiß). Die 
weißen geben HIGH-Flanke aus, denke ich.
Über den Capture Interrupt muss ich noch mehr durchlesen.

Wird nur die Zeit automatisch gespeichert? Woher wissen wir, wenn das 
Rad schon einmal umdreht?

Ich werde nachdem Durchlesen nochmal versuchen zu programmieren.

Vielen Dank für die Hilfe.

MfG,
Ciek

Autor: Ciek S. (cierish)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
WORD T3IMAGE;

void T2_INT (void) interrupt 0x22 {

   T3IMAGE=T2;
   T3 = 0;
}

void main () {

   T3CON = 0x0001;   // 0 0 0 0|001 Teiler 8*2=16
   T2CON = 0x002F;   // 00|10 1|111 Capture Mode, beide Flanke von T30TL
   T2IC = 0x44;      // T2IE=1 ILVL=1 GLVL=0

   T3 = 0;
   T2 = 0;
   T3R=1;
   IEN=1;

   while(1) {

      set_cursor(13,5);
      printf("Counter = %5u", T3);
      set_cursor(14,5);
      printf("Counter = %16u", T3IMAGE);
   }
}


Der Timer T2 fängt die Zeit für beide Flanke von T3OTL ab.
Wenn die Scheibe hat insgesamt 16 Zähne, dann muss ich noch die 
berechnete Zeit mit 8 multiplizieren.
Habe ich richtig verstanden?

Vielen Dank.

MfG,
Ciek

Autor: TManiac (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ciek,

Da muss ich nun deinen Sourcecode etwas trennen:
WORD T3IMAGE;

void T2_INT (void) interrupt 0x22 {

   T3IMAGE=T2;
   T3 = 0;
}

sieht richtig aus. Hast du Keil oder Tasking? Leider unterscheiden die 
beiden sich im Syntax für die Interruptroutinen. Und da ich Tasking 
nutze, kann ich jetzt nicht mit Bestimmtheit sagen, dass es richtig ist. 
Ich denke aber du hast das schon irgend woher.
void main () {

   T3CON = 0x0001;   // 0 0 0 0|001 Teiler 8*2=16

Kann sein. Der Teiler hat aber nix mit der Anzahl deiner Zähne/Flanken 
oder so zu tun. Der bestimmt "nur" deine Auflösung, bzw maximale Dauer. 
Dein Timer läuft schon nach 52.5 ms (bei 20MHz cpu Takt) über. Besser 
für den Anfang ist eine längere Periode.
   T2CON = 0x002F;   // 00|10 1|111 Capture Mode, beide Flanke von T30TL
Zitat aus dem Manual:
The two least significant bits of bit field TxI are used to select the 
active transition (see Table 10-8), while the most significant bit TxI.2 
is irrelevant for capture mode. It is recommended to keep this bit 
cleared (TxI.2 = ‘0’).

also solltest du T2CON = 0x002B setzen.
Das Capture wird nicht durch T3OTL, sondern durch eine Flanke am 
T2IN-Pin ausgelöst. Und daran musst du dann deinen Geber vom Band/Rad 
anschließen.
   T2IC = 0x44;      // T2IE=1 ILVL=1 GLVL=0

   T3 = 0;
   T2 = 0;
   T3R=1;
   IEN=1;

   while(1) {

      set_cursor(13,5);
      printf("Counter = %5u", T3);
      set_cursor(14,5);
      printf("Counter = %16u", T3IMAGE);
   }
}

Der Rest passt. Sei dir aber bewusst dass deine Ausgabe von T3 asynchron 
ist, dh du wirst nicht jeden Wert ausgeben und wenn der Timer sehr 
schnell läuft, sieht es so aus als würde der Timer abwärts zählen obwohl 
er aufwärts zählt.

>Wenn die Scheibe hat insgesamt 16 Zähne, dann muss ich noch die
>berechnete Zeit mit 8 multiplizieren.

Deine Scheibe hat 16 Zähne (16 schwarze und 16 weiße Felder?) mit je 
zwei Flanken, das sind dann also 32 Interrupts pro Umdrehung. Wenn du 
die Umdrehungszeit pro Umdrehung ausrechnen möchtest, musst du also mal 
32 rechnen. Wenn du aber Umdrehung pro Minute oder so Ausrechnen willst, 
wird es etwas komplizierter (zu beschreiben).
An deinem Beispiel mit T3I = 001 entspricht ein "Zeitabschnitt" gleich 
0,8us (bei 20MHz CPU Takt). Daher entspricht eine Sekunde gleich 
1,25x10^6 (1250000) Einheiten. Also würde man die Umdrehung pro Sekunde 
wie folgt ausrechnen:
n = 1250000 / (T3IMAGE x 32)
Bzw einwenig optimieren.

Gruß TManiac

Autor: Ciek S. (cierish)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

> sieht richtig aus. Hast du Keil oder Tasking?
ich nutze Keil Software, also uVision2.

> Besser für den Anfang ist eine längere Periode.
Alles klar, jetzt setze ich T3I=110.

> Der Rest passt. Sei dir aber bewusst dass deine Ausgabe von T3 asynchron
> ist, dh du wirst nicht jeden Wert ausgeben und wenn der Timer sehr
> schnell läuft, sieht es so aus als würde der Timer abwärts zählen obwohl
> er aufwärts zählt.
Ich würde später, die Drehzahl immer ausgeben, sobald die 
Geschwindigkeit des Bands geändert wurde. Es könnte funktionieren oder?

> Deine Scheibe hat 16 Zähne (16 schwarze und 16 weiße Felder?) mit je
> zwei Flanken, das sind dann also 32 Interrupts pro Umdrehung.
Sie hat insgesamt 16 Felder(Zähne?), 8 schwarze und 8 weiße.

Was ich nicht ganz verstehe, die Capture Mode fängt den Wert von T3 ab, 
sobald beide Flanke auftreten. Der Wert ist zwischen 0-65535 (16 Bit).
Dieser Wert wird immer unterschiedlich sein, obwohl das Band mit einer 
gleichen Geschwindigkeit läuft.

Vielen Dank.

MfG,
Ciek

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.