Forum: Mikrocontroller und Digitale Elektronik C167 Drehzahlmessung mit Timer 3


von Ciek S. (cierish)


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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ein Mikrocontroller-Programm hört niemals auf.
1
void main () {
2
3
  DP2 = 0xffff; 
4
  P2  = 0;
5
  T3CON =  0x0249;      // load timer 3 control register
6
  T3    =  0x0000;      // reset timer 3 register
7
  while (1) { // endlose Schleife
8
    while(lauf)
9
      ;
10
    T3R = 1;
11
    while(lauf) 
12
      P2 = T3;
13
    T3R = 0;
14
15
    set_cursor(20,5);
16
    printf("Counter = %4u", P2);
17
  }
18
}

> 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(); ).

von Ciek S. (cierish)


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

von Ciek S. (cierish)


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?
1
WORD T3IMAGE; 
2
3
void main(){ 
4
5
   T3CON = 0x0401; 
6
   T3    = 0; 
7
   T3IE  = 1; 
8
   T3IC  = 0x61; 
9
   T2CON = 0x000D; 
10
   T2    = 0; 
11
   T2IC  = 0x44; 
12
   T2R   = T3R =1; 
13
   IEN   = 1; 
14
15
   while(1){ 
16
17
      T3IMAGE = T2; 
18
      set_cursor(20,5); 
19
      printf("Counter = %5u", T2); 
20
   }
21
22
   T3IE = 0;
23
   IEN = 0;
24
   T3R = 0;
25
   T2R = 0; 
26
}

Vielen Dank.

MfG,
Ciek

von TManiac (Gast)


Lesenswert?

Hallo Ciek,

Du setzt
1
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.

von Ciek S. (cierish)


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?
1
void main(){ 
2
3
   T3CON = 0x0401;  // 0 010|0 0 0|001 T3OTL=1 Teiler 8*2=16
4
   T2CON = 0x000D;  // 0 0 0 1|101 Counter, steigende Flanke von T30TL
5
   T2IC = 0x44;    // T2IE=1 ILVL=1 GLVL=0
6
   T3 = 0;
7
   T2 = 0;
8
   T3R=1;
9
   IEN=1;
10
11
   while(1) {
12
13
        set_cursor(13,5);
14
        printf("Counter = %5u", T3);
15
        set_cursor(14,5);
16
        printf("Counter = %5u", T2);
17
   }
18
}

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

von TManiac (Gast)


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.

von Ciek S. (cierish)


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

von Ciek S. (cierish)


Lesenswert?

Hallo,
1
WORD T3IMAGE;
2
3
void T2_INT (void) interrupt 0x22 {
4
5
   T3IMAGE=T2;
6
   T3 = 0;
7
}
8
9
void main () {
10
11
   T3CON = 0x0001;   // 0 0 0 0|001 Teiler 8*2=16
12
   T2CON = 0x002F;   // 00|10 1|111 Capture Mode, beide Flanke von T30TL
13
   T2IC = 0x44;      // T2IE=1 ILVL=1 GLVL=0
14
15
   T3 = 0;
16
   T2 = 0;
17
   T3R=1;
18
   IEN=1;
19
20
   while(1) {
21
22
      set_cursor(13,5);
23
      printf("Counter = %5u", T3);
24
      set_cursor(14,5);
25
      printf("Counter = %16u", T3IMAGE);
26
   }
27
}

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

von TManiac (Gast)


Lesenswert?

Hallo Ciek,

Da muss ich nun deinen Sourcecode etwas trennen:
1
WORD T3IMAGE;
2
3
void T2_INT (void) interrupt 0x22 {
4
5
   T3IMAGE=T2;
6
   T3 = 0;
7
}

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.
1
void main () {
2
3
   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.
1
   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.
1
   T2IC = 0x44;      // T2IE=1 ILVL=1 GLVL=0
2
3
   T3 = 0;
4
   T2 = 0;
5
   T3R=1;
6
   IEN=1;
7
8
   while(1) {
9
10
      set_cursor(13,5);
11
      printf("Counter = %5u", T3);
12
      set_cursor(14,5);
13
      printf("Counter = %16u", T3IMAGE);
14
   }
15
}

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

von Ciek S. (cierish)


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

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.