Das Open-Control-Projekt - Die Alternative zur C-Control-I


Das Forum zur C-Control-1
Welche C-Control-Varianten existieren?
Übersicht - Suchen - Neueste 50 Beiträge - Neuer Beitrag - Login - Registrieren
INFO - FAQ - CC2-Forum - CCPro-Forum 

 Bis zu 8 Servos mit Open-Makro steuern Kategorie: Open-Micro/Open-Mini/Open-Midi/Open-Macro/Open-Maxi (von Olaf - 24.05.2010 21:15)
Olaf nutzt:  Open-Micro, Open-Mini, Open-Midi, Open-Macro
Hallo,

nachdem ich im Forum mir immer mal wieder nützliche Tips und Tricks geholt habe möchte ich euch mal mein kleines Programm für eine Servosteuerung für bis zu acht Servos vorstellen.
Endstanden ist das ganze eigentlich daraus, dass ich meine im Aufbau befindliche Modellbahnanlage über ein PC-Programm in Verbindung mit mehreren Open-Mini/Midi/Macro steuern und abwechslungsreicher gestalten möchte.
Die Servosteuerung benötige ich um die "Weichen" von Autokreuzungen zu schalten, ein par Türen zu öffnen/schließen und noch so'n par Gimmigs, einfach um mehr Leben reinzubringen.
Ihr benötigt dazu eine Open-Macro, die habe ich gewählt weil ich durch die "Word"-Variablen die Servos, je nach Typ und Drehwinkel bis in ihre Endlagen und einer "theoretischen" Auflösung von bis zu 700-800 Schritten betreiben kann!
Leider erfolgt die Ansteuerung von einen, oder mehreren Servos parallel, immer nacheinander, vieleicht hat ja jemand von euch eine Idee wie man unterschiedliche Servos unabhängig positionieren kann. Auch für weitere Anregungen, Fragen und Tips wäre ich euch dankbar, und vor allen ob das Programm auch bei euch läuft.

Hier der Quellcode von "ServoansteuerungV1.bas":
 

'
' Servoansteuerung V1 von bis zu 8 Servos durch Open-Makro
' von Olaf Stermann
' Beginn: 18.05.2010
' Stand:  24.05.2010
'
' Beschreibung:
' 8 Servos können über Port9 bis Port16 angesteuert werden.
' Durch die neue Open-Makro (Wordverarbeitung) können die Servos über
' ihren vollen Stellbereich genutzt werden (ausprobieren),
' siehe weitere Beschreibungen in "servov1.iia".
'
' Die Auswahl des Servos erfolgt über ein Bit: Servo1=ON
' Soll der Servo nicht mehr positioniert dann: Servo1=OFF
' Es ist auch möglich mehrere Servos zusammen zu positionieren.
'
' Befehl 1:  ServoPositionAbsolut(aaa,bbb)
' aaa = Position (WORD); Bereich ca. 200(Links)-1100(Rechts) je nach Servo
' bbb = Anzahl der Pulse (BYTE);
' Einfache Positionierung auf eine Position.
' Signaldauer = bbb*20ms
'
' Befehl 2:  ServoPositionBewegung(aaa,bbb,ccc,ddd)
' aaa = Startposition (WORD); Werte siehe Befehl 1: aaa
' bbb = Zielposition (WORD); Werte siehe Befehl 1: aaa
' ccc = Positionsänderung (BYTE);
' ddd = Anzahl der Pulse (BYTE) pro Positionsänderung
' Positionierung von aaa nach bbb, dabei it es egal ob von links nach
' rechts oder umgekehrt, die Auswertung erfolgt in "servov1.iia".
' Berechnung Signaldauer:
' Signaldauer=((bbb-aaa)/ccc)*ddd*20ms
' Bsp.: ServoPositionBewegung(250,1050,8,5)
' Signaldauer = ((1050-250)/8)*5*20ms = ca. 10 Sekunden
'

' ---------------------------------------------------------------------------
'INCLUDE "om.def"          'Definitionen fuer Open-Micro und Open-Mini
'INCLUDE "omid.def"        'Definitionen fuer Open-Midi
INCLUDE "omac.def"         'Definitionen fuer Open-Makro
' ---------------------------------------------------------------------------

' ---------------------------------------------------------------------------
' Definition der Ports der OM
' ---------------------------------------------------------------------------
'define RS232        Port[1]  ' RS232-Port
'define RS232_DCD    Port[2]  ' Datenempfang für PC-Programm aktivieren
'define nc           Port[3]  ' nicht benutzt
'define RS232_RTS    Port[4]  ' Datenempfang PC-Programm bereit
'define nc           Port[5]  ' Bustakt für Daten
'define nc           Port[6]  ' Datenleitung

'define Servo1       Port[9]  ' wird in "ServoV1.iia" definiert
'define Servo2       Port[10] ' wird in "ServoV1.iia" definiert
'define Servo3       Port[11] ' wird in "ServoV1.iia" definiert
'define Servo4       Port[12] ' wird in "ServoV1.iia" definiert
'define Servo5       Port[13] ' wird in "ServoV1.iia" definiert
'define Servo6       Port[14] ' wird in "ServoV1.iia" definiert
'define Servo7       Port[15] ' wird in "ServoV1.iia" definiert
'define Servo8       Port[16] ' wird in "ServoV1.iia" definiert
' ---------------------------------------------------------------------------

' ---------------------------------------------------------------------------
' Definition der Allgemeinen Variabeln
' ---------------------------------------------------------------------------
define Servo_Ports_aktive BYTE
define Servo1 BIT[1] of Servo_Ports_aktive  ' Servo aktivieren
define Servo2 BIT[2] of Servo_Ports_aktive  ' Servo aktivieren
define Servo3 BIT[3] of Servo_Ports_aktive  ' Servo aktivieren
define Servo4 BIT[4] of Servo_Ports_aktive  ' Servo aktivieren
define Servo5 BIT[5] of Servo_Ports_aktive  ' Servo aktivieren
define Servo6 BIT[6] of Servo_Ports_aktive  ' Servo aktivieren
define Servo7 BIT[7] of Servo_Ports_aktive  ' Servo aktivieren
define Servo8 BIT[8] of Servo_Ports_aktive  ' Servo aktivieren

' ---------------------------------------------------------------------------
' Die Servoroutinen einbinden
' ---------------------------------------------------------------------------
INCLUDE "servov1.iia"

' ---------------------------------------------------------------------------
' Das Hauptprogramm
' ---------------------------------------------------------------------------
Servo_Ports_aktive=0 'alle Servoports aus
InitServo            'Initialisierung der Ports
pause 50


#main

#Hauptprogramm
Servo2=on           'Servo 2 an
'-------------------------------------------------------------
' Test: Graupner Servo C507
' Ermittelte Werte durch Versuche:
' Links=ca.250; Mitte=ca.650; Rechts=ca.1050.
' Drehbewegung = ca.190°.
' Theoretische Auflösung=ca.0,2375°.
' Gemessene Dauer für die Positionsimpulse:
' Links=ca.0,66ms/Mitte=ca.1,66ms/ Rechts=ca.2,66ms
'-------------------------------------------------------------
'Mittelstellung:
ServoPositionAbsolut(650,20)
pause 50
'Linksanschlag:
ServoPositionAbsolut(250,20)
pause 50
'Mittelstellung:
ServoPositionAbsolut(650,20)
pause 50
'Rechtsanschlag:
ServoPositionAbsolut(1050,20)
pause 50
'Bewegung von Rechts nach links (Dauer ca. 2,5s):
ServoPositionBewegung(1050,250,8,1)
pause 50
'Takten von Links nach Rechts um ca.2° mit Pause von ca.100ms:
ServoPositionBewegung(250,1050,8,5)
pause 50

' Fazit: Graupner Servo C507
' Praktische minimale Auflösung=ca.0,5°-1°,
' da doch bei längerer Taktzeit(Position halten) ein
' leichtes ruckeln im Servo zu spüren ist.
'-------------------------------------------------------------

'Servoauswahl: endweder so....
Servo2=off
Servo1=on
Servo3=on
'....oder auch so möglich
'Servo_Ports_aktive=&b00000101

'-------------------------------------------------------------
' Test: Conrad "Billig" Servo von Prafa
' Ermittelte Werte durch Versuche:
' Links=ca.200; Mitte=ca.580; Rechts=ca.960.
' Drehbewegung = ca.185°.
' Theoretische Auflösung = ca.0,2434°.
' Gemessene Dauer für die Positionsimpulse:
' Links=ca.0,53ms/Mitte=ca.1,49ms/ Rechts=ca.2,42ms
'
'Mittelstellung:
ServoPositionAbsolut(580,20)
pause 50
'Linksanschlag:
ServoPositionAbsolut(200,20)
pause 50
'Mittelstellung:
ServoPositionAbsolut(580,20)
pause 50
'Rechtsanschlag:
ServoPositionAbsolut(960,20)
pause 50
'Bewegung von Rechts nach links (Dauer ca. 2,5s):
ServoPositionBewegung(960,200,8,1)
pause 50
'Takten von Links nach Rechts um ca.2° mit Pause von ca.100ms:
ServoPositionBewegung(200,960,8,5)
pause 50

' Fazit: Conrad "Billig" Servo von Prafa
' Praktische minimale Auflösung=ca.0,5°-1°,
' da doch bei längerer Taktzeit(Position halten) ein ganz
' leichtes ruckeln im Servo zu spüren ist, aber weniger
' als beim Graupner Servo (billigere Bauteile???).
'-------------------------------------------------------------
Servo1=off
Servo3=off


'so kann auch verfahren werden, aber es entstehen kurze
'Aussetzer mit rucklern am Servo

'while ServoHighSignal<960
'ServoHighSignal=ServoHighSignal+20
'ServoPositionAbsolut(ServoHighSignal,4)
'wend


goto Hauptprogramm
END


' ---------------------------------------------------------------------------
' Die Firmware-Routinen einbinden
' ---------------------------------------------------------------------------

'INCLUDE "OM_FW.pro"



und hier der Quellcode von dem eingebundenen Assemblerteil "servov1.iia":


' Assemblermodul:
' Servoansteuerung V1 für 8 Servos über Port 9 bis Port 16 der Open-Macro
' von Olaf Stermann
' Beginn: 18.05.2010
' Stand:  24.05.2010
'
' 18.05.2010:
' Erste Puls-/Pausenverhältnisse getestet (Testport=Port[9]).
' Ermittlung der Dauer des 20ms Positionsignals mit OSZI: Puls+Pause=8000.
' Die Pause wird durch "8000-Puls=Pause" gebildet.
' 19.05.2010:
' Testweise mal mit ein par Werten für den Puls (Positionssignal)
' experimentiert und an unterschiedlichen Servos getestet:
' 1. Es ist nicht so kritisch das, dass gesamte Signal genau 20ms haben muß.
'    +/- 2 bis 5ms interessieren meist überhaupt nicht, also nicht kritisch.
' 2. Auch die eigentlich "definierten" 1ms bis 2ms Pulsdauer sehen die
'    Hersteller nicht so eng. Bei meinen Tests konnte ich bis zu 0,5ms
'    für den Linksanschlag und bis zu 2,7ms für den Rechtsanschlag
'    messen, dadurch ist es möglich den Servo bis in die Grenzen zu drehen!!
' 21.05.2010:
' Den Positionierbefehl in Positionspuls inkl. der Pause in Takten zerlegt,
' dadurch kann durch einen Aufruf mit der Position und durch die Takte
' die Dauer zur Ansteuerung des Servos festgelegt werden:
' Ansteuerdauer Servo = Takte*Positionssignal(20ms). Die Takte müssen
' so gewählt werden das der Servo seine Position erreicht.
' 22.05.2010:
' Aus meinen Programm für die Infrarotsteuerung des DC-Car-System
' habe ich die Portansteuerung von Port9 bis Port16 übernommen.
' Invertierte Servoports (Invert_Servo_PORT) von "Servo_Ports_aktive"
' eingebunden, somit lassen sich bis zu acht gleiche Servos gleichzeitig
' ansteuern. Es muss jetzt nur noch das entsprechende Servobit von
' "Servo_Ports_aktive" gesetzt werden um den Servo anzusteuern.
' Das setzt natürlich mindesten zwei gleiche Servos mit den
' selben Werten vorraus (Bahnschrankensteuerung,Tür- oder Torsteuerung, ein
' par Bäume umfallen lassen, usw.).
' 23.05.2010:
' Positionssteuerung von X nach Y eingebaut. Die Geschwindigkeit wird
' über die Änderung der Pulslänge und der Anzahl der Takte gebildet.
' So ist quasi eine Geschwindigkeitssteuerung möglich, aber die Werte
' müssen halt ausprobiert werden. Mit verschiedenen Kombinationen ist
' es möglich eine fast Ruckfreie Positionierung des Servos hinzubekommen.
'
' Einschränkungen:
' Leider kann immer nur ein Befehl nacheinander abgearbeitet werden.
' Vieleicht ist es möglich mehrere Servos gleichzeitig unterschiedlich
' zu positionieren (Interruptsteuerung???).
' --------------------------------------------------------------------------

' --------------------------------------------------------------------------
' Ports definieren
'DEFINE Servo1  bPTB0      'PTB1  = PORT[9]
'DEFINE Servo2  bPTB1      'PTB2  = PORT[10]
'DEFINE Servo3  bPTB2      'PTB3  = PORT[11]
'DEFINE Servo4  bPTB3      'PTB4  = PORT[12]
'DEFINE Servo5  bPTB4      'PTB5  = PORT[13]
'DEFINE Servo6  bPTB5      'PTB6  = PORT[14]
'DEFINE Servo7  bPTB6      'PTB7  = PORT[15]
'DEFINE Servo8  bPTB7      'PTB8  = PORT[16]
DEFINE ServoPORT PTB       'PORTB = BYTEPORT[2]  'EIN/AUS
DEFINE ServoDDR  DDRB      'DDRB  = BYTEPORT[2]  'Richtung
' --------------------------------------------------------------------------
' Variablen definieren
DIM Invert_Servo_PORT BYTE 'Invertierter Servoport für High-Signal
DIM ServoTakt BYTE         'Takt=Dauer des Signals (Takt*20ms)
DIM ServoTaktZaehler BYTE  'für Abarbeitung des Taktes
DIM ServoHighSignal WORD   'Position des Servos
DIM ServoLowSignal WORD    'Dauer der Pause

DIM StartPos WORD          'Startposition für Bewegung
DIM ZielPos WORD           'Zielposition für Bewegung
DIM ServoGsw WORD          'Ist eigentlich die Änderung von "ServoHighSignal"
DIM ServoGswL BYTE[1] of ServoGsw   'LOW-Byte von "ServoGswL" als Zähler, um
                                    'die Änderung von "ServoHighSignal" zu
                                    'Berechnen
DIM ServoRichtung BYTE     'In welche Richtung der Servo dreht bei Bewegung.
                           'geht sicher auch einfacher
' --------------------------------------------------------------------------
' Servopositionssignal an den Servoport bilden
PROCEDURE ServoPositionsSignal(ZielPos) INLASM

#ServoSTART
! lda ServoTakt              'die Taktzyklen (Signaldauer) laden
! sta ServoTaktZaehler       'und als Zähler speichern

#ServoPositionBeginn         'Beginn des Signals
! lda Invert_Servo_PORT      'aktivierte Servoports laden; Signal=HIGH
! sta ServoPORT              'und hier setzen
'! bset Servo1,ServoPORT     'war zum testen an PORT9
! nsa                        'kleine Pause

! ldhx ServoHighSignal       'die Dauer des HIGH-Impulses laden
! bsr Servo_Verzoegerung     'und in "Servo_Verzoegerung" abarbeiten

! lda #&b00000000            'Alle Servos wieder auf OFF
! sta ServoPORT              'und hier setzen
'! bclr Servo1,ServoPORT     'war zum testen an PORT9
! nsa                        'kleine Pause

! ldhx ServoLowSignal        'die Dauer der Pause laden
! bsr Servo_Verzoegerung     'und in "Servo_Verzoegerung" abarbeiten

! dec ServoTaktZaehler       'die Taktzyklen um 1 verringern
! bne ServoPositionBeginn    'wenn >1 dann zurück zu "ServoPositionBeginn"

'__________________________________________________________________________
'Bei Absolutpositionierung ist die Zielposition gleich der Sollposition,
'deswegen erfolgt kein Aufruf der Servobewegung!

! ldhx ServoHighSignal       'Hier das HIGH-Signal (Position) mit der
! cphx ZielPos               'Zielposition vergleichen
! bne  ServoBewegung         'nicht im Ziel (Bewegung) "Servo_Verzoegerung"
'__________________________________________________________________________

#ServoENDE                   'Ablaufende
! rts                        'ENDE und zurück

#Servo_Verzoegerung          'Hier ist die Verzögerung
! aix  #-1                   'Verzögerung -1
! cphx  #0                   'Vergleich auf 0
! bne Servo_Verzoegerung     'nicht 0 dann nochmal "Servo_Verzoegerung"
! rts                        'zurück zum Aufruf

'...........................................................................
' Servobewegung von X nach Y
#ServoBewegung
! lda ServoRichtung     'Positionierrichtung laden
! cmp #0                'und vergleichen
! beq  ServoLinks       'wenn 0 dann "ServoLinks" (nach Links)
                        'sonst.....
! lda ServoGswL         '.....die Solländerung als Schleifenzähler laden....
#ServoRechts            'Drehrichtung nach Rechts
! ldhx ServoHighSignal  'Puls laden
! aix #1                '+1
! sthx ServoHighSignal  'Puls speichern
! dbnza ServoRechts     'Schleifenzähler verringern. Wenn gleich NULL dann
! bra ServoLinksEnde    'Drehrichtung nach Links überspringen

#ServoLinks             'hier gehts nach links
! lda ServoGswL         '.....die Solländerung als Schleifenzähler laden.....
#ServoLinks_1           'Drehrichtung nach Links
! ldhx ServoHighSignal  'Puls laden
! aix #-1               '-1
! sthx ServoHighSignal  'Puls speichern
! dbnza ServoLinks_1    'Schleifenzähler verringern. Wenn gleich NULL dann

#ServoLinksEnde         'Ende der Pulsberechnung
! ldhx #7800            'Gesamtdauer Puls laden (hier weniger da Berechnung)
! sub  ServoHighSignal  'den Puls abziehen
! sthx ServoLowSignal   'und in die Pause laden

! bra ServoSTART        'wieder zurück "ServoSTART"


! rts                   'ENDE

END PROCEDURE

' --------------------------------------------------------------------------
' Servos Initialisieren

PROCEDURE InitServo INLASM
! lda #&b00000000           'Alles auf LOW
! sta ServoPORT             'Alle Servoports auf LOW
! lda #&b11111111           'Alle Servoports aktivieren
! sta ServoDDR              'Alle Servoports auf Ausgang und LOW
! lda #&b11111111           'Bitmuster alle ON laden und
! and Servo_Ports_aktive    'mit "Servo_Ports_aktive" invertieren (ON=OFF/OFF=ON)
! sta Invert_Servo_PORT     'und in "Invert_Servo_PORT" abspeichern, Signal=ON
! nsa                       'warten...
! nsa                       'warten...
! nsa                       'warten...
! rts                       'Zurück

END PROCEDURE

' --------------------------------------------------------------------------
' Servosteuerung absolut (Position,Impulsanzahl)

PROCEDURE ServoPositionAbsolut(ServoHighSignal,ServoTakt)
  ServoLowSignal=8000-ServoHighSignal  'Pause berechnen und schon mal eintragen
  ZielPos=ServoHighSignal              'Zielposition auf Positionspuls setzen
  SYS InitServo                        'Initialisierung der Servoports alle auf 0
  SYS ServoPositionsSignal(ZielPos)    'Servosignal abarbeiten
  SYS InitServo                        'wieder alle Servoports auf 0
  RETURN
END PROCEDURE

' --------------------------------------------------------------------------
' Servosteuerung Bewegung von (Start,Ziel,Wegänderung,Impulsanzahl)

PROCEDURE ServoPositionBewegung(StartPos,ZielPos,ServoGsw,ServoTakt)
'Auswertung der Richtung durchführen
  if StartPos>=ZielPos then         'Start>Ziel dann
     'hier die Startposition neu berechnen, durch die innere
     'Berechnung "..(StartPos-ZielPos)/ServoGsw.." werden die Kommawerte
     'abgeschnitten, dadurch wird die neue Startposition zu einen glatten
     'Wert der sich im Ablauf mit der Zielposition auf "GLEICH" auswerten lässt!
     StartPos=ZielPos+(((StartPos-ZielPos)/ServoGsw)*ServoGsw)
     ServoRichtung=0   '=negativ Zählen
  else                              'Start<Ziel dann
     'wie bei Start>Ziel
     StartPos=ZielPos-(((ZielPos-StartPos)/ServoGsw)*ServoGsw)
     ServoRichtung=1   '=positiv Zählen
  end if


  ServoHighSignal=StartPos           'Positionspuls eintragen
  ServoLowSignal=8000-StartPos       '1.Pause berechnen und schon mal eintragen
  SYS InitServo                      'Initialisierung der Servoports alle auf 0
  SYS ServoPositionsSignal(ZielPos)  'Servosignal abarbeiten
  SYS InitServo                      'wieder alle Servoports auf 0
  RETURN
END PROCEDURE




Bitte gebt mal Rückmeldung, egal mit welchen Ergebnis!

Viel Spass beim ausprobieren,

Olaf

 Antwort schreiben

Bisherige Antworten:

Re: Bis zu 8 Servos mit Open-Makro steuern (von Dietmar - 31.05.2010 23:47)
Re: Bis zu 8 Servos mit Open-Makro steuern (von Jens - 31.05.2010 10:34)
    Re: Bis zu 8 Servos mit Open-Makro steuern (von Olaf - 31.05.2010 16:59)
        Re: Bis zu 8 Servos mit Open-Makro steuern (von Jens - 31.05.2010 18:30)
            Re: Bis zu 8 Servos mit Open-Makro steuern (von Olaf - 31.05.2010 21:59)
                Re: Bis zu 8 Servos mit Open-Makro steuern (von Jens - 1.06.2010 21:04)
                    Re: Bis zu 8 Servos mit Open-Makro steuern (von Olaf - 1.06.2010 22:09)
                       Re: Bis zu 8 Servos mit Open-Makro steuern (von Jens - 3.06.2010 19:24)
Gemischter Betrieb: Servoport und/oder Digitalausgang (von Olaf - 30.05.2010 13:30)
Re: Bis zu 8 Servos mit Open-Makro steuern (von Bert - 26.05.2010 21:57)