vielen Dank für deine Unterstützung.
Ich sende dir meine Daten dann privat.
@Tim26:
Danke für den Tip. Ich werd da mal nachfragen...
vielen Dank für deine Unterstützung.
Ich sende dir meine Daten dann privat.
@Tim26:
Danke für den Tip. Ich werd da mal nachfragen...
Mich würd's schon interessieren
Ich schick dir mal meine EMail-Adresse als private Nachricht, wenn es dir nichts ausmacht, kannste mir die Doku gerne mailen.
Danke und Gruß
Rainer
Moin,
Danke für die Infos.
An Stäubli hatte ich auch schon gedacht, ich befürchte aber die haben von den alten "Kamellen" keine Unterlagen mehr. Ich schreib mal an den Support....
Danke nochmal und Gruß
Rainer
Hallo Roboman,
Danke für die Antwort.
Ich habe leider keine Ahnung mit welcher Steuerung der Rob arbeitet: wurde mir als Gebrauchtgerät angeboten, allerdings ohne Handbücher/Dokumentation, bin deswegen auf der Suche....
Vielleicht helfen die folgenden Bilder weiter:
Danke und Gruß
Rainer
Hallo zusammen,
hat irgendjemand eine Idee wo bzw. wie ich an Unterlagen zum Bosch Scara SR800 komme ? Insbesondere Handbücher zur Programmierung oder dgl. wären wichtig.
Vielleicht hat jemand auch Originale die er veräußern möchte oder mir (gegen Geld) ausleihen kann damit ich Kopien machen kann.
Bin für jeden Tipp dankbar....
Danke und Gruß
Rainer
Hallo Stefan,
ich hab da mal was vorbereitet....
Vorschlag 1: Synchronisieren der Tasks über dig. Ausgänge
Laut Doku macht WaitUntil ein wiederholtes Abfragen (Polling) der Bedingung (nur) ca. alle 100ms. Wenn man die Synchronisierung über WaitDO, also durch Setzen/Rücksetzen eines digitalen Ausgangs bewerkstelligt, wird die Abfrage mit Interrupt-Geschwindigkeit erledigt. Ist auf jeden Fall (ein wenig) schneller und eleganter... Ein weiterer Vorteil ist, dass man auf der IO-Seite am TeachPanel anhand des Ausgangs direkt sehen kann ob und wann die Bilderkennung aktiv ist.
Vorschlag 2: Triggern der Vision Task direkt nach Verlassen des Kamerasichtfeldes
Durch Teachen eines Zwischen(Trigger)punktes kann man den nächsten Erkennungsvorgang direkt nach Verlassen des Kamerasichtfeldes auslösen, indem man an dieser Position (quasi im "Vorbeifliegen") den dig. Triggerausgang setzt. (Siehe Skizze und Code bzw. Doku. zu MoveLDO bzw. MoveJDO)
Vorschlag 3: Verschiebung von Bewegungsabläufen über Program Displacements realisieren
Nach Möglichkeit sollte man bei der Verschiebung (hier DX,DY) von kompletten Bewegungsabläufe die Manipulation von Robtargets, Pos usw. vermeiden. Besser ist die Verwendung von Program Displacements (siehe Code). Das Gleiche gilt für die Rotation von Achsen, d.h. man könnte (uns sollte) das auch bei der Korrektur der Greiferrotation einsetzen (statt die Tooldaten zu manipulieren!). Hab ich hier aber nicht umgebaut...(schau diesbzgl. mal in die Rob-Doku)
Vorschlag 4: Diverse kleinere Programmänderungen zur Verbesserung der Übersichtlichkeit und Fehlersuche
z.B. Statuscodes des Vision Systems u.a. (siehe Code)
Hier nun die Programmausschnitte. Ist noch nicht ganz vollständig, sollte aber als Basis für weitere "Experimente" ausreichen.
ACHTUNG: logischerweise alles ungetestet und OHNE Gewähr, also auf eigene Gefahr!
VisionTask:
MODULE SHORVI
CONST string CVS_ERRHEAD := "Vision Error";
! Vision Subsystem Stati
CONST num CVS_NOTINIT := 0;
CONST num CVS_INIT := 1;
CONST num CVS_INPROGRESS := 2;
CONST num CVS_RESULTOK := 3;
CONST num CVS_ERR := 4;
PERS num XWERT:=0;
PERS num YWERT:=0;
PERS num ZWERT:=0;
PERS num XROT:=0;
PERS num yROT:=0;
PERS num ZROT:=0;
PERS num TeileNr:=0;
PERS num nVisionStatus := 0;
PROC haupt()
VAR num nStep;
VAR errnum nSaveErr;
nVisionStatus := CVS_NOTINIT;
ORIS_open;
! Status der Initialisierung auswerten (vorausgesetzt ORIS_open setzt den Status !)
IF Status <> ORIS_OK THEN
ErrWrite CVS_ERRHEAD,"FATAL: Unable to init Vision System";
! Anhalten
Exit;
ELSE
nVisionStatus := CVS_INIT;
ENDIF
WHILE True DO
! Auf Trigger warten mit Interrupt (kein Polling = schneller)
WaitDO doVisionActive, 1;
nVisionStatus := CVS_INPROGRESS;
nStep := 1;
Status := ORIS_OK;
WHILE (nStep <= 6) AND (Status = ORIS_OK) DO
TEST nStep
CASE 1:
ORISCom_RunMode\Auto;
CASE 2:
ORISRep_RunMode;
CASE 3:
ORISCom_MeaData 0,1,1;
CASE 4:
ORISRep_GetReslt;
TeileNr:=Oris_PosX;
CASE 5:
ORISCom_MeaData ORIS_PosX,ORIS_PosY,ORIS_PosZ;
CASE 6:
ORISRep_GetReslt;
ENDTEST
Incr nStep;
ENDWHILE
IF Status = ORIS_OK THEN
XWERT:=ORIS_PosX;
YWERT:=ORIS_PosY;
ZWERT:=ORIS_PosZ;
XROT:=ORIS_RotX;
YROT:=ORIS_RotY;
ZROT:=ORIS_RotZ;
nVisionStatus := CVS_RESULTOK;
ELSE
ErrWrite CVS_ERRHEAD,"ORIS Status Err: " + NumToStr(Status,0) + " at step: " + NumToStr(nStep,0);
nVisionStatus := CVS_ERR;
ENDIF
Reset doVisionActive;
ENDWHILE
ORIS_Close;
RETURN;
ERROR
nSaveErr := ERRNO;
ErrWrite CVS_ERRHEAD,"Error: " + NumToStr(nSaveErr,0) + " at step: " + NumToStr(nStep,0);
ORIS_Close;
Reset doTrigVision;
RAISE nSaveErr;
ENDPROC
ENDMODULE
Alles anzeigen
Hier der Ansatz für die MainTask:
CONST num CTeilMax:=20;
CONST string CSaege_Procs {CTeilMax} := ["SaegeTeil1","SaegeTeil2","SaegeDummy", ... ,"SaegeDummy"];
CONST num CVS_NOTINIT := 0;
CONST num CVS_INIT := 1;
CONST num CVS_INPROGRESS := 2;
CONST num CVS_RESULTOK := 3;
CONST num CVS_ERR := 4;
PERS num XWERT:=0;
PERS num YWERT:=0;
PERS num ZWERT:=0;
PERS num XROT:=0;
PERS num yROT:=0;
PERS num ZROT:=0;
PERS num TeileNr:=0;
PERS num nVisionStatus := 0;
! Triggerposition für Vision System
! muß noch an geeigneter Stelle geteacht werden (siehe Skizze)
VAR robtarget rtVSTrigger;
PROC SaegeTeil1()
! hier den Sägeablauf "normal" teachen OHNE Verechnung von DX bzw. DY
! Eine evtl. Verschiebung wird über PDispSet beim Proc-Aufruf geregelt....(s.u.)
MoveJ ...
...
MoveL ...
ENDPROC
PROC SaegeTeil2()
MoveJ ...
...
MoveL ...
ENDPROC
PROC SaegeDummy()
! Dummy = nix machen
ENDPROC
PROC HomePos(bool bOpenGrip)
IF bOpenGrip GreiferAuf;
HOME;
ENDPROC
PROC GreifposAnfahren(num nOffX,num nOffY,num nRotZ)
! Funktion um Greifposition anzufahren
ConfJ\Off;
ConfL\Off;
Greifer1.tframe.rot:=OrientZYX(nRotZ,0,0);
! mit obigem Befehl wird die Orientierung um Z eingestellt mit aktuellem Wert
MoveL [[nOffX,nOffY,80],[0.000395,0.965035,-0.262121,-6.1E-05],[0,0,-1,0],[9E+09,9E+09,9E+09,9E+09,9E+09,9E+09]],vmax,fine,Greifer1\WObj:=wobjKAMERA;
WaitTime\InPos,0;
MoveL [[nOffX,nOffY,-30],[0.000395,0.965035,-0.262121,-6.1E-05],[0,0,-1,0],[9E+09,9E+09,9E+09,9E+09,9E+09,9E+09]],v50,fine,Greifer1\WObj:=wobjKAMERA;
! Der erste MoveL BEfehl fährt über das Teil und der zweite bewegt den greifer senkrecht nach unten
ENDPROC
PROC TeilAnheben(num nOffX,num nOffY)
GreiferZu;
MoveL [[nOffX,nOffY,80],[0.000395,0.965035,-0.262121,-6.1E-05],[0,0,-1,0],[9E+09,9E+09,9E+09,9E+09,9E+09,9E+09]],vmax,fine,Greifer1\WObj:=wobjKAMERA;
ENDPROC
PROC Saegen()
WaitTime 0;
Greifer1.tframe.rot:=[1,0,0,0]; !?
! Vision Triggerpunkt anfahren/verschleifen; innerhalb der Zone wird automatisch das Flag
! zum Starten des Vision-Subsystems gesetzt
! ACHTUNG: unbedingt Geschwindigkeit und Zone den Gegebenheiten anpassen !!
MoveLDO rtVSTrigger,vmax,z50,Greifer1\WObj:=wobj0, doVisionActive,1;
! ggfls. MoveJDO verwenden
! Das Anfahren von HomePos kann man sich u.U. sparen wenn am Triggerpunkt verschliffen
! direkt zum Sägen gefahren wird; hängt von Aufbau/Gegebenheiten ab!
HomePos False;
IF (TeileNr>=1) and (TeileNr<=CTeilMax) THEN
! hier die ggfls. zu verwendenden Verschiebung berücksichtigen
PDispSet [[DX,DY,0],[1,0,0,0]];
%CSaege_Procs{TeileNr}%;
PDispOff;
ENDIF
ENDPROC
PROC haupt()
Reset doVisionActive;
! Nach Home; Greifer auf
HomePos True;
! warten bis Vision initialisiert ist; nur einmal beim Programmstart
WaitUntil (nVisionStatus <> CVS_NOTINIT);
! Vision triggern
Set doVisionActive;
WHILE True DO
! Warten bis Vision fertig
WaitDO doVisionActive, 0;
!
IF nVisionStatus = CVS_RESULTOK THEN
! wenn Ergebnis des Vision Systems gültig ist, dann Teil anfahren, greifen und sägen
GreifposAnfahren XWERT, YWERT, ZROT+30;
TeilAnheben XWERT, YWERT;
! Vision wird erneut beim Verlassen des Sichtfeldes getriggert (siehe Proc "Saegen")
Saegen;
HomePos True;
ELSE
! wenn Vision Result nicht OK, dann erneut triggern
Set doVisionActive;
ENDIF
ENDWHILE
ENDPROC
Alles anzeigen
Wie gesagt, ich weiß nicht ob das so funzt, denke aber es sollte gehen...
Nicht vergessen den Triggerpunkt zu teachen, das doVisionActive-Signal zu definieren und ansonsten viel Spaß beim Experimentieren.
Gruß
Rainer
Hallo Stefan,
bitte, bitte, gern geschehen.
Ich hätte noch ein paar andere Anregungen zu deinem Projekt, aber ich will mich nicht aufdrängen...
Also wenn du noch Bedarf/Fragen hast, dann sag Bescheid.
Grüße und ansonsten noch viel Spaß beim Basteln...
Rainer
Hallo,
vielleicht hilft das ein wenig weiter:
http://robotknowledge.com/mod/…/S4PPlusFileStructure.pdf
Gruß
Rainer
Hallo Stefan,
noch ein Nachtrag:
Man könnte die VisionTask dahingehend optimieren, dass die Initialisierung nur einmal beim Systemstart und nicht bei jeder Messung ausgeführt wird, aber wenn du sonst keine Möglichkeiten zur Anpassung/Parametrierung des Erkennungsprozesses auf dem VisionSystems hast, kannst du zeitlich nicht viel dran machen....
An dem Programm insgesamt ließe sich schon durchaus einiges ändern
Hier z.B. ein Vorschlag für haupt() in der MainTask:
(ACHTUNG: alles ungetestet und OHNE Gewähr !!!!)
PROC haupt()
XWERT:=0;
YWERT:=0;
GreiferAuf;
HOME;
FindItem:=TRUE;
WHILE True DO
WaitUntil (XWERT<>0) AND (YWERT<>0);
XFAHR:=XWERT;
YFAHR:=YWERT;
RotationZ:=ZROT+30;
XWERT:=0;
YWERT:=0;
GreifposAnfahren;
GreiferZu;
Anheben;
Saegevorgang;
GreiferAuf;
HOME;
ENDWHILE
ENDPROC
Alles anzeigen
Man könnte noch andere Dinge weiter vereinfachen und besser strukturieren, nur dafür müsste man natürlich die anderen Procedures entsprechend anpassen.
Noch ein Tip zum Ablegen der verschiedenen Teile:
Du benutzt zum Aufruf der unterschiedlichen Ablagebewegungen diesen großen Case-Konstrukt (TEST/ENDTEST). Ich würde für jedes Teil eine Ablageroutine schreiben und diese dann über den Namen aufrufen. Ist viel übersichtlicher und pflegbarer.....
Beispiel:
CONST num CAblageMax:=20;
CONST string CAblage_Procs {CAblageMax} := ["AblageTeil1","AblageTeil2","AblageDummy", ... ,"AblageDummy"];
PROC AblageTeil1()
MoveJ ...
...
MoveL ...
ENDPROC
PROC AblageTeil2()
MoveJ ...
...
MoveL ...
ENDPROC
PROC AblageDummy()
! Dummy = nix machen
ENDPROC
Alles anzeigen
Der Aufruf der Ablage in Saegevorgang() könnte dann in etwa so aussehen:
PROC Saegevorgang()
WaitTime 0;
Greifer1.tframe.rot:=[1,0,0,0];
MoveL HOMEPOS,vmax,fine,Greifer1\WObj:=wobj0;
FindItem:=TRUE;
%CAblage_Procs{TeileNr}%;
GreiferAuf;
MoveL HOMEPOS,vmax,fine,Greifer1\WObj:=wobj0;
ENDPROC
Gruß
Rainer
Stefan,
scheint ja zumindest vom Ablauf wie gewünscht zu funktionieren.
Wenn ich das richtig sehe, scheint der Step 4 (ORISRep_GetReslt = Teileerkennung?) des VisionSystems () länger zu brauchen (> 2 Sek.). Das würde auch zu deiner Aussage am Anfang des Threads passen, nämlich das der Ablauf mit vorgegebener Teile-Nr. wesentlich schneller funktioniert. Da läßt sich aber wahrscheinlich von deiner Warte aus nicht viel dran drehen....
Wie sieht es denn bei den weiteren/folgenden Durchläufen aus?
Hängt er dann auch genau so lange an der gleichen Stelle ?
Gruß
Rainer
Stefan,
übernehme mal die folgende Log-Routine in die Tasks
PROC logWrite(string Text)
CONST string logFileName := "HOME:run.log";
VAR iodev AFile;
Open logFileName, AFile \Append;
Write AFile, Text + CDate() + " " + CTime();
Close AFile;
ERROR
Return;
ENDPROC
und bau diese (wie vorher) in die entsprechenden Schleifen ein, also
in der MainTask Schleife:
und in der While Schleife in der VisonTask
Nach dem Ausführen steht das Ergebnislog dann in der Datei "run.log".
Kopier das mal aus der Steuerung und poste den Inhalt hier als Antwort. Mich würde mal interessieren was dabei so rauskommt.....
Gruß
Rainer
Hallo Stefan
bau mal in die (NEU-)Schleife in der MainTask folgendes ein:
TPWrite "Main: " + NumToStr(Schleifenzähler,0) + " " + CTime();
und in der While Schleife in der VisonTask
TPWrite "Vision: " + NumToStr(nStep,0) + " " + CTime();
schau dann mal auf dem TPanel was wann gemacht wird.
Rainer
Hallo,
habe mir dein Programm jetzt mal was genauer angesehen.
Gib doch in der NEU Schleife (am besten direkt hinter dem Label "NEU") einen Text (oder besser (Schleifen-)Zählerwert) auf dem Teachpanel aus, dann kann man wenigstens feststellen ob der ProgramCounter steht oder in der Schleife kreist.
Bis gleich
Rainer
Hallo Stefan,
also ich glaube das Problem ist das WaitDO in der GreiferAuf() Proc.
In Haupt() wird zuerst GreiferAuf() und dann Home() aufgerufen.
Wenn du die Zustimmtaste losläßt, dann ist der Rob noch im Wartezustand (WaitDO), zeigt aber schon den nächsten auszuführenden Befehl an (MoveL in Home()) könnte ich mir vorstellen (?). Probiers mal mit vertauschen der Befehle in GreiferAuf().
Gruß
Rainer
Tach auch,
also:
was du da in den GreiferAuf() bzw. GreiferZu() Routinen mit WaitDO machst, ist bestimmt nicht im Sinne des Erfinders. WaitDO wartet so lange bis das entsprechende Signal (Greifer) gesetzt bzw. rückgesetzt wird (oder bis TimeOut), was aber erst im nächsten Befehl ausgelöst wird (!), das kann, glaub ich, so nicht funktionieren. Einfach mal die Reihenfolge der Instruktionen tauschen....
Bei welcher Zeile der Rob die Zeit vertrödelt habe ich aber jetzt nicht wirklich geblickt
Beschreibe bitte die Stelle etwas genauer. Wie hast du denn gemessen wieviel Zeit er wofür braucht ?
Noch was:
Greifer1 ist doch das Werkzeug (tool). Ich würde die Orientierung des Greifer nicht über die Manipulation der Strukturdaten machen, ist nicht so elegant (vielleicht ist es aber auch völlig genial und ich habe nur das Programm nicht geblickt ). Das Verfahren über berechnete Robtargets halte ich für besser (und nachvollziehbarer).
Gruß
Rainer
Hallo Stefan,
ZitatDie leute von Isra sagten mir es könnte daran liegen das ABB die schnittstelle z.B. 2 sek. geöffnet hält und danach schließt und diese nach einer gewissen Zeit wieder öffnet. Kann das sein ?
Klingt für mich zwar nicht unbedigt logisch, unmöglich ist aber (fast) nichts. (Ich habe es auch geschafft die S4C mit serieller IO "bluescreen-mäßig" abzuballern)
Hier ein bisschen Code aus einem damaligem Projekt:
VAR iodev A100;
Open "com1:",A100\Bin;
! Buffer löschen kann nicht schaden
ClearIOBuff A100;
! Vision triggern
WriteStrBin A100,"%S\0D";
! Koordinaten lesen
sX:=ReadStrBin(A100,4\Time:=5);
sY:=ReadStrBin(A100,4\Time:=5);
Close A100;
ERROR
IF ERRNO=ERR_DEV_MAXTIME THEN
Close A100;
RAISE;
ELSEIF ERRNO=ERR_FILEOPEN THEN
RAISE;
ENDIF
Alles anzeigen
Insbesondere das Löschen des SIO-Buffers (ClearIOBuff) kann manchmal Wunder wirken.
Auch das Schließen des Kanals im (Timeout-)Fehlerfall nicht vergessen! (=sonst böse Falle).
Je nachdem in welchem Format das VisionSystem die Kommandos/Parameter erwartet, könnte man ggfls. auch mit angehängten CR und/oder LFs experimentieren.
Zitathat aber leider nicht funktioniert Fehlermeldung war: 40505 Kann nicht öffnen Sio1: Raise Code: Err_Fileopen=1015
Das würde auf einen generellen Fehler bei den SIO-Parametern (Baudrate, Handshake, etc) hindeuten, ist aber auszuschließen wenn die ser. Kommunikation über diesen Kanal sonst prinzipiell funktioniert. Möglicherweise ist der Kanal aber auch schon geöffnet, allerdings weiß ich nicht ob das doppelte Öffnen diese Fehlermeldung provozieren würde. Am besten die komplette Kommunikation zw. Roboter und Vision erstmal in einer Proc isolieren (Kapseln mit Open/Close) und testweise in der Maintask laufen lassen (also alle anderen Tasks beenden um Multitasking Probleme auszuschließen). Vielleicht bringt das mehr Hinweise.
Gruß
Rainer
Nachtrag:
Eine weitere Fehlerquelle könnte die Baudrate sein, deshalb erstmal langsam starten (z.B.: 9600 Baud) und wenns funktioniert langsam steigern.
Hallo,
ich habe im Laufe des letzten Jahres mal zwei Vision-Systeme (einmal Matsushita und einmal Eigenbau) seriell mit der S4C gekoppelt, allerdings nicht mit Multitasking, sondern in der Main-Task.
Ich hatte da auch so meinen "Spaß" mit, aber irgendwann funktionierte es....
Prinzipiell kann man den seriellen Kanal schon offen lassen indem man die entsprechende iodev Variable in einem globalem Modul deklariert, beim Start des Programms einmal initialisiert usw.
Ich habe damit aber keine guten Erfahrungen gemacht (mangelnde Stabilität) und könnte mir auch vorstellen, dass das nicht die Lösung des Problems ist. Um die Problematik einzugrenzen und herauszufinden was wann passiert, sollten Sie versuchen den zeitlichen Ablauf zu analysieren, indem Sie den Prozeß in kleinere logische "Häppchen" zerlegen und nach jedem (Teil-)Schritt eine Meldung mit Zeitangabe auf dem TeachPanel oder in eine Logdatei ausgeben. Dann kann man weitersehen....
Wenn die Koordinatenübergabe reproduzierbar(!) bei 1,5 Sekunden und die Objekterkennung bzw. -verifikation bei 8,5 Sekunden liegt, dann würde ich mich zunächst mal mit dem Vision-System beschäftigen... :wink:
Gruß
Rainer
Hallo Norbert,
auch auf die Gefahr hin, dass ich dich missverstehe:
Ich meinte eigentlich alle 300 robtargets (bzw. Befehle mit robtargets) wenn möglich zu markieren und dann das Suchen/Ersetzen (durch den geschickten Einsatz regulärer Ausdrücke ;)) auf die gesamte Markierung anzuwenden, also alle 300 robtargets mit einem (oder zwei) Durchläufen zu ändern, nicht 300mal einzeln...
Wenn du das auch so gemeint hast, dann bitte meine Antwort ignorieren.... :lipsrsealed:
>Achskonfiguration nur für die Achse 1 abschalten
wüsste nich dass das geht...
Gruß
Rainer
Hallo,
um die Achskonfiguration (oder Teile davon) innerhalb eines robtargets auf einen bestimmten, festen Wert zu setzen, würde ich versuchen mit einem Editor der Suchen/Ersetzen mit regulären Ausdrücken unterstützt (UltraEdit?), den entsprechenden Wert dort einzutragen.
Da reguläre Ausdrücke etwas "gewöhnungsbedürftig" sind, muß man sich allerdings damit zunächst ein bisschen beschäftigen (...mal danach googlen).
Gruß
Rainer