Forum: Mikrocontroller und Digitale Elektronik Idee gesucht um Jitter zu beseitigen


von Mirco K. (superfreak)


Lesenswert?

Hallo,

ich habe hier einen Mikrocontroller der auf ein externes Triggersignal 
triggern soll und anschließend ein Port Pin mit einer bestimmten 
Verzögerungszeit High schalten soll. Da die Verarbeitungszeit dieses 
Mikrocontrollers nicht schnell genug ist entsteht ein Time Delay 
zwischen Triggersignal und dem High schalten des anderen Pins. Um das 
Problem zu umgehen ermittel ich die Frequenz des Triggersignals mit 
einem Timer. Die Frequenz kann ich sehr genau messen, das ist nicht das 
Problem. Da ich die Frequenz des Triggersignals kenne, möchte ich nun 
eine Periode minus Verarbeitungszeit µC abwarten und das Signal 
ausgeben. Wenn ich das Programm so implementiere bekomme ich am Ausgang 
Jitter Probleme.

Die abgewartete Zeit(Periode - Verarbeitungszeit µC) überprüfe ich die 
ganze Zeit mit einem Timer. Erst wenn diese abgelaufen ist soll der Pin 
High geschaltet werden.




Hat jemand von euch eine Idee wie ich das Problem lösen kann ? Ich 
programmiere das ganze in c, liegt es vielleicht am compiler, der 
unterschiedliche Codelaufzeiten verursacht ?  Das Triggersignal hat 
dabei eine Frequenz von 10 Hz bis 300 Hz.

von Zilp Z. (zirp)


Lesenswert?

Das ganze Problem bitte. Die Beschreibung ist ungenuegend.

Der Trigger kommt alle 3-100ms, und soll um wieviel verzoegert werden ?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Wenn deine Timing Anforderungen so hoch sind, ist es im Allgemeinen eine 
gute Idee, zu überlegen, ob man das entweder mit einem schnelleren MC 
oder sogar in Hardware (Monoflop?) nicht besser lösen kann.
Da du nicht schreibst, ob die Verzögerung zwischen In- und Output z.B. 
variabel sein muss, kann man da nicht so viel zu sagen.

von Peter D. (peda)


Lesenswert?

Mirco K. schrieb:
> Das Triggersignal hat
> dabei eine Frequenz von 10 Hz bis 300 Hz.

300Hz sind schnarchlahme 3ms, wie groß darf denn der Jitter sein?

Mit einem 20MHz AVR kannst Du den Jitter auf 50ns drücken.

von Teo D. (teoderix)


Lesenswert?

Je nachdem wie die Daten verarbeitet werden müssen, ist die Laufzeit 
natürlich immer etwas anders!
Die Ausgabe über einen Timer freigeben, dann muss nur noch die 
Verarbeitung der Daten schnell genug sein :)

von 6a66 (Gast)


Lesenswert?

Mirco K. schrieb:
> Da die Verarbeitungszeit dieses
> Mikrocontrollers nicht schnell genug ist entsteht ein Time Delay
> zwischen Triggersignal und dem High schalten des anderen Pins. Um das
> Problem zu umgehen ermittel ich die Frequenz des Triggersignals mit
> einem Timer. Die Frequenz kann ich sehr genau messen, das ist nicht das
> Problem. Da ich die Frequenz des Triggersignals kenne, möchte ich nun
> eine Periode minus Verarbeitungszeit µC abwarten und das Signal
> ausgeben.

Hallo Mirco,

das ist prinzipiell möglich hat aber folgende Fußangeln:
a) Die Reaktionszeit auf einen Trigger dürfte bei eine Cortex-Arm etwa 
in <1us machbar sein (Interrupt auf Pin, Einsprung, Port setzten). Bei 
8-bittern mit geringer Frequenz kann das denke ich bis auf 5us 
anwachsen. Wenn Du schneller sein möchtes brauchst Du eine spezielle 
Methode - das hast Du richtig erkannt.
b) Die von Dir beschriebene Methode würde ich mal "PLL in HW/SW" nennen. 
Um signifikant unter den in a) genannten Wert zu kommen benötigst Du 
einen sehr genauen Timer der dann auch noch sehr genau am Originalsignal 
parallel läuft. Die Nachführung (Erkennung der Differenz, 
Neueinstellung) gestaltet sich dabei als das schwierigste da sie 
möglichst fein sein (Genauigkeit) muss aber auch schnell reagieren soll. 
Meist passt das nicht zusammmen zumal Du auch noch bei 10Hz arbeiten 
willst. Bei schnellen Änderungen in der Frequenz erwarte ich daher 
Abweichungen die deutlich über dem Wert in a) liegen dürften.

rgds

von Mirco K. (superfreak)


Lesenswert?

Peter D. schrieb:
> 300Hz sind schnarchlahme 3ms, wie groß darf denn der Jitter sein?
>
> Mit einem 20MHz AVR kannst Du den Jitter auf 50ns drücken.

Ja, das habe ich gedacht. Deswegen finde ich das ganze noch 
merkwürdiger.


Ich habe den ARM STM32F411 und das dazu passende EVM Nucleo. Wenn ich 
das Triggersignal auf 1 kHz stelle komme ich auch auf Jitterzeiten von 
50 ns. Wohingegen wenn das Triggersignal im milli Sekunden Bereich ist, 
Ist das Jittern im uS Bereich. Ich dachte vielleicht es, das ich von 
vorne herein etwas nicht bedacht habe. Wahrscheinlich liegt es dann wohl 
eher an den verwendeten Libs und meinem Code.
Der Code folgt gleich...

von Peter D. (peda)


Lesenswert?

Nochmal, wie groß darf der Jitter konkret sein?

In vielen Fällen sollten doch <1% völlig ausreichend sein, d.h. bei min 
3ms dann max 30µs.

von Mirco K. (superfreak)


Lesenswert?

Das hier ist meine Main
1
int main() {
2
    trigger.mode(PullDown);           //activate internal pull Down (hardware specific)
3
                     
4
    trigger.rise(&up);              //attach up() to interrupt on rising edge of trigger
5
    trigger.fall(&down);            //attach down() to interrupt on falling edge of trigger
6
   
7
    while(1)
8
    {
9
    
10
    }
11
12
}


und meine Funktionen. Ich weiß nicht gerade gut Programmiert ;)
1
void Pause(void)
2
{
3
    t.stop();
4
    t.reset();
5
    t.start();
6
    while(t.read_us()<correct_delay){ }   // correct_delay = Periodenzeit - uC Verarbeitungszeit
7
    t.stop();
8
    t.reset();
9
}
10
11
void up3(){                          //call this on rising edge - Measures the ton time of the rect start initial
12
    
13
    //Trigger_pulse=1;     
14
    Pause();
15
    Trigger_pulse=1;
16
    
17
 }
18
void down3(){ 
19
        //Trigger_pulse=0;
20
     }

Die unteren beiden Funktionen sind nachher die Funktionen in denen der 
uC beim IRQ reinspringt

von Sven B. (scummos)


Lesenswert?

Wenn du keinen Jitter willst, benutze einen Timer, der startet wenn eine 
Rising Edge an dem Pin kommt und einen aderen Pin auf High schaltet wenn 
er einen bestimmten Wert erreicht. Das ist dann komplett in Hardware und 
die CPU muss gar nichts tun. Entsprechend jittert da auch nix. Wenn dein 
Mikrocontroller keinen solchen Timer hat, nimm einen der einen hat ;)
Aber ich schätze, die meisten Controller können sowas.

Normalerweise heißt das irgendwie "Timer capture" (für den Input), damit 
kann man den Timer auf 0 zurücksetzen oder starten; und "Timer match", 
damit kann man in einem Register einen Wert angeben bei dem der Timer 
irgendeinen Pin irgendwie umschaltet wenn er einen bestimmten Wert 
erreicht.

Interrupts sind immer Mist für sowas.

: Bearbeitet durch User
von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Sven B. schrieb:
> Aber ich schätze, die meisten Controller können sowas.

Falls es billig sein soll, z.B. der STM8S103F3P6 für rund 25ct aus 
China.

von Mirco K. (superfreak)


Lesenswert?

Peter D. schrieb:
> Nochmal, wie groß darf der Jitter konkret sein?
>
> In vielen Fällen sollten doch <1% völlig ausreichend sein, d.h. bei min
> 3ms dann max 30µs.

Das reicht mir dicke!

von Mirco K. (superfreak)


Lesenswert?

Sven B. schrieb:
> Wenn du keinen Jitter willst, benutze einen Timer, der startet wenn eine
> Rising Edge an dem Pin kommt und einen aderen Pin auf High schaltet wenn
> er einen bestimmten Wert erreicht. Das ist dann komplett in Hardware und
> die CPU muss gar nichts tun. Entsprechend jittert da auch nix. Wenn dein
> Mikrocontroller keinen solchen Timer hat, nimm einen der einen hat ;)
> Aber ich schätze, die meisten Controller können sowas.
>
> Normalerweise heißt das irgendwie "Timer capture" (für den Input), damit
> kann man den Timer auf 0 zurücksetzen oder starten; und "Timer match",
> damit kann man in einem Register einen Wert angeben bei dem der Timer
> irgendeinen Pin irgendwie umschaltet wenn er einen bestimmten Wert
> erreicht.
>
> Interrupts sind immer Mist für sowas.

Das mache ich ja quasi.
ich triggere auf die High Flanke des Signals und möchte dann das 
Triggersignal um eine bestimmte Zeitverzögerung wieder ausgeben. Nur 
leider braucht mein Code mit der der IRQ routine um die 3 us bis der 
andere Pin high geschaltet wird. Deswegen möchte ich ja dann eine 
Periode warten ----

von Olaf (Gast)


Lesenswert?

> Das mache ich ja quasi.

Hast du eigentlich schonmal im Datenblatt deines Controllers den 
Abschnitt ueber die integrierten Timer gelesen? Verstanden?

Olaf

von uwe (Gast)


Lesenswert?

> Das mache ich ja quasi.
Nö machst du nicht! Du sollst die Hardware Timer/Counter so 
KONFIGURIEREN das diese alles selbstständig machen.

von Mirco K. (superfreak)


Lesenswert?

uwe schrieb:
> Nö machst du nicht! Du sollst die Hardware Timer/Counter so
> KONFIGURIEREN das diese alles selbstständig machen.

Ja, ich dachte ich könnte das Problem umgehen wenn ich selber sage wann 
der Timer startet und diesen wert als referenz nehmen.

Jetzt kommt das eigentliche Problem. Da ich bis jetzt nur mit den Libs 
gearbeitet habe. Tue ich mich noc hetwas schwer in die STM welt 
einzutauchen ohne die Libs zu verwenden. Ich habe es mal Probiert und 
noch nicht einmal einen Pin / High low geschaltet bekommen 
(Deprimierend^^)

Ich weiß auch wie ich das Programmieren würde.
Counter runterzählen lassen -> währrendessen überprüfen ob overflow bit 
vom timer gesetzt worden is -> Pin High schalten...

nur ich weiß nicht wie ich das in die Register schreibe

http://www.st.com/web/en/resource/technical/document/reference_manual/DM00119316.pdf

Siehe S.244

: Bearbeitet durch User
von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Mirco K. schrieb:
> Da ich bis jetzt nur mit den Libs gearbeitet habe.

Welche Libs?

[ ] Die gute alte Standard Peripheral Library?
[ ] Die neue HAL-API mit STM32CubeF4?
[ ] Sonstiges (mbed.com, …)?

Mirco K. schrieb:
> nur ich weiß nicht wie ich das in die Register schreibe

Das geht auch ohne Libs oder hängt von der Lib ab.

Für welche Variante brauchst Du Hiilfe?

von Mirco K. (superfreak)


Lesenswert?

Torsten C. schrieb:
> Welche Libs?
>
> [X] Die gute alte Standard Peripheral Library?
> [ ] Die neue HAL-API mit STM32CubeF4?
> [ ] Sonstiges (mbed.com, …)?

Ich habe bis jetzt nur die gute alte mbed.lib eingebunden

Normalerweise würde ich ja sagen

mit folgendem Code kann man den Preescaler initialisieren
(http://visualgdb.com/tutorials/arm/stm32/timers/)
1
TIM_TimeBaseInitTypeDef timerInitStructure; 
2
    timerInitStructure.TIM_Prescaler = 40000;
3
    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
4
    timerInitStructure.TIM_Period = 500;
5
    timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
6
    timerInitStructure.TIM_RepetitionCounter = 0;
7
    TIM_TimeBaseInit(TIM2, &timerInitStructure);
8
    TIM_Cmd(TIM2, ENABLE);

wenn ich zusätzlich zu der mbed die ganzen Libs mit *.h und *.c einbinde 
bekomme ich nur Fehlermeldungen , dass er dei ganzen Parameter in der 
Bibliothek nicht kennt

von Lukas K. (carrotindustries)


Lesenswert?

Mirco K. schrieb:
> Wenn ich
> das Triggersignal auf 1 kHz stelle komme ich auch auf Jitterzeiten von
> 50 ns. Wohingegen wenn das Triggersignal im milli Sekunden Bereich ist,
> Ist das Jittern im uS Bereich.

An der Software ändert sich nichts? Das hört sich nach einem analogen 
Problem an. Ändert sich die Flankensteilheit deines Triggersignals oder 
ist dieses gar ein Sinus?

von Mirco K. (superfreak)


Lesenswert?

Lukas K. schrieb:
> An der Software ändert sich nichts? Das hört sich nach einem analogen
> Problem an. Ändert sich die Flankensteilheit deines Triggersignals oder
> ist dieses gar ein Sinus?

Nein, es ist auch ein Rechtecksignal, welches von einem 
Funktionsgenerator gespeist wird.

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Mirco K. schrieb:
> bekomme ich nur Fehlermeldungen

Nun, das hängt dann wieder an der IDE. Bei "einfachen" wie CODE::Blocks, 
EM::Blocks, CoIDE usw, wird alles automatisch so konfiguriert, dass 
keine Fehlermeldungen kommen.

Ansonsten fehlen da noch Interrupts usw. Das Tutoial von  Moritz Diller 
(woisdiekatze) ist zwar für den STM32F1xxx, aber mit ein paar Änderungen 
passt das auch zum F4:

http://www.diller-technologies.de/stm32.html#timer_pwm

Vielleicht hilft das schon weiter oder jemand hat einen besseren Link.

von uwe (Gast)


Lesenswert?

> Ich weiß auch wie ich das Programmieren würde.
> Counter runterzählen lassen -> währrendessen überprüfen ob overflow bit
> vom timer gesetzt worden is -> Pin High schalten...
immer noch nicht! Du sollst den Compare wert setzen dann Schlatet der 
Timer selber den Pin auf High wenn du ihn richtig konfiguriert hast. Und 
kann sich auch wieder selber auf Null zurücksetzen wenn er richtig 
konfiguriert ist. Und kann warscheinlich auch getriggert werden von 
einem externem Signal auch ganz von alleine ohne irgenetwas abzufragen 
oder einen Interupt auszulösen.

von uwe (Gast)


Lesenswert?

Aber naja wenn du noch nicht mal Register setzen kannst...

von Sven B. (scummos)


Lesenswert?

Mirco K. schrieb:
> Sven B. schrieb:
>> Wenn du keinen Jitter willst, benutze einen Timer, der startet wenn eine
>> Rising Edge an dem Pin kommt und einen aderen Pin auf High schaltet wenn
>> er einen bestimmten Wert erreicht. Das ist dann komplett in Hardware und
>> die CPU muss gar nichts tun. Entsprechend jittert da auch nix. Wenn dein
>> Mikrocontroller keinen solchen Timer hat, nimm einen der einen hat ;)
>> Aber ich schätze, die meisten Controller können sowas.

> Das mache ich ja quasi.
> ich triggere auf die High Flanke des Signals und möchte dann das
> Triggersignal um eine bestimmte Zeitverzögerung wieder ausgeben. Nur
> leider braucht mein Code mit der der IRQ routine um die 3 us bis der
> andere Pin high geschaltet wird. Deswegen möchte ich ja dann eine
> Periode warten ----

Nö das machst du überhaupt nicht. Wenn du das so machst wie ich es 
vorschlage hast du nur am Anfang ein bisschen Code zum initialisieren 
und danach wird keine einzige Zeile mehr ausgeführt.

Du brauchst um dieses Problem zu lösen keinen Code, keine Interrupts, 
keine Schleifen, keine GPIOs, nix. Du kannst die Hardware so 
konfigurieren dass sie sich so verhält wie du willst. Der Code 
konfiguriert nur die Hardware einmal am Anfang.

: Bearbeitet durch User
von Mirco K. (Gast)


Lesenswert?

Sven B. schrieb:
> Nö das machst du überhaupt nicht. Wenn du das so machst wie ich es
> vorschlage hast du nur am Anfang ein bisschen Code zum initialisieren
> und danach wird keine einzige Zeile mehr ausgeführt.
>
> Du brauchst um dieses Problem zu lösen keinen Code, keine Interrupts,
> keine Schleifen, keine GPIOs, nix. Du kannst die Hardware so
> konfigurieren dass sie sich so verhält wie du willst. Der Code
> konfiguriert nur die Hardware einmal am Anfang.

Ja, das stimmt. Ich habe es noch mit IRQs gemacht

Ich verzweifle hier gerade eher. Ich habe mir das manual von openstm32 
angeschaut und es dort versucht mit eclipse zu porgrammieren, aber 
leider ohne erfolg -.-

Wie kann ich denn z.B. etwas in ein Register schreiben wenn ich vorher 
die mbed.h includiert habe ?

von Sven B. (scummos)


Lesenswert?

So wie du es auch machen würdest wenn du vorher nicht die mbed.h 
includiert hast. Entweder du benutzt die Makros für die Register, oder 
halt ganz von Hand
1
*(volatile uint32_t*) 0x1234ABCD = 0

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.