# Snap7 mit c++ auf Raspberry Pie



## Hirschfy (2 Juli 2020)

Hallo,

Ich bin neu hier im Forum. Ich möchte/soll für meinen Arbeitgeber &  Studium ein Projekt mit einer SPS und einem Raspberry Pie bearbeiten.  (Studiere Mechatronik)
Ziel ist es ein simples Programm der SPS (Motor rechts-, linkslauf, an, aus) mit einem Raspberry Pie zu steuern.
Ich habe mich für die Kommunikation über Snap7 entschieden und  programmiere in c++ (einzige sprache, die ich bisher gelernt habe).
Leider habe ich nur sehr rudimentäre Kenntnisse was die Programmierung in C++ angeht.
Ich habe mir aus dem Beispiel-Programm ein paar Codeschnipsel zusammen geschrieben und versuche mich da so rein zu arbeiten. 
Bisher klappt das auslesen der CPU infos und die CPU auf START oder RUN  zu setzten. Prinzipiell klappt auch das Auslesen der Ausgänge zum  Beispiel.

Probleme habe ich beim Darstellen der Informationen.
Ich hab schon diverses ausprobiert. Sicher klappt nur die Ausgabe als  hex zahl, was ich aus dem Beispielprogramm rauskopiert habe. Alles  andere gibt entweder kein ergebnis oder (für mich) willkürliche  Ergebnisse. Ich versteh einfach nicht, wie die Informationen verarbeitet  werden.

Mein bisheriger Code zum Auslesen ist im Anfang. Bei Bedarf kann ich auch den ganzen Code anhängen.

Wenn ich das richtig verstehe wurde byte als 8-Bit unsigned in definiert (in snap7.h). (?)
Als ergebnis erhalte ich:
1. 04   ->Richtig
2.  4    ->Richtig
3. 77828 -> ???

Wie gesagt ich habe nur sehr rudimentäre Kenntnisse. Würde mich über Hilfe sehr freuen!
Wenn noch was benötigt wird schicke ich das gerne!

Beste Grüße
Hirschfy


----------



## Thomas_v2.1 (2 Juli 2020)

Mit rudimentären Kenntnissen würde ich das mit C++ bleiben lassen. Vor allem ohne Kenntnisse von Zeigern geht das garantiert schief wie zu sehen ist.
((char*)AB0)[0] ist auch schon sehr zweifelhaft, aber mit
((int*)AB0)[0]
greifst du einfach irgendwo in den Speicher.

Bei einem Array zeigt die Array-Variable (ohne Index) auf das erste Element des Arrays. Mit dem int-Zeiger cast (int*) sagst du dem Compiler, AB0 zeigt jetzt nicht mehr auf ein byte (bzw. unsigned char) sondern auf ein int. Der Array-Index Zugriff [0] entspricht dann sozusagen einem dereferenzieren des Zeigers, d.h. es wird der Wert geholt auf den der Zeiger zeigt. Du hast für die Variable aber nur 1 Byte an Speicher für reserviert, und greifst bei einem int auf 4 (bzw. bei 64 Bit Betriebssystem evtl. 8 ) Bytes ab der Adresse zu. Darum siehst du da 1 Byte von deinem Array (77828dez = 0x13004, die 0x04 gehört zu deinem AB0[0]), und die anderen Bytes gehören einer anderen Variable auf dem Stack.


----------



## Hirschfy (3 Juli 2020)

Super, das erklärt es schonmal.
Also als rudimentäre Kenntnisse bezeichne ich ein Semester während des Studiums vor 1,5 Jahren.
Was ein Array ist weiß ich und auch wie ein Pointer funktioniert auch. 
Aber solche Zusammenhänge, wie du beschireben hast springen mir einfach nicht gleich ins Auge.

Theoretisch reicht mir der jetzige Zustand auch aus, um damit zu arbeiten. Ich kenne ja die Zustände der SPS und kann auch damit weiter machen. Aber ich würde es schon gerne verstehen....

Also das mit dem Int* hab ich verstanden! Vielen Dank, ist einleuchtend. Das erklärt auch, wieso das mit char klappt. Das hat ja eine größe von 8 bit.

Mein größtes Problem, ist glaub ich, dass ich nicht weiß, wieso er mir gar nichts anzeigt, wenn ich einfach nur schreibe, er soll mir den Inhalt des Arrays angeben. Mit:

printf( AB[0] )


----------



## Thomas_v2.1 (3 Juli 2020)

Dein Array hat doch nur ein Element, und das gibst du dezimal mit:
printf("%d", AB[0]);
aus.


----------



## Hirschfy (3 Juli 2020)

ok. 
Da muss ich mich entschuldigen! Habs eben nochmal nachgelesen. Bei printf muss immer ein Umwandlungszeichen für das Argument angegeben werden. 

Ich hab bisher nur mit std::cout gearbeitet.
Dann hier die Frage: Wenn ich

std::cout << AB0[0];

schreibe, gibt er mir nichts aus. Weil er nicht weiß in welchem Format?


----------



## Thomas_v2.1 (3 Juli 2020)

Weil cout ein unsigned char erkennt, und annimmt es handelt sich um dein Zeichen. 4 entspricht aber keinem druckbaren ASCII Zeichen, darum siehst du dort nichts.
Du müsstest das in ein Integer casten, also cout << static_cast<unsigned>(AB0[0]) sollte funktionieren.


----------



## Hirschfy (3 Juli 2020)

Super Danke!

Ich hatte schon was dazu geschrieben, das er mir mit %c nichts ausgibt, weil er das ASCII Zeichen 4 nicht drucken kann, hatte es aber wieder weg gemacht. 
Aber das ist dann genau das, was Sie geschrieben haben. 

Hab es eben mit dem cast auf unsigned ausprobiert. Das klappt! 
Ich hab es allergins einfach so gemacht:

<< (unsigned)AB0 <<     //hab das Array weg gelassen, da ich eh keine Mehrbyteabfrage mache
->in wie weit unterscheidet sich das von deiner eingabe?

Prinzipiell bin ich damit schon zufrieden!
Ich verstehe jetzt was er macht und wieso er es macht!

Viele Danke!


----------



## Thomas_v2.1 (3 Juli 2020)

static_cast ist C++ Stil, das hat gegenüber den C casts den Vorteil von besseren Prüfungen schon während des Übersetzens.


----------



## Hirschfy (3 Juli 2020)

Is ja interessant!

Ich hab in der Uni definitiv C++ gelernt. Da wurde mit meiner Methode gecastet. Das man sowas nicht wenigstens mal Konsistent in einer Sprache macht :roll:


----------



## Thomas_v2.1 (3 Juli 2020)

Wenn man durchgängig C++ programmiert, und nicht einen C++ fähigen Compiler verwendet um C Code zu übersetzen, dann sollte man die nicht nur die casts von C++ verwenden. Von der Funktionalität ist es hier das gleiche, aber du verschenkst damit eben viele Möglichkeiten Programmierfehler schon während des Übersetzens zu erkennen. Aber ich habe auch C++ Bücher in denen das nicht durchgängig gemacht wird, und viele Dinge noch in C Manier programmiert werden.


----------



## Hirschfy (3 Juli 2020)

Wie gesagt, vielen Dank für die Hilfe!

gilt das Thema jetzt mit der markierung der hilfreichsten Anwort als gelöst?


----------

