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
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
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
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
warum den Timer durch 8 Teilen? Bei 16MHz kann sie ihn doch auch noch durch 1024 Teilen, das gibt dann 15,6KHz.
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
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
@@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.
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
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.
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...
@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 :(
@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
> 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?
Warum haeißen eigentlich alle Studenten, die zu faul sind ihre Hausaufgaben zu machen in Foren Sabrina?
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 ?
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
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).
Kein Grund sich aufzuregen. Ich wollte nur auf diesem Wege auf den Motivationsschub hinweisen. Kannst Deine Triggerung wieder auf DC umschalten.
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
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?
@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ß
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
@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 :)
@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.
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
@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
@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...)
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).
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.