www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Signal mit Timer erzeugen


Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

kann mir jemand einen Tip geben wie ich ein Signal mit 80µs High_Pegel,
20µs Low_Pegel und dann 100µs High_Pegel erzeugen kann....???

Gruß

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was für ein Controller (oder NE555:-?)? Bei AVR: Timer im CTC-Modus
betreiben, Compare-Register auf 80µs einstellen, dann bei Compare Pin
umschalten, Compare-Reg. umschalten auf 20 µs usw....

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Controller ist ein Atmega8.....

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es vielleicht irgendwo ein Besispiel wie man so etwas macht....?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für so etwas Spezielles glaub ich weniger... Aber mit den Infos oben
solltest Du das eigentlich hinbekommen.

Kleiner Hinweis noch: Wenn Dein µC mit 8 MHz läuft, stellst Du den
Prescaler des betreffenden Timers auf Taktteilung durch 8, dann zählt
der Timer µs. Brauchst dann im CTC-Modus nur noch in das entsprechende
OCR z.B. ne 80 für 80µs reinzuschreiben. In der
Compare-Interrupt-Routine schaltest Du dann den Pin um und schreibst
den neuen Wert ins OCR (also z.B. beim ersten Interrupt die 20, dann
die 100).

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kapier ich nicht ganz...!

Hab bis jetzt dieses Programm:

#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER0_OVF_vect)
{
  PORTB =~ PORTB; // PORTB inventieren
}

int main()
{
  DDRB  = 0xFF; // PORTB als Ausgang schalten
  PORTB = 0x00; // Alle Ausgaenge auf 0 schalten

  TCCR0B |= (1 << CS01);         //Prescaler auf 1024 stellen
  TIMSK0  |= (1 << TOIE0);              // Timer 0 Overflow Interrupt
enable

  sei(); // Interrupts einschalten

  for(;;); //ever
}

Das gibt mir ein Signal welches abwechselnd alle 160µs einen High- und
Low-Pegel hat.

Nur wie kann ich ich jetzt eine bestimmte Länge der Pegel einstellen?
Versteh das mit dem OCR und dem Pin umschalten nicht ganz....

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit Timer 0 geht das was ich vorgeschlagen habe (und wie ich es machen
würde) auch nicht, weil der keine Compare-Unit hat. Entweder Timer 1
oder Timer 2 nehmen. Den dann im CTC-Modus betreiben (das heißt, der
Timer (TCNTx) wird bei erreichen des Compare-Wertes zurückgesetzt). Je
nachdem, mit welcher Taktfrequenz Du arbeitest, musst Du den Prescaler
entsprechend einstellen. Dann nicht den Overflow-Interrupt, sondern den
Compare-Interrupt benutzen und jeweils den gewünschten Zeitwert ins
Compare-Register laden.

Wenns unbedingt mit Timer 0 sein soll, dann in der Overflow-ISR jeweils
den Pin umschalten und das TCNT0 mit dem entsprechenden Startwert laden.
Geht auch, ist aber mit ein bisschen mehr Denkarbeit verbunden...

Wenn Du das Umschalten der Portpins so machst, wie Du es oben
schreibst, dann kriegst Du das Signal aber bei jedem Mal invertiert
(also in jedem Zyklus High- und Low-Pegel vertauscht).

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich krieg es nicht hin....

Kannst du mir mal nen kleines Beispiel für den Compare Interrupt geben,
wie du ihn schreiben würdest?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähh, wäre vielleicht besser, wenn Du, bevor Du so 'komplizierte'
Signale erzeugst, Dich erst mal mit den Grundlagen befasst... Wie ein
Timer eigentlich arbeitet und so. Wenn das Verständnis nicht da ist,
dann bringt es eh nix.

Lass den Compare erst mal weg (wie gesagt, so würde ich es machen, aber
mit dem Overflow gehts auch) und lass Dein Programm erst mal so wie es
oben ist mit Timer 0 (außer, dass Du vielleicht darauf achten solltest,
dass Dein Kommentar auch mit dem Programmcode übereinstimmt, was
zumindest bei der Prescaler-Initialisierung nicht der Fall ist). Und
dann überlegst Du mal, wie Du die Zeit, die der Timer vom Start bis zum
Überlauf braucht, verändern kannst. Ohne das Verständnis könnte ich Dir
höchstens ein komplettes Programm schreiben, wofür ich jetzt aber
erstens keine Zeit habe und zweitens würde es Dir nix bringen.

BTW: Mit welcher Taktfrequenz betreibst Du den µC eigentlich jetzt???
Wenn das oben tatsächlich 160µs ergeben sollen, dann müssten das 12,8
MHz sein...

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Hinweis von mir:
Der Timer zählt ständig von 0 bis 255.
Wenn 255  erreicht sind, kommt der Overflow Interrupt.
Das dauert eine bestimmte Zeit.
Wenn du den Zähler aber nicht bei 0 sondern bei x
lauslaufen lässt, dann passiert was? (Da kommst
du sicher selbst drauf. Ist völlig logisch).

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also,

der Mikrocontroller läuft mit 8MHz. Das mit dem Prescaler Kommentar
oben ist mir auch schon aufgefallen und ist falsch, der Teiler beträgt
8.

Sowie ich das jetzt verstehe zählt das TCNT-Register von 0 bis 255 und
fängt danach wieder bei 0 an.

Wenn es jetzt nicht bei null anfängt sondern bei x, wird der Interrupt
schneller ausgelöst.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yep.
D.h. du musst jetzt 'nur noch' die Werte rausfinden,
bei denen du den Zähler loslaufen lässt, damit x
Zeit vergeht, bis der nächste Overflow Interrupt
kommt. Bei jedem Overflow Interrupt lädst du dann
den Timer mit einem dieser Werte, schaltest den Port
um und wartest bis der nächste Overflow kommt.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau. Aber bei 8 MHz bekommst Du mit den obigen Einstellungen keine 160
µs sondern 256 µs... Jetzt musst Du nur noch für die Zeiten, die Du
brauchst, jeweils das TCNT0 mit dem richtigen Wert versehen.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, soweit hab ich das kapiert! Die Dauer der High- und Low-Pegel kann
ich schon ändern, das klappt.

Nur verschiedene Längen bekomm ich noch nicht hin!

Versteh das nicht ganz mit dem Port umschalten? Und wie kann ich denn
angeben, mache beim ersten Overflow das, beim zweiten das usw.?

So ganz check ich das noch nicht....

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wäre der Vorteil der Sache mit dem Compare. Da bräuchtest Du bei
jedem Interrupt nur nachsehen, was grad im Compare-Register (OCRxy)
drinsteht und entsprechend den nächsten Wert reinschreiben, also z.B.:


1.-es tritt ein Compare-Interrupt auf
2.-Du schaltest den Portpin um
3.-Du schaust nach, was im OCR steht
  --steht eine 80 drin, dann schreib ne 20 rein
  --steht ne 20 drin, dann ne 100 rein
  --steht ne 100 drin, dann ist Ende der Sequenz
4.-Ende der Interrupt-Bearbeitung

Das zu dem Beispiel ganz oben (Reihenfolge 80µs H - 20µs L - 100µs H).

Bei der Lösung mit dem Overflow ist es komplizierter. Da müsstest Du
mit einer globalen Hilfsvariable (Achtung! volatile nicht vergessen!)
arbeiten, in der Du jeweils den aktuellen Reload-Wert für TCNT0
speicherst und den dann abfragst, also z.B.:

1.-Es tritt ein Overflow-Interrupt auf
2.-Du schaltest den Portpin um
3.-Du schaust, was in der Variable 'reload' steht
  --steht ne 176 drin, dann schreib ne 236 rein
  --steht ne 236 drin, dann schreib ne 156 rein
  --steht ne 156 drin, dann Ende der Sequenz
4.-Du schreibst reload in TCNT0
5.-Ende der Interrupt-Bearbeitung

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ungefähr so:

#include <avr/io.h>
#include <avr/interrupt.h>

volatile int reload;

ISR(TIMER0_OVF_vect)
{

  PORTB =~ PORTB;  // PORTB inventieren
  reload = TCNT0;

  if (reload = 0) reload = 150;

  TCNT0 = reload;

}

int main()
{

  DDRB  = 0xFF; // PORTB als Ausgang schalten
  PORTB = 0x00; // Alle Ausgaenge auf 0 schalten


  TCCR0B |= (1 << CS01);         //Teiler 8
  TIMSK0  |= (1 << TOIE0);              // Timer 0 Overflow Interrupt
enable



  sei(); // Interrupts einschalten

  while(1); //ever
}

Doch wo gebe ich nun an, das er beim zweiten Overflow nicht mehr den
Wert 150 sondern 30 ins TCNT0 schreibt.

Wenn ich das auch in der ISR schreibe übernimmt er das doch sofort....

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Versteh das nicht ganz mit dem Port umschalten?

Das versteh jetzt ich wieder nicht.
Hast du doch schon gemacht:

  PORTB =~ PORTB; // PORTB inventieren

> Und wie kann ich denn angeben, mache beim ersten Overflow das,
> beim zweiten das usw.?

Na ja. passeiern muss beim Overflow Interrupt immer
das selbe: Der Timer wird mit einem Wert vorgeladen. Nur
der Wert ändert sich von einem Overflow Interrupt zum
nächsten. Du wirst also mitzählen müssen, der wievielte
Interrupt das war. Mit diesem Wert gehst du zb. in eine
Tabelle und holst dir von der Tabelle den nächsten vorzuladenden
Wert:

(Ich nehm jetzt mal irgendwelche Zahlenwerte)

unsigned char Preloads[] =  { 20, 180, 40, 230 };
unsigned char NrOverflow = 0;

ISR(TIMER0_OVF_vect)
{
  PORTB =~ PORTB;                   // PORTB inventieren

                                    // welcher Vorgabewert muss als
                                    // nächstes geladen werden?
  NrOverflow++;
  if( NrOverflow == 4 )
    NrOverflow = 0;

  TCNT0 = Preloads[ NrOverflow ];   // Den Timer damit laden
}

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So wie Karl Heinz es unten vorgeschlagen hat, ist es elegant gelöst. Was
bei Dir vor allem noch falsch ist, ist, dass Du TCNT0 in reload
einliest! Was soll das? In TCNT0 steht am Anfang der Overflow-ISR immer
der selbe Wert (wahrscheinlich 0, 1 oder 2, je nachdem, wie lange der
Aufruf der ISR nach dem Auftreten des Interrupts dauert, und das sind
u.U. schon einige Takte). Außerdem kann reload nur Werte von 0..255
annehmen, wozu also der int? Da reicht auch ein char.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oops, da seh ich noch ein kleines Detail in deinem
Code (den ich per Copy&Paste übernommen habe :-)

  PORTB =~ PORTB;                   // PORTB inventieren

Das ist, nun ja, missverständlich formuliert (es geht
nur um die Schreibweise).

=~  bilden hier optisch eine Einheit. Da es in C ja diese
Kurzschreibweisen, wie += *= &= etc gibt, könnte ein geneigter
Leser beim drüberlesen, dass als eine dieser Kurzschreibweise
ansehen. Ich muss gestehen, ich hab auch erst beim 3-ten Blick
gesehen, dass es keine Kurzschreibweise ist! Und ich seh viel,
was du noch nicht siehst!

  PORTB = ~PORTB;

So ist es viel klarer, was hier wirklich passiert. Der
Inhalt von PORTB wird genommen, wird invertiert und wieder
PORTB zugewiesen. Das hat nichts mit irgendeiner dieser
Kurzschreibweisen zu tun. Nur jetzt sieht mans auch auf
einen Blick.

Du glaubst gar nicht, wieviele läppische Fehler durch Verwendung
einer vernünftigen Formatierung des Programmtextes vermeidbar
sind.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, vielen Dank!

Jetzt hab ich es kapiert!

Nur eine Frage noch. Wie bekomm ich es jetzt hin, dass er mit nach den
4 Interrupts einen dauerhaften High Pegel liefert?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Indem Du in der ISR den Port auf HIGH schaltest und den Timer
anhältst...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und noch eine kleine Frage.

Wie kann ich das mit dem Port invertieren anders schreiben. Gibt es
nicht ne Möglichkeit ihn einfach auf HIGH oder LOW zu setzen...??

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PORTB = 0xFF;
bzw.
PORTB = 0;

ist es das, was Du meinst?

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Gibt es nicht ne Möglichkeit ihn einfach auf HIGH oder LOW zu
> setzen...??

Kann es sein, dass dir mächtig Grundlagen fehlen?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kann es sein, dass dir mächtig Grundlagen fehlen?

Vermutlich ist Björn ja deshalb hier und stellt diese Fragen, um sich
die fehlenden Grundlagen anzueignen.

Duck & wech...

...

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na, ja
Es ist aber schon ein Unterschied ob jemand Schwierigkeiten
mit dem Erzeugen eines Timings hat oder ob er Schwierigkeiten
mit dem 'Einschalten einer LED' hat.
In letzterem Fall ist die einzig sinnvolle Antwort:
'Schau ins Tutorial, dort ist alles erklärt. Wenn du das
durchhast, dann haben wir mal eine Basis auf der man aufbauen
kann'
Ich erklär ja auch niemandem die Feinheiten einer
Extremwertaufgabe, wenn er beim Lösen von einfachen Gleichungen
in einer Variablen nur mit der Schulter zuckt.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl Heinz, du kennst meine Einstellung zum Thema Grundlagen aus anderen
Threads und weißt daher vermutlich auch, wie du meinen Spruch zu
interpretieren hast.

Björn, wenn es unbedingt C sein muss, weil dir ASM zu primitiv ist,
dann schau dir das GCC-Tutorial an und kauf dir ein C-Buch und versuche
Beides zu verstehen.

Ich mach' Sowas in ASM, für C bin ich zu doof.

...

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> daher vermutlich auch, wie du meinen Spruch zu
> interpretieren hast.

Klar doch.
Ich arbeite nur zur Zeit grade an einem Setup. Im Moment
ist der Status so, dass zwar (meiner Ansicht nach) alles
korrekt installiert wird, trotzdem schmiert das installierte
Pgm sofort ab. Da hab ich wohl noch irgendeine DLL vergessen.
Mal schön suchen :-)

> für C bin ich zu doof.

Das glaub ich nicht :-)

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaub, Assembler erfordert i.a. mehr Intellenz als C...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey,

da Tuorial hab ich soweit schon durch. Das mit dem einschalten der
LED's, einrichten PORT'S und DDR's  habe ich verstanden. Ich denke
meine Frage wurde oben falsch verstanden.

Ich beschäftige mich erst seid ein paar Wochen mit der Programmierung
von µC.

Erst habe ich ein paar LED's ein und ausgeschaltet, danach dann Daten
per UART gesendet und empfangen.

Und nun wollte ich mich mal mit den Timern beschäftigen. Mein Ziel ist
es nun, je nach ankommendem Byte daraus bestimmte Signale zu erzeugen
und damit einen Servo zu steuern....

Zu dem Programm das Dank Karl Heinz und Johnny nun soweit läuft, bin
ich schon ein kleines Stück weiter.

Nun hab ich noch ne Frage. Hab mir das Signal gerade mal auf dem Osz.
angeschaut. Wenn ich zb. 4mal den Wert 250 nehme oder 4mal den Wert 0,
bekomme ich ein sauberes Signal. Bei verschiedenen Werten spiegelt sich
das Signal leicht versetzt wieder. Woran kann das liegen....??

Schon einmal vielen Dank für die bisherige Hilfe!

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mein Ziel ist
> es nun, je nach ankommendem Byte daraus bestimmte Signale zu
> erzeugen und damit einen Servo zu steuern....

Ein handelsübliches Modellbauservo?
Das hat ein völlig anderes Timing.

> Nun hab ich noch ne Frage. Hab mir das Signal gerade mal auf dem
> Osz. angeschaut. Wenn ich zb. 4mal den Wert 250 nehme oder 4mal den
> Wert 0, bekomme ich ein sauberes Signal. Bei verschiedenen Werten
> spiegelt sich das Signal leicht versetzt wieder. Woran kann das
> liegen....??

Bin mir jetzt nicht sicher ob ich deine Fehlerbeschreibung
richtig verstehe. Was meinst du mit 'leicht versetzt'?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was heißt 'versetzt'? Wenn Du die Verzögerungen meinst, die Du durch
das verzögerte Umschalten der Portpins und das ebenfalls verzögerte
Neuschreiben des TCNT0 bekommst, das liegt eben an der Zeit, die der µC
benötigt um die ISR aufzurufen (dabei werden einige Register
gesichert...), was schon einige Takte (so 1-2µs werden es wohl sein) in
Anspruch nimmt. Der Port wird ja erst in der ISR, also einige Takte nach
dem Auftritt des eigentlichen Interrupt-Ereignisses, umgeschaltet. Hinzu
kommt noch die Tatsache, dass Du das Timer-Register TCNT0 ebenfalls erst
verzögert neu schreibst. Dadurch gibts natürlich einen Versatz, den Du
nicht hättest, wenn Du mit der Compare-Einheit arbeiten würdest. Da
kannst Du nämlich einen bestimmten Portpin hardwaremäßig (also
verzögerungsfrei) beim Compare-Ereignis umschalten und brauchst
außerdem nicht das TCNT zu ändern, wodurch kein Versatz entsteht.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ein handelsübliches Modellbauservo?
> Das hat ein völlig anderes Timing.

Nein, keinen handelsüblichen Modellbauervo! Der Servo wird über eine
bestimmte Impulsfolge gesteuert, wenn ein Byte empfangen wird. Wie das
Signal zum steuern des Servos aussehen muss weiß ich.

> Bin mir jetzt nicht sicher ob ich deine Fehlerbeschreibung
> richtig verstehe. Was meinst du mit 'leicht versetzt'?

Wenn ich mir ein Signal mit dem obigen Beispiel von dir erzeuge und
setze 4mal die Werte für TCNT0 = 250 , bekomme ich ein sauberes Signal
mit einem wechselden Pegel von 12µs. Sobald ich aber nur einen der
Werte auf z.B. 247 ändere, bekomm ich zwar das gewünschte Signal, aber
zusätzlich ein identisches Signal ein paar µs nach rechts verschoben
und das Signal auch noch mal gespiegelt. Also es sieht so aus als wären
es 3 Signale.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Ein handelsübliches Modellbauservo?
>> Das hat ein völlig anderes Timing.
>
> Nein, keinen handelsüblichen Modellbauervo! Der Servo wird über
> eine bestimmte Impulsfolge gesteuert, wenn ein Byte empfangen wird.
> Wie das Signal zum steuern des Servos aussehen muss weiß ich.

Alles klar.
In diesem Forum ist mit einem 'Servo' normalerweise ein
Modellbauservo gemeint. Daher dir Frage.

> Wenn ich mir ein Signal mit dem obigen Beispiel von dir erzeuge
> und setze 4mal die Werte für TCNT0 = 250 , bekomme ich ein
> sauberes Signal mit einem wechselden Pegel von 12µs. Sobald
> ich aber nur einen der Werte auf z.B. 247 ändere, bekomm ich
> zwar das gewünschte Signal, aber zusätzlich ein identisches
> Signal ein paar µs nach rechts verschoben und das Signal auch
> noch mal gespiegelt. Also es sieht so aus als wären es 3 Signale.

Ich kann mir immer noch nichts drunter vorstellen. Im Moment
hört sich das für mich so an, als ob dein Oszi mal auf die
eine Flanke und mal auf die andere Flanke triggert, daher
siehst du am Oszi eine Überlagerung desselben Signals mit sich
selbst. Der eine Puls ist 12 µs lang, der andere etwas kürzer.
Wenn du die jetzt übereinander malst, könnte das der Beschreibung
entsprechen.

Kannst du vom Oszi einen Screenshot machen. Digicam - Photo
machen, was auch immer.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vermute ich mittlerweile auch. Kannst Du am Oszi die Holdoff-Zeit
verstellen? Wenn ja, dann tu das mal und schau mal, was sich ergibt.
Wenn die Holdoff-Zeit nicht 'synchron' mit der Zyklusdauer Deines
Signals ist, dann 'wackelt' es halt auf dem Bildschirm...

Autor: Björn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also am Osz. hab ich schon alles versucht, krieg das Signal nicht sauber
hin.

Hab mal ein Bild davon gemacht, leider nur mit dem Handy!

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kein Problem.
Sieht tatsächlich so aus, als ob Dein Oszi abwechselnd
mal auf den kurzen Puls und dann auf den langen Puls
triggert.
Zeigst du mir noch mal schnell das Pgm, dass da jetzt läuft?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe nur einen Uralt-Oszi aus DDR-Zeiten, der arge
Sync-Probleme hat.
Aber beim Anzeigen selbst (mit AVR) erzeugter Signale gibt es doch die
Möglichkeit, an einem weiteren Pin ein Synchronisationssignal zu
generieren und damit den Oszi zu triggern.

...

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ne gute Idee.
Einfach an einem 2. Pin ein Sync-Signal erzeugen, wenn
der AVR mit der Zeitsequenz von vorne anfängt.

Autor: Marko B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hilft Dir zwar wahrscheinlich nicht weiter, aber es gibt Controller,
z.B. den Renesas R8C/13, welche einen speziellen Timer-Modus haben, der
sich "Programmable Waveform Generator" nennt. Mit diesem kann man die
genaue High- und Lowzeit für einen Pin getrennt einstellen und so
beliebige Impulsfolgen erzeugen.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dem CTC Modus des Timers im Zusammenhang mit dem
Compare Interrupt ist das auch kein Problem.
Ich denke aber, dass es Björn mal darum geht, den
Timer mal gaaaanz langsam in Betrieb zu nehmen und
zu sehen wie man ihn programmiert und was man
damit machen kann.
Hab ich auch so gemacht.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Mega8 schafft das.

Leider rückt Björn die Informationen nur häppchenweise auf Nachfrage
heraus, so dass derzeit nicht bekannt ist, was der Mega8 außer der
Impulserzeugung noch so alles machen muss.

Denn das entscheidet, wie man an die Sache herangehen kann.

Das Erzeugen einer Impulsfolge mit festem oder variablen Impulszeiten
und Pausenzeiten kann ein Timer-Interrupt erledigen. Dazu würde ich (in
ASM) die Zeiten (Timer1-Compare-Intervall) in einer Liste im SRAM führen
und in der ISR mit Increment-Load einlesen. Dabei den Pointer überwachen
und bei Erreichen des Endwertes definierten Pegel ausgeben (sbi oder
cbi) und den Pointer auf Startwert setzen (ldi). In den übrigen Fällen
(also nicht beim Telegrammende) wird der Port (aber nur das gewünschte
Bit!) einfach invertiert. Das geschieht durch Einlesen (in) des Ports,
exor mit Hilfsregister, in dem das zu toggelnde Bit gesetzt ist und
Zurückschreiben des Ports.

Sollen die Impulsmuster in Abhängigkeit von Ereignissen verändert
werden, so kann das Hauptprogramm in aller Ruhe die Ereignisse pollen,
auswerten und die neuen Impulszeiten in einen anderen SRAM-Bereich
ablegen. Die ISR kann dann bei Erreichen des Telegrammendes (dann, wenn
der Pointer zurückgesetzt wird) die neuen Zeiten in den dafür
vorgesehenen SRAM-Bereich kopieren, womit Änderungen während des
Telegramms verhindert werden (Glitch vermeiden).

Also alles in allem ist das auf dem Mega8 mit meinen bescheidenen
Kenntnissen (in ASM) machbar. In C geht das mit Sicherheit auch wenn
man die Hardware des AVRs detailliert kennt und in C so formulieren
kann, dass effizienter, hardwarenaher Code entsteht, der keine
überflüssigen zeitverschwendenden Registersicherungen usw. enthält.
Dazu muss man aber ASM und C schon recht gut beherrschen.

Da mir die C-Kenntnisse fehlen, könnte ich es nur in (primitivem) ASM
realisieren.

...

Autor: Björn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

nachdem ich von meinem Wochenendausflug zurück bin, werde ich mich nun
wieder dem Timer widmen...

Karl Heinz hat mal wieder Recht! Erst mal will ich schauen wie dieser
Timer funktioniert und was ich damit überhaupt für Möglichkeiten habe.


Das Programm habe ich angehängt!

Wahrscheinlich wird es zwar mit dem anderen Timer, dem CTC-Modus und
dem Compare Interrupt einfacher gehen. Doch das es mit diesem auch
funktionieren muss, ist für mich Anreiz genug es damit hinzubekommen.
Wie es bis jetzt funktioniert ist zwar ok, aber irgendwie nicht
akzeptabel. Da jetzt aufzugeben bring mir glaube ich gar nichts. Wenn
es mit diesem vernünftig funktioniert, werd ich es auch mal mit dem
anderen probieren und den dann wohl auch verwenden.

Nun zu meinem Projekt. Ich habe vor ein Modellauto zu steuern. Es
sollen Licht, Blinker, Lenkung und Antrieb programmiert werden. Das
Licht und die Blinker funktionieren bereits. Nun bin ich gerade beim
Servo für die Lenkung. Wie das Signal des Servos aussehen muss weiß
ich. Das habe ich bei einem funktionierendem Modell mit dem Osz.
aufgezeichnet. Deshalb versuche ich dieses Signal einfach mal
hinzubekommen und den Servo mal anzusteuern.

Weiß nicht ob dieses die Richtige vorgehensweise ist, aber so habe ich
es erst einmal vor um zu verstehen wie das alles funktioniert.

Für Tips und Ratschläge bin ich super dankbar....

Gruß Björn

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich habe vor ein Modellauto zu steuern. Es
> sollen Licht, Blinker, Lenkung und Antrieb programmiert werden. Das
> Licht und die Blinker funktionieren bereits. Nun bin ich gerade beim
> Servo für die Lenkung.

Also doch ein Modellbauservo.
Das Timing für solche Dinger ist ziemlich einfach.
Du schickst ihm einfach ständig einen Puls. Die
Breite des Pulses ist ein Mass für den Ausschlag des
Servos. Pulsbreiten bewegen sich im Bereich von 1ms
bis 2ms. Die meisten Servos können auch mit 0.8ms bis 2.4ms
arbeiten. Tja. und das wars dann auch schon. Die 20ms Pause
ist normalerweise nicht notwendig (die hat eigentlich mehr
mit der Funkübertragung vom Sender zum Empfänger zu tun
als mit allem anderen).
Und ja: So ein Timer kann diesen 1-2 ms Puls ganz leicht
alleine erzeugen.

Autor: der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch eine Idee (ohne mir das Programm angeguckt zu haben):
Einige Timer haben ja 2 OC-Register.
Wenn man nun beiden Registern aufeinanderfolgende Werte übergibt, so
dass zwei Interrupts in den vorgegeben Zeitabständen auftreten (einer
fürs Einschalten, der andere fürs Ausschalten), dann bräuchte man in
den ISR nur den OC-Wert für das folgende Ereignis dort eintragen.
Sprich: Die erste OC-ISR scheibt den Timer-Vergleichswert für den
folgenden Interrupt ins das zweite Register.
Die ISR für das 2. OC-Ereignis schreibt dann den Wert für das andere
Ereignis in das Register.
In den ISR wird dann auch immer der Portpin ein- und ausgeschaltet.

(Modellbau-)Servo-Signale erzeugt man am einfachsten mit dem
CTC-Interrupt (den man auch noch mit ICP und/oder OC koppeln kann...)

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Also doch ein Modellbauservo.

Nein, ist kein typischer Modellbauservo. Dieser Servo hat 4 Anschlüsse
noch einen eigenen Controller. Er wird mit einem Byte angesteuert,
wobei das erste Bit (15µs Impuls) als Starbit verwendet wird. Je nach
Länge der anderen Impulse wird dann die Stellung des Servos verändert.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was'n das für ein Teil? (persönliches Modellbauinteresse geweckt).
Kannst mal ein Photo machen? (Auto + Details)

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was das für ein Teil ist...?

Gute Frage! Hab ich mich auch schon gefragt. Keine Aufschrift, kein
Datenblatt, keine Infos!

Hab halt nur das Ding in nem funktionierendem Auto und dabei
festgestellt wie die Anschlüsse belegt sind und das Signal aussieht.

Hab da noch ne Hand voll von und würd die schon gern verwenden.

Kann Morgen mal nen Foto machen, hab die Dinger nicht hier....

Autor: Björn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Schade, irgendwie klappt das mit dem Timer 0 nicht.

Kann es vielleicht sein, das die Signale sich irgendwie überlagern. Bei
4 gleichen Werten bekomme ich ja ein sauberes Signal, nur bei
unterschiedlichen Werten treten diese Probleme auf.

Hab jetzt einfach mal versucht, den Timer 2 im CTC Modus zu
programmieren. Ein Signal gibt er mir aus, aber es wird nur der Wert
für OCR2A benutzt, der in der ISR gesetzt wird. Der vordefinierte hat
gar keine Auswirkung.

Sind da irgendwelche Fehler im Programm?

Hab es mal angehängt....

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie schon oben gesagt: Du hast Verzögerungen drin durch den Aufruf der
ISRs und das Ändern von TCNT0. Dadurch bekommst Du bei gleichen Werten
immer denselben Fehler, der u.U. gar nicht großartig auffällt. Bei den
anderen Varianten sieht das dann anders aus. Deshalb macht man so etwas
auch mit Compare-Einheiten, weil die 1. ohne Verzögerung den Portpin
umschalten und 2. eine Änderung des Compare-Wertes in der ISR sich
nicht sofort auf das Timing auswirkt.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
..Ach ja, und in dem Code mit Timer 2 darfst Du natürlich nicht den
Overflow-Interrupt nehmen, weil der nie auftritt, es sei denn, OCR2 =
255. Du musst den Compare-Interrupt nehmen!

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was ist dann an dem Timer4.C Programm falsch, dass im vorigen
Beitrag angehängt habe?

Hab es da mit dem Compare versucht, haut aber auch nicht ganz hin.....

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zunächst mal solltest Du den Kommentar an den Code anpassen. Dann denke
ich nämlich nicht, dass Du den falschen Interrupt aktiviert hast!

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OCIE2B ist doch aber der Compare Inrerrupt, nur der Kommentar dahinter
ist falsch.....

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falsch ist außerdem, dass der ATMega8 kein Register OCR2A hat. Das
(einzige) Compare-Register von Timer2 heißt OCR2! Es gibt auch kein
TCCR2A und TCCR2B sondern nur TCCR2. Ich weiß nicht, was Dein Compiler
dazu gesagt hat, aber ich wundere mich, dass Du nichts von
Fehlermeldungen beim compilieren erzählst...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Programm habe ich mangels C-Kenntnissen nicht angesehen. Aber wenn
du mit Timer-overflow arbeiten willst/musst, dann solltest du nicht
einfach den Reload-Wert in den Timer schreiben, sondern ihn zum
aktuellen Timerstand dazu addieren. Denn der Timer läuft ja weiter,
auch wenn die ISR aus irgendwelchen Gründen "Verspätung" hat. Somit
wird durch Addition der Relosds zum (eingelesenen) Stand die Verspätung
kompensiert.

Besser ist natürlich das Benutzen der Compare-Einheiten.

...

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du stellst den Wert für Compare-Match A ein, benutzt aber den
Compare-Match-B-Interrupt.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das liegt daran, dass ich im Moment nicht Zuhause bin und hier in der
Uni den Atmega48 verwende.

Hätte ich vielleicht angeben sollen, Sorry!

Also das mit den Registern passt soweit alles und ein Signal wird auch
erzeugt. Kann die Länge der Impulse auch durch setzen des OCR2A Wertes
ändern. Anscheinend wird wohl aber nur der Wert verglichen, der in der
ISR ins OCR2A geschrieben wird. Bei dem anderen, den ich in meiner main
definiert habe, passiert gar nichts. Und das kapier ich nicht ganz...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Autsch! Das hättest Du tatsächlich mal früher sagen können. Frage mich
dann aber immer noch (und da bin ich scheinbar nicht der einzige), was
Du mit dem Compare Match B Interrupt machst. Das ergibt alles keinen
Sinn. OCR1B wird nirgend initialisiert und dürfte deshalb '0' sein.
Das kann so nicht wirklich funktionieren...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...Meinte natürlich OCR2B...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich eine Wert für den Compare Match B einstelle, bekomme ich einen
dauernden High-Pegel......

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann lass doch zum Teufel noch mal die Finger von dem Compare Match B!!!
Was soll das überhaupt? Für ein einzelnes Signal brauchst DU nur einen
Compare. Du musst Dich aber entscheiden!

Autor: Björn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Jo, jetzt habe ich es kapiert. War mir nicht ganz klar was jetzt der
Unterschied zwischen Compare Match A & B ist.

Hab es jetzt noch mal umgeschrieben und angehängt. Bis zu 2 Werte
klappen ohne Probeme. Nur bei mehr als 2 kommen wieder diese komischen
Überlagerungen im Signal.....

Wie könnte ich denn die Werte anders in das OCR1A schreiben....??

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmal: Wie misst Du die Signale? Du musst bei der Darstellung am Oszi
drauf achten, dass immer auf die selbe Flanke des Signals getriggert
wird. Entweder mit nem externen Trigger oder durch Veränderung der
Holdoff-Zeit. Sonst kriegst Du nie ein stehendes Bild!

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab ja ein stehendes Bild! Hab die Holdoff-Zeit schon geändert und
alles mögliche probiert.

Wenn ich in die Single Seq gehe, habe ich ein saubers Signal!

Ansonsten nicht.....

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich hab ja ein stehendes Bild!

Nein, hast du nicht.
Na ja. Das Bild steht schon, nur siehst du alle
(was weiss ich) 10ms einen anderen, verschobenen
Ausschnitt aus dem Signal:

Einmal so (nur jetzt mal so zum Bleistift)

        +----+        +--------+
        |    |        |        |
        |    |        |        |
   -----+    +--------+        +------

und dann wieder so:

          +--------+      +----+
          |        |      |    |
          |        |      |    |
   -------+        +------+    +------

Wenn dein Oszi jetzt alle (sagen wir mal) 10 ms
auf die jeweils andere Flanke triggert, dann siehst
du (mit deinem trägen Auge) die Überlagerung der beiden:


        +----+-----+  +---+----+
        | |  |     |  |   |    |
        | |  |     |  |   |    |
   -----+-+  +-----+--+---+    +------

Erkennbar daran, dass du in einem Puls auch bei 0V
eine durchgehende Linie hast. Da sollte eigentlich
nichts sein. Der Schreibstrahl sollte nur eine einzige
durchgehende Linie von Links nach Rechts sein.

Du musst dafür sorgen, dass das Oszi immer
auf dieselbe Flanke triggert.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Jo, jetzt habe ich es kapiert. War mir nicht ganz klar was jetzt
> der Unterschied zwischen Compare Match A & B ist.

Es sind einfach zwei getrennte Einheiten. Für den Timer gibt es zwei
Vergleicher, die ständig den aktuellen Zählerstand mit dem Wert in
einem Register vergleicht. Sobald sie gleich sind, gibt es ein
Compare-Match-Event, das z.B. einen Interrupt auslösen kann.
Die beiden Einheiten sind eben mit A und B benannt. Wenn du das
Compare-Match-A-Register benutzt, bedeutet das, daß du auch die
Compare-Match-A-Einheit verwendest. Diese kann aber nur den
Compare-Match-A-Interrupt erzeugen.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Krieg ich nicht hin. Hab es so eingestellt, dass das Osz. nur auf die
steigende Flanke triggert.

Bei nur zwei Werten in meinem Programm klappt es ohne Probleme und es
gibt ein sauberes Signal so wie es sein soll. Bei mehr als zwei kommen
dann diese komischen Überlagerungen raus. Warum klappt das denn mit
zwei aber nicht mit mehr Werten?

Hab auch schon mehrere andere Signale mit dem Osz. gemessen, klappt
alles wunderbar.....

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hab es so eingestellt, dass das Osz. nur auf die steigende Flanke
> triggert.

Das bringt eigentlich auch nichts. Lass dir nochmal das Posting von
Karl Heinz durch den Kopf gehen. Wenn du nacheinander zwei
unterschiedlich lange Pulse hast, triggert dein Oszi auf die steigende
Flanke beider Pulse. Es weiß ja nicht, welches der erste sein soll
und welches der zweite. Es überlagert dir deshalb zwei gegeneinander
verschobene Bilder desselben Signals.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es nicht vielleicht doch irgenwie am Programm liegen?

Hat nicht jemand die Möglichkeit, das Programm mal bei sich laufen zu
lassen um zu schauen ob es da funktioniert?

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie kann ich denn dafür sorgen, dass das Osz. immer nur auf die selbe
Flanke triggert?

Ihr habt was von externen triggern erzählt. Wäre das ne Möglichkeit?
Was muss ich da machen...?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Externe Triggerung bedeutet, daß du ein zweites Signal hast, das nicht
dargestellt, sondern nur zur Triggerung verwendet wird. Das wäre eine
Möglichkeit. Du müßtest an einem zweiten Pin des Controllers ein Signal
generieren, das nur eine einzige steigende Flanke pro Periode hat, z.B.
indem es nur den ersten Impuls enthält.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs, was für eine schwere Geburt....!!!

Wie ihr es alle schon gesagt habt, lag es an der Triggerung...!!

Nun klappt es!


Vielen Dank für die Hilfe......!!!!

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie sieht das Servo-Protokoll nun aus???

...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Servo Signal soll nun so aussehen:

Wenn ein Byte übertragen wird fungiert das erste Bit (15µs Lowpegel)
als Startbit. Dann jeweils 100µs Pause (Highpegel) zwischen den
anderen.

Je nach gewünschter Stellung des Servos müssen die anderen Impule eine
bestimmte Länge haben.

Werd mich jetzt mal daran machen das hinzubekommen....

Haste nen Tip für mich wie ich da am besten vorgehen sollte....??


Gruß

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schade, nen paar Tips hätt ich echt gut gebrauchen können...!!!

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Haste nen Tip für mich wie ich da am besten vorgehen sollte....??

> Schade, nen paar Tips hätt ich echt gut gebrauchen können...!!!

Sorry, ich war den ganzen Tag nicht online.

Andererseits nützen dir meine Tips nix, da wir unterschiedliche
Sprachen sprechen (Programmiersprachen). Dann kenne ich die von dir
erwähnten Servos nicht, die Servos, mit denen ich bisher zu tun hatte,
hielten sich alle (halbwegs) an die im Modellbau seit Jahrzehnten
übliche Norm.

Mit Modellbau-Servoimpulsen habe ich schon Einiges gemacht, von der
Servoimpulserzeugung über die Umcodierung bis hin zu Fahrtreglern,
Schaltdecodern, Servoelektronik... Ein Teil davon steht auch im Netz,
bei www.hanneslux.de/avr wirst du fündig. Quelltexte gibt's da auch,
aber eben nur in primitivem Assembler, für C bin ich zu doof.

...

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, kein Problem!

Geht mir gar nicht um die Programmierung, sondern eher die allgemeine
Vorgehensweise.

Hab ja schon soweit erklärt, wie der Servo angesteuert werden soll. Nun
stellt sich mir die Frage, wie sich das am besten realisieren lässt. Im
Moment erzeug ich mir ja das Signal mit dem Timer und setze die
verschiedenen Pulslängen mit bestimmten Werten im Array fest, die dann
im Compare Modus verglichen werden und den Port umschaltewn.

So würd ich es machen:

Je nach gewünschter Stellung werden die Werte im Aray geändert. Also je
nach ankommendem Wert per UART würde ich dann halt die entsprechenden
Werte ins Array schreiben.

Nun weiß ich nicht ob es der richtige Weg ist oder es noch andere
"bessere" Möglichkeiten gibt so etwas zu machen und welche davon
empfehlenswert sind. Ist halt mein erstes "größeres" Projekt und die
meisten hier haben ja schon eine Menge mehr Erfahrung mit der ganzen
Thematik.

Daher dachte ich dass mir der eine oder andere nen guten Tip zur
Vorgehensweise für mich hätte...

Gruß

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abend.

Björn, mach dir jetzt nicht zuviele Gedanken.
Häng einfach mal dein Servo an den µC an und sieh
nach ob das Ding reagiert. Wenns klappt, dann anderst
du mal die Werte im Array und siehst nach wie das Servo drauf
reagiert.
Danach beschäftigst du dich mal mit der UART. Und zwar ohne
an das Servo auch nur im entferntesten zu denken. Immer nur
eine Baustelle auf einmal!
Wenn du dann über die UART was empfangen kannst
(Dein erstes Testprogramm könnte zum Beispiel alles Empfangene
einfach wieder an den Sender zurückschicken), kannst du ja mal
mit einer einfachen Auswertung des Empfangenen anfangen: Wenn
ein bestimmtes Zeichen ankommt, dann LED einschalten. Bei einem
anderen LED ausschalten, etc. Einfache Übungen also. Wenn
du soweit bist, dann kannst du mal anfangen die beiden
Welten zusammenzubringen.

Eine gute Methode zur Programmentwicklung ist das Arbeiten
in kleinen Schritten. Die meisten Neulinge verfransen sich
ganz einfach in der Komplexität einer Aufgabe. Also muss
man die Komplexität drücken. Und das macht man, indem man
Dinge isoliert betrachtet. Die UART hat zunächst mal nichts
mit einem Servo zu tun. Klar, dein langfristiges Ziel ist
es über die UART das Servo zu steuern. Nur: Die UART kann man
auch für sich alleine untersuchen und programmieren. Daher
wird das langfristige Ziel zu Gunsten eines kurzfristigen Ziels
zurückgestellt (mit der UATR einfach mal klarkommen).

Bei der Programmierung kann man unzählige Dinge falsch machen
und sich selbst in eine Sackgasse manövrieren. Das ist
nicht weiter schlimm. Das ist der ganz normale Lernprozess,
den wir alle durchlaufen haben. Das kann dir auch keiner
abnehmen, da musst du schon selber durch.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Nun weiß ich nicht ob es der richtige Weg ist oder es noch
> andere "bessere" Möglichkeiten gibt

So was wie 'eine beste' Möglichkeit gibt es ganz selten.
Im Zweifelsfall ist die 'beste' Möglichkeit diejenige
die du realisieren kannst und die auch funktioniert.

Klar lernt man mit der Zeit dazu. Man lernt was gut
funktioniert und was weniger gut funktioniert. Aber:
was in einem speziellen Fall gut ist, kann im nächsten
speziellen Fall schon wieder schlecht sein.
Hilft alles nichts: Erfahrung erlangt man nur in dem man
verschiedene Möglichkeiten ausprobiert und rausfindet womit
man gut klar kommt und womit nicht.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,

erst mal Danke für die Tips!

> Häng einfach mal dein Servo an den µC an und sieh
> nach ob das Ding reagiert.

Also den Servo hab ich schonm mal drangehangen, da tut tut sich auf
jeden Fall was. Werd Morgen mal das Programm umschreiben und mal
schauen was sich bei anderen Werten tut.

Dazu hätt ich ne Frage:

Kann ich direkt das ganze Array neu beschreiben. Oder muss ich das für
jeden Wert einzeln z.B. "Preloads[1] = 42" tun?


> Danach beschäftigst du dich mal mit der UART

Das hab ich schon hinter mir und es klappt (hab mich selber gewundert"
schon ziemlich gut. Hab den UART auch mit nem Interrupt realisiert und
kann Daten emfangen und senden. Hab da ein kleines Programm
geschrieben, welches mir bei einem bestimmten emfangenen Zeichen eine
LED ein/aus schaltet und das Zeichen wieder zurück schickt. Klappt
bestens!

Auch einen Blinker hab ich schon programmiert, der sich bei einem
bestimmten empfangenen Zeichen ein/aus schalten lässt.

Nun ist halt der nächste Schritt den Servo anzusteuern....

Autor: der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unsigned char preloads[] = {42;32;...};
siehe auch "Die Programmiersprache C" von einem gewissen Brian
Kernighan und einem Dennis Ritchie...

Autor: Stephan E. (stephan_e)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
siehe auch http://www.pronix.de/pronix-4.html (online-Versin von C von A
bis Z)

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So erzeuge ich mir das Array ja auch, das ist kein Problem.

Nur ich wollte das Array aber so auch in einer switch Anweisung bei
einem bestimmten "case" mit anderen Werten beschreiben. Nur da klappt
es nicht. Sobald ich das Array da so mit neuen Werten versehen will.
bekomm ich ne Fehlermeldung dass sich das break nicht in einer switch
Anweisung befindet.

Keine Ahnung warum, vielleicht gibt es da Probleme mit den {}
Klammern....

Autor: der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das {} geht auch nur bei der Array-Deklaration.
Im Programm selbst kannst du nur auf die einzelnen Feldeinträge
zugreifen.
Vielleicht solltest du dir eine andere Lösung überlegen (Bits in einem
Byte auswerten).
Dann bräuchte man nur eine Ausgabe-Routine, der man einen ein Byte
übergibt, das dann an das Servo "weitergeleitet" wird.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ich mir fast gedacht.

Das mit der Ausgabe-Routine hört sich gut an! Kannste mir das genauer
erklären.....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sei mal ein bischen erfinderisch :-)

Du könntest zum Beispiel mit dir selbst vereinbaren,
dass das Servo nach links drehen soll, wenn immer über
die Serielle ein 'L' daherkommt. Das Servo soll
nach rechts drehen bei einem 'R'. Und wenn ein 'C'
daherkommt, dann soll das Serve wieder in Mittelstellung
gehen (C wie center).

Das Drehen ist doch kein Problem. Dazu muss einfach nur
ein Wert in deinem Array immer kleiner und kleiner
(bzw. groesser und groesser) werden. Und bei 'C' schreibst
du einfach wieder den bekannten Wert für Mittelstellung
hinein.

Du könntest auch die Buchstaben von '0' bis '9' nehmen
und jedem dieser Buchstaben einen bestimmen Zahlenwert
fürs Array zuordnen, der dann in das Timingarray geschrieben
wird

oder ...

Da gibt es kein Richtig oder Falsch. Was immer du mit dir
selbst vereinbarst ist per Definition richtig.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werd ich mich Morgen mal dransetzen!

Vielen Dank!

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, noch eimal vielen Dank für eure Hilfe!

Hab mir nun noch nen standard Servo bei Conrad besorgt und es erst mal
mit dem Probiert. Klappt alles wunderbar.

Mit den anderen Servos klappt das soweit auch, nur nach dem Einschalten
zittern die Servos. Wenn ich sie dann über ein gesendetes Zeichen in die
gewünschte Stellung bringen will, klappt das nur ab und zu. Nach ein
paar gesendeten Zeichen hört das zittern irgendwann auf und es klappt
alles wie es soll!

Woran kann das mit dem zittern liegen? Und eigentlich müssten die
Servos doch trotz zittern in die gewünschte Position fahren. Warum
machen Sie das nur ab und zu?

Gruß  Björn

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keiner eine Ahnung was das sein kann.....???

Autor: der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wird ein Timingproblem sein.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und das heißt genau...? Was kann ich dagegen tun...?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.