Hallo liebe Leute. Bin ganz neu beim Arduino und gerade am kennenlernen. Habe mich vorher mit dem Tiva C Series TM4C1294 beschäftigt, und komme mit dem sehr gut klar. Also kein absoluter Neuling auf dem Gebiet. Ich bräuchte jetzt etwas Hilfe beim Arduino UNO und PWM, da blicke ich gerade nicht ganz durch. Hat einer von euch viell. einen exampple Code. Möchte ein PWM Signal von 1,5ms rausschicken, und stehe etwas auf der Leitung. Danke im Vorraus.
Almir J. schrieb: > Möchte ein PWM Signal von 1,5ms rausschicken, und stehe etwas auf der > Leitung. Lass mich raten - meinst du ein 1,5ms Puls mit etwa 20ms Wiederholrate? Um RC-Servos anzusteuern? Dann sollte das hier helfen: https://www.arduino.cc/en/Reference/Servo
Vielen Dank für deine Antwort. Genau, ich möchte einen Servomotor steuern. Was ich bis jetzt gefunden habe ist dass ich mit PWM's: 1 - 1,5 ms in Uhrzeigersinn drehen kann 1,5 ms = stop 1,5 - 2 ms gegen Uhrzeigersinn. als Platfrom dient mir der Arduino Uno. Ich möchte das aber ohne Sktech machen, also reiner C-Code mit so wenig Librarys wie möglich. Wie es bei dem Tiva C board geht weiß ich. Aber hier stehe ich etwas an. Am hilfreichsten wäre ein example wo das wirklich ausprogrammiert ist, leider konnte ich bis jetzt nur sketch Beispiele finden. z.b. myservo.write(pos); ich weiß dass hier ein PWM gesendet wird, aber wie sieht das ohne die library aus. gibt es ein bsp wo quasi drinnen steht? "PWM(dauer) auf PIN XY" für das AVR studio. oder ein tutorial dazu?
Nennt sich AVR Tutorial, oben links auf dieser Internetseite zu finden. Wenn du nach Arduino googelst findest du Sketche, wenn du nach AVR googelst C-Code.
So ich habe jetzt aus Tutorials und mit Internetrecherche einen Code. Leider bewegt sich der Motor kein Stück. Irgenwdo ist da noch ein Wurm drinnen, den ich leider nicht sehe. Vielleicht weiß jemand was es sein könnte. Zur erklärung. Ein Servomotor hängt jetzt bei mir am Arduino UNO am Pin 5. Das ist der PD5. Im Sketch funktioniert es, daher ist der Motor und das Board ok. Aber in meinem Code hab ich einen Fehler. Der Motor müsste sich jetzt eigentlich im Uhrzeigersinn drehen. Der Code müsste mir mit einer Frequenz von 50 HZ ein 1.264ms PWM Signalerzeugen. Bin für Hilf sehr dankbar. LG #include <inttypes.h> #include <avr/io.h> #define F_CPU 16000000 int main( void ) { TCCR1A|= (1<<7)| (1<<5) | 1; //COM1A1 COM1B1 WGM11 non inverted pwm TCCR1B|= (1<<4) | (1<<3) | 1<<1 | 1<<0;; //WGM13 WGM12 CS11 CS10 prescaler = 64 ICR1 = 4999; //pwm = 50Hz DDRD |= (1<<5); // DataDirection Port D: Pin D5 = Output (Led) while (1) { OCR1A=316; } // endlessly return(0); }
:
Bearbeitet durch User
Almir J. schrieb: > TCCR1A|= (1<<7)| (1<<5) | 1; //COM1A1 COM1B1 WGM11 non inverted pwm Diese Schreibweise ist uncool - man blickt ja gar nicht durch, was nun gesetzt wird. Schreib lieber
1 | TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); |
ALs nächstes musst du PB1 (OC1A) noch auf Ausgang setzen, sonst passiert da gar nichts. An PB1 sollte dann das PWM Signal auftauchen. Almir J. schrieb: > Der Motor müsste sich jetzt eigentlich im Uhrzeigersinn drehen. Das Servo fährt dann aber nur die Stelle an und bleibt dann stehen. Erst wenn du mit OCR1A eine andere Pulslänge angibst, fährt das Servo die neue Position an. Almir J. schrieb: > Ein Servomotor hängt jetzt bei mir am Arduino UNO am Pin 5. > Das ist der PD5. Das ist aber OC0A und ist für Timer 0. Du benutzt Timer 1, der OC1A und OC1B bedient, die befinden sich auf PB1 und PB2.
:
Bearbeitet durch User
Almir J. schrieb: > Der Motor müsste sich jetzt eigentlich im Uhrzeigersinn drehen. Der Code > müsste mir mit einer Frequenz von 50 HZ ein 1.264ms PWM Signalerzeugen. Dein Code wird einmal ausgeführt und dann macht der Controller irgendwas. Bei einem Mikrocontroller musst du dich im Gegensatz zu einem Betriebsystem um alles selber kümmern.
Matthias S. schrieb: > Das ist aber OC0A und ist für Timer 0. Sorry, das ist Unsinn. An PD5 liegt OC0B, ist aber hier nicht so wichtig. Du brauchst für Timer 1 auf jeden Fall OC1A und evtl. für ein zweites PWM Signal OC1B.
:
Bearbeitet durch User
Matthias S. schrieb: > Matthias S. schrieb: >> Das ist aber OC0A und ist für Timer 0. > > Sorry, das ist Unsinn. An PD5 liegt OC0B, ist aber hier nicht so > wichtig. Du brauchst für Timer 1 auf jeden Fall OC1A und evtl. für ein > zweites PWM Signal OC1B. Verstehe ich nicht ganz. Warum kann ich nicht den OC0B verwenden? Laut Arduino Schema ist das doch einer der Pins die für PWM genutzt werden. PIN 3,5,6,9,10,11. daher auch der Pin D5 @ STK500-Besitzer (Gast) Der Motor ist ein Spring SM S430 3R. Der bleibt nicht stehn. Wenn du ihm ein PWM Signal zwischen 1 und 1,5 ms schickst, dann dreht der sich solange bis du ihm ein Signal von 1,5ms schickst. Der Code ist ja als solches noch nicht ganz fertig. Sobald ich es schaffe ihm mal das Signal zwischen 1 . 1,5 zu schicken bringe ich ihn auch zum stehen. Leider klappt das bis jetzt noch nicht.
:
Bearbeitet durch User
Almir J. schrieb: > Verstehe ich nicht ganz. Warum kann ich nicht den OC0B verwenden? Laut > Arduino Schema ist das doch einer der Pins die für PWM genutzt werden. Arduino hin oder her, aber die Hardware des Mega ist nun einmal so eingerichtet, das die OC Ausgänge für Timer 1 an PB1 (OC1A) und PB2 (OC1B) liegen. Wenn du also Hardware PWM mit Timer 1 machen willst, und das ist ja der einzige 16-bit Timer des Mega328, dann wird die PWM eben nur an diesen Pins auftauchen. Und PWM an OC0A und OC0B kommt ja tatsächlich an PD6 und PD5 raus, aber nur wenn Timer 0 benutzt wird. Das ist aber auch nur ein 8-bit Timer. Also schalte PB1 auf Ausgang, und leg deinen Motor an diesen Pin - sonst gehts nicht.
Endlich- Habs zum laufen bekommen. Hier der Code. /* * GccApplication4.c * * Created: 17.03.2016 12:37:16 * Author : user */ #include <inttypes.h> #include <avr/io.h> #include <util/delay.h> #define F_CPU 16000000 int main( void ) { DDRD |= (1<<PORTD5); TCCR0A|= (1<<COM0A1)| (1<<COM0B1) | (1<<WGM01) | (1<<WGM00); TCCR0B|= (1<<CS02) | (1<<CS00); while (1) { OCR0A=15; _delay_us(3000); OCR0A=90; _delay_us(3000); OCR0A=50; _delay_us(3000); OCR0A=150; _delay_us(3000); OCR0A=250; _delay_us(3000); } // endlessly return(0); } leider dreht sich der Motor jetzt stur nur gegen Uhrzeigerrichtung. Vielleicht jemand ne Idee? Die verschiedenen OCR0A werte sollen bewirken dass er sich mit verschiedenen Geschwindigkeiten auch teils in verschiedene Richtungen dreht.
:
Bearbeitet durch User
> (1<<COM0A1)| (1<<COM0B1) Erkläre mal, warum du diese Bits gesetzt hast. Warscheinlich fällt Dir dann schon selbst auf, woran es hakt. Un dann noch was: Du hast den Prescaler auf 64 gestellt. Bei 16MHz hast dein Timer also eine Taktfrequenz von 250kHz. Die teilt er durch 256 -> Macht 977 Impulse Pro Sekunde. R/C Servos erwarten aber 50 Impulse Pro Sekunde. Vielleicht magst du mal von dem hier abgucken, da kannst du auch die I/O Pins beliebig zuordnen: http://stefanfrings.de/servocontroller/index.html
> Was ich bis jetzt gefunden habe ist dass ich mit PWM's: > 1 - 1,5 ms in Uhrzeigersinn drehen kann > 1,5 ms = stop > 1,5 - 2 ms gegen Uhrzeigersinn. Das gilt nur für Gehackte Servos ohne Endanschlag. Normale Lenkservos fahren einen bestimmten Winkel an (je nach Pulsbreite) und verharren dann auf dieser Position. Normalerweise gilt dies: 1-1,5ms: Nach links lenken 1,5ms: Geradeaus fahren 1,5-2ms: nach rechts lenken
Stefan U. schrieb: >> (1<<COM0A1)| (1<<COM0B1) > > Erkläre mal, warum du diese Bits gesetzt hast. Warscheinlich fällt Dir > dann schon selbst auf, woran es hakt. > > Un dann noch was: > Du hast den Prescaler auf 64 gestellt. Bei 16MHz hast dein Timer also > eine Taktfrequenz von 250kHz. Die teilt er durch 256 -> Macht 977 > Impulse Pro Sekunde. > > R/C Servos erwarten aber 50 Impulse Pro Sekunde. > > Vielleicht magst du mal von dem hier abgucken, da kannst du auch die I/O > Pins beliebig zuordnen: > http://stefanfrings.de/servocontroller/index.html TCCR0B|= (1<<CS02) | (1<<CS00); der prescaler ist hier 1024 16.000.000 / (1024 * 256) = 61,035. Die 61 Hz waren fü mich halt die größte näherung an die 50Hz
Stefan U. schrieb: >> Was ich bis jetzt gefunden habe ist dass ich mit PWM's: >> 1 - 1,5 ms in Uhrzeigersinn drehen kann >> 1,5 ms = stop >> 1,5 - 2 ms gegen Uhrzeigersinn. > > Das gilt nur für Gehackte Servos ohne Endanschlag. Normale Lenkservos > fahren einen bestimmten Winkel an (je nach Pulsbreite) und verharren > dann auf dieser Position. > > Normalerweise gilt dies: > > 1-1,5ms: Nach links lenken > 1,5ms: Geradeaus fahren > 1,5-2ms: nach rechts lenken Dieser servo ist vno der Bauart her aber so. Der hat keinen Endanschlag. Hat sich jetzt gerade 5 mal im Kreis gedreht.
> der prescaler ist hier 1024 Gut, dann habe ich mich da verguckt. Ich hatte CS01 gelesen, statt CS02. > Hat sich jetzt gerade 5 mal im Kreis gedreht. Na dann kann es ja eigentlich nur noch am Timing liegen. Wir haben also einen Timer-Takt von 16Khz. Dass heisst, 16 Takte wären 1ms, 32 Takte wären 2ms. In diesem bereich solltest du erstmal bleiben. > OCR0A=15; > OCR0A=90; > OCR0A=50; > OCR0A=150; > OCR0A=250; Die meisten deiner Vergleichswerte sind ganz andere außerhalb dieses Bereiches.
Mit dem 8-Bit Timer 0 bekommst du nur sehr wenig Auslösung in dem interessierenden Bereich von 1-2ms. Deswegen ja der Vorschlag, den 16-bit Timer, den du oben ja fast fertig konfiguriert hattest, zu benutzen. Dessen PWM Ausgänge sind aber nun mal auf PB1 und PB2. Es hat auch keine Sinn, mir deswegen PMs zu schicken, denn ich kann auch nur das Datenblatt zitieren.
while (1) { OCR0A=15; _delay_us(3000); OCR0A=16; _delay_us(3000); OCR0A=17; _delay_us(3000); .. .. OCR0A=31; _delay_us(3000); OCR0A=32; _delay_us(3000); } // endlessly probier mal so Axelr. DG1RTO
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.