Frequenz errechnen

OP #2844966
Lesenswert?

Hallo zusammen,

ich habe ein RN-MEGA2560 Mikrocontroller und möchte einen Takt für einen 
Schrittmotor von 400 Hz erzeugen. Der Quarz hat einen Wert von 16000000, 
der Prescaler liegt bei 256 und ich verwende einen 16-Bit Timer den ich 
auf einen Timerwert von 65380 einstelle. Als Ergebnis erhalte ich einen 
Wert von 400,6410256 Hz.

Kann mir bitte jemand mitteilen, ob das Ergebnis falsch oder richtig 
ist.

Vielen Dank für die Hilfe.
Gast #2844985
Lesenswert?

Müsste stimmen.
Aber wenn du schon einen 16Bit Timer hast, könntest du ja auch einen 
kleineren Prescaler wählen und die 400Hz deutlich besser erreichen, z.B. 
ganz ohne Prescaler und Vorbelegung mit 25.536 oder andere 
Kombinationen...
Gast #2844993
Lesenswert?

Die Antwort hängt davon ab, was du damit meinst:

Thomas Holländer schrieb:
> einen 16-Bit Timer den ich auf einen Timerwert von 65380 einstelle

Wenn du den Timer im CTC-Modus betreibst und diesen Wert als CTC-Wert 
einstellst, ist es falsch. Wenn du den eher ungeschickteren Weg nimmst, 
wirklich den Zählwert des Timers mit dem obigen Wert quasi vorzubelegen, 
ist die Timer-Wartezeit grob 1/400 Sekunde, was so jetzt auch erstmal 
noch nichts mit einem Takt von 400 Hz zu tun hat.
Gast #2845237
Lesenswert?

Vielleicht schrieb:
> Denk aber dran, daß die Frequenz, mit dem der Timer seinen TOP Wert
> erreicht, nicht gleich der Frequenz des Signals für den Stepper sein
> muß.

Thomas Holländer schrieb:
> Was meinst du damit?

ca. 400Hz ist die Frequenz die du ausgerechnet hast. Du schreibst aber 
nicht, wie du daraus ein Signal auf dem µC Pin machst. per ISR, per Pin 
toggle, per PWM, per sonstigem Programm und wie sieht das aus ??? Und 
weiter vom Pin geht es durch einen Treiber zum Stepper. All das kann 
Einfluß auf den Steppertakt haben. Da die Infos nicht vorliegen, können 
wir nicht wissen, ob die 400Hz auch am Stepper ankommen.
OP #2845279
Lesenswert?

Hier mal das Bascom-Programm:
1
' Stepper Testprogram
2

3
$prog , 255 , &B11011001,
4
$regfile = "m2560def.dat"
5
$hwstack = 82                                               '80
6
$framesize = 68                                             ' 64
7
$swstack = 68                                               '44
8

9

10
$crystal = 16000000                                         'Quarzfrequenz
11
$baud = 19200
12

13

14
Config Pind.5 = Output
15
Led Alias Portd.5
16

17
Config Pinc.0 = Output                                      ' Stiftleiste JP 2; Pin 3; PC0
18
Stepper1_reset Alias Portc.0
19

20
Config Pinc.1 = Output                                      ' Stiftleiste JP 2; Pin 4; PC1
21
Stepper1_direction Alias Portc.1
22

23
Config Pinc.2 = Output                                      ' Stiftleiste JP 2, Pin 5; PC2
24
Stepper1_enable Alias Pinc.2
25

26
Config Pinc.3 = Output                                      ' Stiftleiste JP 2, Pin 6; PC3
27
Stepper1_step Alias Pinc.3
28

29
Echo Off
30

31
Led = 0                                                     ' LED einschalten
32

33

34
Stepper1_direction = 0                                      
35
Stepper1_enable = 0                                        
36

37

38
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
39
Config Timer1 = Timer , Prescale = 64                     
40
Enable Timer1
41
On Timer1 Timer_irq
42
Enable Interrupts
43
Timer1 = 64911
44
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
45

46
  Do
47
      Toggle Led
48
      Waitms 500
49
  Loop
50

51
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
52
End
53

54
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
55
Timer_irq:
56
Timer1 = 64911
57
Stepper1_step = 0 : Waitus 1 : Stepper1_step = 1            
58
Return

Das Signal wird über Pin 6 an die Schrittmotorsteuerung weiter gegeben. 
Von da aus gehts zum Schrittmotor.

Ich hoffe die Angaben reichen jetzt:-)
Gast #2845597
Lesenswert?

Thomas Holländer schrieb:
> 2. Welche Nachteile hat meine Variante?

Die ISR kann man sich sparen. Die low Zeit des Signals stellst du über 
die Krücke WAITMS und das auch noch im Interrupt ein.
1
COMPARE1A = 2499
2
CONFIG TIMER1 = TIMER , COMPARE A = TOGGLE , CLEAR TIMER = 1 , PRESCALE = 8

Damit kann man den CTC mode einstellen. Der Timer läuft bis zum 
COMPARE1A Wert und fängt dann wieder bei 0 an. Bei dieser Einstellung 
und dem 16MHz Systemtakt tut er das mit 800Hz. Durch das "COMPARE A = 
TOGGLE", schaltet er den OC1A Pin des µC immer um und du erhältst ein 
400Hz Rechteck mit 50% Tastverhältnis.

Damit bist du allerdings auf den OC1A Pin des µC festgelegt und 
müßtest die Verkabelung entsprechend anpassen. (Dieser CONFIG TIMER 
Befehl konfiguriert sogar den OC1A Pin auf OUTPUT - muß also nicht 
explizit als Output eingestellt werden.

Zugegebenermaßen ist der CONFIG TIMER BASCOM Befehl nicht gut 
dokumentiert und ich bin hinter die Funktion nur mit Datenblatt des µC 
und Simulator gekommen.

Es gibt je nach Anforderung viele Möglichkeiten das Signal zu erzeugen. 
Komplett kann man das nur dem Datenblatt entnehmen.
OP #2857694
Lesenswert?

Ich nehme jetzt den "normalen" Timer und habe folgendes Programm 
erstellt, womit ich erfolgreich einen Schrittmotor drehen lassen kann.
1
' Stepper Testprogram
2

3
$prog , 255 , &B11011001,
4
$regfile = "m2560def.dat"
5
$hwstack = 82                                               '80
6
$framesize = 68                                             ' 64
7
$swstack = 68                                               '44
8

9

10
$crystal = 16000000                                         'Quarzfrequenz
11
$baud = 19200
12

13

14
Config Pind.5 = Output
15
Led Alias Portd.5
16

17
Config Pinc.0 = Output                                      ' Stiftleiste JP 2; Pin 3; PC0
18
Stepper1_reset Alias Portc.0
19

20
Config Pinc.1 = Output                                      ' Stiftleiste JP 2; Pin 4; PC1
21
Stepper1_direction Alias Portc.1
22

23
Config Pinc.2 = Output                                      ' Stiftleiste JP 2, Pin 5; PC2
24
Stepper1_enable Alias Pinc.2
25

26
Config Pinc.3 = Output                                      ' Stiftleiste JP 2, Pin 6; PC3
27
Stepper1_step Alias Pinc.3
28

29
Config Pinb.7 = Output
30
Takt Alias Pinb.7
31

32
Dim I1 As Integer
33
Dim Takt_hz As Long
34

35
Echo Off
36

37
Led = 0                                                     ' LED einschalten
38

39

40
Do
41
   Toggle Led
42
   Waitms 75
43
   I1 = I1 + 1
44
Loop Until I1 = 20
45

46
Wait 5
47

48
Stepper1_direction = 0                                      ' Stepper1_direction = off (0 Volt); Stiftleiste JP 2; Pin 4; PC1
49
Stepper1_enable = 0                                         ' Stepper1_enable    = off (0 Volt); Stiftleiste JP 2, Pin 5; PC2
50

51
Takt_hz = 64147
52
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
53

54
On Timer1 Timer_irq
55
Enable Timer1
56
Config Timer1 = Timer , Prescale = 64                       ' Stiftleiste JP 1; Pin 26
57
Enable Interrupts
58
' Timer1 = 60536                                              ' 50 Hz     64147
59
Timer1 = Takt_hz
60
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
61

62
  Do
63
      Toggle Led
64
      Wait 5
65
      Takt_hz = 63036                                       ' 100 Hz
66

67
      Toggle Led
68
      Wait 5
69
      Takt_hz = 63869                                       ' 150 Hz
70

71
      Toggle Led
72
      Wait 5
73
      Takt_hz = 64286                                       ' 200 Hz
74

75
      Toggle Led
76
      Wait 5
77
      Takt_hz = 64536                                       ' 250 Hz
78

79
      Toggle Led
80
      Wait 5
81
      Takt_hz = 64703                                       ' 300 Hz
82

83
  Loop
84

85
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
86
End
87

88
'Dies ist der Programmteil, der in dem von ihnen gewählten
89
'Intervall aufgerufen wird
90
Timer_irq:
91
Timer1 = Takt_hz
92

93
Stepper1_step = 0 : Waitus 3 : Stepper1_step = 1 : Waitus 3 ' Stiftleiste JP 2, Pin 6
94

95
Return

Laut meinen Berechnungen steigert sich alle 5 Sekunden die Frequenz um 
50 Hz, beginnend ab 50 Hz. Das funktioniert auch, allerdings zeigt mein 
Frequenzmessgerät andere Hz-Werte an:

Errechnet Timer1:         Messgerät:

 50 Hz                     50 Hz
100 Hz                     75 Hz
150 Hz                    100 Hz
200 Hz                    125 Hz
250 Hz                    150 Hz
300 Hz                    175 Hz

Wie kommt es zu den Unterschieden? Geht des Messgerät 
(http://www.conrad.de/ce/de/product/124403/VOLTCRAFT-VC170-Digital-Multimeter-VC100-Serie-4000-Counts-CAT-III-250-V/1101010&ref=list)
falsch oder habe ich mich bei den Timerwerten verrechnet?

Vielen Dank für die Hilfe.
OP #2857760
Lesenswert?

Die Berechnung erfolgte nach folgender Formel:
Ich hoffe die Formel stimmt.
Gast #2857767
Lesenswert?

Simon K. schrieb:
> Brauch man denn für alles heute ein Tutorial?

Zu jedem Mist ein Tutorial ist wohl etwas übertrieben. Ein vernünftiger 
Quellcodegenerierungsassistent sollte es auch tun ;-)

Früher (tm) musste man sich durch Tabellen und Erläuterungen im 
Datenblatt durchwühlen :-(
#2857771
Lesenswert?

Thomas Holländer schrieb:
> Die Berechnung erfolgte nach folgender Formel:

Die Formel hab ich jetzt nicht kontrolliert. Ich hab deine Werte 
nachgerechnet und sie scheinen zu stimmen.

Trotzdem ist der ganze Ansatz verquert.
Nimm den CTC Modus und Toggle in der ISR den Pin. Dann brauchst du auch 
solche Hacks mit der Wartezeit in der ISR nicht um einen Puls zu formen.

Dein Messgerät ist sicherlich nicht 'zu ungenau'. 200Hz muss jeder 
Frequenzmesser problemlos messen können und ausserdem sind die 
gemessenen Werte zu schön im 25Hz Raster, als das das Zufall sein 
könnte.

Was ich mir höchtens vorstellen könnte ist, dass dein Messgerät mit den 
3 µs Pulsen nicht glücklich ist.

Daher. mach es richtig. In der Timer ISR den Pin Toggeln, so dass es 
immer 2 Aufrufe braucht, um 1 komplette 'Schwingung' fertig zu stellen.

Und anstatt dem #*&$@ Timer vorladen, nimmst du den CTC Modus und gut 
ists. Dann braucht man auch nicht mehr so bescheuert von 65535 aus 
runterrechnen, sondern weist einfach dem OCR1A Register den neuen Wert 
zu und schon 'tickt' der Timer mit der neuen Frequenz. Genau dafür hat 
ATmel den CTC Modus eingebaut .... damit man ihn benutzt, wenn er 
angebracht ist. Und deine Anwendung ist ein Paradebeispiel für 
'angebracht sein'. Wenn nicht hier, wo sollte der CTC sonst angebracht 
sein?
#2857774
Lesenswert?

Troll schrieb:
> Simon K. schrieb:
>> Brauch man denn für alles heute ein Tutorial?
>
> Zu jedem Mist ein Tutorial ist wohl etwas übertrieben. Ein vernünftiger
> Quellcodegenerierungsassistent sollte es auch tun ;-)
>
> Früher (tm) musste man sich durch Tabellen und Erläuterungen im
> Datenblatt durchwühlen :-(

Das ist auch heute noch vernünftig anstelle des Assistenten. Die 3 
Einstellungen raussuchen dauert keine 2 Minuten. Gegenüber dem Rest der 
Entwicklungszeit sind das Peanuts, die komplett untergehen.
#2857857
Lesenswert?

Es ist wirklich ganz einfach.
Du konfigurierst den Timer auf CTC

Config Timer1 = Timer , Prescale = 64, Clear_Timer = 1

und hängst eine ISR an den Compare Match vom OC1A

On OC1A ToggleStep


und in der ISR Funktion toggelst du einfach den Pin

ToggleStep:
  Toggle Stepper1_step
  return


Jetzt weist du an OCR1A einfach einen Wert zu.
  OCR1A = 2000

der Timer zählt dann von 0 bis 2000 und wenn die 2000 erreicht sind, 
passieren 2 Dinge
* der Timer beginnt wieder bei 0 zu zählen
* da es sich hier um einen Compare Match handelt (also eine 
Übereinstimmung
  des Zählregisters mit dem OCR1A Register), wird die zugehörige ISR
  aufgerufen.

Bumm. Nicht mehr lange rumrechnen. Wenn du 258 Timer Schritte brauchst, 
dann schreibst du auch 257 (258-1) in das OCR1A Register
Kein Timer Vorladen mehr. Der Timer beginnt ganz von alleine wieder bei 
0 zu zählen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren