Forum: Mikrocontroller und Digitale Elektronik Rechtecksignal


von No (freund_007)


Lesenswert?

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
von Rainer W. (rawi)


Lesenswert?

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?

von C-hater (c-hater)


Lesenswert?

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.

von No (freund_007)


Lesenswert?

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.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

kein delay() oder solchen Mist. Verwende einen Timer.

von No (freund_007)


Lesenswert?

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?

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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
von Thomas R. (Gast)


Lesenswert?

No schrieb:
> Mit Interrupts kenne ich mich leider nicht so gut aus..

Dann lerne das ... und dann niemals "delay"!

von Michael B. (laberkopp)


Lesenswert?

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.

von Rainer W. (rawi)


Lesenswert?

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"

von No (freund_007)


Lesenswert?

> 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?

von Marcel V. (mavin)


Angehängte Dateien:

Lesenswert?

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.

von Rainer W. (rawi)


Lesenswert?

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
von No (freund_007)


Lesenswert?

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

von Veit D. (devil-elec)


Lesenswert?

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
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von No (freund_007)


Lesenswert?

> 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 ??

von Rainer W. (rawi)


Lesenswert?

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
von Veit D. (devil-elec)


Lesenswert?

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
von No (freund_007)


Lesenswert?

> 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

von Veit D. (devil-elec)


Lesenswert?

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
von No (freund_007)


Lesenswert?

> 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.
von Veit D. (devil-elec)


Lesenswert?

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.

von No (freund_007)


Lesenswert?

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

von Veit D. (devil-elec)


Lesenswert?

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
von Michael B. (laberkopp)


Lesenswert?

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.

von Xanthippos (xanthippos)


Lesenswert?

Muss der MC nebenbei noch Eingaben bearbeiten? Willst du im laufenden 
Betrieb die Frequenz ändern?

von Mi N. (msx)


Lesenswert?

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.

von No (freund_007)


Lesenswert?

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!

von Peter D. (peda)


Lesenswert?

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.

von Gerald K. (geku)


Lesenswert?

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
von Veit D. (devil-elec)


Lesenswert?

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.

von Mi N. (msx)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Rainer W. (rawi)


Lesenswert?

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?

von Gerald K. (geku)


Lesenswert?

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.

von Mi N. (msx)


Angehängte Dateien:

Lesenswert?

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.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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
von Rainer W. (rawi)


Lesenswert?

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
von Mi N. (msx)


Lesenswert?

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.

von Rainer W. (rawi)


Lesenswert?

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
von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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.

von Rainer W. (rawi)


Lesenswert?

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

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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
von Rolf (rolf22)


Lesenswert?

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
Noch kein Account? Hier anmelden.