mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega8 Servo Steuerung


Autor: Philipp Maricek (lord-maricek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute,

ich versuche grad eine Servo steuerung zu bauen.
An Portd.0 ist das Signal Kabel meines EMpfänger (Fernsteuerung: 
Graupner x-412). Das SIgnal soll ausgewertet werden und dann in Servo 
bewegungen umgewandelt werden. Wenn ich das Programm übertrage bleibt 
der Servo wo er war und beim bewegen der Knüppel passsiert auch nichts. 
Der Servo fährt auch niht in die Ausgangsposition wie ers eigentlich tun 
sollte.
Ich hoffe ihr könnt mir helfen.
$regfile = "m8def.dat"

$crystal = 8000000


'Servo wird festgelegt
Config Servos = 1 , Servo1 = Portb.0 , Reload = 10 , Timer = Timer1

'Ports werden difiniert
Config Portb = Output   
Config Portd = Output


Enable Interrupts

Dim Kanal(1) As Word    'Der Puls
Dim Zaehler As Integer   'Der Zaehler für die Schritte
Servo(1) = 100  'Startposition

Do

Pulsein Kanal(1) , Pind , 0 , 1    'Puls einlesen. An Portd.0

While Kanal(1) > 110                  'Währedn Knüppel Rechts, fahre langsam nach Rechts
   If Kanal(1) >= 150 Then           'Falls Position schon ganz Rechts, bleibe da
      Return
   Else
      Zaehler = Zaehler + 1           'Falls Position nicht ganz Rechts, fahre nach Rechts
      Servo(1) = Zaehler                
      Waitms 150
   End If
Wend

While Kanal(1) < 90                  'Während Knüppel links
   If Kanal(1) <= 50 Then           'Falls Servo schon ganz links, bleibe da
      Return                          
   Else
      Zaehler = Zaehler - 1           'Falls nicht ganz links, fahre nach links
      Servo(1) = Zaehler
      Waitms 150
   End If
Wend
Loop
End



Philipp

: Gesperrt durch Moderator
Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> $crystal = 8000000

Sicher oder Wunsch?

Der Mega8 wird mit 1 MHz internem Takt ausgeliefert...

Wozu dienen die While-Wend-Konstrukte? Endlagenbegrenzungen erreichst Du 
mit If besser und vor allem schneller.

Denn normal willst Du doch:

- Servoimpuls einlesen (Impulsbreite messen, entspricht Servoposition)

- Impulsbreitenwert (Position) nach oben und unten begrenzen, oder

- Impulsbreitenwert manipulieren (Mittenposition ändern, Steilheit
  ändern, Wertänderung verzögern, ...)

- Servo ansteuern (korrigierte oder manipulierte Position als
  Servoimpuls ausgeben)

Was sich hinter "Pusein" verbirgt, habe ich nicht recherchiert, ich gehe 
aber davon aus, dass diese Funktion wartet, bis der nächste Impuls 
komplett durch ist. Dies bremst den Programmablauf, wodurch weitere 
"Bremsen" (While-Wend-Schleifen, Waitms darin) kontraproduktiv sind.

Mein Vorschlag:

- Eingangsimpuls im ICP-Interrupt des 16-Bit-Timers messen, Messwert
  bereitstellen, mit Merker neuen Messwert melden

- In Mainloop nur den Messwert manipulieren (begrenzen oder was auch
  immer)

- Im Compare-Interrupt des 16-Bit-Timers den Termin für die nächste
  Flanke des/der Ausgangsimpulse(s) setzen (Impulsbreite auf aktuellen
  Zeitstempel aufaddieren) und über einen Schrittzähler (als Index)
  das entsprechende Bitmuster an die Portpins ausgeben.

Dies funktioniert bestens in ASM und müsste auch in Bascom gut 
funktionieren, denn das Programm muss an keiner Stelle auf irgend etwas 
warten.

...

Autor: Ratgebender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

In "Pulsein" steckt "in"

"Config Portd = Output"

Nachdenken!

Auserdem, was soll in der Config Servo Zeile
das "Timer = Timer1"?

MfG

Autor: Philipp Maricek (lord-maricek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe ein neuen Code geschrieben. Aber der Servo zuckt jetzt nur ein 
bisschen rum, und das wars:
$regfile = "m8def.dat"



$crystal = 8000000



Config Servos = 1 , Servo1 = Portb.0 , Reload = 10



Config Portb = Output



Dim Kanal(1) As Word

Dim Zaehler As Integer

Zaehler = 100



Enable Interrupts



Servo(1) = 100



Do



Pulsein Kanal(1) , Pind , 0 , 1



If Kanal(1) > 120 Then

   If Zaehler >= 150 Then

      Return

   Elseif Zaehler < 150 Then

      Zaehler = Zaehler + 1

      Servo(1) = Zaehler

   End If

Elseif Kanal(1) < 100 Then

   If Zaehler <= 50 Then

      Return

   Elseif Zaehler > 50 Then

      Zaehler = Zaehler - 1

      Servo(1) = Zaehler

   End If

End If





Loop







End

Philipp

Autor: Verzweifelnder (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Was sollen diese Returns!
Mit Return beendet man eine Sub und sonst nichts!

Code zu kopieren denn Du nicht kapierst bringt nichts.

In Bascom gibt es eine Hilfedatei. Da stehen doch glatt
viele wissenswerte Sachen drin.

MfG

Autor: Philipp Maricek (lord-maricek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verzweifelnder schrieb:
> Hallo!
>
> Was sollen diese Returns!
> Mit Return beendet man eine Sub und sonst nichts!
>
> Code zu kopieren denn Du nicht kapierst bringt nichts.
>
> In Bascom gibt es eine Hilfedatei. Da stehen doch glatt
> viele wissenswerte Sachen drin.
>
> MfG

Hi,

den code hab ich nicht kopeirt sonder selber geschrieben. Und dieses 
Return soll bedeuten, dass er die if anweisung verlässt. Aber anscheind 
ist das nicht der richtige Befehl dafür. Wie ist er denn richtig?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philipp Maricek schrieb:
> Verzweifelnder schrieb:
>> Hallo!
>>
>> Was sollen diese Returns!
>> Mit Return beendet man eine Sub und sonst nichts!

Falsch, eine SUB beendet man mit END SUB.
Mit RETURN beendet man eine ISR oder ein mit GOSUB aufgerufenes 
Codestück (was deshalb BASIC-verwaltungstechnisch noch lange keine SUB 
ist).

>>
>> Code zu kopieren denn Du nicht kapierst bringt nichts.

Richtig, trifft hier aber wohl kaum zu, denn solchen Code wird man kaum 
zum Kopieren finden.

>>
>> In Bascom gibt es eine Hilfedatei. Da stehen doch glatt
>> viele wissenswerte Sachen drin.

Wieder richtig, viele Leute benutzen aber Bascom, um nicht in 
Hilfedateien, Datenblättern oder anderen Dokumentationen lesen zu 
müssen.

>>
>> MfG
>
> Hi,
>
> den code hab ich nicht kopeirt sonder selber geschrieben.

Das sieht man schon alleine daran, dass Du keine Kommentare geschrieben 
hast, in denen Du erklärst, was Du mit Deinem Code bewirken willst. 
Somit hast Du es einem Hilfewilligen unnötig erschwert, den Sinn Deines 
(fehlerhaften) Codes zu verstehen.

> Und dieses
> Return soll bedeuten, dass er die if anweisung verlässt.

Das ist ein Irrtum, ein Blick in die Bascom-Onlinehilfe hätte Dir das 
auch gezeigt. Einfach mal F1 drücken, wenn der Cursor auf der 
unverstandenen Anweisung (hier "IF") steht. Programmieren (auch in 
Bascom) ist kein Multimediakonsum, hier sollte man auch mal zur Tastatur 
greifen und nicht alles mit der Maus machen wollen. ;-)

> Aber anscheind
> ist das nicht der richtige Befehl dafür.

Richtig erkannt, es ist die falsche Anweisung für Deinen Zweck...

> Wie ist er denn richtig?

IF beendet man mit END IF (wird je nach BASIC-Dialekt getrennt oder 
zusammen geschrieben).

Der Hase liegt aber ganz woanders im Pfeffer. Selbst wenn Du alle 
Anweisungen auswendig gelernt hast, wirst Du sie nicht richtig einsetzen 
können, wenn Du nicht in der Lage bist, die zu Problemlösung als 
programmiersprachenunabhängigen Algorithmus zu formulieren. Dies erkenne 
ich z.B. daran:
   If Zaehler >= 150 Then
      Return
   Elseif Zaehler < 150 Then
      Zaehler = Zaehler + 1
      Servo(1) = Zaehler
   End If
Das Return wird Dir einen Stacküberlauf bescheren, was zum 
Programmabsturz führt. Selbst wenn man das Return entfernt (also keine 
Anweisung im If-Block hat), ist es doppeltgemoppelt und verschlechtert 
die Lesbarkeit.
So wäre es zumindest lesbarer:
   'Servo-Bewegung nach oben:
   If Zaehler < 150 Then          'wenn Endwert noch nicht erreicht
      Zaehler = Zaehler + 1       'Hilfsvariable erhöhen und
      Servo(1) = Zaehler          'als neue Servoposition setzen
   End If

Ob Dein Programm damit funktioniert, kann ich Dir nicht sagen, denn ich 
werde deshalb die Schaltung nicht aufbauen und Bascom anwerfen. Weitere 
Fehlerquellen stecken nämlich im Hintergrund der Bascom-Lib in den 
Funktionen Pulsein und Servo und dem verwendeten Takt. Diese sind für 
4MHz berechnet, Du definierst aber 8MHz, und der AVR läuft vermutlich 
mit 1MHz (Auslieferungszustand). Solange Du das noch nicht zweifelsfrei 
geklärt hast, stocherst Du weiterhin im Dunkeln.

...

Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo
Versuche es doch einmal mit...

Config Pind.5 = Input 
'freq'Output'Led1

...

Pulsein Pulsbreite , Pind , 5 , 0                           'Pulsbreite 
auslesen an PB2 pulse = GND


so wie es
Autor: Ratgebender (Gast)
am 27.12.2009 um 17:33
schrieb!!!

mfg
Phil

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Phil schrieb:
> Versuche es doch einmal mit...

Und Du meinst, dass den das nach 44 Monaten noch interessiert?

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.