Forum: Compiler & IDEs PWM-Timer Problem


von Morgen Stevesant (Gast)


Lesenswert?

Hallo,

da ich noch nie einen Timer benötigt habe stehe ich jetzt an dem Punkt,
dass ich nicht so recht weiss wie man ihn anwedet. Ich benutzte den
Mega8 und werte ein PWM Signal aus, lege Daten in MMC ab und sende über
Uart. Senden und speichern ist nicht so schwierig für mich, aber mit der
Funktionsroutine für Timer habe ich einige Probleme. Wäre schön wenn
sich mal jemand meine Codeschnipsel ansehen könnte, weil es
wahrscheinlich falsch sein wird.

Kann mir vielleich jemand die Routine beschreiben oder Codeschnipsel
posten, wie man das Auslösen der Interrupts auswerten kann
(var2-var1).
ist die überlegung richtig?:
Timer startet -> st.Flanke -> Interrupt -> Timer startet -> st.Flanke2
-> Interrupt2

Danke schon mal


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

SIGNAL(SIG_INTERRUPT0)
{
  Daten an MMC(frequenz);
}

void main(void)
{

   GICR = _BV(INT0);               //enable int0

   for(;;){
         TCCR1B = _BV(CS12)              //timer starten ...255
   MCUCR = _BV(ISC01) | _BV(ISC00) //interrupt bei steigender fl
   //...steigende Flanke löst interrupt aus
   var1;

   MCUCR = _BV(ISC01) | _BV(ISC00) //interrupt bei steigender fl
   //...nächste Flanke löst interrupt aus
   var2;
         Timer zurücksetzen
   frequenz=var2-var1;
   }
}

von Jörg Wunsch (Gast)


Lesenswert?

Würde ich nicht so machen.  Ich würde den input capture interrupt
benutzen.  Zuerst auf die eine Flanke setzen, beim Interrupt den
capture-Wert merken und ihn auf die andere Flanke umschalten.  Bei der
zweiten Flanke die Differenz bilden.  Da müßte doch ungefähr sein, was
Du willst, oder?

Beim externen Interrupt hast Du immer das Problem, daß die
Interrupt-Latenz und insbesondere die mögliche Varianz dieser Latenz
das Ergebnis beeinflussen.

von Morgen Stevesant (Gast)


Lesenswert?

Ich glaube das habe ich ungefähr verstanden.

1.TCCR1B = _BV(ICES1) | _BV(CS12) //Timer starten, steigende flanke
ICP
2.TIMSK = _BV(TICIE);
3.TIFR = _BV(ICF1); //Bit wird gesetzt, wenn Capture-Ereignis
aufgetreten ist
4.var1 = ICR1 //Wert an Variable übergeben

Jetzt habe ich doch den ersten Wert var1, doch jetzt ist mir unklar ob
der Timer angehalten wurde(neu gestartet werden muss) und wie man den
Flankenwechsel in "C" ausdrückt.
Timer soll ja weiterlaufen und auf Interrupt2 (fallende Flanke)
reagieren.

Kennt vielleicht jemand ein Beispiel im Netz?

Danke nochmal

von Morgen Stevesant (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ich habe immer noch (Verständnis-)probleme mit dem Timer/Counter.

ICP kann ich nicht nutzen, da ich mehrere (so viele wie möglich)
Sensoren (ADXL202) auswerten möchte.

Also bleibt mir nur übrig über INT0 und INT1 die Pulsbreiten zu
bestimmen. Jetzt habe ich aber ein Problem in der Grundüberlegung.

1. Ich nehme einen Counter mit großer Frequenz (prescale = 1) und lasse
ihn mit SIG_OVERFLOW so lange durchlaufen, bis der Interrupt vorbei
ist.

oder:
2. Ich passe den Counter so an, dass er für einen Durchlauf in etwa die
Zeit der Pulsbreite (bzw. etwas mehr) benötigt und lese dann den
Zählerstand aus dem TCNT0-Register. Also bräuchte ich dann doch
SIG_INTERRUPT!?

Jetzt würde mich interessieren, was falsch ist bzw. wie man es nicht
machen sollte. Wie gesagt ICP kann ich leider nicht nutzen.

von Morgen Stevesant (Gast)


Lesenswert?

Was ich ausserdem nicht ganz verstehe ist, wann genau der Zähler
startet. Entweder beim ausgelösten Interrupt oder bereits wenn man den
AVR mit Strom versorgt.

Bei 1. hab ich das Problem, dass mir u.U. 1 Durchlauf fehlen können
(wenn der Zähler schon auf 254 z.B. steht, dann würde schon ein Zähler
einen Durchlauf bedeuten (1=255).

Mit 2. funktioniert das sowieso nicht, da die Sensorperiode 10ms
beträgt und ich nur auf 0,512ms pro Counterperiode komme.

Sehe ich das jetzt richtig, dass ich ein SIG-OVERFLOW benötige?

von Jörg Wunsch (Gast)


Lesenswert?

Ich verstehe nicht, warum Du einerseits ICP nicht nutzen kannst, aber
andererseits mit den blöden externen Interrupts zufrieden bist.

Vielleicht ist es ja eine Option, den ATmega8 durch einen ATmega88 zu
ersetzen?  Dort hast Du die Möglichkeit, pin change interrupts zu
benutzen.

Einen Zähler adaptieren würde ich nicht, sondern ICP in Software
simulieren: der entsprechende Interrupthandler muß den Wert des Timers
auslesen und irgendwo notieren, danach setzt er ein Flag, daß er
getriggert worden ist, so daß die Hauptschleife das Ereignis
verarbeiten kann.

Wenn die PWM-Eingangssignale beinahe gleichzeitig auftauchen, hast Du
aber notgedrungen ein Jitter in Deiner Interpretation, d. h. die
interpretierten PWM-Werte weichen (bedingt durch die schnell
nacheinander eintreffenden Interrupts) von den tatsächlichen Werten
ab.

Ein übergelaufener 16-bit Zähler ist übrigens gar kein Problem, sofern
sichergestellt ist, daß maximal ein Überlauf zwischen den beiden
Ereignissen stattfand: Du liest den jeweiligen Zählerstand einfach als
uint16_t aus und subtrahierst den älteren vom jüngeren, das Ergebnis
wird dank 2er-Komplement auch dann noch korrekt, wenn der ältere
Zählerwert größer als der jüngere ist.

von Morgen Stevesant (Gast)


Lesenswert?

"Wenn die PWM-Eingangssignale beinahe gleichzeitig auftauchen, hast Du
aber notgedrungen ein Jitter in Deiner Interpretation, d. h. die
interpretierten PWM-Werte weichen (bedingt durch die schnell
nacheinander eintreffenden Interrupts) von den tatsächlichen Werten
ab."

Ich dachte so ein Fall wäre nicht möglich, da der erste Interrupt
zuerst abgearbeitet wird, bis wieder ein Interrupt möglich ist. Also
der zweite, der deiner Meinung nach beinahe auftaucht, erst gar nicht
erkannt wird. Aber ich lese hier schon länger und vertraue deiner
Meinung.

"Ich verstehe nicht, warum Du einerseits ICP nicht nutzen kannst,
aber
andererseits mit den blöden externen Interrupts zufrieden bist."

Ich bin auch immer davon ausgegangen das die Pins INT0, INT1 und ICP
dazu gedacht sind, digitale Signale zu verarbeiten, im Gegensatz zu
anderen Pins wie die ADCs.

Ist es möglich, 4 digitale Signale an einem einzigen ICP abzuarbeiten?
Wie müsste da die Beschaltung aussehen?

von Morgen Stevesant (Gast)


Lesenswert?

Wäre es also besser, wenn ich z.B. die vier digitalen Signale über vier
UND-Gatter mit µC verbinde und die Gatter dann mit µC steuere.

Gatter1=High + PWM
Gatter2=Low +PWM
Gatter3=Low +PWM
Gatter4=Low +PWM

danach

Gatter1=Low +PWM
Gatter2=High +PWM
Gatter3=Low +PWM
Gatter4=Low +PWM

usw.

Sowas wollte ich eigentlich vermeiden, weil ich mir nicht sicher bin ob
dann nicht andere effekte auftreten können.

Leider gibt es hier nicht so viele gute Beispiele in "C" wie man die
Pulsbreite eines PWM-Signals verarbeiten kann. Viele benutzen dann
einfach die ADC, davon gibt es ja immer mehr als man brauchen kann -
aber nur ein ICP?
Ist das noch zeitgemäß, dass man dann noch über externe Gatter schalten
muss, wenn man mehrere Signale verarbeiten möchte? Fast alle guten
Sensoren liefern ja inzwischen ein digitales Signal.

von Jörg Wunsch (Gast)


Lesenswert?

Nein, ich würde das nicht über externe Gatter machen.

Das mit dem Jitter bezog sich auf verschiedene Interrupts.  Ist aber
richtig, Du würdest wohl in der Tat nur einen pin changed interrupt
bekommen, in dessen ISR mußt Du dann alle möglichen Ereignisse
auswerten.  Dennoch dürfte sich das Timing der ISR zwischen einem und
mehreren Ereignissen unterscheiden, damit hast Du keine konstante
Interruptlatenz mehr, folglich einen Jitter.

Ob der zeitlich für Dich relevant ist, weiß ich natürlich nicht.

Meine Bemerkung mit den externen Interrupts bezog sich darauf, daß Du
mit diesen ja auch nur genau zwei Kanäle abfragen kannst.  Wenn ich
Dich richtig verstehe, willst Du aber mehr abfragen können.

> Ist das noch zeitgemäß, dass man dann noch über externe Gatter
> schalten muss, wenn man mehrere Signale verarbeiten möchte? Fast
> alle guten Sensoren liefern ja inzwischen ein digitales Signal.

PWM ist aber eher ein digital übertragenes Analogsignal, daher hast Du
ja auch den Streß mit der Digitalisierung.  Ein digitales Signal wäre
eine Übertragung mit SPI.

von Morgen Stevesant (Gast)


Lesenswert?

>Meine Bemerkung mit den externen Interrupts bezog sich darauf, daß Du
>mit diesen ja auch nur genau zwei Kanäle abfragen kannst.  Wenn ich
>Dich richtig verstehe, willst Du aber mehr abfragen können.

Ich trete immer noch etwas auf der Stelle herum und komme nicht
weiter.

-ICP, leider nur einer, der sollte auch für die MMC herhalten
-INT0 und INT1, sollen nicht so toll sein
-UND-Gatter davor schalten auch nicht so optimal

was nun?

Es wäre ein Controller gut der über 4-8 ICP verfügt, kennt da jemand
einen?

von Morgen Stevesant (Gast)


Lesenswert?

Sorry, dass ich deshalb das Forum so zumüllen muss. Ich werde jetzt
nochmal alles mit SIG_OVERFLOW an den etx.Int.Pins testen und melde
mich dann wieder.

Vielleicht hat hier schon mal jemand gleiches versucht und kann mir
links, tips oder codeschnipsel posten.

Danke
Morgen

von Jörg Wunsch (Gast)


Lesenswert?

Was Du mit einem Interrupt-Handler an externen Pins willst, verstehe
ich leider nicht.

Was spricht gegen die Verwendung es pin change interrupts beim
ATmega88?  Der ist ja sogar pinkompatibel zum ATmega8.  Du kannst auf
Änderungen an bis zu 24 Pins reagieren.

von Morgen Stevesant (Gast)


Lesenswert?

Ich hoffte mehr über die Abarbeitung mehrerer Signale zu erfahren, da
ich nicht der einzige bin, der damit Schwierigkeiten hat.

Jemand aus dem schönen Brisbane, an der University of Queensland, dem
Sunshine State in Australien, hatte auch das Problem mit einem AVR und
hat die beiden Sensorsignale gemultiplext, mit einem extra IC.
http://innovexpo.itee.uq.edu.au/2001/projects/s369518/thesis2.pdf

von Jörg Wunsch (Gast)


Lesenswert?

Ja, dafür konnte er den Hardware-ISP benutzen.  Wie geschrieben, wenn
Du möglichst viele dranklemmen willst (und keine extremen
Genauigkeitsforderungen hast), wer hindert Dich daran, das mit pin
change interrupts und einem ATmega88 zu tun?  Darauf bist Du bislang
noch nicht eingengangen.

Andernfalls, falls Du gute Genauigkeit (Hardware-PWM) bei 2 Kanälen
haben willst ohne externe Mimik, ATmega162, ATmega64 und ATmega128
haben zwei 16-bit Zähler und damit zwei ICP-Eingänge.

von Morgen Stevesant (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

erst mal danke, dass ihr meinen Beitrag weiter verfolgt!

Zum ATmega88: Wusste bis gestern gar nicht, dass es einen solchen gibt,
hört sich aber gut an, wenn ich auch irgendwo hier im Forum gelesen habe
dass es einen AT89.... (bin mir nicht mehr sicher) gibt, der über fünf
ICP verfügt.

Aber das ist jetzt auch egal - ich hatte gestern nur ein Problem mit
der Grundüberlegung (Timer läuft über..., TCNT auslesen oder Polling[so
nennt man das doch... count++]...)

Habe vor einigen Stunden den ADXL eingelötet und wollte mal ein Signal,
wie empfohlen, mit dem ICP auslesen. Aber meine erhaltenen Werte sind zu
hoch. Ausserdem erkennt er meine if-Funktion nicht richtig - bzw. die
Abfrage ob jetzt gerade eine fallende oder st. Flanke gecaptured wurde.

Erkennt nur den LOW-state des PWM-Signals und ist obendrein fast
doppelt so lange wie die eingestellte Frequenz am Sensor.

Code ist im Anhang und hier er kennt er die steigende flanke irgendwie
nicht richtig:

#######################################################
SIGNAL(SIG_INPUT_CAPTURE1){
unsigned char  *hilf, *hilf2;
unsigned int timer_wert1, timer_wert2, flanke;

flanke = ((TCCR1B) & 0x40);

if(flanke != 0x00){     //ich habs auch schon mit int und "0"
probiert
                        //bei steigender flanke...
timer_wert1 = ICR1;  //wert auslesen
...
########################################################

Zu den berechneten Werten:

Clock = 4MHz
Prescale = 8
daraus resultiert 0,002ms pro Periode

Werte für den LOW-state des Sensors erhalte ich um die 5-6000
(entspricht doch dann 5000*0,002ms ~ 10ms), das würde mich auch nicht
stören, wäre meine Sensorperiode nicht bei 7,6ms!

von Morgen Stevesant (Gast)


Lesenswert?

Vielleicht kann es mal jemand brauchen, war ziemlich versteckt hier im
Forum:

http://www.al-williams.com/pak7.htm

Damit sollte man bis zu 8 Signale verarbeiten können.

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.