Ich bin ein Beginner wenn es um Microcontroller geht und versuche gerade
mithilfe von PWM die Geschwindigkeit eines Motors zu regeln.
Ich benutze den Atmega32U4 und den 16-bit Timer1.
Mein Vorgehen ist, den Fast PWM Mode zu benutzen (Mode 14) wobei ich den
ICRn als Top und den OCRnx als Output Generator für OCnA.
Als Beispiel habe ich es an den OC1A / PB5 probiert.
Was passieren sollte: Der Motor läuft mit 25% Geschwindigkeit.
Wenn ich dies nun ausführe, läuft der Motor bei voller Geschwindigkeit.
Es kommt nie zu Compare Matches mit dem OCR1A und somit ist es einfach
die ganze Zeit auf HIGH.
Wenn ich inverted-mode gehe, dann läuft der Motor gar nicht, da es die
ganze Zeit auf LOW ist.
Also liegt es anscheinend irgendwie daran, dass es nie zu Compare
Matches kommt nehme ich an?
Hat jemand eine Idee woran es liegen könnte?
MfG
Mangels eines ATmega32u4 kann ich nichts ausprobieren, rein theoretisch
sieht es für mich gut aus; bis auf dieses Ver-odern in der
Initialisierung, das ist eine dumme Angewohnheit, sollte aber allenfalls
bei einem schlechten Bootloader eine Rolle spielen.
S. Landolt schrieb:> Mangels eines ATmega32u4 kann ich nichts ausprobieren, rein theoretisch> sieht es für mich gut aus; bis auf dieses Ver-odern in der> Initialisierung, das ist eine dumme Angewohnheit
Das ist mehr als eine dumme Angewohnheit. Wenn eine bestimmte
Konfiguration erreicht werden muss, muss man sie auch explizit
herstellen. Das kann man nicht durch verodern mit einem (zumindest
potentiell unbekannten) Ausgangszustand.
Es gibt natürlich Register, wo diese Veroderei (unter bestimmten
Randbedingungen, z.B. halt den definierten Resetzustand) einen Sinn
ergibt, z.B. die DDRn oder PORTn, aber für die allermeisten Register zur
Kontrolle der Peripherie ergibt das auch dann schlicht absolut keinen
Sinn. Also besser einfach nicht machen.
Was nun das Problem des TO betrifft: Bei solchen Sachen sollte man immer
auch sämtliche sonstigen "alternate port functions" im Blick haben.
Sprich: dringende Frage an den TO: benutzt du eventuell auch Timer4,
möglicherweise sogar mit einer ähnlich schwachsinnigen Konfiguration per
Veroderung?
Das mit dem Ver-odern war mir nicht bewusst. Ich habe es einfach
aufgeschnappt von anderen Tutorials.
Timer4 benutze ich nicht.
Hier ein paar mehr Infos:
Ich benutze noch eine H-Bridge, der Aufbau sieht dem hier sehr ähnlich:
https://youtu.be/dyjo_ggEtVU?t=690
Die Ports PB5 und PB6 nutze ich als Outputs, und die gehen nach IN von
der Bridge (wie in dem Bild im Video halt). Am PB5 ist auch OC1A.
Also lege ich das PWM Signal nicht an den ENAble, sondern an den Input,
aber das sollte ja theoretisch das gleiche machen.
1
#include<avr/io.h>
2
#include"Motor.h"
3
4
voidinitMotors()
5
{
6
DDRB|=(1<<DDB5);//output
7
DDRB|=(1<<DDB6);//output
8
TCCR1A|=(1<<WGM11);
9
TCCR1A|=(1<<COM1A1);//non-inverted
10
TCCR1B|=(1<<WGM12);
11
TCCR1B|=(1<<WGM13);//Fast PWM Mode
12
TCCR1B|=(1<<CS10);//no prescaler
13
ICR1=799;//frequency: 20KHZ
14
OCR1A=200;// 200/800 = 25% duty cycle
15
}
16
17
intmain()
18
{
19
initMotors();
20
while(1){}
21
}
Was ich will: Motor soll mit 25% Geschwindigkeit laufen
Was wirklich passiert: Motor läuft mit max Geschwindigkeit
Für Motoren empfiehlt Atmel den Einsatz des Phase Correct PWM Mode. Auch
ist fraglich ob dein Motor überhaupt mit 20kHz ansteuerbar ist. Zur
Beschaltung gibt es ja keine Angaben. Aber sei es drum. Du beschreibst
da Problem ja als ausbleiben des "Endanschlages"
Für mich sieht der Code erstmal korrekt aus. Bis auf diese Stelle im
Datenblatt, die du wohl übersehen hast:
The Timer/Counter (TCNTn), Output
Compare Registers (OCRnA/B/C), and Input Capture Register (ICRn) are
all 16-bit registers. Special procedures must be followed when accessing
the 16-bit registers.
Da der Atmega ein 8-Bit breiten Bus hat, müssen die 16 Bit Register von
Timer1 entsprechend in zwei Schritten beschrieben werden. Zuerst High
Byte, dann Low Byte.
Vielleicht liegt da der Hund begraben?
Hendrik schrieb:> The Timer/Counter (TCNTn), Output> Compare Registers (OCRnA/B/C), and Input Capture Register (ICRn) are> all 16-bit registers. Special procedures must be followed when accessing> the 16-bit registers.>> Da der Atmega ein 8-Bit breiten Bus hat, müssen die 16 Bit Register von> Timer1 entsprechend in zwei Schritten beschrieben werden. Zuerst High> Byte, dann Low Byte.>> Vielleicht liegt da der Hund begraben?
Nein, da kümmert sich der Compiler drum. Der kennt die nötige
Zugriffsreihenfolge. Wenn man ganz sicher gehen will, darf man aber auch
gerne mal in's Listfile schauen.
Wenn nämlich die SFRs mit anderen als den Defaultwerten vorbesetzt sind,
z.B. durch einen schlechten Bootloader, dann führt '|=' ins Chaos.
Ansonsten kann ich nach wie vor keinen Fehler erkennen; wenn vorhanden,
sollte mal die Spannung an den Outputs mit einem Voltmeter nachgemessen
werden.
hoalu schrieb:> Also lege ich das PWM Signal nicht an den ENAble, sondern an den Input,> aber das sollte ja theoretisch das gleiche machen
Nein, das macht nicht das gleiche, aktiv bremsen vs. frewheeling, aber
in beiden Fällen sollte ein Motor langsamer werden.
Aber was soll der Unsinn mit 20kHz, welchen Motor besitzt du,
Mückenflugmuskeln ?
Meinst du nicht, dass dein Motor wie jeder Motor zu träge sein sollte um
selbst bei 50Hz eine mittlere Geschwindigkeit einzunehmen ?
c-hater schrieb:> Das kann man nicht durch verodern mit einem (zumindest> potentiell unbekannten) Ausgangszustand.
Prinzipiell richtig, allerdings ist der Ausgangszustand der Register
nach einem Reset weder potentiell noch überhaupt unbekannt, sondern wohl
definiert.
Wenn da also vorher niemand an den Registern rungefummelt hat, passt das
schon.
Oliver