Hallo, ich möchte die Ausgangssignale von einem Inkrementalgeber mit Hilfe eines Microcontrollers(aussuchbar) emulieren. Ich möchte vorab eine Frequenz initalisieren(variabel von 50-200Hz) und 2 um 90 Grad verschobene Rechtecksignale digital ausgeben. Pro Umdrehung sollen 2000 Impulse gesetzt werden, das heisst bei einer Frequenz von 80Hz wäre das eine Periode von 0,0125 Sekunden und pro Impuls sind das 0,00000625 sekunden. Nun zum Problem: Bei einem herkömmlichen Arduino würde ich jetzt sagen, man könnte eine delay() Funktion verwenden und die Pins auf high bzw. Low setzten. Aber dies würde nicht funktionieren, da die Funktion eine int Variable in Microsekunden erwartet und ich einen exakten Taktpegel brauche. Mit Interrupts kenne ich mich leider nicht so gut aus.. Hat jemand eine Idee oder Anregung?
:
Bearbeitet durch User
No schrieb: > ich möchte die Ausgangssignale von einem Inkrementalgeber mit Hilfe > eines Microcontrollers(aussuchbar) emulieren. Mit oder ohne Drehrichtungswechsel? Einen Indexpuls brauchst du nicht?
No schrieb: > Hat jemand eine Idee oder Anregung? Ja: Lerne Programmieren. Als Annäherung erstmal auf Arduino verzichten. Wenn du es so geschafft hast, kriegst du es leicht hin, das auch innerhalb der Arduino-Umgebung zu tun.
Rainer W. schrieb: > No schrieb: >> ich möchte die Ausgangssignale von einem Inkrementalgeber mit Hilfe >> eines Microcontrollers(aussuchbar) emulieren. > > Mit oder ohne Drehrichtungswechsel? > Einen Indexpuls brauchst du nicht? Ich möchte keinen Drehrichtungswechsel vornehmen. Den Nullimpuls brauche ich auch, das kommt dann im Anschluss.
Veit D. schrieb: > Hallo, > > kein delay() oder solchen Mist. Verwende einen Timer. Könntest du mir grob sagen, wie ich das mit dem Timer anstelle, dass er je nach Eingangsfrequenz unterschiedlich ist?
Wenn es so genau sein soll, würde ich in programmierbarer Logik eine 2-bit-Statemachine bauen, die Software kann das genauso machen. Also mit vierfacher Frequenz die Zustände 00-01-11-10... durchlaufen. Damit ergeben sich die beiden Rechteckschwingungen. Oder in simpler TTL-Technik einen Rechteckoszillator der vierfachen Frequenz mit zwei D-Flipflops herunterteilen. Also zwei D-FF hintereinander, der /Q-Ausgang des zweiten geht auf den D des ersten. So macht man das gern bei simplen SDR-Schaltungen.
:
Bearbeitet durch User
No schrieb: > Mit Interrupts kenne ich mich leider nicht so gut aus.. Dann lerne das ... und dann niemals "delay"!
No schrieb: > Nun zum Problem Das Problem scheint mit vorher zu liegen. No schrieb: > Ich möchte vorab eine Frequenz initalisieren(variabel von 50-200Hz) und > 2 um 90 Grad verschobene Rechtecksignale digital ausgeben. > Pro Umdrehung sollen 2000 Impulse gesetzt werden, das heisst bei einer > Frequenz von 80Hz wäre das eine Periode von 0,0125 Sekunden und pro > Impuls sind das 0,00000625 sekunden Du meinst vermutlich Drehzahl statt Frequenz. Und Drehzahl wird in Umdrehungen pro Minute gezählt. Und schon sehen seine Impulse viel gemütlicher aus, nicht mehr 2.5us pro Impuls zu dem der zweite dann wohl um 1.25us zeitversetzt erfolgen muss, sondern 150us pro Impuls und maximal alle 75us ein Zustandswechsel. Das schafft ein Arduino (ATmega328) als Interruptroutine des ansonsten ungenutzten Timer1, passende Timeronitialisierung vorausgesetzt.
1 | uint8_t state,gray[]={1,3,2,0}; |
2 | ISR(TIMER1_COMPA_vect) |
3 | {
|
4 | PORTB=gray[state++&3]; |
5 | }
|
Auch stellt sich die Frage, ob wirklich 2000 und nicht doch eher nur 200 Impulse pro Umdrehung kommen. Bei einem Zustandswechsel alle 1.25us wird es schwer ohne Hatdwareunterstützung.
Veit D. schrieb: > Verwende einen Timer. Selbst das wird sportlich. Bei 12000 1/min und einem Inkrementalgeber mit 2000 Pulsen bräuchte man einen Basistakt mit einer Periode von 625 ns. Das hört sich eher nach einem Thema für einen FPGA an. Auch irgendwelche Interuptspiele sind da viel zu langsam. No schrieb: > ... man könnte eine delay() Funktion verwenden ... > Aber dies würde nicht funktionieren, da die Funktion eine int Variable > in Microsekunden erwartet ... Millisekunden Vielleicht solltest du dir erstmal über die Zeitskalen klar werden. > ... und ich einen exakten Taktpegel brauche. Was meinst du in diesem Zusammenhang mit "Taktpegel"
> Du meinst vermutlich Drehzahl statt Frequenz. Ob ich jetzt die Drehzahl oder die Frequenz einlesen lasse, ist doch egal oder nicht? Umrechenbar ist es beides. > Und schon sehen seine Impulse viel gemütlicher aus, nicht mehr 2.5us pro > Impuls zu dem der zweite dann wohl um 1.25us zeitversetzt erfolgen muss, > sondern 150us pro Impuls und maximal alle 75us ein Zustandswechsel. Mich würde Interessieren, was du gerechnet hast. > Auch stellt sich die Frage, ob wirklich 2000 und nicht doch eher nur 200 > Impulse pro Umdrehung kommen. Also der eigentliche Inkrementalgeber hat 2000 Striche, daraus leite ich es sind 2000Inkremente pro Umdrehung > Bei einem Zustandswechsel alle 1.25us wird es schwer ohne > Hatdwareunterstützung. Was könnte hierbei in Frage kommen?
Die 2000 Impulse pro Umdrehung kann man schon mal mit einem Frequenzteiler durch zwei teilen. Ein weiterer Frequenzteiler, der von der Ursprungsfrequenz, durch Vorschalten eines Inverters, auf die negative Flanke reagiert, erzeugt unabhängig von der Drehzahl immer ein exakt um 90° verschobenes Signal.
No schrieb: > Also der eigentliche Inkrementalgeber hat 2000 Striche, daraus leite ich > es sind 2000Inkremente pro Umdrehung Wie kommst du darauf? Da ist dir ein Faktor vier verloren gegangen.
:
Bearbeitet durch User
Rainer W. schrieb: > No schrieb: >> Also der eigentliche Inkrementalgeber hat 2000 Striche, daraus leite ich >> es sind 2000Inkremente pro Umdrehung > > Wie kommst du darauf? > Da ist dir ein Faktor vier verloren gegangen. Bitte um Erklärung
No schrieb: > Veit D. schrieb: >> Hallo, >> >> kein delay() oder solchen Mist. Verwende einen Timer. > > Könntest du mir grob sagen, wie ich das mit dem Timer anstelle, dass er > je nach Eingangsfrequenz unterschiedlich ist? Hallo, warum Eingangsfrequenz? Du willst doch einen Inkrementalgeber simulieren, demnach gibts nur 2 Ausgangsfrequenzen vom Controller aus gesehen. Das du 2000 Pulse pro Umdrehung simulieren möchtest ist hier irrelevant. Das ist nur die Interpretation des Auswertens also des Empfängers. Im Grunde programmierst du dir einen einstellbaren Frequenzgenerator mit einem Timer und 2 Compare Match Ausgängen. Timer 1 ist bei Arduino Uno/Mega immer frei für eigene Zwecke. Du fängst an mit irgendeinen Rechtecksignal erzeugen mit Timer 1. Absolute Grundlage dafür ist das Lesen des Timer Kapitels des Controller Manuals. Nochmal wegen deinen 2000 Pulsen und 80Hz usw. 2000 Pulse sind 2000 Pulse. Da gibt es keine Zeitangaben. 80Hz sind 80Hz. Das ist eine Zeitangabe was umgerechnet 12,5ms Periodendauer sind. Gibt man Pulse mit 80Hz aus ändert sich dadurch nicht plötzlich die Frequenz. Die bleibt ja 80Hz. Also wenn du 2000 Pulse mit 80Hz ausgehen möchtest dauert der Spaß 12,5ms * 2000 = 25s.
:
Bearbeitet durch User
No schrieb: > eine Periode von 0,0125 Sekunden und pro Impuls sind das 0,00000625 > sekunden. Techniker nehmen da gerne die Kürzel milli 'm' und mikro 'µ' um die Zahl der Nullen in erträglichem Rahmen zu halten... No schrieb: > Also der eigentliche Inkrementalgeber hat 2000 Striche, daraus leite ich > es sind 2000Inkremente pro Umdrehung Wenn der Geber tatsächlich 2000 Striche hat, dann kann ich aus dem Quadratursignal 8000 Inkremente ableiten (in "quad" taucht dieser Faktor 4 auf) . Wenn es nur 200 sind, dann reicht es immerhin für 800 Inkremente.
> Nochmal wegen deinen 2000 Pulsen und 80Hz usw. 2000 Pulse sind 2000 > Pulse. Da gibt es keine Zeitangaben. 80Hz sind 80Hz. Das ist eine > Zeitangabe was umgerechnet 12,5ms Periodendauer sind. Gibt man Pulse mit > 80Hz aus ändert sich dadurch nicht plötzlich die Frequenz. Die bleibt ja > 80Hz. Also wenn du 2000 Pulse mit 80Hz ausgehen möchtest dauert der Spaß > 12,5ms * 2000 = 25s. Das ist mir schon klar dass 80Hz=80Hz ist. Wie gesagt, mal ist die Frequenz 50 Hz mal ist sie 100Hz. Und je nachdem welche Frequenz ich habe, desto breiter/schmaler ist mein Impuls. 2000 Impulse sind für mich eine Periode, heisst wenn ich 50Hz hätte ergibt sich eine Periode von 0,02 Sekunden und jeder Impuls ist dann 0,00001s ??
No schrieb: > Bitte um Erklärung Pro Impuls auf A bzw. B hast du vier verschiedene Zustände n.
1 | A 0 0 1 1 0 0 1 1 ... |
2 | B 0 1 1 0 0 1 1 0 ... |
3 | n 1 2 3 4 1 2 3 4 ... |
Wenn du jede Flanke auswertest, ist die Zahl der Inkremente also einen Faktor vier höher als die Zahl der Pulse. https://de.wikipedia.org/wiki/Inkrementalgeber#Signalauswertung
:
Bearbeitet durch User
No schrieb: >> Nochmal wegen deinen 2000 Pulsen und 80Hz usw. 2000 Pulse sind 2000 >> Pulse. Da gibt es keine Zeitangaben. 80Hz sind 80Hz. Das ist eine >> Zeitangabe was umgerechnet 12,5ms Periodendauer sind. Gibt man Pulse mit >> 80Hz aus ändert sich dadurch nicht plötzlich die Frequenz. Die bleibt ja >> 80Hz. Also wenn du 2000 Pulse mit 80Hz ausgehen möchtest dauert der Spaß >> 12,5ms * 2000 = 25s. > > Das ist mir schon klar dass 80Hz=80Hz ist. Wie gesagt, mal ist die > Frequenz 50 Hz mal ist sie 100Hz. Und je nachdem welche Frequenz ich > habe, desto breiter/schmaler ist mein Impuls. 2000 Impulse sind für mich > eine Periode, heisst wenn ich 50Hz hätte ergibt sich eine Periode von > 0,02 Sekunden und jeder Impuls ist dann 0,00001s ?? Hallo, wenn du das so durcheinander würfelst haben wir ein Problem. Was machst du wenn du nur 123 Pulse ausgeben möchtest? Dann endet die gesamte Beschreibung im absoluten Kaos. Wenn dann redet man von der Frequenz des Pulses und deren Anzahl. Du musst ja den Puls erzeugen davon x in der Anzahl. Also ein Puls hat eine Periodendauer von angenommen 10µs. Das sind 100khz. Wäre noch machbar mit 16Bit Timer und 16MHz "Arduino". Auflösung wäre 160, sollte für etwas Phasenverschiebung reichen. Jetzt gehst du ran und konfigurierst dir deinen Timer für 100kHz. Wie gesagt am Ende programmierst du dir einen einstellbaren Frequenzgenerator inkl. änderbaren Duty. Falls du noch nie programmiert hast ist das ein schönes aber schon anspruchsvolles Projekt. Aus der Kalten heraus wird das jedoch nichts. Die Grundlagen müssen schon vorhanden sein. Denn irgendwie einstellbar muss er ja sein. Ob nun über Taster oder eigenen Inkrementalgeber oder über serielle Eingabe kommt ja noch alles dazu. Nur der Timer alleine ist es ja nicht.
:
Bearbeitet durch User
> Hallo, > > wenn du das so durcheinander würfelst haben wir ein Problem. > Was machst du wenn du nur 123 Pulse ausgeben möchtest? Dann endet die > gesamte Beschreibung im absoluten Kaos. Wenn dann redet man von der > Frequenz des Pulses und deren Anzahl. Du musst ja den Puls erzeugen > davon x in der Anzahl. Eine inkrementaler Drehgeber liefert Impulse pro Umdrehung. Je höher diese PPR bzw. je mehr Impulse pro Umdrehung, desto kleiner ist der Winkel zwischen jedem Impuls. Die Impulse pro Umdrehung werden bei normalen inkrementalen Drehgebern am Werk festgelegt. Da ich 2000 Striche abfahren würde, hat je nach umdrehungzahl der Impuls eine unterschiedliche dauer
Hallo, ich weiß wie ein Inkrementalgeber funktioniert. Ich kenne auch den nicht vorhandenen Zusammenhang zwischen Auflösung und Drehzahl. Ich kenne auch den Zusammenhang zwischen Drehzahl und Pulsbreite der Signale. Nur was willst du denn jetzt? Willst du die Signale messen? Oder willst du sie simulieren sprich ausgeben? > Da ich 2000 Striche abfahren würde, hat je nach umdrehungzahl der Impuls > eine unterschiedliche Dauer. Sag ich doch. Du willst die Frequenz des Pulses variabel halten. Es macht jedoch keinen Sinn immer von 2000 Pulsen zu reden die Dein Teil pro Umdrehung kann, sprich Auflösung hat. Man wird ja nie immer nur volle Umdrehungen haben wollen.
:
Bearbeitet durch User
> Nur was willst du denn jetzt? Willst du die Signale messen? Oder willst > du sie simulieren sprich ausgeben? Ich möchte die Signale simulieren >> Da ich 2000 Striche abfahren würde, hat je nach umdrehungzahl der Impuls >> eine unterschiedliche Dauer. > > Sag ich doch. Du willst die Frequenz des Pulses variabel halten. Es > macht jedoch keinen Sinn immer von 2000 Pulsen zu reden die Dein Teil > pro Umdrehung kann, sprich Auflösung hat. Man wird ja nie immer nur > volle Umdrehungen haben wollen. Was ich dann aber nicht verstehe, ich muss doch wissen wieviele Pulse er in einer Umdrehung machen kann. Um zu sagen, wenn ich jetzt bspw 16,3U/min mache wieviel Impulse er absetzten muss in welchen Zeitschritten
Beitrag #7428016 wurde vom Autor gelöscht.
No schrieb: >> Nur was willst du denn jetzt? Willst du die Signale messen? Oder willst >> du sie simulieren sprich ausgeben? > Ich möchte die Signale simulieren Also ausgeben. Kannst du das nicht einfach schreiben. Es geht um Verständigung! >>> Da ich 2000 Striche abfahren würde, hat je nach umdrehungzahl der Impuls >>> eine unterschiedliche Dauer. >> >> Sag ich doch. Du willst die Frequenz des Pulses variabel halten. Es >> macht jedoch keinen Sinn immer von 2000 Pulsen zu reden die Dein Teil >> pro Umdrehung kann, sprich Auflösung hat. Man wird ja nie immer nur >> volle Umdrehungen haben wollen. > > Was ich dann aber nicht verstehe, ich muss doch wissen wieviele Pulse er > in einer Umdrehung machen kann. Um zu sagen, wenn ich jetzt bspw > 16,3U/min mache wieviel Impulse er absetzten muss in welchen > Zeitschritten Das ist doch alles nachgelagert und nur die Art der Interpretation. Es geht doch erstmal um die Erzeugung der Signale. Dafür ist nur die Pulsfrequenz und deren Anzahl entscheidend. Wenn das geht gibst du nur Parameter ein und der Simulator gibt entsprechende Signale aus. Wenn du weißt das der Gegenüber 2000 Pulse benötigt gibts du 2000 ein. Benötigt ein anderes Gegenüber für eine Umdrehung nur 1000 Pulse gibts du 1000. Variabel bleiben! Nicht auf irgendwelche Werte versteifen. Immer den kleinsten gemeinsamen Nenner suchen - das ist der einzelne Puls. Den willst du ja schließlich mit deinem Simulator erzeugen und variieren. Sonst braucht du auch keinen Simulator.
Das ist doch alles nachgelagert und nur die Art der Interpretation. Es > geht doch erstmal um die Erzeugung der Signale. Dafür ist nur die > Pulsfrequenz und deren Anzahl entscheidend. Wenn das geht gibst du nur > Parameter ein und der Simulator gibt entsprechende Signale aus. > Wenn du weißt das der Gegenüber 2000 Pulse benötigt gibts du 2000 ein. > Benötigt ein anderes Gegenüber für eine Umdrehung nur 1000 Pulse gibts > du 1000. Variabel bleiben! Nicht auf irgendwelche Werte versteifen. > Immer den kleinsten gemeinsamen Nenner suchen - das ist der einzelne > Puls. Den willst du ja schließlich mit deinem Simulator erzeugen und > variieren. Sonst braucht du auch keinen Simulator. Aber ich muss die Impulse doch für eine gewisse Zeit auf high oder low legen. Dafür muss ich doch aus der eingelesenen Umdrehungszahl wissen, wieviel impulse der eigentlich machen soll. Ich kann ja nicht einfach nur weil Umdrehungszahl 30 1/min ist sagen dass die Pulsfrequenz 2 Hz ist
Hallo, Mensch Meier. Wir reden vom Simulator. Deswegen soll und muss es variabel bleiben und du darfst dich nicht immer auf deine 2000 Pulse etc. versteifen. Natürlich muss das Programm die Parameter Drehzahl, Auflösung und Winkel bzw. Umdrehungen umrechnen und daraus den Timer entsprechend konfigurieren. Das hatte ich vorausgesetzt. Und genau deswegen muss der Timer für die eine Pulsdauer konfiguriert werden und schaltet nach x Pulsen ab. Mach dir einmal die Zusammenhänge klar.
:
Bearbeitet durch User
No schrieb: > Was könnte hierbei in Frage kommen? Nicht die internen Timer des ATmega. Es nützt auch nichts, 16MHz durch 10 zu teilen bis bei 12000 Umdrehungen pro Minute alle 625ns ein Zustandswechsel erfolgt, weil der nächste Teiler dann 11 ist und nur noch 10909 Umdrehungen pro Minute entspricht, ein ziemlich grosser Schritt, dann 10000upm, dann 9230. Es nützt auch auch nichts, dir jetzt aufwändig alle Grundlagen der Impulsetzeugung vorzukauen, weil viel wahrscheinlicher ist, dass du Hz und upm durcheinanderbringst. Schliesslich sind Incrementalencoder, egal ob optisch oder magnetisch abgetastet, normalerweise nicht in der Lage unter 1us Impulse auszugeben.
Muss der MC nebenbei noch Eingaben bearbeiten? Willst du im laufenden Betrieb die Frequenz ändern?
Was ist denn das Problem mit meiner Lösung? http://mino-elektronik.de/Generator/takte_impulse.htm#bsp5a Man kann die Frequenz noch erhöhen und mit einem anderen µC auch noch mehr. Recht schnell würde ein RP2040 mit einem autarken PIO-Kanal arbeiten und sich dabei noch langweilen.
Mi N. schrieb: > Was ist denn das Problem mit meiner Lösung? > http://mino-elektronik.de/Generator/takte_impulse.htm#bsp5a > > Man kann die Frequenz noch erhöhen und mit einem anderen µC auch noch > mehr. > Recht schnell würde ein RP2040 mit einem autarken PIO-Kanal arbeiten und > sich dabei noch langweilen. Moin, ich hatte deine Nachricht übersehen. Ja du hast echt eine gute Lösung, ich müsste nur die Schrittzahl anpassen und den Poti herausnehmen. Vielen Dank dafür!
No schrieb: > 2000 Impulse sind für mich > eine Periode Also meint 200Hz dann 200s^-1 = 12000min^-1, das ist ganz schön schnell. Die Frequenz ist also 400kHz bzw. 2,5µs Pulsdauer. Das sind dann bei 16MHz 40 Takte je Puls. Das wird in C tricky, da sollte man wohl Assembler nehmen. Für Interruptgedöns ist auch keine Zeit mehr, da geht nur Polling.
Vorschlag von ChatGPT für den MC MSP430G2553 Interrupt gesteuerte Lösung:
1 | #include <msp430g2553.h> |
2 | |
3 | #define SIGNAL_PIN1 BIT0 // P1.0
|
4 | #define SIGNAL_PIN2 BIT6 // P1.6
|
5 | |
6 | volatile unsigned int frequency = 50; // Startfrequenz (in Hz) |
7 | volatile unsigned int half_period_count = 0; |
8 | volatile unsigned int half_period_delay = 0; |
9 | |
10 | void setupPWM() |
11 | {
|
12 | TA0CCR0 = 1000 - 1; // Timer-A0 Zählergrenze (1ms Zykluszeit) |
13 | TA0CCTL1 = OUTMOD_7; // Timer-A0 Capture/Compare 1 in Set/Reset-Modus |
14 | TA0CCR1 = 500; // Signalbreite (Anpassung für 50% Tastverhältnis) |
15 | |
16 | TA1CCR0 = 1000 - 1; // Timer-A1 Zählergrenze (1ms Zykluszeit) |
17 | TA1CCTL1 = OUTMOD_7; // Timer-A1 Capture/Compare 1 in Set/Reset-Modus |
18 | TA1CCR1 = 500; // Signalbreite (Anpassung für 50% Tastverhältnis) |
19 | |
20 | TA0CTL = TASSEL_2 + MC_1; // SMCLK als Timer-A0 Quelle, Up-Modus |
21 | TA1CTL = TASSEL_2 + MC_1; // SMCLK als Timer-A1 Quelle, Up-Modus |
22 | }
|
23 | |
24 | void setupInterrupts() |
25 | {
|
26 | CCTL0 = CCIE; // CCR0 Interrupt aktivieren |
27 | CCR0 = 1000 - 1; // Timer-A0 Zählergrenze (1ms Zykluszeit) |
28 | TACTL = TASSEL_2 + MC_1; // SMCLK als Timer-A0 Quelle, Up-Modus |
29 | }
|
30 | |
31 | void main(void) |
32 | {
|
33 | WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer anhalten |
34 | BCSCTL1 = CALBC1_1MHZ; // DCO auf 1 MHz einstellen |
35 | DCOCTL = CALDCO_1MHZ; |
36 | |
37 | P1DIR |= SIGNAL_PIN1 + SIGNAL_PIN2; // Signal-Pins als Ausgänge konfigurieren |
38 | P1OUT &= ~(SIGNAL_PIN1 + SIGNAL_PIN2); // Signal-Pins auf LOW setzen |
39 | |
40 | setupPWM(); |
41 | setupInterrupts(); |
42 | |
43 | __bis_SR_register(LPM0_bits + GIE); // Low-Power-Modus 0 + globale Interrupts aktivieren |
44 | }
|
45 | |
46 | #pragma vector = TIMER0_A0_VECTOR
|
47 | __interrupt void Timer_A0_ISR(void) |
48 | {
|
49 | half_period_count++; |
50 | |
51 | if (half_period_count >= half_period_delay) |
52 | {
|
53 | P1OUT |= SIGNAL_PIN1; |
54 | }
|
55 | |
56 | if (half_period_count >= half_period_delay + 500) |
57 | {
|
58 | P1OUT &= ~SIGNAL_PIN1; |
59 | half_period_count = 0; |
60 | }
|
61 | }
|
62 | |
63 | #pragma vector = TIMER1_A0_VECTOR
|
64 | __interrupt void Timer_A1_ISR(void) |
65 | {
|
66 | P1OUT ^= SIGNAL_PIN2; // Rechtecksignal um 90 Grad verschoben |
67 | }
|
In diesem Code wird Timer A0 verwendet, um das erste Rechtecksignal zu erzeugen, und Timer A1, um das zweite Rechtecksignal um 90 Grad zu verschieben. Die Funktion setupPWM() konfiguriert die Timer und die entsprechenden Capture/Compare-Register, um das PWM-Signal zu erzeugen. Die Funktion setupInterrupts() konfiguriert den Timer A0, um die gewünschte Frequenz zu erzeugen, und aktiviert den Interrupt für Timer A0. Der Timer_A0_ISR-Interrupt-Handler wird bei jedem Timer-A0-Überlauf ausgelöst. Er erhöht den half_period_count und überprüft, ob es an der Zeit ist, das Rechtecksignal ein- oder auszuschalten, basierend auf der aktuellen half_period_delay (halbe Periode). Das half_period_count wird zurückgesetzt, wenn das Rechtecksignal ausgeschaltet wird. Der Timer_A1_ISR-Interrupt-Handler wird bei jedem Timer-A1-Überlauf ausgelöst und schaltet einfach das zweite Rechtecksignal um 90 Grad (invers) ein und aus. Die Konstante OUTMOD_7 ist Teil der MSP430-Bibliothek und wird verwendet, um den Ausgangsmodus eines Timer-A Capture/Compare-Registers (CCR) zu konfigurieren. Entwicklungsboard 12,49€ : https://mou.sr/3WTczix
:
Bearbeitet durch User
Hallo, tja wie ich schon sagte, es wird ein Frequenzgenerator. Takt ist auf einen Puls bezogen plus Anzahl der Pulse. Warum das nicht verstanden wurde kann ich nicht nachvollziehen. Weil genau darauf laufen alle gezeigten Lösungen hinaus.
Peter D. schrieb: > Das sind dann bei 16MHz 40 Takte je Puls. Das wird in C tricky, da > sollte man wohl Assembler nehmen. Wie erwähnt, ein RP2040 macht das ganz locker mit einer Schrittfrequenz > 100 MHz. Entsprechend konfiguriert werden vier Befehle benötigt, was dann symbolisch so aussehen kann: .wrap target set pins,0 set pins,1 set pins,3 set pins,2 .wrap Mit 'autowrap' braucht die Schleife keinen einzigen Takt. Für etwas niedrigere Frequenzen kann man die set-Befehle mit bis zu 31 Wartezyklen im Raster < 10 ns versehen oder noch langsamer mit Warteschleifen mit einem internen Register oder externen IRQ einfügen. Die Befehle kann man zudem zur Laufzeit umprogrammieren. Eine kleine Spielerei und wer es braucht auch in Arduino ;-) Gerald K. schrieb: > Entwicklungsboard 12,49€ : https://mou.sr/3WTczix Das muß nicht sein.
No schrieb: > Pro Umdrehung sollen 2000 Impulse gesetzt werden, das heisst bei einer > Frequenz von 80Hz wäre das eine Periode von 0,0125 Sekunden und pro > Impuls sind das 0,00000625 sekunden. Diese Angaben sind sehr verwirrend, wenn Du mit 80Hz eigentlich 160kHz meinst. Klar ist auch nicht, ob Du 2000 Phasenwechsel oder 2000 Quadraturperioden meinst. Bei Deinen max 400kHz sind das dann 2,5µs je Wechsel oder 625ns. Beim AVR mit 16MHz sind das 40 bzw. 10 CPU-Zyklen je Wechsel. 10 Zyklen ist sportlich, aber machbar, wenn man 2 PWM-Ausgänge nimmt. Im Interruptpolling alle 20 Zyklen kann man dann die Pulse zählen und den Timer stoppen.
Gerald K. schrieb: > Der Timer_A0_ISR-Interrupt-Handler wird bei jedem Timer-A0-Überlauf > ausgelöst. Er erhöht den half_period_count und überprüft, ob es an der > Zeit ist, das Rechtecksignal ein- oder auszuschalten, Und du bist sicher, dass der ChatGPT berücksichtigt hat, dass bei 12000 1/min und 2000 Pulsen pro Umdrehung genau 1.25us zwischen den Interruptaufrufen liegen?
Rainer W. schrieb: > Gerald K. schrieb: >> Der Timer_A0_ISR-Interrupt-Handler wird bei jedem Timer-A0-Überlauf >> ausgelöst. Er erhöht den half_period_count und überprüft, ob es an der >> Zeit ist, das Rechtecksignal ein- oder auszuschalten, > > Und du bist sicher, dass der ChatGPT berücksichtigt hat, dass bei 12000 > 1/min und 2000 Pulsen pro Umdrehung genau 1.25us zwischen den > Interruptaufrufen liegen? Das wird sich bei einen Takt von 1MHz nicht ausgehen. No schrieb: > Ich möchte vorab eine Frequenz initalisieren(variabel von 50-200Hz) und > 2 um 90 Grad verschobene Rechtecksignale digital ausgeben. 200Hz sind Rechtecksignale von 5ms Periode.
Zum Feierabend habe ich mit dem RP2040 gespielt. Das Programm zum Erzeugen der Ausgangssignale sieht so aus:
1 | void init_PIO_encoder(void) |
2 | {
|
3 | // PIO0 aktivieren
|
4 | RESETS_CLR->RESET = RESETS_RESET_pio0_Msk; |
5 | while (!(RESETS->RESET_DONE & RESETS_RESET_pio0_Msk)); |
6 | // Pin0 und Pin1 fuer PIO0
|
7 | IO_BANK0->GPIO0_CTRL = IO_BANK0_GPIO0_CTRL_FUNCSEL_pio0_0; |
8 | IO_BANK0->GPIO1_CTRL = IO_BANK0_GPIO0_CTRL_FUNCSEL_pio0_0; |
9 | SIO->GPIO_OE_SET = 0x3; // als Ausgang |
10 | // Zuordnung fuer set-Befehle
|
11 | PIO0->SM0_PINCTRL = 2<<PIO0_SM0_PINCTRL_SET_COUNT_Pos | 0<<PIO0_SM0_PINCTRL_SET_BASE_Pos; |
12 | PIO0->SM0_INSTR = 0xe083; // set pindirs |
13 | |
14 | // Schleife 0 -> 3
|
15 | PIO0->SM0_EXECCTRL = (0 << PIO0_SM0_EXECCTRL_WRAP_BOTTOM_Pos) | |
16 | (3 << PIO0_SM0_EXECCTRL_WRAP_TOP_Pos); |
17 | // ab ADR0
|
18 | PIO0->INSTR_MEM0 = 0xe000; // set pins,1 |
19 | PIO0->INSTR_MEM1 = 0xe001; // set pins,2 |
20 | PIO0->INSTR_MEM2 = 0xe003; // set pins,3 |
21 | PIO0->INSTR_MEM3 = 0xe002; // set pins,2 |
22 | |
23 | PIO0->SM0_INSTR = 0; // Startadresse |
24 | PIO0->SM0_CLKDIV = (1 << PIO0_SM0_CLKDIV_INT_Pos); // Taktteiler = 1 |
25 | PIO0_SET->CTRL = (1 << (PIO0_CTRL_SM_ENABLE_Pos)); // starten |
26 | while(1); // PIO0_SM0 laeuft |
27 | }
|
Die Ausgangsfrequenz läßt sich zur Laufzeit einfach durch Ändern des 'PIO0->SM0_CLKDIV'-Registers anpassen. Bei 200 MHz Taktfrequenz und Vorteiler 1 ergibt sich ein 50 MHz Signal mit vier Phasen. Bei 0xffff sind es rund 755 Hz. Noch langsamer wäre kein Problem. Dazu noch die Bilder, die kein besonders gutes Massesignal zeigen - egal.
http://www.elexs.de/iq1.htm Hier eine Version nur mit Hardware. Ein seriell einstellbarer Taktgenerator (CY27EE16) speist zwei D-Flipflops (74HC74), die zwei um 90 Grad versetzte Rechteckschwingungen ausgeben. Anschließend ein Mischer aus Analogschaltern für einen SDR. Für eine Drehrichtungsänderung reicht übrigens ein Schalter 2*um als "Polwendeschalter" beschaltet.
:
Bearbeitet durch User
Gerald K. schrieb: > 200Hz sind Rechtecksignale von 5ms Periode. No schrieb: > ... und pro Impuls sind das 0,00000625 sekunden No, wie wäre es, wenn du an Stelle deiner Prosa ein vernünftiges Zeitdiagramm zeigt, aus dem klar hervor geht, was du nun wirklich erzeugen willst? Und möglichst nicht mit Kindergartenzahlen mit 12-und-drölfzig Nullen ...
:
Bearbeitet durch User
Rainer W. schrieb: > No, wie wäre es, Was im Detail passieren soll, ist mir zwar auch nicht klar, aber das muß der TO selber wissen. Dafür brauche ich allerdings keine Diagramme oder Fotos von seiner virtuellen Anwendung. Hinreichend Vorschläge hat er erhalten.
Christoph db1uq K. schrieb: > http://www.elexs.de/iq1.htm Ist es wirklich so schwierig, lesbare Schaltpläne zu malen? Grausig - wozu wurden eigentlich aussagekräftige Schaltzeichen erfunden?
:
Bearbeitet durch User
Ja, so würde es jemand malen, der das ganze auf einem Steckbrett handverdrahtet. Der muss sich dann nicht wundern, wenn er HF-Einstreuungen bekommt. Was ich damit sagen wollte, wenn irgendwo ein Rechteckgenerator rumliegt kann der mit nur einem 74HC74 zum gewünschten 0/90 Grad Oszillator erweitert werden. Mit einem DDS-Synthesizer ließen sich auch hohe Frequenzen fein abgestuft erzeugen, mit allerdings größerem Phasenjitter. Auch einen Arduino kann man als DDS-Generator programmieren, vielleicht wäre das eine Möglichkeit, wenn es unbedingt auf dem Arduino laufen soll.
Christoph db1uq K. schrieb: > Ja, so würde es jemand malen, der das ganze auf einem Steckbrett > handverdrahtet. Das ist für mich eine Steckanleitung (Malen-nach-Zahlen), aber kein Schaltplan. "Ein Schaltplan (auch Schaltbild oder Schaltskizze) ist eine in der Elektrik und Elektronik gebräuchliche grafische Darstellung einer Schaltung. Sie berücksichtigt nicht die reale Gestalt und Anordnung der Bauelemente, sondern ist eine abstrahierte Darstellung der Funktionen in Form definierter Symbole für die einzelnen Bauelemente und deren elektrische Verschaltung." aus: https://de.wikipedia.org/wiki/Schaltplan
Ich kenne solche Pläne noch aus der Anfangszeit des Atari ST um 1987. Da gab es ein Malprogramm, mit dem man solche Bilder Strich für Strich zeichnen konnte. Ich habe das auch mal benutzt. Sogar Bücher wurden mit solchen Zeichnungen illustriert. Es gab noch keine kostenlose oder preisgünstige Schaltplansoftware. Aber heute ist das nur noch Nostalgie, in Ehren ergraut. Beispiel: https://www.atariuptodate.de/de/727/schaltplan# https://www.atariuptodate.de/de/image https://www.atariuptodate.de/de/atari-pd-serie/st-computer/1-50
:
Bearbeitet durch User
No schrieb: > Könntest du mir grob sagen, wie ich das mit dem Timer anstelle, dass er > je nach Eingangsfrequenz unterschiedlich ist? Grob: Der Timer muss je nach gewünschter Frequenz on-the-fly (um)programmiert werden. Die Eingangsfrequenz muss man vorher per Software aus einem Eingangssignal errechnen. Um beides zu schaffen, wirst du das Datenblatt des Prozessors genauestens(!) studieren müssen und hardwarenah programmieren (d. h. auf Registerebene denken) können. Einige haben hier Interrupts erwähnt. Die braucht man aber je nach Prozessor überhaupt nicht (oder sie sind zu langsam). Oft gibt es ja Timer mit Ausgängen, an denen man bei passender Programmierung unmittelbar ein Rechtecksignal abnehmen kann. Der ATmega328 mit 16 Megahertz zum Beispiel hat solche Timer, die Rechteck-Signale bis 8 MHz ausgeben können. Er hat auch einen Input-Capture-Eingang, über den man die gewünschte Frequenz per Software ermitteln kann. Ob es mit diesem Prozessor geht, weiß ich dennoch nicht: Die Probleme liegen oft in winzigen Details. Das alles wirst du jedenfalls mit ein paar Tipps nicht schaffen. Allein schon das Datenblatt verlangt beim Lesen so einiges an Sprachdisziplin. Umdrehungszahl ist etwas anderes wie Drehzahl, Puls ist nicht Impuls, ...
:
Bearbeitet durch User
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.