Forum: Compiler & IDEs Compare A Match setzt immer 0


von David Knochenhauer (Gast)


Lesenswert?

Hallo zusammen,

ich versuch schon seit Stunden ein einfaches Problem zu lösen.
Es wird die Drehzal eines Motors über den ICP und eine PID-Regelung 
geregelt.

Beim ICP Interrupt (steigende Flanke) wird der Timer auf 0 gesetzt und 
der Wert des ICR1 an die PID-Regelung übergeben. Das funktioniert soweit 
ganz gut.
Jetzt soll aber noch aus dem anliegenden Signal ein weiteres generiert 
werden. Dazu habe ich mir überlegt, das ich den Output Compare A Mode 
benutze und OCR1A auf ICR1<<1 (also die Hälfte)setze. So dass ich aus 
einem Signal mit asymetrischem Tastverhältnis ein symetrisches 
Rechtecksignal bekomme.

Controller ist ein AT43USB355. OC1A ist auf PD5

mal ein bisschen Code:
1
// Interrupt Routine ICP
2
static unsigned int ui_lastval=0;
3
unsigned int ui_actval=0;
4
  
5
  ui_actval = ICR1;
6
  
7
  TCNT1H = 0x00;  //Counter auf 0
8
  TCNT1L = 0x00;
9
    
10
  SetTrigger();  //Trigger auf High
11
      
12
  if (uc_OvrFlow)
13
  {
14
  ui_NipSpeed = 0xFFFF;
15
  uc_OvrFlow = FALSE;
16
  }
17
  else
18
  {
19
  ui_NipSpeed = ui_actval;  
20
    
21
  ui_NipLast = ui_lastval;
22
  ui_lastval = ui_actval;
23
  }
24
  
25
  OCR1AH = (ui_NipSpeed>>9) & 0xEF; //CompareRegister auf Belichtungszeit/2, Rücksetzen von Trigger dann autom.
26
  OCR1AL = (ui_NipSpeed>>1) & 0xFF;
27
  
28
  if (PIDFlag) PID_control(ui_NipSpeed);

Der Timer ist wie folgt konfiguriert (Bezeichner sind aus UsbWizard):
1
#define PORTD_EXIST      1
2
#define AG_DDRD  255
3
#define AG_PORTVALD  129
4
5
#define AG_TIMSK    0xC8 // Input Capture Int enable; NO Compare A Interrupt enable; Overflow Interrupt enable
6
#define AG_TICTRLA  0x80 // Clear OC1A Output Pin on Match
7
#define AG_TICTRLB  131 // CK/64; No Clear on Match; Rising Edge; Noise Canceller ON //war 195

Das Problem ist nun folgendes:
Mit den obigen Einstellungen ist PD5/OC1A immer low. Bei TICTRLA 0xC0 
(set on Match) immer high. Der Portpin ist richtig konfiguriert. Wenn 
ich den Output Compare abschalte und in die ISR ein "Toggle PD5" 
einbaue, geht es (allerdings mit halber Frequenz).

Danke für die Hilfe :-)

von Gock (Gast)


Lesenswert?

Hi!
Kann es sein:
Wenn Du die Zeitkonstante des ICP (der ja weiterhin auslöst) für OCR 
verdoppelst, weil DU die halbe Frequenz willst, dann wird OCR vom 
schnelleren ICP IRQ überschrieben, bevor es auslösen konnte.
Allerdings erkenne ich nicht, was uc_OvrFlow ist...
Gruß

von David N. (knochi)


Lesenswert?

Ich verdoppel den Wert ja nicht, sondern halbiere ihn.
Das Signal wird gesetzt, wenn der Interrupt passiert und soll dann nach 
der Hälfte der Zeit (die aus der vorigen Umdrehung ermittelt wurde) 
zurückgesetzt werden. So ergibt sich dann ein gleichmässiges Rechteck.

Übrigens hatte ich das TCCR1B Register falsch gesetzt, hatte auf 
fallende statt auf steigende Flanke getriggert. Macht aber auch keinen 
Unterschied, hätte auch funktionieren sollen, da das Eingangsignal recht 
kurz high pegel hat und dann lange low ist. Änderung brachte aber auch 
nix.

uc_OvrFlow ist ein bool, der gesetzt wird, wenn der Zähler überläuft 
(was in der Regel nicht passiert, ist nur für den Anlauf gedacht um 
Überläufe zu vermeiden)

von Stefan E. (sternst)


Lesenswert?

> Mit den obigen Einstellungen ist PD5/OC1A immer low. Bei TICTRLA 0xC0
> (set on Match) immer high.

Weder dem Codeschnipsel, noch deiner Beschreibung, ist zu entnehmen, wie 
und wo sich der Pegel auch wieder "zurückändern" soll.

von David N. (knochi)


Lesenswert?

Na "zurückändern" soll der Pegel des OC1A Ausganges sich durch ein 
Output Compare Match.

Ich versuchs mal so:
Eingangssignal an ICP/PF3
 <-------T-------->
+---+              +---+
|   |              |   |
+   +--------------+   +-----
1                  1

gewünschtes Ausgangssignal an OC1A/PD5
 <---T/2-->
+----------+           +-----
|          |           |
+          +-----------+
1          2           1


Bei (1) kommt der Interrupt durch den ICP (Input Capture), der Zähler 
wird auf Null gesetzt und das OCR1A Register wird auf T/2 gesetzt.
Nach dem ICP Interrupt läuft der Zähler wieder von 0 los und wenn er den 
Wert von OCR1A erreicht setzt der Controller selbstätig OCR1A/PD5 auf 
"0" (Zeitpunkt (2))(Clear the OC1A output line (to zero)).
So hab ich jedenfalls den Mechanismus interpretiert, korrigiere mich 
bitte, falls ich falsch liegen sollte.

von Stefan E. (sternst)


Lesenswert?

Und du meinst, der Pegelwechsel zum Zeitpunkt 1 passiert von alleine?

von David N. (knochi)


Lesenswert?

Narf...
Der Pegelwechsel (low-high) am Zeitpunkt "1" erfolgt durch das Makro 
SetTrigger() (siehe Kommentar). Der Pegelwechsel (high-low) zum 
Zeitpunkt "2" sollte durch den Output Compare Mechanismus erfolgen.

von Stefan E. (sternst)


Lesenswert?

David Knochenhauer wrote:

> Der Pegelwechsel (low-high) am Zeitpunkt "1" erfolgt durch das Makro
> SetTrigger() (siehe Kommentar).

Aha, der OC1A-Output-Pin heißt bei dir "Trigger", kann ich ja nicht 
wissen. Wo ist der Code zu SetTrigger?

von David N. (knochi)


Lesenswert?

Eigentlich hatte ich gehofft hier Hilfe zu bekommen und nicht vorgeführt 
zu werden, wie ein kleiner Schuljunge. Mir ist durchaus bewusst das 
meine Schilderungen, nunja etwas undurchsichtig waren.
Das ist aber sicher kein Grund, solch einen Ton anzuschlagen.

Der Code zu SetTrigger, setzt ganz normal den Portpin und funktioniert 
auch.
1
#define SetTrigger()  PORTD |= BIT5
2
#define ClearTrigger()  PORTD &= ~BIT5
3
#define ToggleTrigger()  PORTD ^= BIT5

PIDFlag ist übrigens ein bool und dient dazu die Regelung ein oder aus 
zu schalten. Ist für die gewünschte Funktion aber nicht von Bedeutung.

von Micha (Gast)


Lesenswert?

> Eigentlich hatte ich gehofft hier Hilfe zu bekommen und nicht vorgeführt
> zu werden, wie ein kleiner Schuljunge.
Dann solltest du aber auch die zum Helfen benötigten Informationen 
posten, sprich: eine kompilierbare Minimalversion des Programmes, die 
das Problem enthält.

> Das ist aber sicher kein Grund, solch einen Ton anzuschlagen.
Ob dein Ton soviel besser ist... ;-)

von Stefan E. (sternst)


Lesenswert?

David Knochenhauer wrote:

> Das ist aber sicher kein Grund, solch einen Ton anzuschlagen.

Welcher Ton denn bitte?
Dein "siehe Kommentar" kann man durchaus interpretieren als "es steht 
doch da, du musst nur richtig hinschauen". Darauf habe ich geantwortet.

von David N. (knochi)


Lesenswert?

Äh Leute...
Wollen wir uns jetzt mit dem Problem beschäftigen oder weiter zwischen 
den Zeilen irgendwelche Anschuldigungen rein interpretieren?

Ich dachte halt, das vieleicht jemand in dem Codeschnipsel einen 
Flüchtigkeitsfehler entdeckt, der mir endgangen ist. Das Ganze ist ja 
nun kein Hexenwerk. Eine minimal kompilierbare Version zu posten ist 
relativ schwierig, da es sich um einen USB-Controller AT43USB355 handelt 
und das mitgeliefert Codegerüst (ja das muss man nutzen, da dieses auf 
vorkompilierte Programmteile zurückgreift) recht umfangreich ist.

Ich wollte eigentlich nur wissen, was ich übersehen haben könnte beim 
einstellen des Timer1 Compare A Match.

Können wir jetzt auf einer normalen Ebene kommunizieren oder muss ich 
woanders Hilfe suchen?

von Stefan E. (sternst)


Lesenswert?

David Knochenhauer wrote:
> Äh Leute...
> Wollen wir uns jetzt mit dem Problem beschäftigen oder weiter zwischen
> den Zeilen irgendwelche Anschuldigungen rein interpretieren?
> ...
> Können wir jetzt auf einer normalen Ebene kommunizieren oder muss ich
> woanders Hilfe suchen?

Sorry, aber du hast schließlich angefangen, dich über den Ton zu 
beschweren. Da werde ich ja wohl noch drauf reagieren dürfen.

von Jörg G. (joergderxte)


Lesenswert?

@OP:Für mich sieht das so aus, als ob du zwei Sachen (Interrupts?) 
laufen lassen willst , die BEIDE den Timer1 löschen ?
Wie soll das denn funktionieren?
Versuch's doch mal anders (falls die Frequenzen niedrig genug sind):
 - Die ICR1 ISR lässt den Timer in Ruhe und berechnet die Differenz 
zum vorherigen ICR1-Wert (Musst du natürlich speichern)
 - Der OC1A output wird auf "Toggle on compare match" eingestellt
 - in der OC1A-ISR wird der Halbe Sollwert (ist das ICR1/2 ?) auf das 
OC1A Register addiert (nicht wundern, das GEHT).

Und poste Code, kurz&kompilierbar, wie schon mehrfach erwähnt.

hth, Jörg

von David N. (knochi)


Lesenswert?

Hmm den Timer1 löscht eigentlich nur die Input Capture Routine.

Kann es sein, das immer bei einem Capture Interrupt auch der Compare A 
Match auslöst?

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.