Guten morgen, gibt es eine möglichkeit, ein Servo an einem Mikrocontroller anzuschließen ?? Muss doch eigentlich, oder ? Habe ein ganz normales Servo mit den 3-Adern, wie kann ich das nun mit meinem uc ansteuern ? Gibt es da eine bestimmte Schaltung, auf welche Tricks/Kniffe muss ich achten ?? Könnt ihr ne schaltung (falls erforderlich) empfehlen ?? Danke
> gibt es eine möglichkeit, ein Servo an einem Mikrocontroller > anzuschließen ?? Muss doch eigentlich, oder ? Jou, das geht. Wenn es mehrere Servos sein dürfen, dann schau mal hier: http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html ...
Danke für deine Antwort HanneS, kennst du auch eine Seite, wo die Servo-Ansteuerung in C-Code geschrieben ist ? Assembler ist nicht ganz meine Muttersprache :)
Du musst alle 20ms einen Impuls von 1ms..2ms Breite erzeugen. Die Impulsbreite ist die Information für die Winkelstellung des Servos. Da C nicht meine Muttersprache ist (meine Muttersprache ist Deutsch), kann ich dir da nicht weiter helfen. C erzeugt aber auch nur ASM-kompatiblen Maschinencode, es dürfte also kein Problem sein, den Code zu analysieren. Die Befehlstabelle steht sogar im Datenblatt des AVRs. ...
Also gut, @ ...HanneS... Lux (HanneS) mein uc läuft nun mit 1 MHz Takt, wie berechne ich nun, wie lange er für einen Takt braucht und wie generiere ich dann einen Impuls von 1ms bis 2ms. und Wie sollte ich z.B. das Servo anschließen ??? es hat 3 Adern Schwarz,Rot,Gelb. Welches davon ist die Impulsleitung und welches muss an GND und welches an +5V ?? Ich hoffe ich bin nicht zu anstrengend [sorry]
> mein uc läuft nun mit 1 MHz Takt, Da du nicht verrätst, welchen MC du benutzt, kann ich mir ja einen aussuchen. Ich wähle daher den ATmega8. > wie berechne ich nun, wie lange er für einen Takt braucht und Das geht bestens mit Timer1 (16 Bit). Der hat 2 Compare-Interrupts. > wie generiere ich dann einen Impuls von 1ms bis 2ms. Timer1 mit Controllertakt laufen lassen, mit dem einen Compare-Interrupt alle 20ms (20000 Takte bei 1MHz) den Impuls starten, dann mit dem anderen Compare-Interrupt den Zeitpunkt festlegen, wann der Impuls wieder abgeschaltet werden soll. Das ist dann 1000 bis 2000 Takte später, je nach gewünschter Servostellung. Berechnen kann man das z.B. mit dem Dreisatz. Bei 1MHz ist das sogar recht einfach, denn ein Takt dauert genau eine µs (Mikrosekunde). Da klappt es sogar ohne Taschenrechner. Dabei lässt man den Timer am besten frei durchlaufen. Den Zeitpunkt des nächsten Interrupts bestimmt man dann, indem man in der ISR den Zeitpunkt des aktuellen Interrupts aus dem Compare-Register holt, den Wert für das Intervall (die gewünschte Zeitdauer) dazu addiert und die Summe wieder in das Compare-Register zurück schreibt. Erreicht der Timer diesen Wert im Compare-Register, so löst er einen Interrupt aus, in dessen ISR man den gewünchten Portpin setzen bzw. löschen kann. > und Wie sollte ich z.B. das Servo anschließen ??? > es hat 3 Adern Schwarz,Rot,Gelb. > Welches davon ist die Impulsleitung und welches muss an GND und > welches an +5V ?? Da fragst du am besten mal das Datenblatt oder die Gebrauchsanweisung des Servos. Ich würde schwarz an GND anschließen, rot an +5V und den Impuls an gelb legen. Aber das muss nicht unbedingt stimmen. ...
Habe ein Board mit einem ATMega16 chip drauf... Ich blicke da nicht ganz durch wie du das meinst, Datenblatt zu meinem Servo habe ich nicht, habs gebraucht bei eBay erstanden, aber die Belegung Schwarz->GND, Rot->+5V und Gelb->Impuls hatte ich mir auch schon gedacht... Wie kann ich denn Timer1 mit Controllertakt laufen lassen ich kenne mich auf dem Gebiet so garnicht aus.... was ist nen Timer, ist das ne Routine, wie programmiere ich dergleichen ??.... Beispielcode wäre sehr verständlich... Das Prinzip habe ich verstanden, nur weiß ich nicht wie ich in das Compare register schreibe..... [Ich will wirklich nicht nerven, aber jeder hat mal ganz klein angefangen] [sorry]²
Dann brauchst du zuerst mal das (vollständige!!!) Datenblatt des Mega16 und etwas Geduld. Im Kapitel Timer ist alles erklärt. ...
Hi, danke für Deinen Tipp HanneS, also ich habe mich da mal reingelesen, verstehe das aber noch nicht so ganz. Hab auch mal auf Deiner Webpage ein wenig rumgestöbert, also wenn Du mal nicht ein absoluter Freak bist, dann weiß ich es auch nicht :) Respekt && Hochachtung :) Also zu dem was ich bisher geschnallt habe: es gibt mehrere Funktionen für timer und interupt kontrolle. ich muss nun hingehen, und eine funktion schreiben, die aufgrund der taktfrequenz des uc arbeitet.... es gibt die Funktionen/Routinen TOV0 TIFR Timer1 wie lasse ich den Timer1 mit kontrollertakt laufen, kennst du vielleicht beispiel c-code, der würde mir echt besser weiterhelfen....
Also TCCR0 heisst Timer Counter Control Register ist also nen Register welches... sagt der name ja schon :)
> TCCR0 heisst Timer Counter Control Register ist also nen Register > welches... sagt der name ja schon :) Richtig... Und dieses Register hat einzelne Bits, von denen jedes einen "Schalter" verkörpert, der eine bestimmte Funktionalität einschaltet bzw. aussschaltet. Und je nachdem, was der Timer tun soll, muss man die entsprechenden Bits setzen oder löschen. Was jedes Bit (oder Bitgruppe) für eine Aufgabe hat, muss man im Datenblatt des jeweiligen Controllers nachschlagen, denn das ist von Typ zu Typ unterschiedlich, da die einzelnen Typen unterschiedliche Hardware-Ausstattung haben. Um diese Register (es gibt da noch mehrere, und die liegen alle im I/O-Bereich) anzusprechen, brauche ich die Befehle IN, OUT, SBR, CBR, LDI. IN liest ein, OUT schreibt 'raus, SBR setzt Bits im Register, CBR cleart Bits im Register, LDI lädt immidiate (Konstante). Also einfacher geht es nicht. Zumindest habe ich auf diese Art jedes einzelne Bit unter Kontrolle und kann genau nachvollziehen, welche Bits ich beeinflusse. Das geht sicher auch in C, aber C kann ich nicht, das ist mir zu kryptisch, in ASM kann ich jeden Befehl nachvollziehen und habe die volle Übersicht. Da pfuscht mir kein Compiler oder Linker dazwischen und optimiert mir unter Umständen gutgemeinte Routinen weg. Wer C allerdings beherrscht, der ist mit C besser bedient, aber dazu muss man C schon richtig beherrschen. Übrigens versteht ein guter C-Programmierer auch etwas ASM. Unterm Strich ist es aber egal, welche Sprache man benutzt. Beim AVR werkelt man ja direkt an der Hardware (und nicht unter einem abstrahierenden Betriebssystem), da sollte man die Hardware schon kennen (Datenblatt!). Und bei hardwarenaher Programmierung ist es eigentlich Wurscht, ob man über das SREG und die bedingten Sprünge verzweigt oder über ein Hochsprachenkonstrukt. Es wird oft als lästig angesehen, dass man sich in ASM selbst um die Verwaltung der Variablen (Register und SRAM) kümmern muss, ich persönlich empfinde das aber als übersichtlicher. Aber auch das ist Ansichtsache. Profis benutzen C, weil sie damit schneller zum Ziel kommen. Aber sie kennen auch die Architektur und beherrschen C ohne jegliche Missverständnisse. Zu den Profis zähle ich mich aber nicht. Danke für dein Lob, aber ich zähle mich weder zu den Freaks noch zu den Profis. Ich mach' das auch nur zum Hobby. Sowas macht mir mehr Spaß als z.B. das Leeren von Bierflaschen... ...
Hallo Steffi, schau mal unter http://www.avr-asm-tutorial.net/ wäre vileicht mal was zum ansehen. Assembler oder C ist eigentlich "egal" - wenn man mal die Grundlagen drauf hat. IMHO Programmiert es sich in C leichter. Es schadet aber nicht zu wissen was so alles passiert. Such dir vieleicht auch nochmal ein Anderes "Tutorial" zu Microcontrollerprogrammierung... Grüße, Stefan
Hi, ich glaube ich komme so langsam dahinter.... also ich habe in dem kompletten datenblatt [ http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf ] die Tabelle 54 gefunden, dort steht drin, wie ich die 3 Bits (CS20-CS22) setzten muss, dementsprechen erhalte ich einen Teiler, der den Arbeitstakt unterteilt in z.B. alle 8 32 64... Takte, soweit richtig ?? und dann habe ich in der c'T Ausgabe 6 diesen Jahres [c'T-Bot] folgendes Codesegment gefunden....(Die arbeiten glücklicherweise mit C): #define XTAL 16000000 // [Hz] (müsste 1000000 als Takt reinschreiben #define TIMER_2_CLOCK 5619 // [Hz] ... OCR2 = ((XTAL/64/Timer_2_CLOCK) -1); TCCR2 = _BV(WGM21) | _BV(CS22); jetzt weiss ich zwar noch nicht ganz genau was das bewirkt, könnte mir aber denken, dass ind der Zeile OCR2.... folgender Wert reingeschrieben wird: 43.49190247 was dieser Wert bedeutet und wie man auf die 5619 gekommen ist weiß ich zwar nicht, aber die 64 kommt sehr wahrscheinlich aus der tabelle 54 (bzw aus der dem ATMega32 entsprechendem Datenblatt, da der c'T-Bot nen ATMega32 hat....) Im text steht dazu: Das WGM21 Bit sorgt dafür dass der Zähler nach jedem Erreichen des Vergleichwertes wieder bei Null anfängt.Den Anfangswert schreibt man direkt in das Timer-Register und aktiviert zuletzt die Interrupts, die per defaul abgeschaltet sind (Wobei ich nicht weiß wie das geht) desweiteren habe ich folgende befehle gefunden, dia auch anscheinend was mit timern und interrupts zu tun haben: TCNT2 = 0; TIMSK |= _BV(OCIE2); sei(); Im Text steht dazu: Das OCIE2-Bit im TIMSK-Register schaltet den Vergleichs-Interrupt ein und das Makro sei(), das in avr/interrupt.h definiert ist, aktiviert systemweit alle Interrupts (Das heißßt ??)... Also vielleicht könnt mir da noch nen bisschen helfen ! [Ich geb nicht auf, und das ist gut !!] :)
> die Tabelle 54 gefunden, dort steht drin, wie ich die > 3 Bits (CS20-CS22) setzten muss, dementsprechen erhalte ich einen > Teiler, der den Arbeitstakt unterteilt in z.B. alle 8 32 64... > Takte, > soweit richtig ?? Ja, richtig... > jetzt weiss ich zwar noch nicht ganz genau was das bewirkt, könnte > mir > aber denken, dass ind der Zeile OCR2.... folgender Wert > reingeschrieben > wird: 43.49190247 Nein, OCR2 ist ein 16-Bit-Register, in das nur ein uint16 rein passt. Die Nachkommastellen finden darin also keinen Platz. Wenn ich mich nicht irre, rechnet dein Compiler auch nur mit Ganzzahlen. Beim AVR-Assembler z.B. wird (vom Assembler) mit 32-Bit-Ganzzahlen gerechnet. Das Konstrukt: > OCR2 = ((XTAL/64/Timer_2_CLOCK) -1); ist übrigens was für Profis oder Mathematiker, ich habe es gern einen Level niedriger, so dass ich es beim ersten Blick verstehe. Wo die 5619 herkommen, wird wohl nur aus dem Zusammenhang des kompletten Programms erkennbar sein. > TCCR2 = _BV(WGM21) | _BV(CS22); setzt die Bits wgm21 und cs22 und würde in ASM so aussehen: ldi r16,(1<<wgm21)|(1<<cs22) ;beide Bits im Register r16 setzen out tccr2,r16 ;nach tccr2 schreiben _BV ist wohl ein Macro, was das 1<< (Linksschieben einer 1) wie eine Funktion aussehen lässt. Jedem Tierchen sein Pläsierchen... > Das WGM21 Bit sorgt dafür dass der Zähler nach jedem Erreichen des > Vergleichwertes wieder bei Null anfängt. Da müsste ich erst im DB nachschauen. Bei älteren AVRs war dafür das CTC-Bit (Clear Timer by Compare) zuständig, aber aufgrund der verschiedenen PWM-Modi ist das beim Mega32 und den neueren AVRs etwas unübersichtlicher geworden. Einige dieser Steuerbits haben ja je nach Modus unterschiedliche Steuerfunktion. > TCNT2 = 0; setzt einfach nur den Zählerstand des Timer2 auf 0 > TIMSK |= _BV(OCIE2); setzt das Bit ocie2 im I/O-Register timsk, ohne die anderen Bits dieses Registers zu beeinflussen (|=, OR). Das Bit ocie2 löst einen Interrupt aus, wenn gleichzeitig das zugehörige Bit im Register TIFR (hoffentlich heißt das jetzt beim Mega32 auch so) gesetzt ist (das macht die Hardware beim Erreichen des Vergleichswertes) und wenn Interrupts global erlaubt sind, also das i-Flag im SREG gesetzt ist. > sei(); ist von der Syntax her als Funktion getarnt und ruft den ASM-Befehl 'sei' auf, der nix weiteres macht, als das i-Flag im Statusregister sreg zu setzen und damit den Aufruf von Interrupts zu ermöglichen. > Also vielleicht könnt mir da noch nen bisschen helfen ! Mach' ich doch, ich kann aber kein C... > [Ich geb nicht auf, und das ist gut !!] :) Richtig. ...
Hi @all, schonmal vielen Dank für eure bisher großartige Hilfestellung, Hier ist nun mein Programm, wie weit ich bisher bin: //////////////////////////////////////////////////// //////////////////////////////////////// //// Verfuegbare Funktionen //// //// lcd_gotoxy(0,0); //// //// lcd_puts("__TEXT__"); //// //// lcd_gotoxy(0,1); //// //// lcd_puts("__TEXT__"); //// //// schlaf(8); //// //// //// //// Servo ist folgendermaßen //// //// angeschlossen: //// //// Black -> PORTC0 //// //// Red -> PORTC1 //// //// Yellow -> PORTC2 //// //////////////////////////////////////// #include <stdlib.h> #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #include <avr/sleep.h> #include <avr/pgmspace.h> #include <math.h> #include "lcd.h" #define XTAL 1000000 // [Hz] void schlaf(float anz) { for(int i = anz; i > 0; i -= 0.25) { _delay_ms(250); } } void main(void) { DDRA = 0xff; //Port A als Ausgang definieren[Display] DDRC = 0x07; //Port C0-C2 als Ausgang definieren PORTC |= 0x02; //Port C0 und C2 auf LOW, Port C1 auf HIGH lcd_init(LCD_DISP_ON); lcd_clrscr(); } //////////////////////////////////////////////////// Soweit so gut,nur meine Fragen : [1] bishierher alles richtig ? ist es korrekt, das ich PORTC0 und PORTC2 auf LOW gesetzt habe und PORTC1 auf High ??? Meines wissens nach wird ein Servo doch so angeschlossen, oder ? Schwarz ist gnd, rot ist +(4,8 - 6 in d.R.)V und Gelb Steuer / Impulsleitung... [2] Was msuu ich jetzt wegen der Timer und Interrups programmieren, um das ans laufen zu bekommen ? [3] Brauche ich nur folgende Register Bits Fktn. ?: OCR2, TCNT2, TIMSK, CTC, OCIE2, WGM21, sei(), TCCR2 [4] Hab ich was vergessen ?? [5] Das XTAL ist doch nur dafür da, das ich im Programm erkenn, mit welcher Frequenz mein uc läuft, oder war das in dem Makefile irgendetwas ??
Da rot und schwarz (vermutlich/ziemlich sicher) die Versorgung des Servos sind (Mittig ist eigentlich immer + wegen Verpolbarkeit...), würde ich die beiden nicht über Portpins betreiben. So ein Servo zieht im Lastfall wirklich Strom; mehr als dein ganzer Port liefern kann. Zu den anderen Sachen schreibe ich vielleicht später was. Hast du dir den Thread angeguckt, den ich oben gepostet habe? Da müsste eigentlich mein Quellcode für 2 Servos drin sein.
> ist es korrekt, das ich PORTC0 und PORTC2 auf LOW gesetzt habe > und PORTC1 auf High ??? Meines wissens nach wird ein Servo doch > so angeschlossen, oder ? Schwarz ist gnd, rot ist > +(4,8 - 6 in d.R.)V und Gelb Steuer / Impulsleitung... Deine Farbzuordnung stimmt. Aber: Schwarz und Rot schliesst Du ganz normal an die Versorgungsspannung an, also nicht ueber den Port! Wenn der Motor im Servo laeuft (besonders unter Last) dann zieht das Ding wesentlich mehr Strom als der PortPin liefern kann. Von den Stoerungen, die das Servo auf der Versorgungs- spannung verursachen wird reden wir mal gar nicht. Die moechtest Du naemlich so weit als moeglich vom µC fernhalten. Ansonsten: Ein Vorschlag. Vergiss zunaechst mal das Servo und beschaeftige Dich damit eine LED an einem Port-Pin zum Blinken zu bringen. Details dazu findest Du in den Tutorials. Ein Servo anzusteuern funktioniert im Prinzip naemlich auch nicht anders, nur das das Blinken schneller geht und in einem etwas anderem Zeitraster erfolgen muss. Nur: Dieses Zeitraster kannst Du nur mit einem Oszi sichtbar machen. Bei einer LED siehst Du aber sehr gut auch ohne andere Hilfsmittel ob das Ding blinkt oder nicht.
Hi, also zum blinken hab ich meine LED bekommen.... aber halt nur auf diese primitive art und weise: void schlaf(float anz) { for(float i = anz; i > 0; i -= 0.25) { _delay_ms(250); } } void main(void) { DDRA = 0xff; //Port A als Ausgang definieren[Display] DDRC = 0x01; //Port C0 als Ausgang definieren lcd_init(LCD_DISP_ON); lcd_clrscr(); while(1) { PORTC |= 0x01; //Port C0 auf HIGH schlaf(1); PORTC &= 0xFE; //Port C0 auf LOW schlaf(1); } } Wie ich das Ganze mit Interrups machen muss verstehe ich nicht... @Rahul: wie heißt denn dein source code für 2 Servos ? es gibt da zwei dateianhänge 1) RC_SIGNAL4ok4LED.c 2) PWM.c ??
@Steffi: Irgendwo war das... Anbei ein Thread, der auch damit zutun hat: http://www.mikrocontroller.net/forum/read-4-91553.html#new
Also gut, nach der folgenden Reihenfolge sollte ich mein Programm aubauen.... folgendes entnehme ich dem Tutorial: [1] TCCR0 [In diesem Register stellen wir ein, wie wir den Timer/Counter verwenden möchten] Ich möchte als Quelle meinen CPU-Takt verwenden und stelle die Bits (CS02, CS01, CS00 (Clock Select Bits)) wie folgt ein: CS02 = 1 CS01 = 0 CS00 = 1 Womit ich meinen CPU-Takt durch 1024 teile, richtig ? wie würde das in C-Code aussehen ? : TCCR0 = 0x05; oder CS02 = 1; CS01 = 0; CS00 = 1; ?? [2] TCNT0 : Dieses ist als 8-Bit Aufwärtszähler mit Schreib- und Lesezugriff realisiert. Wenn der Zähler den Wert 255 erreicht hat beginnt er beim nächsten Zyklus wieder bei 0. [3] Um nun also den Timer0 in Betrieb zu setzen und ihn mit einer Frequenz von 1/1024-tel des CPU-Taktes zählen zu lassen, schreiben wir die folgende Befehlszeile: TCCR0 |= (1<<CS00)|(1<<CS02); Das reicht erstmal.... muss ich dem timer/counter denn noch irgendwas anderes mitteilen, z.b. wie groß mein cpu-takt ist ? wenn nicht dürfte mein c-code bisher doch folgendermaßen aussehen... void main(void) { DDRA = 0xff; //Port A als Ausgang definieren[Display] DDRC = 0x01; //Port C0 als Ausgang definieren TCCR0 |= (1<<CS00)|(1<<CS02);//Timer mit CPU-Takt/1024 laufen lassen lcd_init(LCD_DISP_ON); lcd_clrscr(); while(1) { } } soweit richtig ?
[1] TCCR0 = (1<<CS2) | (1<<CS0); [2] ja, genau, und das Overflow-Interrupt-Flag wird gesetzt. Ausgewertet wird es aber nur, wenn man es entweder abfragt oder die dazugehörende ISR freigeben hat. [3] siehe [1] Die Taktfrequenz muss der/die Programmierer/in wissen. void main(void) { DDRA = 0xff; //Port A als Ausgang definieren[Display] DDRC = 0x01; //Port C0 als Ausgang definieren TCCR0 |= (1<<CS00)|(1<<CS02);//Timer mit CPU-Takt/1024 laufen lassen lcd_init(LCD_DISP_ON); lcd_clrscr(); while(1) { } } soweit richtig ? ja Passiert aber noch nix dolles.
stimmt... meintest du diesen surcecde (den ich im anhang habe) ??? habe versucht das an mein servo anzupassen hat aber nicht geklappt, weil der die biliotheken nicht alle vorhanden hat.... es fehlt die sig-avr.h habe mal gegoogelt und auch ne entsprechende gefunden, aber kann er nichts mit anfangen... hier mal am besten die fehlermeldungen: > "make.exe" clean -------- begin -------- Cleaning project: rm -f servo.hex rm -f servo.eep rm -f servo.obj rm -f servo.cof rm -f servo.elf rm -f servo.map rm -f servo.obj rm -f servo.a90 rm -f servo.sym rm -f servo.lnk rm -f servo.lss rm -f servo.o lcd.o rm -f servo.lst lcd.lst rm -f servo.s lcd.s rm -f servo.d lcd.d rm -f .dep/* Errors: none -------- end -------- > Process Exit Code: 0 > Time Taken: 00:02 > "make.exe" all -------- begin -------- avr-gcc.exe (GCC) 3.4.5 Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiling: servo.c avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=servo.lst -std=gnu99 -Wp,-M,-MP,-MT,servo.o,-MF,.dep/servo.o.d servo.c -o servo.o servo.c:92: warning: `_overflow0_' appears to be a misspelled signal handler servo.c: In function `_overflow0_': servo.c:107: warning: implicit declaration of function `sbi' servo.c:117: warning: implicit declaration of function `cbi' servo.c: In function `main': servo.c:147: error: `UBRR' undeclared (first use in this function) servo.c:147: error: (Each undeclared identifier is reported only once servo.c:147: error: for each function it appears in.) "make.exe": *** [servo.o] Error 1 > Process Exit Code: 2 > Time Taken: 00:01
Zumindest ist es gut dokumentiert... (So im Nachhinein finde ich es nicht wirklich klasse...) Zum allgemeinen Ablauf: Dein Controller hat eine Taktfrequenz von 1MHz. Das sind 1000 Takte/Millisekunde. Wenn du den Teiler jetzt auf 1024 einstellst, kannst du nur Impulse erzeugen, die ca.1 ms lang sind. Also: Teiler runter. Ich habe aus Faulheit einen 16Bit-Timer benutzt. Bei 1MHz hat man dann eine Auflösung von 1µs. Timer benutze ich gerne in CTC-Modus (ich weiß jetzt nicht, ob Timer0 das auch kann). Da braucht man nur ins OCR-Register einen sinnvollen Wert schreiben, damit der Timer regelmässig ein Interrupt auslöst. In der ISR dazu wird dann eine Variable herunter gezählt. Sobald die Variable = 0 ist, macht man den Pin wieder aus. Man schreibt also erst einen Wert in eine Variable, setzt den Pin, startet dann den Timer und wartet, bis die Variable = 0 ist. Dann mancht man den Pin wieder aus. Viel schöner finde ich die Methode, den Timer1 durchlaufen zu lassen, und in die beiden OC-Register einen Vergleichswert zu schreiben. In der Timer1-OVerflow-ISR werden die QC-Register aktualisiert, und die Ausgangspins gesetzt. In den OCR-ISR werden dann die Pins zurückgesetzt. Bei 1MHz würden die OCR-Werte dann zwischen 1000 und 2000 variieren. Durch den Überlauf hat man dann auch eine Pause nach den Impulsen. Bis jetzt haben sich meine Servos nicht daran gestört, dass das Telegramm nicht alle 20ms wiederholt wurde.
Habe mein Mikrocontroller auf 1MHz laufen und ein Servo an PORTD2 mit der Impulsleitung... habe mir das Programm mal angeguckt und folgenden Fehler gefunden: ////////////////////////////////////////////////////////////////// /*Timer0 so setzen, dass es 1ms bis zum erneutem Auslösen des Interrupt dauert 8M *1000m = 8000; 1ms sind bei 8MHZ 8000 Takte 8000 / 64 = 125; 8000 Takte durch Prescaler = 64 bedeutet der Timer muss 125 mal weiter zählen, damit 1ms um ist 256 -125 = 131; Bei 256 läuft der Timer über und er muss 125 mal weiter zählen bis das passiert, also muss er bei 131 anfangen zu zählen. Um den Bewegungsbereich etwas zu verbessern senken wir die Zeit um 20*64 Takte (131+20= 151) */ ////////////////////////////////////////////////////////////////// muss das nicht heissen 8M *1m = 8000 ??? bei mir wäre es dann doch so : ////////////////////////////////////////////////////////////////// /* Timer0 so setzen, dass es 1ms bis zum erneutem Auslösen des Interrupt dauert 1M *1000m = 1000; 1ms sind bei 1MHZ 1000 Takte 1000 / 8 = 125; 1000 Takte durch Prescaler = 8 bedeutet der Timer muss 125 mal weiter zählen, damit 1ms um ist ...... */ ////////////////////////////////////////////////////////////////// richtig oder ? ach und woher bekomme ich die Baudrate, kenn ich nur von Modems :) die ist doch sicherlich vom CPU-Takt abhängig, richtig ? Woher bekomme ich denn die entsprechende für 1MHz ??
Ahh hab doch schon was in dem datenblatt zu baudraten gefunden... kann ich das denn dann einfach definieren wie es in der datei mit #define baudrate 9600 steht ?? habe da im kompletten datenblatt die tabelle 68 auf Seite 166 gefunden... http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf
Wo finde ich denn die sig-avr.h ?? der mach mir beim compilen immer folgenden fehler: -------- begin -------- avr-gcc.exe (GCC) 3.4.5 Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiling: servo.c avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=servo.lst -std=gnu99 -Wp,-M,-MP,-MT,servo.o,-MF,.dep/servo.o.d servo.c -o servo.o servo.c:92: warning: `_overflow0_' appears to be a misspelled signal handler servo.c: In function `_overflow0_': servo.c:109: warning: implicit declaration of function `sbi' servo.c:123: warning: implicit declaration of function `cbi' servo.c: In function `main': servo.c:157: error: `UBRR' undeclared (first use in this function) servo.c:157: error: (Each undeclared identifier is reported only once servo.c:157: error: for each function it appears in.) "make.exe": *** [servo.o] Error 1 > Process Exit Code: 0 > Time Taken: 00:03 > Process Exit Code: 2 > Time Taken: 00:01
Danke für die Datei pet, es funktioniert soweit, das ich kompilieren kann ohne probleme :) habe zum ausprobieren mein controller auf 8MHz laufen gelassen aber das servo zuckt nur immer nen bisschen hin und her, aber immerhin es tut sich etwas :) das was es wert, den ganzen tag davor zu sitzen und auszuprobieren.... welche werte muss ich denn in deinem programm ändern, um das servo mal bis zum anschlag in beide richtungen fahren zu lassen ? wie soll ich das Servo anklemmen (Versorgungstechnisch) mit an das Entwicklungsboard meines ATMega16 ? oder zieht das ding soviel spannung/strom, das es am besten wäre ne eigene versorgung für das servo zu organisieren ?
Hi, also folgendes habe ich schon in meinem programm: TCCR0 = 2; // CPU-Takt/8 TIMSK = (1<<TOIE0); // Timer Overflow Interrupt aktiv TOIE0 (Timer/Counter Overflow Interrupt Enable Timer/Counter 0) Wenn dieses Bit gesetzt ist, wird bei einem Überlauf des Datenregisters des Timer/Counter 0 ein Timer Overflow 0 Interrupt ausgelöst. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein. (aus dem AVR-GCC Tutorial) habe versucht etwas über das Gloabal Enable Interrupt zu finden, hab aber nichts gefunden.... wie setze ich das denn ?? soweit so gut ?? oder noch nicht richtig
@ Steffi Habe es gerade ausprobiert (mit echtem Servo) und bei mir geht es. Du musst mal schauen, ob die Timer2 Register vom M32 und 16 übereinstimmen. Ich glaube aber schon. Um den Weg zu ändern musst du werte von 0 bis 250 in Servo_Position schreiben. 0 = Impuls von 1ms 250 = Impuls von 2 ms. 125 = Mittelstellung
>wie soll ich das Servo anklemmen (Versorgungstechnisch) >mit an das Entwicklungsboard meines ATMega16 ? oder zieht das ding >soviel spannung/strom, das es am besten wäre ne eigene versorgung für >das servo zu organisieren ? Wenn der Spannungswandler an deinem Entwicklungsboard das kann ja. Richtwert: Spannungswandler 5V/1A (z.B. 7805 in TO220 Gehäuse) ist ok. Sollte es etwas kleineres sein oder du bist dir unsicher, nimm eine extra Spannungsversorgung ,aber vergiss nicht die beiden Massen zu verbinden! Auch solltest du dann einen 1kOhm Widerstand zwischen ServoSignaleingang und Portpin anschliessen. Das macht bei der Ansteuerung keinen Unterschied, sollte es aber irgendein Problem geben, so wird der Strom begrenzt der zwischen dem Mikrocontrollerpin und dem Servoeingang fliesst.
Also mein Programm sieht bisher so aus: TCCR0 = 2; //Timer läuft mit CPU-Takt/8 TIMSK = (1<<TOIE0); //Timer Overflow Interrupt aktiv TCNT0 = 151; /* Timer0 so setzen, dass es 1ms bis zum erneutem Auslösen des Interrupt dauert 1M *1m = 1000; 1ms sind bei 1MHZ 1000 Takte 1000 / 8 = 125; 1000 Takte durch Prescaler = 8 bedeutet der Timer muss 125 mal weiter zählen, damit 1ms um ist 256 -125 = 131; Bei 256 läuft der Timer über und er muss 125 mal weiter zählen bis das passiert, also muss er bei 131 anfangen zu zählen. Um den Bewegungsbereich etwas zu verbessern senken wir die Zeit um 20*64 Takte (131+20= 151) */ sei(); @pet: das habe ich mir gedacht und bereits ausprobiert, doch stelle ich null ein, [1] fährt das servo bis zum anschlag in eine richtung und versucht immer weiter in diese richtung zu fahren (ist das normal) [2] und es läuft nur sehr sehr langsam in die richung, man kann jeden einzelnen schritt sehen und beinahe mitzählen... wie kann ich das servo so richtig schnell laufen lassen ? so wie in dem video im anhang ?? [3] sind die servos im video spezielle schnelle servos??
> fährt das servo bis zum anschlag in eine richtung und versucht > immer weiter in diese richtung zu fahren (ist das normal) Dann stell eben nicht genau 0 ein, sondern geh etwas hoeher. Die Impulsbreite von 1ms - 2 ms (Endausschlag zu Endausschlag) ist ein Wert der bei vielen aber eben nicht bei allen Servos passt. Es haengt auch davon ab, wie du deinen µC betreibst: Kann der die 1 ms ueberhaupt einigermassen genau liefern? > und es läuft nur sehr sehr langsam in die richung das ist ein Hinweis darauf, dass Deine Stromversorgung nicht so ganz mitkommt (Du versorgst doch das Servo mitlerweile extra und nicht mehr ueber die Prozessor-Pins?). > wie kann ich das servo so richtig schnell laufen lassen Setzte den Servo_Wert auf 200 Warte bis das Servo die Position erreicht hat Dann setzte den Servo Wert auf 10 Das Servo geht dann mit seiner schnellsten Geschwindigkeit in die neue Position. Wenn das sehr langsam geht: * Entweder hast du tatsaechlich ein langsames Servo erwischt. Ist aber eher unwahrscheinlich * Deine Stromversorgung fuer das Servo kann dem Motor nicht genug Saft liefern.
@Steffi Ich hab Dir auch mal eine Demo auf die schnelle gemacht. Vielleicht verstehst Du die besser: Ich benutze einen Timer um einen regelmaessigen Timer- Overflow zu erzeugen. Bei meinen 8Mhz irgibt das mit einem taufrischen Timer der bei 256 ueberlauft, eine Zeit- basis von 0.032 MilliSekunden. In der Timeroverflow Routine zaehle ich jetzt einfach mit, wie oft die Funktion aufgerufen wurde und setzte entsprechend den AUsgangspin auf 1 oder 0, so dass sich auf der Stuerleitung zum Servo ein Impuls mit einer Laenge von ca. 1 ms bis 2 ms ergibt. Die Aufloesung ist nicht gerade ueberragend. Da muesste man jetzt noch mit dem Timer arbeiten, so dass die Funktion oefter als alle 0.32 ms aufgerufen wird (einfach einen Wert vorgeben, so dass der Timer nicht von 0 bis 255 zaehlt, sondern nur von zb. 128 bis 255: dann wird die Funktion klarerweise doppelt so oft aufgerufen, usw.) Quarz: 8Mhz Das Servo haengt am PinC.4
Oosp. Die Formatierung ist grauenhaft. Hier nochmal, besser formatiert.
ich habe hier ein altes nokia netzteil rumfliegen, es steht drauf, outut:5V 420mA eigentlich ideal, für IC#s und so, servo eigentlich auch, doch wenn ich nachmesse messe ich eine spannung von 8,61V und einen Strom von hmm kann ich nicht mesen, leigt ausserhalb des bereiches meines billig voltmeters :) ist also nicht geeignet... aber habe noch eine 4,5V batterie und eine 1,5V, bastel mir mal eben was daraus..
also bei 125 ist der nicht in der mittelstellung, da fährt er nach ganz nach rechts und versucht immer weiter zu fahren... ?!?
mhh es ist völlig egal, was für werte ich da einstelle, der tut einfach nicht...... bin voll am verzweifeln...
Hab hier mal noch ne kleine Info zu Servo-signalen gefunden... Ich gehe zwar davon aus das mittlerweile klar is wie sich Servos bewegen*g* aber viellt. nützt es ja noch jemand. http://www.the-starbearer.de/Roboterelektronik/servo/SERVOS.htm
> bin voll am verzweifeln...
Hast Du beruecksichtigt, dass Dein µC mit einer
anderen Taktfrequenz läuft (welche eigentlich?)
Je nach Takt muessen die Zeitkonstanten angepasst werden!
Hallo und danke kojote, die seite ist wirklich gut, aber wie ein servo funzt weiss ich mittlerweile.... ich kriege das programm einfach nicht ans laufen.... fürs erste würd mir ein programm reichen, welches das servo in mittelstellung bringt, eine gewisse zeit dort verharren lässt und dann zum linksanschlag, verharren und rüber zum rechtsanschlag.... aber das bekomm ich ja schon nicht hin.....
Hab grade bei Durchsicht des Threads gesehen, dass Dein µC anscheinend mit 1 Mhz läuft. Sowohl der Code von pet als auch meiner ist aber für 8Mhz ausgelegt. Wenn Du den einfach 1:1 übernommen hast, ist klar, dass das nicht gehen kann: Das ganze Timeing stimmt nicht.
doch doch, habe den code angepasst an meine 1MHz !! siehe im Anhang....
und ich habe auch schon versucht mal meinen uc auf 8MHz laufen zu lassen... aber da tat das programm auch nicht... beide möglichkeiten tun es nicht ....
Weiter als so komme ich einfach nicht... habe mir das AVR-GCC Tutorial schon x-mal durchgelesen, aber ich komme da einfach nicht dahinter.... was muss ich denn noch in meine c-code reinschreiben, damit das servo folgendes macht: Mittelstellung anfahren 2 sec warten rechtsanschlag anfahren 2 sec warten linksanschlag anfahren 2 sec warten wieder von vorne
ach ja hier der source code, kann nicht irgendwer, der das gut drauf hat meinen code so anpassen, ist doch weniger zeitaufwendig, als immer auf meine blöden nervigen anfängerfragen einzugehen ?? nen funktionierendes beisp. würd mir am besten weiterhelfen... [Bitte]
> doch doch, habe den code angepasst an meine 1MHz !!
Aehm. Der Code von pet verwendet einen Prescaler
von 32. Den hast Du geaendert auf 8. Macht einen
Faktor von 4. Dein µC läuft aber 8 mal so langsam
wie der von pet.
> nen funktionierendes beisp. würd mir am besten weiterhelfen...
Ich hab dir doch auch schon eine funktionierende
(getestete) Version gepostet. Nach Umsetzung von
8Mhz auf 1 Mhz: hast du die schon mal probiert.
(Der Code von pet geht bei mir uebrigens auch nicht.
Das Servo macht keinen Mucks).
ja läuft ja nicht..... servo rennt in eine richtung und ballert immer und immer wieder gegen die andlage, habe bestimmt 20 verschiede werte für die servoposition angegeben,nichts tut, kannst du nicht die beigelegte datei anpassen ? würd mir am besten helfen... ehrlich, weil eure beispiele funktionieren nicht bei mir, entweder es fehlen bibliotheken,(hab oben häufiger danach gefragt) oder das servo rennt gegen die endlage (aber immer nur die eine) .....
@Karl Heinz Buchegger Habe deinen code nochmals probiert und meinen uc auf 8MHz laufen lassen tut nicht.... habe das Servo folgendermaßen angeklemmt: Black -> GND [Battery] Red -> +5V [Battery] Yellow-> PORTC0 und einen Taster an PORTC3 und GND aber es passiert nichts, weder so noch wenn ich den taster drücke... habe ich was falsch angeklemmt ??
Also ich kann euch versichern, dass der Code geht. Habe jetzt mit einem digitalen Servo und ein Standart Servo getestet und beide laufen ohne Problem. Ohne zu Zucken oder an den Anschlag zu laufen usw. Benutze den Mega32 mit 8Mhz. Man kann doch einfach mal im AVR-Studie simulieren und schauen ob das Timing Stimmt. Dann muss es auch im Real gehen Also ob ein Impuls von 1 -2 ms mit einer Pause von 18ms generiert werden. Bei mir Stimmen die Pulse im Studie, ich weiß nicht warum es bei euch nicht läuft
Klemm die Steuerleitung an PORTC4 (Ich hab bei mir an PORTC0 bis PORTC3 ein paar Taster haengen, daher PORTC4) Uebrigens: Ich habe pet's Code mitlerweile am laufen. Peinlich. Hab ebenfalls den falschen Pin angesteuert.
> servo rennt in eine richtung und ballert immer und immer wieder > gegen die andlage, EIn deutliches Indiz, dass das Timing nicht stimmt. Wie gesagt: Den Prescaler von 32 auf 8 runtersetzen bringt erst einen Faktor 4, Deine 1 Mhz zu den vorgegebenen 8 Mhz sind aber ein Faktor 8 ! Und so wie da Timing in pet's Code erzeugt wird, ist das schon kritisch.
Mach mal folgendes: Setz den Prescaler in pet's Code auf 1024 und haenge eine LED an den AusgabePin. (Einfach Pin - 220Ohm - Led - GND verbinden. Auf Polung der Led achten). Die LED muesste so ungefaehr im Sekundentakt kurz dunkel werden.
Nee habe meine uc auf 8MHz laufen, brauche keinen Prescaler anpassen... Das funktioniert einfach alles nicht, ist einfach scheisse..... es gibt echt nichts depremierenderes als misserfolge, langsam hab ich auch keine lust mehr
GND von Batterie mit GND Microcontrollerschaltung verbinden nicht vergessen.
@Rahul : Mit den Fuse-Bits im Ponyprog, muss die dann von CKSEL0 CKSEL1 CKSEL2 CKSEL3 0 0 0 1 auf CKSEL0 CKSEL1 CKSEL2 CKSEL3 0 1 0 0 setzen, dazu muss an der stelle wo ne 1 stehen soll kein häkchen sein... soweit ich das richtig verstanden habe
> @Hornet : > wozun dass ?? Oh, Mann. Verwendest Du eine extra Batterie fuer das Servo? Wenn ja, dann mustt du natuerlich die GND verbinden. Damit beide Stromversorgungen das gleiche Bezugspotential haben.
hab das ding jetzt wieder an der Versorgung des uc's hängen, sollte eigentlich auch laufen[zwar langsam], tut es aber nicht... Ich habe das alles ohne Battery durchprobiert es geht nicht... da passiert garnichts... kann es sein das folgende zeile falsch ist ? TCCR0 = ( 1 << CS00 ); // Prescaler: 1 / 8 meiner meinung nach ist das nen prescaler von 1 / 1 ??? müsste es nicht vielmerh so lauten ??: TCCR0 = ( 1 << CS01 ); // Prescaler: 1 / 8 ??
Du meinst in meinem Code? Richtig. Der Kommentar ist falsch. Der Prescaler steht auf 1:1. Das stimmt schon.
stimmt denn dann der rest mit dem code, das muss doch dann nicht verbessert werden oder ? also ist nur der kommentar falsch ??
aber warum läuft das servo dann nicht bei mir ? habe doch alles richtig angeklemmt: Servo: Black - GND Red - +5V Yellow- PORTC4 Der Takt steht auf 8MHz, prescaler auf 1 / 1 (muss so, richtig?) Compiliert ohne probleme, nur es passiert nichts... mein takt ist auch auf 8MHz, (das mit den Security Bits / Configuration Fuses) was ich da erzählt habe stimmt docha auch, oder ?? Woran kann es dann liegen das das nicht tut
Wir muessen das systematisch angehen. Sonst wird das nur ein Stochern im Nebel. Also, Du baust auf: +--------------+---------------------------------+ | | | | 5V | | --- +--------------+ | --- | Deine Mega16 | | Servo-Rot | | Platine | +---------+ | | | Servo-Gelb | Servo | | | PortA.0 --------------------| | | +--------------+ +---------+ | GND | | Servo-Schwarz +--------------+---------------------------------+ Dann programmierst Du den Mega16 mit dem beigelegten Pgm. Weiters stellst Du sicher, dass der Mega16 mit 8Mhz laeuft. Wenn das Programm anlaueft, sollte das Servo in eine Position fahren. Versuchst Du dann, den Hebel am Servo mit der Hand zu verdrehen, muesstest Du einen Widerstand vom Servo spueren (weil es versucht, die Position zu halten). Wenn Du sehr stark drueckst, kannst Du auch den Motor knurren hoeren. Das setzt aber voraus, dass Deine Stromversorgung nicht aus ein paar halb ausgelutschten Batterien besteht, sondern dass da schon noch was rueberkommt. Deine Schilderung, dass das Servo nur sehr langsam, fast widerwillig faehrt, erinnert mich eher an halb zusammenbrechende Batterien als an eine stabile Stromversorgung. Ach ja. Das Pgm ist so geschrieben, dass es egal ist an welchem Pin am PortA du das Servo anschliesst. Es werden alle 8 Ausgaenge identisch bedient.
Wenn es dann immer noch nicht geht, dann ersetzt du probehalber Das Servo mit einer LED PORTA.0 ----- 220 Ohm ----- LED ---- GND und aenderst im Pgm um: von TCCR0 = ( 1 << CS00 ); nach TCCR0 = ( 1 << CS01 ); Die LED muss deutlich blinken. Geschaetzt so etwa 2 bis 3 mal in der Sekunde. Die LED ist die meiste Zeit eingeschaltet und wird nur kurz 2 bis 3 mal in der Sekunde ausgeschaltet. Ist aber deutlich zu sehen.
Besorg dir das Soundkarten-Oszi. http://polly.phys.msu.su/~zeld/oscill.html Dann kannst du die Pulse Messen. Es sollte so aussehen wie im Bild
:) :) :) :) :) :) :) :) :) :) :) :) Also das tut schonmal jetzt hab ich richtig Spaß
was machen wir als nächstes ? wenn ich die werte ändere (40) auf 31 bis 62 nimmt es doch andere stellungen ein oder ?
OK. Gut Ich glaube ich weiss, warum es bei Dir am Port C nicht funktioniert hat. Da ist uns wohl das JTAG Interface dazwischen gekommen. Schalt das gleich mal ab (Im PonyProg die Fuses einlesen und das Haeckchen bei JTAGEN wegnehmen), sonst kommt es Dir woanders wieder in die Quere und Du suchst Dich dumm und daemlich. Was ist mit pet's Original-Program? Ich habs nochmal angehaengt. Das muesste jetzt genauso funktionieren (Servo an PortA.0)
Du kannst auch folgendes Program ausprobieren. Es basiert wieder auf meinem Code, nur hab ich jetzt noch eine kleine Erweiterung gemacht. Das Servo faehrt von einer Endstellung in die andere, wartet dann ein bischen und faehrt wieder zurueck. Und das immer und immer wieder. Ich muss jetzt leider weg. Ev. ist ja jemand anderer im Forum, der Dir weiterhelfen kann.
Habe den Hacken bei JTAGEN weggemacht und nun tut auch das Programm von pet. nur leider stimmern die positionen noch nicht... Beim Programm von pet hab ich das so verstanden: SERVO_POSITION = 250; // Endlage SERVO_POSITION = 0; // andere Endlage SERVO_POSITION = 125; // Mittelstellung also mittelstellung passt auch so ziemlich genau, aber die anderen stimmen nicht über ein. Bei dem Programm von Karl Heinz Buchegger hab ich das so verstanden: Servo = 62; // Ein Wert von 31 liefert 1 ms, 62 liefert 2 ms Wobei 31 die Endlage ist und 62 die andere Endlage und die Mitte also ~ 46 ist Mittelstellung... leider verhält es sich bei keinem der programme wie gedacht... servo = 46, da lief das servo irgendwo nach links und 40 brachte es nach rechts nahe der endlage wie muss es dann lauten, wenn ich die endlagen anfahren möchte ?
Ok habe deinen veränderten source-code ausprobiert, aber das servo fährt nur in die linke endlage und bleibt dort, hab ne minute gewartet, da passierte nicht mehr ....???
Das kann man so nicht genau sagen. Da sind die Servos alle etwas unterschiedlich. Da wirst Du wohl etwas testen muessen. Siehst Du die Schraube oben in der Mitte des Hebels an Deiner Scheibe. Die kann man aufmachen und den Hebel abziehen. Der Hebel selbst ist dann mit einer Verzahnung mit dem Servo verbunden, so dass man den Hebel selbst wiederum verdrehen und anders aufsetzen kann, ohne das das Servo irgendetwas davon mitbekommen wuerde. Am besten faehrst Du durch Wertverkleinerung bzw. Vergroesserung das Servo in die jeweiligen mechanischen Endpositionen (das hoert man deutlich, wenn das Getriebe ansteht! Aber nicht lange dort lassen, gleich wieder die Versorgungsspannung weg nehmen!). Dann bildest du den Mittelwert fuer die Mittellage und steckst den Hebel so um, dass der ebenfalls in der Mitte steht. Dann sollte der Weg nach rechts und nach links so ziemlich gleich gross sein. Im Grunde ist das Timing von meinem Pgm laengst nicht so genau, wie das von pet. Es ist nur etwas einfacher. D.h. du solltest das von pet nehmen. Bei meinem Pgm wollte ich im Grunde nur erreichen, dass wir alle Fehler in Deiner Hardware (Stromversorgung) rauskriegen. Und dazu sind einfache Programme meist besser geeignet.
> leider verhält es sich bei keinem der programme wie gedacht... > servo = 46, da lief das servo irgendwo nach links > und 40 brachte es nach rechts nahe der endlage Was Du auch unbedingt als einen der naechsten Schritte machen solltest: Haenge einen Quarz an den Controller. Die internen 8Mhz sind naemlich mehr so lala, als wirkliche 8Mhz. Die driften auch mit der Temperatur weg, und da diese Basisfrequenz entscheidend fuer das komplette Timing ist, sollten die schon moeglichst stabil sein.
ok, ok, vielen dank soweit, ich werde mal nen bisschen rumprobieren wenn noch was ist, frage ich einfach Danke
ich habe beide stellungen mal aufgezeichnet also mit wert 0 und wert 250 und habe den winkel dazwischen gemessen, es kam fast 70° raus, ist das realistisch?? Haben Servos nicht generell 60°, kann das aufgrund von messungenauigkeiten sein, oder gibt es servos mit 70°
Hallöchen habe noch eine Frage zuzüglich der im thread drüber: und zwar habe ich versucht das servo in die endlage fahren zu lassen kurz zu warten und dann in die andere endlage zu fahren, geht aber nicht oben ist der source code Karl Heinz Buchegger sagte vorhin, er habe soetwas basierend auf seinem source gebastelt, aber da hat er anscheinend die source files verwechselt, denn es war das alte programm, hat jemand von euch ne idee wie sowas geht also so wie ich es gemacht habe geht es nicht
Nee, war doch das richtige programm [sorry] hab den falschen source-code runtergeladen, :) die heissen ja auch alle gleich :) (ist wohl einfacher der MAKEFILE wegen) Alles klar :)
Habe nuch eine kleine UART Ein-Ausgabe für die Servoposition eingebaut Dann kann man die Position von 0 bis 250 über den UART eingeben.
cool, sehr nett, bleibt für mich nur noch die frage, was zum teufel ist ein UART ??? :) habe ich echt keine ahnung,bin bisher noch nicht im tut drauf gestoßen... les das gleich nachm abendessen nach..
Seite 142 des Complete-Datashett...Atmel nennt es auch gerne USART, da das Ding etwas umfangreicher als das "normalpopelige" UART ist.
Du kannst dann die Werte über die serielle Schnittstelle mit dem PC zum µC senden, sofern du auf deiner Platine die benötigte Hardware (Pegelwandler z.B. MAX232 usw.) hast. Die Daten werden seriell vom PC im ASCII-Format an den µC gesendet. Dazu benötigst du noch ein Terminal Programm .z.B. Hyper Terminal, das bei Windows schon enthalten ist, je nach Installation musst du es vielleicht noch nachinstallieren.
Hi, jetzt hätte ich doch noch eine Frage :) und zwar zum beiliegendem Programm: Da Steht an folgender Stelle: SIGNAL(SIG_OVERFLOW0) // wird alle 0.032 ms aufgerufen { ....... } und TCCR0 = ( 1 << CS00 ); // Prescaler: 1 / 1 // Bei 8 Mhz wird dann alle 0.032 ms ein // Overflow Interrupt ausgeloest Fragen: [1] Wie kommt man auf den Wert 0.032 [2] Weiter oben steht im Programm, // Ein neuer 20 ms Zyklus hat begonnen, wofür brauch ich den 20ms Zyklus ? ist das der Abstabd zwischen den 1-2ms langen signalen die zum steuern des servos gebraucht werden ?? Danke :)
[1] durch Rechnen. Der Prozessor läuft mit 8 Mhz. Prescaler 1, d.h. der Timer wird ebenfalls mit 8 Mhz getaktet. Der Timer zaehlt einmal von 0 bis 255, danach läuft er über und erzeugt einen Overflow Interrupt. 8000000 / 256 -> 31250 d.h. es vergehen 31250 Takte bis ein Overflow eintritt. 1 / 31250 -> 0.000032 Sekunden oder 0.032 Millisekunden [2] 20 ms ist das Timing das das Servo vorgibt. Alle 20 ms moechte das Servo einen Puls sehen, dessen Laenge (von 1 bis 2 ms) die Servo-Position darstellt. 20 ms deshalb weil ja an einer echten Fernsteuerung nicht nur 1 Servo sitzt sondern mehrere. +-+ +-+ | | | | Servo1: ----+ +--------------------+ +------- +--+ +--+ | | | | Servo2: -------+ +-------------------+ +---- +---+ +---+ | | | | Servo3: ------------+ +-----------------+ +---- Servo4: etc. Das alleine ist noch kein wirklicher Grund. Aber auf der FUnkstrecke werden ja die Servo-Signale nicht parallel uebertragen, sondern seriell hintereinander. D.h. zunaechst wird ein Puls fuer Servo 1 uebertragen, dann kommt der Puls fuer Servo 2, dann der fuer Servo 3, etc. Funkstrecke: +-+ +--+ +---+ | | | | | | ---+ +-+ +-+ +------ S S S e e e r r r v v v o o o 1 2 3 alle 20 ms wiederholt sich dann das Spielchen. Der Empfaenger macht jetzt nichts anderes als aus diesem einen Pulsstrom die Signale fuer jedes einzelne Servo zu extrahieren und an das Servo weiterzugeben. D.h. der Puls fuer Servo2 wird logischerweise dann etwas spaeter weitergegeben als der fuer Servo1. Aber auch: Servo1 erhaelt nur alle 20 ms einen Puls, da sich ja das komplette Impuls-Telegram auf der Funkstrecke nur alle 20 ms wiederholt. Normalerweise ist das nicht besonders kritisch, wie oft ein Servo einen Puls bekommt. Es gibt aber Servos, die auch diese Abstaende auswerten und wenn das nicht stimmt, gehen sie von einer Funkstoerung aus und fahren eine bestimmte, vordefinierte Position an und ruehren sich nicht mehr.
[1] 256/8MHz, also 1 Überlauf bei 8MHz dauert 32µs (32*8 = 256). [2] Nach 20ms wiederholt sich normalerweise das Telegramm einer Modellbaufernsteuerung. Das wurde vermutlich mal festgelegt, um bei 8 Servos (damaliger Standard) ein nicht zu grosse Verzögerung/Reaktionszeit zu haben. Bis jetzt haben sich meine Servos nie über zu kurze oder womöglich zu lange Pausen beschwert...
> 8000000 / 256 -> 31250 > > d.h. es vergehen 31250 Takte bis ein Overflow eintritt. Falsch. Muss natuerlich heissen: D.h. in 1 Sekunde erfolgen 31250 Overflows. Tschuldigung.
Da war Karl-Heinz etwas schneller... Wenn längere Zeit nichts vom Sender kommt, hat der Empfänger einfach seinen Impuls-Zähler zurückgesetzt. Deswegen 20ms und nicht 16,17,18 oder 19.
Hi, ich muss ein Projekt in der Schule machen, indem ich einen Microcontroller Programmieren muss in Reads. An dem Microcontroller soll ein Servomotor angeschlossen sein. Da ich mich mit Programmieren absolut nicht auskenne, wollte ich fragen ob jemdan zufällig schon so ein Programm hat oder weiß wo ich sowas finden kann. Danke Julian
>Reads Ist das eine Programmiersprache? Servomotor != Modellbauservo >Da ich mich mit Programmieren absolut nicht auskenne, wollte ich >fragen ob jemdan zufällig schon so ein Programm hat oder weiß wo >ich sowas finden kann. Deinen Lehrer? (Nein, das ist hier kein machtmaleinermeineHausaufgabenfürmich-Forum!)
>in der Schule >mit Programmieren absolut nicht auskenne Was lernt ihr an dieser Schule? Warum bekommst dann gerade Du diesen Auftrag, wenn Du kein Plan hast? Verstehe ich nicht. Man bekommt doch so ein Projekt nicht einfach so - da muss im Unterricht was drann genommen worden sein? Warst Du Krank? Bist du der einzige in der Klasse, der sich damit beschäftigt? Sorry. mit "READS" kennne ich mich nicht aus - bin ich schon zu alt?
es geht hier um einen seminarkurs, bei dem ich programmieren muss. aber an für sich ist es ja egal warum ich das machen muss, usw. tatsache ist, ich muss programmieren und kenne mich absolut nicht damit aus. deshalb dachte ich mi, dass mir vielleicht hier einer helfen kann oder vielleicht sogar schon ein fertiges programm in reads51 hat, in dem er einen microcontroller steuern kann. Es wäre cool wenn sich vielleicht doch noch jemand finden lässt. MFG Julian
Von 51ern habe ich keine Ahnung, schade. Tut mir leid. Du müsstest eigentlich mit einem AD-Wandler die Potiposition des Servomotors auslesen (da hängt meist ein POTI am Getriebedrann, oder mit Lochscheibe und Lichtschranke) und die gewonnenen Positionsinformationen mit deiner Sollposition vergleichen und den Motor zwischen 2Ports+Treibern (H-Brücke) rechts-oder linksrum laufen lassen bis die Istposition mit der Sollposition übereinstimmt. Da ich von Regelungstechnik leider keine Ahnung habe, musst Du selbst nach PID-Reglerimplementationen suchen, oder jemand anders aus dem Forum kann Dir bei Design des Reglers weiterhelfen? Was hast Du denn für einen Servomotor genau? Was hat dein Board für Anschlussmöglichkeiten? Achso, mach am besten einen neuen Thread auf mit "READS51 - HILFE" oderso.
Jaja, die Fachleute von morgen... Alles nur geklaut, wie bei den Prinzen. ...
Hey Axel ja es muss nicht undbedingt in Reads. Ich muss einfach ein Microcontroller Programmieren. Das Programm sieht so aus, dass ein Poti ein Signal an den Controller weiter gibt und der Controller wandelt es dann um, sodass der Servo weiß ob und wie weit er in die jeweilige Richtung muss. Meinst du du könntest mir da weiter helfen? MFG Julian
Nur um sicher zu gehen: Was musst du genau machen? Möglichkeit A) Gegeben ist ein handelsübliches Modellbauservo. Dieses Servo ist am µC angeschlossen Weiters ist gegeben ein Poti. Auch das ist am µC angeschlossen. Deine Aufgabe ist es nun, die aktuelle Position vom Poti auszulesen und das Servo in eine dem Poti entsprechende Position verfahren zu lassen. Brauchen könnte man das zb. dann wenn das Servo mechanisch mit einer Klappe verbunden ist. Durch drehen am Poti kann man dann die Klappe auf und zu fahren bzw. in einer bestimmten Klappenstellung stehen lassen. Oder brauchst du Möglichkeit B) Gegeben ist ein Motor. Dieser Motor ist mittels einer H-Brücke am µC angeschlossen. Weiters ist gegeben ein Poti, dass mechanisch mit dem Motor gekoppelt ist. Die Potistellung ist daher ein Mass für die aktuelle Motorstellung. Weiters ist gegeben ein Eingangssignal, welches in irgendeiner Form eine bestimmte Motorstellung kodiert. Deine Aufgabe ist es, den Motor über die H-Brücke so anzusteuern, dass die aktuelle Motorposition, gemessen mit dem Poti, der Vorgabe durch das Eingangssignal entspricht. Brauchen könnte man das zb. um damit ein Servo zu bauen, dass zb in Möglichkeit A) eingesetzt wird. Dieses System realisiert den Regelkreis, der in einem Modellbauservo abläuft und der dafür sorgt, dass das Servo sich auf bestimmte Positionen hin bewegt und diese Positionen auch hält. Also: Was solls sein? Persönlich denke ich nicht, dass du den Regelkreis implementieren musst, denn für jemanden der keine Ahnung von Programmierung hat, ist das dann doch recht 'heavy'. Wobei man der Fairness halber auch sagen muss: Auch Möglichkeit A) ist nicht unbedingt anfängertauglich. Man sollte da eigentlich schon programmieren können um dieses Problem anzugehen. Das größte Problem wird wohl die Programmiersprache Reads51 sein (ist das überhaupt eine Programmiersprache?). Die kennt hier nämlich keiner (sag ich mal so). PS: Ich wollte das hier nur mal nachfragen um deine Chancen auf Hilfe zu erhöhen. Ich werde mich dann wieder raushalten. Das ganze klingt mir nämlich etwas zu sehr nach: Ich war das ganze Schuljahr über Videospielen und hab in der Schule nicht aufgepasst und jetzt soll ich dieses Projekt machen; macht das wer für mich?
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.