Forum: Mikrocontroller und Digitale Elektronik Servo am Mikrocontroller


von Steffi (Gast)


Lesenswert?

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

von Hannes L. (hannes)


Lesenswert?

> 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

...

von Steffi (Gast)


Lesenswert?

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 :)

von Hannes L. (hannes)


Lesenswert?

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.

...

von Steffi (Gast)


Lesenswert?

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]

von Hannes L. (hannes)


Lesenswert?

> 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.

...

von Steffi (Gast)


Lesenswert?

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]²

von Hannes L. (hannes)


Lesenswert?

Dann brauchst du zuerst mal das (vollständige!!!) Datenblatt des Mega16
und etwas Geduld. Im Kapitel Timer ist alles erklärt.

...

von Steffi (Gast)


Lesenswert?

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....

von Steffi (Gast)


Lesenswert?

Also
TCCR0 heisst Timer Counter Control Register ist also nen Register
welches... sagt der name ja schon :)

von Hannes L. (hannes)


Lesenswert?

> 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...

...

von Stefan Sczekalla (Gast)


Lesenswert?

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

von Rahul (Gast)


Lesenswert?


von Frank Simon (Gast)


Lesenswert?


von Steffi (Gast)


Lesenswert?

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 !!] :)

von Hannes L. (hannes)


Lesenswert?

> 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.

...

von Steffi (Gast)


Lesenswert?

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 ??

von Rahul (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Steffi (Gast)


Lesenswert?

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
??

von Rahul (Gast)


Lesenswert?

@Steffi:
Irgendwo war das...
Anbei ein Thread, der auch damit zutun hat:
http://www.mikrocontroller.net/forum/read-4-91553.html#new

von Steffi (Gast)


Lesenswert?

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 ?

von Rahul (Gast)


Lesenswert?

[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.

von Steffi (Gast)


Angehängte Dateien:

Lesenswert?

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

von Rahul (Gast)


Lesenswert?

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.

von Steffi (Gast)


Lesenswert?

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 ??

von Steffi (Gast)


Lesenswert?

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

von Steffi (Gast)


Lesenswert?

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

von Steffi (Gast)


Angehängte Dateien:

Lesenswert?

ach am besten hier mal das programm

von pet (Gast)


Angehängte Dateien:

Lesenswert?

habe auch eine billiges Beispiel für die Steuerung für ein Servo

von Steffi (Gast)


Lesenswert?

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 ?

von Teardrop (Gast)


Lesenswert?

Hat jemand ein gutes Beispielprog,
würde mich auch interessieren

von Steffi (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

sei();

von pet (Gast)


Lesenswert?

@ 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

von Wolfram (Gast)


Lesenswert?

>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.

von Steffi (Gast)


Angehängte Dateien:

Lesenswert?

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??

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

@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

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Oosp. Die Formatierung ist grauenhaft.
Hier nochmal, besser formatiert.

von Steffi (Gast)


Lesenswert?

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..

von Steffi (Gast)


Lesenswert?

also bei 125 ist der nicht in der mittelstellung, da fährt er nach ganz
nach rechts und versucht immer weiter zu fahren... ?!?

von Steffi (Gast)


Lesenswert?

mhh es ist völlig egal, was für werte ich da einstelle, der
tut einfach nicht......

bin voll am verzweifeln...

von Kojote (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

> 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!

von Steffi (Gast)


Lesenswert?

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.....

von Karl H. (kbuchegg)


Lesenswert?

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.

von Steffi (Gast)


Angehängte Dateien:

Lesenswert?

doch doch, habe den code angepasst an meine 1MHz !!
siehe im Anhang....

von Steffi (Gast)


Lesenswert?

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 ....

von Steffi (Gast)


Lesenswert?

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

von Steffi (Gast)


Angehängte Dateien:

Lesenswert?

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]

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

> 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).

von Steffi (Gast)


Lesenswert?

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)
.....

von Steffi (Gast)


Lesenswert?

@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 ??

von pet (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Steffi (Gast)


Lesenswert?

Nee tut auch nicht,
da passiert nichts

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Steffi (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

Sorry.
Aber wenns bei 2 von 3-en funktioniert, ....

von Hornet (Gast)


Lesenswert?

GND von Batterie mit GND Microcontrollerschaltung verbinden nicht
vergessen.

von Rahul (Gast)


Lesenswert?

wie schaltest du den µC eigentlich zwischen 1MHz und 8MHz um?

von Steffi (Gast)


Lesenswert?

@Hornet :
wozun dass ??

von Steffi (Gast)


Lesenswert?

@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

von Karl H. (kbuchegg)


Lesenswert?

> @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.

von Steffi (Gast)


Lesenswert?

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

??

von Karl H. (kbuchegg)


Lesenswert?

Du meinst in meinem Code?

Richtig. Der Kommentar ist falsch. Der Prescaler steht
auf 1:1. Das stimmt schon.

von Steffi (Gast)


Lesenswert?

stimmt denn dann der rest mit dem code, das muss doch dann nicht
verbessert werden oder ? also ist nur der kommentar falsch ??

von Karl H. (kbuchegg)


Lesenswert?

Es ist nur der Kommentar falsch. Der Rest geht bei
8 Mhz.

von Steffi (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von pet (Gast)


Angehängte Dateien:

Lesenswert?

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

von Steffi (Gast)


Lesenswert?

:)    :)    :)    :)    :)    :)    :)    :)    :)    :)    :)    :)

Also das tut schonmal
jetzt hab ich richtig Spaß

von Steffi (Gast)


Lesenswert?

was machen wir als nächstes ?
wenn ich die werte ändere (40) auf 31 bis 62 nimmt es doch andere
stellungen ein oder ?

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

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)

von Karl H. (kbuchegg)


Lesenswert?

> wenn ich die werte ändere (40) auf 31 bis 62

Yep. Probier das mal.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

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.

von Steffi (Gast)


Lesenswert?

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 ?

von Steffi (Gast)


Angehängte Dateien:

Lesenswert?

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 ....???

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Steffi (Gast)


Lesenswert?

ok, ok,
vielen dank soweit,
ich werde mal nen bisschen rumprobieren
wenn noch was ist, frage ich einfach
Danke

von Steffi (Gast)


Lesenswert?

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°

von Steffi (Gast)


Angehängte Dateien:

Lesenswert?

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

von Steffi (Gast)


Lesenswert?

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 :)

von pet (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Steffi (Gast)


Lesenswert?

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..

von Rahul (Gast)


Lesenswert?

Seite 142 des Complete-Datashett...Atmel nennt es auch gerne USART, da
das Ding etwas umfangreicher als das "normalpopelige" UART ist.

von pez (Gast)


Lesenswert?

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.

von Steffi (Gast)


Lesenswert?

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 :)

von Karl H. (kbuchegg)


Lesenswert?

[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.

von Rahul (Gast)


Lesenswert?

[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...

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Rahul (Gast)


Lesenswert?

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.

von Julian Wolf (Gast)


Lesenswert?

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

von Rahul D. (rahul)


Lesenswert?

>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!)

von Axel R. (Gast)


Lesenswert?

>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?

von Julian Wolf (Gast)


Lesenswert?

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 Axel R. (Gast)


Lesenswert?

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.

von Hannes L. (hannes)


Lesenswert?

Jaja, die Fachleute von morgen... Alles nur geklaut, wie bei den 
Prinzen.

...

von Julian Wolf (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.