Forum: Mikrocontroller und Digitale Elektronik ATmega8 Servo Steuerung


von Philipp M. (lord-maricek)


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.
1
$regfile = "m8def.dat"
2
3
$crystal = 8000000
4
5
6
'Servo wird festgelegt
7
Config Servos = 1 , Servo1 = Portb.0 , Reload = 10 , Timer = Timer1
8
9
'Ports werden difiniert
10
Config Portb = Output   
11
Config Portd = Output
12
13
14
Enable Interrupts
15
16
Dim Kanal(1) As Word    'Der Puls
17
Dim Zaehler As Integer   'Der Zaehler für die Schritte
18
Servo(1) = 100  'Startposition
19
20
Do
21
22
Pulsein Kanal(1) , Pind , 0 , 1    'Puls einlesen. An Portd.0
23
24
While Kanal(1) > 110                  'Währedn Knüppel Rechts, fahre langsam nach Rechts
25
   If Kanal(1) >= 150 Then           'Falls Position schon ganz Rechts, bleibe da
26
      Return
27
   Else
28
      Zaehler = Zaehler + 1           'Falls Position nicht ganz Rechts, fahre nach Rechts
29
      Servo(1) = Zaehler                
30
      Waitms 150
31
   End If
32
Wend
33
34
While Kanal(1) < 90                  'Während Knüppel links
35
   If Kanal(1) <= 50 Then           'Falls Servo schon ganz links, bleibe da
36
      Return                          
37
   Else
38
      Zaehler = Zaehler - 1           'Falls nicht ganz links, fahre nach links
39
      Servo(1) = Zaehler
40
      Waitms 150
41
   End If
42
Wend
43
Loop
44
End


Philipp

: Gesperrt durch Moderator
von Hannes L. (hannes)


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.

...

von Ratgebender (Gast)


Lesenswert?

Hallo!

In "Pulsein" steckt "in"

"Config Portd = Output"

Nachdenken!

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

MfG

von Philipp M. (lord-maricek)


Lesenswert?

ich habe ein neuen Code geschrieben. Aber der Servo zuckt jetzt nur ein 
bisschen rum, und das wars:
1
$regfile = "m8def.dat"
2
3
4
5
$crystal = 8000000
6
7
8
9
Config Servos = 1 , Servo1 = Portb.0 , Reload = 10
10
11
12
13
Config Portb = Output
14
15
16
17
Dim Kanal(1) As Word
18
19
Dim Zaehler As Integer
20
21
Zaehler = 100
22
23
24
25
Enable Interrupts
26
27
28
29
Servo(1) = 100
30
31
32
33
Do
34
35
36
37
Pulsein Kanal(1) , Pind , 0 , 1
38
39
40
41
If Kanal(1) > 120 Then
42
43
   If Zaehler >= 150 Then
44
45
      Return
46
47
   Elseif Zaehler < 150 Then
48
49
      Zaehler = Zaehler + 1
50
51
      Servo(1) = Zaehler
52
53
   End If
54
55
Elseif Kanal(1) < 100 Then
56
57
   If Zaehler <= 50 Then
58
59
      Return
60
61
   Elseif Zaehler > 50 Then
62
63
      Zaehler = Zaehler - 1
64
65
      Servo(1) = Zaehler
66
67
   End If
68
69
End If
70
71
72
73
74
75
Loop
76
77
78
79
80
81
82
83
End

Philipp

von Verzweifelnder (Gast)


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

von Philipp M. (lord-maricek)


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?

von Hannes L. (hannes)


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:
1
   If Zaehler >= 150 Then
2
      Return
3
   Elseif Zaehler < 150 Then
4
      Zaehler = Zaehler + 1
5
      Servo(1) = Zaehler
6
   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:
1
   'Servo-Bewegung nach oben:
2
   If Zaehler < 150 Then          'wenn Endwert noch nicht erreicht
3
      Zaehler = Zaehler + 1       'Hilfsvariable erhöhen und
4
      Servo(1) = Zaehler          'als neue Servoposition setzen
5
   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.

...

von Phil (Gast)


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

von Hannes L. (hannes)


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.