Forum: Mikrocontroller und Digitale Elektronik STM32F4 Flanken eines PWM-Signals erkennen


von Florian K. (f-kae)


Angehängte Dateien:

Lesenswert?

Hallo mal wieder,

ich möchte ein PWM-Signal eines RC-Empfängers auf meinem STM32F4 
einlesen. Dafür habe ich einen hochzählenden Timer mit zwei 
Input-Captures (Rising, Falling) und einem Output-Compare erzeugt. Der 
Timer läuft nach 15ms über.

Ich habe es mir so vorgestellt, dass bei einer steigenden Flanke in den 
Timer-Interrupt gesprungen wird, ebenso bei einer fallenden Flanke. 
Zusätzlich läuft das Output-Compare im inaktiven Modus und zählt bis 3ms 
hoch um dann auch in den Interrupt zu springen.
Das OutputCompare nutze ich zur Erkennung eines neuen PWM-Blocks, welche 
20ms lang sind und mit einem abschließenden PWM-Pulse >= 4ms erkenntlich 
ist.
Läuft der Timer über, also 15ms ohne die anderen Bedingungen, wurde kein 
vernünftiges Signal erkannt. Durch den SlaveModeReset setze ich den 
Timer bei jeder Rising-Edge zurück.

Die eigentliche Auswertung des Signals erfolgt dann über die 
Interrupt-Routine.

Insgesamt funktioniert es noch nicht so richtig, erstmal stelle ich aber 
fest das mein Problem schonmal daran liegt, dass der Timer überläuft 
(15ms) obwohl durch den SlaveModeReset doch bei jedem Rising-Edge der 
Timer resetet werden sollte. Das passiert anscheinend aber nicht, da 
regelmäßig ein "No Signal long time" detektiert wird.(Siehe Output.txt)

Ich freue mich wie immer über jede Antwort die mir irgendwie 
weiterhelfen könnte.

Ach ja und ich möchte das Signal nicht per "einfacher" Abtastung oder 
PWM_Input einlesen. Ich möchte jetzt gerne wissen wo das Problem liegt 
und nicht nur das Problem "irgendwie" lösen. Es sei denn ist gibt 
konkrete Gründe weshalb meine Variante schlecht ist :)

Meine PLL-Config:

PllM =   8
PllN = 336
PllP =   2
PllQ =   7
HSE_Value(8MHz) / 8 = 1MHz ->
1Mhz * 336 / 2 = 168 MHz (SysCLK)
1Mhz * 336 / 7 =  48 MHz (USB,SDIO,RNG)
SysCLK(168MHz) / 4 = 42MHz (APB1)
  APB1(42MHz)  * 2 = 84MHz (Tim2,3,4,5,6,7,12,13,14)
SysCLK(168MHz) / 2 = 84MHz (APB2)
  APB2(84MHz)  * 2 = 168MHz (Tim1,8,9,10,11)

Viele Grüße,
Florian

von mach mal (Gast)


Lesenswert?

Vom Prinzip her würde ich bei Beginn des Signals den Timer reseten, oder 
Wert speichern und erst jetzt Capture scharf schalten. Beim nächsten 
Wechsel kommt das Capture und du kannst die Pulslänge bestimmen.
Wenn die Pwm Periodenlänge unbekannt ist, wertet man den Zähler beim 
nächsten Beginn oder nimmt ein 2 Capture.

von Florian K. (f-kae)


Lesenswert?

Aber was spricht gegen meine Variante. Sie sollte ja eigentlich auch so 
funktionieren...

von EitelSonnerschein (Gast)


Lesenswert?

Florian K. schrieb:

> Aber was spricht gegen meine Variante. Sie sollte ja eigentlich
> auch so
> funktionieren...

Sollte, sollte, Witwe Bolte.

von Florian K. (f-kae)


Lesenswert?

EitelSonnerschein schrieb:
> Florian K. schrieb:
>
>> Aber was spricht gegen meine Variante. Sie sollte ja eigentlich
>> auch so
>> funktionieren...
>
> Sollte, sollte, Witwe Bolte.

Ja von der Theorie dahinter "sollte" es funktionieren. Nur meine 
praktische Umsetzung ist anscheinend gescheitert, nun ist meine Frage: 
An welcher Stelle?

Konkret wäre erst einmal sehr interessant zu wissen, weshalb vor jedem 
Rising-Inputcapture (bzw. nach jedem Falling-InputCapture) auch das 
Update-Flag gesetzt ist, ich dachte das wird nur beim Überlauf des 
Timers(15ms) gesetzt?! Also im Grunde nie solange ein InputCapture 
(innerhalb der 15ms) erkannt wird, da dann der Timer doch automatisch au 
Null gesetzt wird!

So sollte das Signal ungefähr aussehen:

 <----------------20ms----------------->
_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-----|_
  1   2   3   4   5   6   7   8     9

von Florian K. (f-kae)


Lesenswert?

Ich habe gerade eine Passage in der ApplicationNote AN4013.pdf gelesen:

"As the buffered registers (ARR, PSC, CCRx) need
 an update event to
 be loaded with their
 preload values, set the URS (Update Request Source) to 1 to avoid the
 update flag each
 time these values are loaded. In this case, the update event is only
 generated if the counter
 overflow/underflow occurs
"
Gibt es hierfür eine StandardLibraryFunction, oder steckt diese Funktion 
schon irgendwie mit drin? Das würde mein Problem erklären

von Florian K. (f-kae)


Angehängte Dateien:

Lesenswert?

Hallo nochmal,

bitte bitte bitte, kann sich irgendjemand nochmal meinem Problem 
annehmen?! Ich verzweifele langsam.
Durch die Zeile:
1
/* Configures the TIM3 Update Request Interrupt source (SETS the CR1->URS bit)*/   
2
  TIM_UpdateRequestConfig(TIM3,TIM_UpdateSource_Regular);
verhindere ich nun schon einmal das bei jedem Rising-Event auch ein 
update-event generiert wird. Nun wird also kein Überlauf des Timer3 mehr 
erkannt, solange das PWM-Signal anliegt!

Mein Problem ist aber, dass die Interrupt-Routine anscheinend nur bei 
einem Rising-Event betreten wird und dann gleichzeitg auch immer ein 
Falling-Event bereits eingetreten ist.

Das ist meine aktuelle Bluetooth-Ausgabe:

...
---------------------------------------------

-RISING-EVENT- sumLength: 4512

-OUTPUTCOMPARE-RESET- 3ms has gone: Reset long Pulse-timer

-FALLING-EVENT- PulseLength: 2999

-OUTPUT-COMPARE->----------- Long Pulse captured -----------

---------------------------------------------
...

Wobei die gestrichelte Linie bei jedem Aufruf des TIM3_IRQHandler 
auftritt. eigentlich erwarte ich also folgendes:

...
---------------------------------------------

-RISING-EVENT- sumLength: 4512

-OUTPUTCOMPARE-RESET- 3ms has gone: Reset long Pulse-timer

---------------------------------------------

-FALLING-EVENT- PulseLength: 2999

---------------------------------------------
...

Wenn ich in TIM3_IRQHandler aus der Abfrage:
1
/* Falling ------------------------------------------------------------------*/
2
if((TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET))
3
{
folgendes mache:
1
/* Falling ------------------------------------------------------------------*/
2
else if((TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET))
3
{
Tritt dieser Teil, also "Falling-Event" überhaupt nicht mehr auf. Das 
heißt, bei jedem betreten von TIM3_IRQHandler gibt es ein 
Rising-Event!!!

Ich habe nochmal die beiden interessanten Code-Ausschnitte angehangen.

Bitte bitte helft mir :/

Viele Grüße,
Florian

von Jan B. (berge)


Lesenswert?

Hi,

ich kann dir da leider nicht helfen, da ich damit noch nie gearbeitet 
habe. Aber hier ein Link, wo zumindest ein PWM Signal mit Hilfe von 
Timern ausgelesen wird. Vielleicht hilft der Code dir. 
http://mikrocontroller.bplaced.net/wordpress/?page_id=2125

Liebe Grüße,

Jan

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.