Direkte Auswertung von Digitalen Zuständen mit OPC

bloodymichael

Level-1
Beiträge
21
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,
wie ihr sehen könnt bin ich neu hier und noch blutiger Anfänger. Aufgrund eines Projektes habe ich ein Problem. Ich möchte eine Verbindung zwischen digitalen Eingängen und Ausgängen ohne Auswertung über eine S7 CPU schaffen um diese dann direkt über den PC verarbeiten zu können.
Ich hab mir mal einen kleinen Probeaufbau gemacht (so als Stand wie weit ich schon bin und wo ich hänge)
PCI-Profibuskarte (SIMATIC NET CP5613A2) in meinen PC eingebaut. Die Karte habe ich dann via Profibuskabel mit der SIMATIC ET 200M verbunden wobei diese jetzt noch mit einem DI (SM321 32xDC24V) und einem DO (SM322 32xDC24V/0,5V) gekoppelt wurde. Hab dann die Software installiert und via OPC Scout dem Komponenten Konfigurator alles so eingestellt, dass ich schon eine Verbindung zur ET 200M aufbauen konnte und mir so im OPC Scout die aktuellen Eingangszustände anzeigen lassen kann.
Mein gedanklich nächster Schritt ist, dass ich diese digitalen Werte jetzt nehmen kann und die Eingänge auswerten, verarbeiten kann um dann die von mir bestimmten Ausgänge in ihrem Zustand zu ändern.
Ich bin aber leider total ratlos wie es weitergehen kann. Es müsste doch eine Datei geben, in der ich die aktuellen Zustände abrufen kann. Wie kann ich diese ansprechen? Mit welchem Programm?
Das ist jetzt viel Text gewesen aber ich hoffe ihr könnt mir helfen.
Gruß
Michael
 
Hallo,
der OPC stellt eigentlich nur die (projektierten) SPS-variablen bereit und aktualisiert sie.
Was hast du dir denn vorgestellt, wie du die Verknüpfung realisieren willst ?
Excel-VBA ? Oder Visual Studio ? Oder ...?

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für die schnelle Antwort. Also ich kann C und Java programmieren. Es wäre hilfreich wenn es sich das dort realisieren lasse würde, da ich dann keine neue Sprache lernen müsste. Aber vielleicht geht das alles auch viieeel einfacher und ich find es einfach nicht.
Am Ende des Tages soll eine Oberfläche in tabellarischer Form heraus kommen, die Alarme auswertet und anzeigt (Füllstandsüberwachung etc.)
 
Was steht dir denn für C (Java würde ich nicht machen) als Programmier-Werkzeug zur Verfügung ?
Bei tabellarischer Darstellung drängt sich für mich allerdings auch ein bißchen das gute alte Excel auf ...
 
Ja ich werde es wohl in C programmieren. Aber mir geht es vorrangig jetzt ersteinmal darum, wie ich an die Eingänge des DI komme, damit ich diese überhaupt mit C ansteuern bzw. verwalten kann. Gibt es da ein Tool oder vielleicht eine Libary mit der ich das lösen könnte?
Vielleicht ist meine Herangehensweise ja auch total falsch. Ich wäre auch dankbar für alternative Vorschläge. Bin halt gerade neu im Thema und verschaffe mir einen Überblick.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... ich muß dir gestehen, dass meine Kenntnisse ab dem Punkt eher Allgemein sind. Etwas vergleichbares (und vor Allem "C") habe ich noch nicht gemacht. Allerdings sollte der von dir verwendete OPC-Server dazu Beispiele (mit Sicherheit auch C - wobei welches C ... C++ oder C# oder ...) liefern.

Gruß
Larry
 
Dir erstmal vielen Dank Larry,
vielleicht kann mir sonst noch jemand weiterhelfen. Habe jetzt erstmal ein paar C beispielprogramme gefunden und werde euch über den weiteren Verlauf in Kenntniss setzten.
Über weitere Posts würde ich mich sehr freuen.
Gruß
Michael
 
Falls es noch jemanden interessiert, hier nochmal meine Antwort. Wie Larry Laffer schon erwähnt hat, gibt es tatsächlich einige Beispiele, und sogar ganz gute, wie ich persönlich finde.

Hab dann die Software installiert und via OPC Scout dem Komponenten Konfigurator alles so eingestellt, dass ich schon eine Verbindung zur ET 200M aufbauen konnte und mir so im OPC Scout die aktuellen Eingangszustände anzeigen lassen kann.
Dann hast du BeitragsID: 29645558 vermutlich schon gelesen, alle anderen, die es noch nicht so weit geschafft haben, sollten sich dies jedenfalls durchlesen
http://support.automation.siemens.com/WW/llisapi.dll?func=cslib.csinfo〈=de&siteid=cseus&aktprim=0&extranet=standard&viewr eg=WW&objid=10805995&treeLang=de

Um den Rest auch noch zu verstehen solltest du auch Beitrags-ID: 21045282 durcharbeiten, da wird genau das beschrieben was du machen willst, SourceCode ist auch dabei.
http://support.automation.siemens.com/WW/llisapi.dll?func=cslib.csinfo&objid=34677186〈=de&cspltfrm=0&cssw=0&csbinh=8

Das ist im Prinzip genau das was du brauchst. Folge dem jeweiligen Link und gib die BeitragsID als Suchbegriff ein.
 
Hallo Leute,
inzwischen ist fast ein Monat vergangen und muss euch sagen, es läuft so lala. Die Verbindung via C++ zur et200 Baugruppe läuft wie im Beispiel wunderbar. Nur alles was jetzt kommt, da tue ich mich sehr schwer. Bis zur Erstellung von einer kleinen Gui, die sich mit dem Et200M Modul verbindet lief alles ganz gut. Aber beim Ansprechen der einzelnen Bits bzw. Bytes komme ich einfach nicht mehr weiter und habe auch überhaupt keinen Ansatz mehr.
Hab schon nebenbei ein bisschen mit WinCC rumgedokter und festgestellt, dass es damit sehr leicht gehen würde mein Programm zu realisieren. Leider würde das aufgrund der Lizenzen viel viel zu teuer werden.
Habt ihr vielleicht noch ne Idee wie ich mir das Projekt kostengünstig vereinfachen kann?
Was z.B ist Libnodave und wie funktioniert das?
gruß Michael
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... Nur alles was jetzt kommt, da tue ich mich sehr schwer ... Aber beim Ansprechen der einzelnen Bits bzw. Bytes komme ich einfach nicht mehr weiter und habe auch überhaupt keinen Ansatz mehr.

Hallo,
wo hängst du denn da konkret bzw. wo ist das Problem ?
Ich glaube nicht, dass du es mit Libnodave wirklich einfacher hättest, da das im Wesentlichen einfach nur eine andere Sammlung von Methoden ist, um mit der SPS zu kommunizieren.
Ich vermute, dass dein Problem die Visualisierung von Zuständen ist ...?

Gruß
Larry
 
Genau da stecke ich jetzt fest. Die Zustände aus der Et200M auszulesen und sie dann zu visualisieren. Ich habe mir eine List kontrol erstellt, Spalten eingefügt und würde jetzt z.B. gerne, wenn der Eingang xy kommt einen Text in diese Tabelle schreiben. Die frage ist nur, wie komme ich an die Abfrage von Eingang xy heran?
 
List-Control ?
Also erstmal wirst du ja die Eingänge als BYTE oder ggf. sogar WORD haben. An die einzelnen Bits hiervon kommst du nur über Maskieren dran (myBit_0 = myBte and 1) .
Um deren Zustand anzuzeigen würde ich eine Checkbox verwenden (je eine für jedes Bit) oder du baust dir ein eigenes Control zusammen (das ist auch nicht so schlimm ...).

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Genau, Du bist eigentlich schon sehr nah dran.

Du hängst dich in den Eventhändler des OnDataChange (die Items müssen natürlich hinzugefügt sein in eine aktive Gruppe). In diesem EventHandler fummelst Du dir die Bits raus aus den Bytes/Words die da kommen und dann weist du sie den Feldern in deinem ListControl zu.

Wenn Du Texte hinterlegt hast in einem StringArray kannst du auch über den Index (entsprechend dem Bit in dem Byte/Word) die Texte holen und die dann dem List (oder Grid-) Control zuweisen.
 
Was ich bis jetzt gemacht habe, ist das Projekt, das mir Dr. OPC am 08.09.2010 19:12 gezeigt hat zu öffnen und mich intensiv damit auseinander zu setzen. Hab es auch soweit hinbekommen, dass es mit meinen Ein und Ausgängen funktioniert. Jetzt bin ich halt dabei meine eigene GUI zu erstellen, was ich auch schon gemacht habe und nun müsste ich eigentlich die Ein und Ausgänge "nur" noch in Variablen einfügen, mit denen ich diese dann ausgeben, bzw. bearbeiten kann.
Ich verstehe z.B. überhaupt nicht wo sich das Programm aktualisiert also sprich wo das Programm schaut, dass sich Eingänge geändert haben.
Außerdem hab ich bis jetzt noch keine Variable in dem Beispiel von Dr. OPC gefunden wo man klar sagen kann, "DAS ist jetzt die Variable für E0.0". Vielleicht gibt es die schon aber ich habe auf jedenfall keine Ahnung wo und wie.
Kann man vielleicht in ein paar Zeilen schon schreiben: Ruf den OPC-Server auf, erstelle eine Gruppe mit einem Item und dann schreib den Wert des Items in eine Variable?
Es wäre echt nett wenn mir jemand mal einen kleinen Anstoss verpassen würde.

gruß Michael
 
Bezugnehmend auf die Beitrags-ID:21045282

in "ServerDefines.h" sind die Items für das Beispiel definiert worden
in "UserInterface.cpp" siehst du im OnBtnConnectClick()
Code:
void CUserInterface::OnBtnConnectClick()
hr = m_pOPCServerMgt->ConnectOPCServer(OPCCLIENT_SERVER_PROGID);
//blabla
hr = m_pOPCServerMgt->AddGroup(m_pOPCGroupMgt);
//blabla vorbereiten der Itemstrukturen
hr = m_pOPCGroupMgt->AddItems( //blabla
dass die Verbindung zu OPC Server aufgebaut wird, eine Gruppe angelegt wird und die Items hinzugefügt werden. Wenn das Hinzufügen geklappt hat, wird der Callback am Objekt der Gruppe angemeldet
Code:
// Connect data callback to receive OnDataChange events from OPC server
                hr = m_pOPCGroupMgt->ConnectCallback((CDataCallback*)this);
und das war es schon!
Nun wirst DU gerufen vom OPC Server wenn sich die Variablen ändern. In der "UserInterface.cpp" in der Methode CUserInterface:: DataChange kommen die Werte an und werden in die Controls der Oberfläche abgefüllt.
Code:
STDMETHODIMP CUserInterface::DataChange(HRESULT                hrMasterquality,
                                        UINT                dwCount,
                                        const CUIntArray   &aClientHandles,
                                        const CVARIANTArray&aValues,
                                        const CUIntArray   &aQualities,
                                        HRESULT*            pErrors)


//blabla

                if(aQualities[i] != OPC_QUALITY_GOOD)
                    SetDlgItemText(dwControlID,CErrorLookup::GetQuality(aQualities[i]));
                else
                    SetDlgItemText(dwControlID,(CString)aValues[i].bstrVal);
hier musst du nun auch deine GUI Controls befüllen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Super DANKE!! Das war auf jedenfall hilfreich. Jetzt hab ich halt noch ein Verständnis Problem bzgl. der erstellung der Items. Wenn ich z.B. nur ein Item erstellen möchte hab ich mir überlegt, folgenden code in der OnBtnConnectClick() zu verwenden.
Code:
CUIntArray anServerHandle;   // Array of client item handles - returned from AddItems
CHRESULTArray ahrErrors;     // Array of result codes for each item - returned from AddItems
            CStringArray astrItems;
            CUIntArray anRequDatatypes;
            CUIntArray anClientHandles;

            astrItems.Add("DP:[CP 5613 A2]Slave005M00_IX0.0,1");
            anRequDatatypes.Add(VT_BOOL);
            anClientHandles.Add(1);

            // Add items to the group
            hr = m_pOPCGroupMgt->AddItems(  1,         // Item count 
                                            astrItems,               // ItemIDs
                                            anRequDatatypes,    // Requested datatyp
                                            anClientHandles, // Client handles
                                            anServerHandle, // Returned serv handles
                                            ahrErrors);     // Returnded item results
            if(SUCCEEDED(hr))
            hr = m_pOPCGroupMgt->ConnectCallback((CDataCallback*)this);
Dann hab ich zum testen im DataChange an dieser Stelle:
Code:
for(UINT i=0; i < dwCount; i++)
    {
        // Get the ControlID for the item
        // Access with Client Handle
        DWORD dwControlID = m_aOPCItemMgt[aClientHandles[i]].ControlID;
            
        if(pErrors[i] == S_OK)
        {      
            // Get the requested data type
            VARTYPE vt = aValues[i].vt;
            
            if(vt == VT_BSTR)
            {
                // Data Type is string -> Control is a text box
                // Write value to the text box with the control ID from OPCItemMgt
                if(aQualities[i] == OPC_QUALITY_GOOD)

                    SetDlgItemText(dwControlID,(CString)aValues[i].bstrVal);
            
            }
            else if(vt == VT_BOOL)
            {
[B]                      CString strbla;
                        strbla.SetString("Läuft");
                        AfxMessageBox(strbla);  [/B]
                     ((CButton*)GetDlgItem(dwControlID))->SetCheck(aValues[i].boolVal);
                // Invalidate the control to get a repaint
                GetDlgItem(dwControlID)->Invalidate();

            }
umgeändert, dass mir bei jeder Variablenänderung eine afxmessagebox ausgegeben wird. Leider funktioniert das immer noch nicht. Ich vermute mal, dass da irgendwo noch der Wurm in der Itemerstellung liegt. Ich verstehe halt nicht, wieso da so gar nichts passieren mag.
Schönes Wochenend wünsch ich euch.
gruß
Michael
 
An der Stelle nach dem Anlegen des Items solltest du mal reindebuggen und dir anschauen ob das überhapt klappt.
Code:
            // Add items to the group
            hr = m_pOPCGroupMgt->AddItems(  1,         // Item count 
                                            astrItems,               // ItemIDs
                                            anRequDatatypes,    // Requested datatyp
                                            anClientHandles, // Client handles
                                            anServerHandle, // Returned serv handles
                                            ahrErrors);     // Returnded item results

if(SUCCEEDED(hr))
hr = m_pOPCGroupMgt->ConnectCallback((CDataCallback*)this);
selbst wenn der "hr" (vom AddItems) hier OK sein sollte, muss eigentlich auch noch der "ahrErrors" geprüft werden, auch hier könnte noch ein FehlerCode drin stehen.
Nur wenn alles geklappt hat, kommt nachher auch ein Callback.
Ich vermute das hier der "hr" schon einen Fehler gibt.

Achso, und du solltest dich auch nicht auf den "OPC.SimaticNET.DP" sondern auf den "OPC.SimaticNET" verbinden (ProgID in der ServerDefines.h). Der Grund ist dass der "mit *.DP" ein sogenannter InprocServer ist, das ist zum Testen und Spielen eher ungünstig da immer nur ein Client verbunden sein kann (der Server ist eine DLL und wird in den Prozess des Client geladen, dass ist zwar sauschnell aber es kann sich immer nur ein Client verbinden). Der OutprocServer (ohne *.DP) ist auch noch schnell aber es können mehrere Clients verbunden sein und dann kannst du besser Spielen und mit dem OPCScout z.B. Werte schreiben und sehen ob bei dir was ankommt. Später wenn alles läuft, kannst du immer noch zurück auf den DLL-Server gehen, ist ja alles OPC und geht dann einfach, brauchst nur die ProgID zurückändern.
 
Hallo zusammen!

Hab mich heute wieder drangemacht und die Tipps von Dr. OPC berücksichtigt. Ich habe noch etwas nach dem folgenden Ausdruck beim Verbindungsaufruf
Code:
hr = m_OPCGroupMgt->ConnectCallback((CDataCallback*)this);
folgendes hinzugefügt:
Code:
m_pOPCGroupMgt->SetActive(TRUE);
Nach dem ich das getan hatte bekam ich nach einen diesen Fehler.
Run-Time Check Failure #0 - The value of ESP was not
properly saved across a function call. This is usually a
result of calling a function declared with one calling
convention with a function pointer declared with a
different calling convention.
Und das Programm bleibt in der STDMETHODIMP COPCDataCallback::OnDataChange(...) stehen. Und zwar genau an der stelle:
hr = m_pDataCallback->DataChange(bla
bla
pErrors);
Übergehe ich diesen fehler in dem ich auf "weiter" klicke, funktioniert das Programm und der Fehler taucht wieder auf, sobald ich ein TRUE am Eingang anliegen habe. Also reagiert es endlich. Nur nicht ganz so wie ich es will.
Habt ihr ne Vermutung wo da der Fehler ist? Oder braucht ihr dazu mehr Code?
gruß Michael
 
Zurück
Oben