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.
Das ganze Problem bitte. Die Beschreibung ist ungenuegend. Der Trigger kommt alle 3-100ms, und soll um wieviel verzoegert werden ?
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.
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.
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 :)
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
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...
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 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
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
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.
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!
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 ----
> Das mache ich ja quasi.
Hast du eigentlich schonmal im Datenblatt deines Controllers den
Abschnitt ueber die integrierten Timer gelesen? Verstanden?
Olaf
> Das mache ich ja quasi.
Nö machst du nicht! Du sollst die Hardware Timer/Counter so
KONFIGURIEREN das diese alles selbstständig machen.
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
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?
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
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?
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.
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.
> 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.
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
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 ?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.