Forum: Mikrocontroller und Digitale Elektronik c't - Bot Geschw.regelung


von Sabrina (Gast)


Angehängte Dateien:

Lesenswert?

Hallöchen zusammen,
ich heiße Sabrina und studiere Mechatronik und belege zZ ein
Wahlpflichfach, wo wir den c't Bot aufbauen und programmieren...
(Motoren sind an einem L293D  und dann am ATMega32 der mit 16Mhz läuft)
[http://www.heise.de/ct/ftp/projekte/ct-bot/pdf/schaltplan-final.pdf]
Ich bin in der Gruppe die für die Motoren zuständig ist und ich muss
bis zum nächsten mal wissen wie das funktioniert und auch schon was
programmiert haben, sonst stehts schlecht um die Prüfung :( Bammel
Programmieren das mit AVR-Studio in C-Sprache

Also was ich bisher weiß:
steht in dem Word-Dokument, und zwar wie ich die motoren ansteuere...
bisher bin hin hingegangen, und habe einfach die Ports D4 und D5 auf
"HIGH" gesetzt, eigentlich nicht falsch, nur das die motoren dann
immer auf 100% laufen, also nach meiner methode keine regelung der
geschwindigkeit....

Soweit ich weiß muss ich da mit den Frequenzen arbeiten und nen
prescaler hab ich mir schon ausgesucht, das ist der Codeausschnitt:

TCNT0=0;       // Counter auf 0
TCCR0 = 0x05;  // Timer einschalten, Prescaler auf Quartztakt / 1024

so und meine Frage lautet, wie kann ich damit jetzt eine PWM erzeugen
um die Geschwindigkeit der Motoren zu regeln ??
Es soll beispielsweise in 5% Schritten geregelt werden ???

Muss wissen, wie ich damit jetzt verschiedene PWM-Signale erzeuge...
Bitte helft mir, habe mich schon bisher ne halbe Woche versucht da rein
zu lesen, blick da nicht ganz durch......


Danke
eure Sabrina

von Roland P. (pram)


Lesenswert?

Der Timer zählt bis 256 (mit 16MHz/1024), dann wird SIG_OVERFLOW0
aufgerufen.
Es wird also Sig-Overflow mit ca. 61 Hz aufgerufen (meiner Meinung nach
zu Langsam).

Jetzt musst nur noch dafür sorgen, dass z.B. bei 15 Aufrufen der Pin LO
wird und beim 16. Aufruf der Pin High. Dann hättest in dem Fall 6,25 %
Motorleistung (allerdings mit ca. 3 Hz gepulst, deshalb sollte man die
Timerfrequenz erhöhen)

Gruß
Roland

von Tubie (Gast)


Lesenswert?

schau doch mal ins datenblatt des Mega32 da steht eigentlich alles drin,
was du wissen willst. Du hast im TCCR0 lediglich gesagt, CLK /1024 das
ist schonmal richtig allerdings solltest du mal versuchen, den wert von
$05 auf $6D zu setzen.

Soll heißen:
 CLK / 1024
 Fast PWM
 Clear OC0 on compare match

steht aber wie gesagt alles im Datenblatt Seite 78

OCR0 solltest du auf den gewünschten PWM Wert setsen

Datenblatt S. 80

Viel erfolg
Tubie

von Tubie (Gast)


Lesenswert?

Nachtrag:
Du solltest aber den Timer auf /8 stellen sonst wird der motor nur vor
sich her brummen und stottern. Einfach mal versuchen. Evtl. sogar Clk
direkt

Tubie

von @tubie (Gast)


Lesenswert?

warum den Timer durch 8 Teilen? Bei 16MHz kann sie ihn doch auch noch
durch 1024 Teilen, das gibt dann 15,6KHz.

von Tubie (Gast)


Lesenswert?

Klar ergibt das 15,6Khz mit denen der Timer getaktet wird. Er zählt aber
jedesmal bis 255 also nochmal /256 ergibt ca. 61Hz PWM Frequenz und da
würde der Motor anfangen zu Brummen (60Hz).

Gruß,
Tubie

von @tubie (Gast)


Lesenswert?

aah, okay tubie stimmt, und was sind sinnvolle frequenzen für einen
dc-motor? bin nämlich auch grad dabei einen motor über pwm zu steuern

von Philipp Burch (not logged in) (Gast)


Lesenswert?

@@tubie:
Ausprobieren ;)
Je nachdem, welche Geräuse du magst musst halt was auswählen. Ist wohl
auch von Motor zu Motor verschieden, ich würde mal einige Stufen von
z.B. 100Hz bis 10kHz oder so ausprobieren und schauen, wo er einen
guten Wirkungsgrad bei erträglichem Lärm erzeugt. Wenn es einfach leise
sein soll, kannst du auch Frequenzen oberhalb des hörbaren Bereiches
(max. ca. 20kHz) ausprobieren.

von Tubie (Gast)


Lesenswert?

Also das hier ist eine Persönliche Meinung von mir:
wenn der Timer bei /8 läuft, erhalte ich eine PWM Frequenz von 7,8kHz
ziemlich nervendes Geräusch. Wenn ich direkt, ohne vorteiler arbeite,
komme ich bei 62,5kHz raus - das hört man nichtmehr.

Aber zu diesem Thema sollten sich die Experten bitte nochmals äußern,
denn soviel ich weiß ist es nicht so ganz egal, mit welcher Frequenz
ein Motor betrieben wird. Da kommen dann so sachen wie Drehmoment und
HF-Störungen ins Spiel.

Gruß,
Tubie

von Peter Schwarz (Gast)


Lesenswert?

In der letzten c't 10/2006 stand auch ein Leserbrief von einem
Regelungstechniker im Ruhestand drin. Der beschrieb in seinen
Ausführungen was alles bei dem c't Bot mit dieser Steuerung 'falsch'
gemacht wurde. An Lösungsansätze kann ich mich jetzt nicht genau
erinnern, aber es war sehr interessant was in dieser Zuschrift drin
stand.

von Rahul (Gast)


Lesenswert?

Ich frage mich gerade, wer sich die Kombination aus Datenblatt und
doc-Datei überhaut angegucxkt hat.
Der Mega32 (und viele seiner "Kumpels" besitzen fertige
PWM-Einheiten, wo man sich eigentlich um nichts ausser der
Initialisiern kümmern muß.
Die Enable-Eingänge des L293D hängen an D4 und D5. Das sind
gleichzeitig die OC-Ausgänge des Timer 1.
Um da eine PWM drauf zu tun, guckt man sich die Beschreibgung der
verschiedenen PWM-Modi im Datenblatt an. Und wenn man schon Mechatonik
studiert (hab ich nämlich auch gemacht), dann sollte man da eine Lösung
finden. Falls nicht, einfach noch mal fragen...

von Sabrina (Gast)


Lesenswert?

@Rahul:
Freut mich hier im forum einen gleichgesinnten gefunden zu haben,
leider bleibt mir noch zu sagen, dass dies unser erster kontakt mit
elektronik ist, da ich grade erst mitten im 4. semester bin. und wie du
ja weisst hat man in den semestern davor leider nur so ziemlich
langweilige theoretische sachen wie mathe, physik und mechanik un
andere kleinigkeiten.... ;)

So leider habe ich es seit meinem letzte post noch nicht auf die reihe
bekommen, eine gescheites PWM signal für den motortreiber zu
erzeugen...
dabei habe ich lange genug in dem datenblatt gestöbert, habe es sogar
ausgedruckt und gebunden vor mir liegen :(

von wegstabenverbuchsler (Gast)


Lesenswert?

@Sabrina

Vielleicht soltest du erst mal versuchen die Abkürzung PWM zu
expandieren ... es steht für "Puls-Weiten-Modulation"

Fehlt es dir jetzt an der Theorie oder an der Praxis? Theorie:
:: warum wird durch eine Modulation einer Pulsweite eine
unterschiedliche Geschwindigkeit erreicht
:: Wieso wird der Motor mit Pulsen betrieben
:: wieso haben die Pulse eine unterscheidliche Weite
:: was bedeutet die Modulation der Pulsweite
:: Wieso braucht man Zähler und Interupts um Pulse zu erzeugen

Praxis:
:: Wie kommen Pulse für die einzelnen Phasen des Motors von ein
Registerwert bis zum Stecker des Motors?
:: wie bediene ich die entwicklungsumgebung damit die Software bis in
den Chip reinflutscht

von mh789 (Gast)


Lesenswert?

> So leider habe ich es seit meinem letzte post noch nicht auf
> die reihe bekommen, eine gescheites PWM signal für den
> motortreiber zu erzeugen...
> dabei habe ich lange genug in dem datenblatt gestöbert,
> habe es sogar ausgedruckt und gebunden vor mir liegen :(

Dann mach Dir doch mal bitte die Mühe und schreibe auf, was Du bisher
verstanden hast, was Dir unklar ist und was Du bisher versucht hast und
wie es schiefging.

Du hast bisher viele wichtige Hinweise bekommen, in welcher Richtung Du
suchen musst. Wenn Du noch weitergehende Hilfe brauchst, reicht ein
"ich bin immer noch nicht weiter" leider nicht aus, denn unsere
Kristallkugeln funktionieren nicht so gut ;) Okay?

von ??? (Gast)


Lesenswert?

Warum haeißen eigentlich alle Studenten, die zu faul sind ihre
Hausaufgaben zu machen in Foren Sabrina?

von Sabrina (Gast)


Lesenswert?

Ach ja da hätte ich dann noch eine Frage,
wie sieht es aus, wenn der ATMega32 über einen externen Quarz seinen
Takt bekommt ?? muss ich dann noch wieder was besonderes beachten ??

Wir haben da nämlich einen 16MHz quarz drauf fällt mir grad ein, und
mit den eigenen internen oszillator bekommt der ja sowieso nicht auf
seine 16MHz.... ??

Was muss ich dabei noch beachten ?

von Rahul (Gast)


Lesenswert?

Du musst die Fuses wie im Datenblatt angegeben einstellen...

von Markus (Gast)


Lesenswert?

Hallo Sabrina,

in einer der ersten CT's mit dem Projekt steht, wie das mit der
Anteuerung funktioniert. In der Vorletzten glaube ich stand die
Drehzahlregelung sehr gut beschrieben. Da stand auch noch was von
Problemen mit den Radencodern. Da gibt es jetzt neue gefräste, mit
denen soll es wohl deutlich besser gehen.

Welche Ausgaben das genau waren, hab ich grad nicht zur Hand, schau
doch einfach mal bei Heise.

Grüße, Markus

von Chris... äh Nicole (Gast)


Lesenswert?

Der Trick mit Sabrina ist echt gut :-)

von Rahul (Gast)


Lesenswert?

Und da haben wir es doch wieder: Hier wird niemand gezwungen, anderen zu
helfen. Wenn es sich bei Sabrina um ein männliches Wesen handelt, sollte
er sich mal überlegen, ob er nicht lieber mal (regelmässig) beim
Klapsendoktor vorbeiguckt.
Bis jetzt hat noch niemand Sabrina einen fertigen Code zur Verfügung
gestellt (dafür ist ja auch die Codesammlung da...).
Was spricht dagegen, jemandem bei seinen Hausaufgaben zu helfen, vor
allem wenn es sich um so ein interessantes Thema wie
"Mikrocontroller-Programmierung" geht?
Leute, die solche Sprüche von sich geben, haben wohl noch nie Probleme
gehabt, bei denen sie sich festgefahren haben, und die Hilfe anderer
brauchten.
Übrigens halte ich es für realistisch, dass es sich bei Sabrina um eine
Frau handelt, da an meiner FH sogar mehrere Frauen das
Mechatronik-Studium gewählt haben (damals noch Feinwerktechnik), und es
ziemlich erfolgreich abgeschlossen haben (diverse 1,xx-Noten im Diplom).

von Christian Rötzer (Gast)


Lesenswert?

Kein Grund sich aufzuregen. Ich wollte nur auf diesem Wege auf den
Motivationsschub hinweisen. Kannst Deine Triggerung wieder auf DC
umschalten.

von Sabrina (Gast)


Lesenswert?

Hi,
also ich lese mir grade das Tutorial über PWM durch, hat bisher schon
eniges verdeutlicht...
Also ich habe mich entschlossen, den 8-Bit Conuter zu verwenden,
da es für meine Zwecke (so glaube ich) völlig ausreichend ist bis 256
zu zählen. Dann habe ich aber etwas von versch. Modi gelesen und zwar
:
    *  Normal (evtl. für Software PWM)
    * Clear Timer on Compare (CTC) (eingeschränkte PWM)
    * Fast PWM
    * Phase Correct PWM
Und wie sollte es anders sein, tendiere ich zum * Phase Correct PWM...

Dann habe ich eine Schritt für Schritt Anleitung gefunden
    1 Pins low setzen
    2 Pins als Ausgang konfigurieren.
    3 Geeignete Wellenform ermitteln
    4 Registerinformationen für ausgewählten T/C im Datenblatt
aufschlagen
    5 Modus & Prescaler setzen und damit starten
          o Bits in Control Register TCCRnA & TCCRnB schreiben. Siehe
Bitmanipulation
    6 Vergleichswert OCRnx setzen

zu 1) Pins auf low setzen brauch ich denke ich nicht, weil alle Ports
standartmäßig auf low
      geschaltet sind, richitg ?! Andernfalls PORTD &= 0xCF
      (Motortreiber hängt an PortD.6 und .7)
zu 2) PORTD |= (1 << 6);
      PORTD |= (1 << 7);
zu 3) Rechtecksignal, am besten wie es im Datenblatt des L293D steht
auf Seite 3-3, richtig?
zu 4) Uiuiui, also im DataSheet des ATMega32 steht nun auf Seite 76
über die Phase Correct
      PWM Mode : "...(WGM01:0=1)..." heißt doch schonmal soviel, das
ich die Bits
      namens WGM01:0 auf mode 1 setzten muß, richtig ? also vielleicht
so : WGM00 |= (1 << 0); WGM01 &= (0 << 1); ??
      Desweiteren brauche ich das Interruptflag ToVn nicht, oder ist es
für die Erzeugung einer
      PWM von bedeutung, ich denke nicht :) jedenfalls ist es auf
Bottom gesetzt.
      Und COM00 setze ich auf "0" und COM01 auf "1", um ein
"Non-inverted PWM" zu erhalten,
      -> Clear OC0 on compare match when up-counting. Set OC0 on
compare match when downcounting
      Wenn ich jetzt die geschw. regeln will, muss ich doch nur einen
anderen Wert in OCR1A schreiben,
      richtig? Dann habe ich noch eine Formel gefunden, um die "PWM
Freq. for the output" zu bestimmen,
      dabei muss ich darauf achten, das OCR1A ungleich MAX und ungleich
BOTTOM ist, weil sonst das output
      signal continuously high bzw low ist....oder bezog das auf =OC0
oder auf was ganz anderes??
zu 5) Modus setzen:          WGM00 |= (1 << 0);     WGM01 &= (0 << 1);
      Prescaler setzen:      CS00  |= (1 << 0);     CS01  &= (0 << 1);
   CS02 |= (1 << 2);
      (dann hab ich einen Prescaler von 1024),richtig?
      PWM-Modus aktivieren:  PWM10 |= (1 << 0);     PWM11 &= (0 << 1);
 (-> Max=255, fTC1/510)
zu 6) Jetzt muss ich doch nur noch mein OCR1A anpassen, jenachdem wie
ich die Geschwindigkeit haben will oder ??


Ich hoffe ich habe meine "Hausaufgaben" richtig und zu eurer
Zufriedenheit gemacht...?
Habe mir sogar extra das Datenblatt vom ATMega32 beidseitig ausgedruckt
und binden lassen :)

Aber ich hoffe mal das alles ist richtig und rechtfertig die Mühe und
den Aufwand den ich da hinein gesteckt habe....

Bitte gebt mich nicht auf, falls etwas falsch sein sollte, ihr seht ja
ich gebe mir allergrößte Mühe,

Danke

von mh789 (Gast)


Lesenswert?

Ich hab PWM noch nie genutzt. Also alles unter diesem Vorzeichen.

> zu 4) Uiuiui, also im DataSheet des ATMega32 steht nun auf Seite
> 76 über die Phase Correct PWM Mode : "...(WGM01:0=1)..." heißt
> doch schonmal soviel, das ich die Bits namens WGM01:0 auf mode 1
> setzten muß, richtig ? also vielleicht so :
> WGM00 |= (1 << 0); WGM01 &= (0 << 1); ??

Die Tabelle 38 auf Seite 80 ist da geeigneter. Oben auf dieser Seite
ist ersichtlich: WGM00 und WGM01 sind Bits des Registers TCCR0.
Außerdem hast Du die Bits verwechselt und das Löschen von einzelnen
Bits geht anders. Also
  TCCR0 |= (1 << WGM01); TCCR0 &= (uint8_t)~(1 << WGM00);

> Und COM00 setze ich auf "0" und COM01 auf "1", um ein
> "Non-inverted PWM" zu erhalten, -> Clear OC0 on compare match
> when up-counting. Set OC0 on compare match when downcounting

Genau. Tabelle 41 ist Dein Freund. Beide Bits stehen wieder in TCCR0.

Ich denke, das dürfte erst einmal ein Stück weiterhelfen, oder?

von Sabrina (Gast)


Lesenswert?

@mh789:
Du hast vollkomen recht, ich meinte ja auch mit der Seitenangabe, den
Teil des Datenblattes, der für mich interessant wird....
also die werte habe ich auch genau der tabelle 38 von seite 80
entnommen :)
Wirklich super, dass du mich draufhingewießen hast, das WGM00 und WGM01
Bits des Registers TCCR0 sind, hätte ich garnicht bemerkt, dachte ich
könnte diese einfach so setzten wie ich es oben geschrieben habe..
Aber wie kommst du darauf, dass das Bits des Registers sind, also in
dem AVR-GCC Tutorial habe ich dazu nichts gefunden, steht es vielleicht
im Datenblatt und habe es überlesen ??(Bitte Seitenangabe) oder kennst
due eine Tabelle wo drin steht welche bits zu welchem register gehören
??

Im Tut steht desweiteren: Mit den AVR's können wir direkt PWM-Signale
erzeugen. Dazu dient der 16-Bit Zähler, welcher im sogenannten
PWM-Modus betrieben werden kann.

Aber ich kann doch auch mit dem 8Bit register ne PWM erzeugen oder ?
weil ich möchte liebe nur bis 256 bzw 255 zählen !!(zählt di 0
eigentlich mit und dann bis 255 oder von 0 bis 256 ??)

Trotzdem schonmal vielen dank, das war ein super hinweiß

von Sabrina (Gast)


Lesenswert?

Ok jetzt habe ich es gesehen es steht ja dort wo du beschrieben hast auf
seite 80 oben !!
daraus erkennt man also immer, welche bits zu welchem register
gehören... super tip !!!

Gibt es dennoch eine gesamtübersicht, damit mir nicht nochmal so eine
dumme vermutung pasiert ?? :)

SPITZEFORUM-hier aber echt mal

von Sabrina (Gast)


Lesenswert?

@mh789:
Eine Frage hätte ich da doch noch und zwar:
was bedeutet denn folgende Zeile: TCCR0 &= (uint8_t)~(1 << WGM00)
Also
TCCR0 ist mein Register
&= ist klar ich will irgendwas auf 0 setzten, was das ist folgt noch
uint8_t) ?? unsigned int ?? oder was hat das hier zu bedeuten ?? und
wie kommt man genau darauf ??
~ bedeutet NEGATION, richtig ??
(1 << WGM00) da schiebe ich die 1 mittels Bit-Shift an die Stelle des
Bit WGM00, richtig ??

also zusammen:
TCCR0 z.B = 0b10011010; dann mit &= ~ (1 << WGM00)
         &= 0b10111111; ergibt dann logischerweise
0b10011010;

Hab ich das richtig interpretiert ??

Also dann ich wünsch ne gute N8 :)

von smay4finger. (Gast)


Lesenswert?

@Peter Schwarz: Der Regelungstechniker wies in seinem Leserbrief darauf
hin, daß ein D-Anteil im PID-Regler alles eher verschlimmbessert. Das
liegt einfach an der groben Auflösung der Taktscheibe und damit der
hohen Totzeit für die Messung. Der verbesserungsvorschlag war eine
wesentlich höher aufgelöste Taktscheibe, die dann zu einer niedrigeren
Totzeit führt. Erst dann macht auch ein D-Anteil Sinn und verbessert
die Regelung sehr stark.

Ich habe bei meinem Bot eine andere Taktik versucht. Ich messe nicht
die Anzahl der Takte in einer bestimmten Zeit, sondern die Abstände
zwischen den High und Low-Flanken. Nachteil ist, daß die Taktscheibe
dann ziemlich genau sein muß.

mfg, Stefan.

von Jörn-H. G. (joern_g)


Lesenswert?

Am Rande:
Datenblatt ausdrucken wird von unseren Studies auch immer gerne
gemacht, aber es ist im Prinzip überfüssig, weil man nicht darin suchen
kann und daher das PDF später nur verwendet wird und das Papier
herumliegt.
Im Bett kann man zwar besser die Papierversion schmökern, aber wer tut
das schon?

cu joern

von Mike S. (memme)


Lesenswert?

@Jörn-H. Ich hab das mit dem Ausdrucken auch gemacht, als ich angefangen
habe. Und ich finde, es war echt hilfreich am Anfang, da man dann ja
doch etwas mehr lesen muß, um den Controller erst mal zu verstehen.
Später wirst du nur noch das pdf nutzen, aber daweißt du dann auch
schon, wo du suchen mußt.
Außerdem hat man mit einem gedruckten Datenblatt in langweiligen
Vorlesungen was zu lesen .

Mike

von Rahul (Gast)


Lesenswert?

@Joern: es gibt auch Leute die das Ding im Bus lesen, und (Rand-)
Notizen kann man sich auf Papier auch besser machen.
Sonst hast du schon recht.

@Sabrina:
(uint8_t) ist ein Type-Cast (der in diesem Fall gar nicht nötig ist).
Damit kann man zwischen den Variablen-Typen Daten besser austauschen
(Grundlagen C-Programmierung...), und ist bei Berechnungen mit
verschiedenen Datentypen notwendig (int und float gemischte
Berechnungen...)

von Rahul (Gast)


Lesenswert?

Ergänzung zu 2.):
Die Datenrichtung eines Ports stellt man mit DDRx = ... ein.
Ein PORTx = ... stellt den Ausgangszustand eines Ports ein (High oder
Low, Pull-Up ein oder aus).

von mh789 (Gast)


Lesenswert?

> Eine Frage hätte ich da doch noch und zwar:
> was bedeutet denn folgende Zeile: TCCR0 &= (uint8_t)~(1 << WGM00)

Du hast das schon richtig verstanden. TCCR0 &= 0b10111111 löscht Bit 6,
also das zweite von links. (1 << WGM00) ergibt 0b01000000, also mit
einer 1 an der Stelle, die gelöscht wird. Mit einer bitweisen
Verneinung davor (~) kommt 0b10111111 raus, also genau das, was wir
brauchen.

Nun gibt's noch einen Haken bei den Compilern. Die sind nicht 100%ig
auf so kleine Prozessoren wie den AVR optimiert. So kann es durchaus
vorkommen, dass der Wert nach der Verneinung plötzlich 16 Bit "breit"
ist, während wir ja weiterhin mit 8 Bit breiten rechnen wollen. Deshalb
stelle ich sicherheitshalber noch einen "Type-Cast" davor, so dass
der Compiler ganz sicher weiß, dass ich hier nur mit 8-Bit-Werten
rechen möchte. (Damit ich mir darüber nicht jedesmal neu den Kopf
zerbrechen muss, hab ich das übrigens in ein Makro-Gepackt.)


So, Sabrina, jetzt müsstest Du die paar Zeilen doch zusammengekriegt
haben. Oder woran hängt's denn noch?

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.