Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka DotNetSiemensPlcToolboxLibrary

4

Dzisiaj zajmiemy się trzecią, i jednocześnie ostatnią, z bibliotek które planowałem opisać w tej krótkiej serii. Będzie to DotNetSiemensPlcToolboxLibrary (uff – długa nazwa).

Dla mnie jest to tak naprawdę pierwsza .Net-owa biblioteka do komunikacji ze sterownikami Siemens-a, z którą się zetknąłem po klasycznym libnodave. Pełny kod źródłowy biblioteki znajdziemy tym razem również na github.

Mamu tutaj do czynienia, tak naprawdę, z bardzo rozbudowanym wrapperem na libnodave (w skompilowanym projekcie zawsze znajdziemy dll-kę lekko zmodyfikowanego libnodave).

DotNetSiemensPlcToolbox prezentuje nieco wyższy poziom abstrakcji, niż pozostałe biblioteki, gdzie operowaliśmy zakresami adresów w blokach, a następnie wyłuskiwaliśmy dane z odczytanej tablicy bajtów. Ewentualnie, jak w przypadku s7netplus, odczytywaliśmy pojedynczą zmienną podając jej adres w notacji sterownikowej. W tym przypadku mamy do czynienia z podejściem opartym o tzw. Tag-i. Pojęcie jest to z pewnością doskonale znane każdemu, kto miał do czynienia z systemami SCADA. Tag to nic innego jak po prostu pewna reprezentacja zmiennej, opisana jej adresem, nazwą i czasami różnymi innymi właściwościami.

Operujemy tutaj właśnie na pojedynczych tag-ach, lub na listach tagów. Wykonanie na takiej liście operacji odczytu zwróci nam wartość, wykonanie zaś zapisu ustawi odpowiednią wartość w sterowniku. Służy nam do tego obiekt klasy PLCTag.

W przypadku rzeczonej biblioteki nie jesteśmy niestety rozpieszczani dokumentacją, jak to miało miejsce w przypadku poprzednio opisywanych bibliotek. Za dokumentację musi nam w tym przypadku posłużyć duża liczba różnego rodzaju przykładów, które znajdziemy w repozytorium github.

Bibliotekę zainstalujemy do naszego projektu za pomocą Nuget-a:

Install-Package DotNetProjects.DotNetSiemensPLCToolBoxLibrary

Przy nawiązywaniu połączenia musimy ustawić tym razem więcej parametrów, podobnie jak robilibyśmy to w klasycznym libnodave. Na początek musimy utworzyć obiekt klasy PLCConnectionConfiguration i wypełnić odpowiednie parametry. Nazwy parametrów są bardzo intuicyjne, więc nie będę ich tutaj szczegółowo opisywał:

var cfg = new PLCConnectionConfiguration
{
   CpuIP = ipAddress,
   Port = 102,
   CpuRack = rack,
   CpuSlot = slot,
   TimeoutIPConnect = TimeSpan.FromSeconds(5),
   Timeout = TimeSpan.FromSeconds(5),
   ConnectionType = LibNodaveConnectionTypes.ISO_over_TCP,
   ConnectionName = "S7_Connection",
   Routing = false,
   RoutingDestinationRack = 0,
   RoutingDestinationSlot = 0,
   RoutingDestination = String.Empty
};

Następnie należy wywołać metodę SaveConfiguration obiektu klasy PLCConnectionConfiguration:

cfg.SaveConfiguration();

Do realizacji połączenia wykorzystamy obiekt klasy PLCConnection, któremu jako parametr przekażemy referencję do obiektu zawierającego konfigurację:

_plcConnection = new PLCConnection(cfg);

Połączenie nawiążemy za pomocą metody Connect, a o statusie połączenia poinformuje nas parametr Connected:

_plcConnection.Connect();

if (!_plcConnection.Connected) RaiseError();
else RaiseIsConnected();

Operacje zapisu i odczytu wykonamy wkorzystując metody WriteValue, lub ReadValue obiektu klasy PLCConnection – podając jako parametr pojedynczy obiekt klasy PLCTag. Lub odpowiednio WriteValues i ReadValues, które jako parametr przyjmują listę tagów (obiektów klasy PLCTag).

Obiekt możemy łatwo utworzyć podając jako parametr adres w notacji sterownikowej, oraz typ danych z enum-a TagDataType:

var tag = new PLCTag("DB10.DBX0.0", TagDataType.Bool) { Value = 1 };

W tym przypadku przypisałem też od razu wartość, gdyż jest to tag który chcę zapisać do sterownika.

W przypadku wywołania metody odczytu, zmienna value przyjmie wartość odczytaną ze sterownika, skonwertowaną już odpowiednio bazując na ustawionym podczas tworzenia obiektu typie tagu (enum TagDataType).

Dobrą praktyką jest nie grupowanie zmiennych pochodzących z różnych bloków (różnych przestrzeni pamięci, lub różnych bloków DB). Lepiej pogrupować zmienne z tego samego obszaru – zoptymalizujemy w ten sposób odczyt czy też zapis.

Przykładowy kod tradycyjnie do znalezienia na moim github.

Wszystkie posty w tym cyklu:

Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – wstęp
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – protokół S7 i konfiguracja sterownika
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – projekty testowe
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka s7netplus
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka Sharp7 (Snap7)
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka DotNetSiemensPlcToolboxLibrary

Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka Sharp7 (Snap7)

0

Witam w kolejnej odsłonie cyklu o bibliotekach do komunikacji ze sterownikami PLC Siemens Simatic.

Snap7 jest w chwili obecnej najbardziej znaną biblioteką do komunikacji ze sterownikami Siemens-a. Biblioteka ta wspiera (w różnych wersjach) wiele platform i wiele języków programowania. Znajdziemy więc porty dla C#, Javy, Pythona, Node.js itp. Istnieje nawet wersja dla systemów IoT i Arduino. Co ważne, wersje dedykowane w większości przypadków są napisane od zera w natywnej technologii (np. Settimino dla Arduino jest napisane wprost w Arduino C).

W tym poście zajmiemy się portem Snap7 w C# o nazwie Sharp7.

Jest to rozwiązanie bardzo fajne z kliku względów:
  • cała biblioteka to jeden plik .cs – bez żadnych dodatkowych zależności
  • działa zarówno z .Net jak i z Mono
  • jest kompatybilna z UWP.
  • działa również z Win 10 IoT
„Instalacji” tym razem nie przeprowadzimy za pomocą nuget-a. Wszystko co musimy zrobić to pobrać archiwum a następnie plik z biblioteką i dołączyć do naszego projektu.
Warto zwrócić tutaj jednak uwagę na kwestie licencjonowania. Wszystkie porty Snap7 oparte są na licencji LGPLv3. Jeżeli tworzymy więc oprogramowanie o otwartym źródle, lub oddajemy po prostu kod źródłowy klientowi to nie ma w zasadzie ma żadnego problemu. Natomiast tworząc rozwiązanie komercyjne o zamkniętym źródle warto zadbać o spełnienie wszystkich warunków licencji.

Jako że Sharp7 jest w 100% tożsamy z Snap7 mamy dostępną bardzo dobrą dokumentację do tej biblioteki. Wewnątrz pobranego archiwum z biblioteką znajdziemy obszerną dokumentację w pdf. Dokładnie tak jak w przypadku omawianej ostatnio s7netplus. W archiwum znajdziemy również sporo przykładów.

Podobnie, jak w przypadku poprzedniej biblioteki, za pomocą Sharp7 połączymy się bez problemu z całą gamą sterowników Simatic. Pamiętać należy jednak o właściwej parametryzacji Hardware sterownika, o której wspominałem w tym poście.

Nawiążmy więc połączenie ze sterownikiem. Metoda nawiązująca połączenie będzie bardzo podobna jak metoda dla opisywanego wcześniej s7netplus:
Zaczniemy od stworzenia obiektu klasy S7Client (w moim kodzie jest to zmienna prywatna w klasie odpowiedzialnej za komunikację)
_s7Plc = new S7Client();

Teraz nawiążemy połączenie:

var result = _s7Plc.ConnectTo(IpAddress, Rack, Slot);

Metoda ConnectTo zwróci nam liczbę całkowitą (int). W przypadku poprawnego połączenia powinniśmy otrzymać wartość 0. Jeżeli pojawi się kod błędu, to łatwo go rozszyfrujemy (np. aby zwrócić wyjątek z odpowiednim opisem) za pomocą metody ErrorText:

string message = = _s7Plc.ErrorText(result);

W Sharp7 najwygodniej realizuje się zapis i odczyt za pomocą metod operujących na tablicach bajtów (Dane w pamięci sterownika to przecież tak naprawdę taka tablica).

Dane z bloku DB przeczytamy za pomocą metody DBRead, zapiszemy zaś za pomocą DBWrite. W obu tych przypadkach metody te (podobnie jak metoda ConnectTo) zwracają nam liczbę całkowitą reprezentującą kod błędu, który w przypadku wartości innej niż 0 rozszyfrujemy podobnie jak w przypadku metody nawiązującej połączenie.

Dane przed zapisem do sterownika musimy odpowiednio skonwertować i umieścić w tablicy bajtów do zapisu. Podobnie po wykonaniu odczytu, musimy właściwe dane wyłuskać z tablicy bajtów i skonwertować do właściwego (.Net-owego) formatu.

Na szczęście w przestrzeni nazw S7 mamy szereg metod, które ułatwią nam mocno to zadanie.

Konwersja do formatu sterownika realizowana jest przez metody o nazwach Set[typ_zmiennej]At. I tutaj jako parametr podamy referencję do tabeli bajtów, która będziemy zapisywać, pozycję pierwszego bajtu w tabeli, oraz wartośc. Metoda uzupełni nam tabelę bajtów od wskazanego miejsca o odpowiednią ilość bajtów zawierających skonwertowaną wartość.

S7.SetIntAt(outBuffer, 0, (short)value);

Konwersja w drugą stronę realizowana jest przez metody o nazwach Get[typ_zmiennej]At. I tutaj jako parametr podamy referencję do tabeli z bajtami odczytanymi ze sterownika oraz numer bajtu, od którego zaczyna się nasza zmienna. Metoda zwróci nam już skonwertowaną wartość:

var value = S7.GetIntAt(_inBuffer, 0);

Listę dostępnych metod konwertujących znajdziemy w dokumentacji, albo wprost w kodzie źródłowym w pliku Sharp7.cs

Przykładowy kod z wykorzystaniem Sharp7 znajduje się oczywiście w mojej aplikacji testowej dostępnej na github.

Od siebie dodam tylko, że Sharp7 jest moją ulubioną biblioteką. Jest bardzo lekka. W projekcie mamy kod źródłowy, łatwo jest więc debugować ewentualne problemy. Ponieważ jest napisana w całości w C# może posłużyć jako fajny materiał do poznania komunikacji ze sterownikiem „od kuchni”. Nie robiłem nigdy co prawda porównań wydajnościowych pomiędzy bibliotekami, ale moje subiektywne wrażenie jest takie, że Sharp7 jest najszybszy z dostępnych obecnie rozwiązań.

Wszystkie posty w tym cyklu:

Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – wstęp
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – protokół S7 i konfiguracja sterownika
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – projekty testowe
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka s7netplus
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka Sharp7 (Snap7)
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka DotNetSiemensPlcToolboxLibrary

Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka s7netplus

2

Na początek krótki wstęp historyczny. Pierwszą bibliotekę oferującą dostęp z własnej aplikacji do zasobów sterownika oferował sam Siemens. Biblioteka ta nazywała się PRODAVE i była rozwijana tak naprawdę do 2012 roku, kiedy to pojawiła się jej ostatnia wersja 6.2 oferująca kompatybilność z Windows 7. Był to oczywiście produkt płatny z zamkniętym źródłem.

Najstarszym rozwiązaniem open source istniejącym do dzisiaj jest biblioteka libnodave (jak widać nawiązująca sprytnie nazwą do wspomnianego Prodave). Biblioteka jest napisana w C i można ją znaleźć na sourceforge lub github

O libnodave wspominam celowo, gdyż przetarła ona szlaki dla kolejnych rozwiązań, które są dzisiaj aktywnie rozwijane. Oczywiście można się pokusić o korzystanie z czystego libnodave w aplikacji .Net przez mechanizm pozwalający na korzystanie z bibliotek niezarządzanych lub skorzystać z przygotowanego wrappera, ale chyba nie warto tego robić gdy istnieją wygodniejsze rozwiązania.

Długo zastanawiałem się od jakiej biblioteki zacząć i zdecydowałem się wybrać s7netplus . Biblioteka jest wciąż utrzymywana i aktualizowana – poza jej autorem posiada również kilku kontrybutorów. Jest ona całkiem wygodna i dość bezproblemowa w wykorzystaniu. Bez pro blemu połaczymy się za jej pomocą ze sterownikami S7-200, S7-300, S7-400, S7-1200 oraz S7-1500. Działa również z zyskującym ostatnimi czasy na popularności SoftPlc.

Do dyspozycji otrzymujemy również bardzo fajny manual (dostępny tutaj). Dokumentacja jest na tyle dobra, że posiadając jakąkolwiek wiedzę na temat architektury przechowywania danych w sterowniku Simatic S7 bez problemu zrozumiemy jak korzystać z udostępnionych funkcji.

Bibliotekę do naszego projektu możemy zaimportować korzystając z nuget-a.

PM> Install-Package S7netplus

Algorytm komunikacji ze sterownikiem można opisać bardzo prosto:

  1. Nawiąż połączenie
  2. Odczytaj/Zapisz dane
  3. Zamknij połączenie

Oczywiście jeżeli nasza aplikacja wykonuje odczyt lub zapis cyklicznie, to operacji nawiązywania i zamykania połączenia nie musimy wykonywać, a nawet nie powinniśmy, za każdym razem. Warto jednak wtedy odpowiednio monitorować stan połączenia (w przypadku opisywanej biblioteki obiekt realizujący komunikację posiada właściwość IsAvaiable, która sprawdza jego dostępność w sieci oraz IsConnected, która informuje o stanie połączenia). W razie jego zerwania (np. przez rozłączenie z siecią) możemy wtedy nawiązać połączenie ponownie.

Ja w przypadku konieczności odczytu/zapisu cyklicznego używam zwykle timer-a z przestrzeni System.Timers, który realizuje komunikację, w momencie zaś odebrania paczki danych wystawia zdarzenie informujące o tym fakcie (przykład w kodzie źródłowym na github).

Dlaczego timer a nie np. wątek ? Ponieważ należy pamiętać o tym, że bez względu na to, czy komunikacja realizowana jest przez fizyczny port ethernetowy w CPU sterownika czy też przez procesor komunikacyjny to i tak CPU realizuje większość funkcji komunikacyjnych. Realizując komunikację przez wątek i nie stosując opóźnień obciążamy mocno CPU i w przypadku słabszych modeli może się okazać, że jest duży problem z dodatkowym połączeniem się za pomocą np. programatora.

Warto też pamiętać o tym, że cała komunikacja odbywa się na jednym porcie (w przypadku sterowników S7 jest to zawsze port 102) i nie jest wielowątkowa. Jeżeli realizujemy cykliczny odczyt realizowany w wątku (czy też timera realizowanego jako wątek), to w momencie incydentalnego zapisu (np. w reakcji na wciśnięcie przycisku na formie) należy zadbać o to, aby zapis nie był realizowany w tym samym czasie co odczyt. Do tego celu można oczywiście dowolnego mechanizmu kontroli wątków. Ja zwykle używam do tego najprostszego mechanizmu lock.

Zdefiniujmy więc obiekt klasy Plc i przypiszmy parametry naszego połączenia:

_s7Plc = new Plc(CpuType.S71200, IpAddress, (short)rack, (short)slot);

Myślę, że nie trzeba tu wiele tłumaczyć. O rack i slot wspominałem już w poprzednim poście.

następnie nawiązujemy połączenie:

var result = _s7Plc.Open();

W zmiennej result otrzymamy informację zwrotną odnośnie wyniku. Jest to enum ErrorCode, opisany dokładnie we wspomnianym wcześniej manualu. Oczywiście chcemy otrzymać tutaj NoError potwierdzający poprawność połączenia.

Dane ze sterownika odczytamy za pomocą metody Read a zapiszemy za pomocą metody Write. Metoda ta posiada przeciążenie i możemy zarówno przeczytać lub zapisać pojedynczą zmienną korzystając z adresowania sterownikowego (np. DB10.DBW0) lub przeczytać czy też zapisać konkretną ilość bajtów z pożądanej przestrzeni.

Jeżeli czytamy większą ilość zmiennych rozsianych po całym bloku, to zdecydowanie lepiej przeczytać większą ilość danych a następnie wyłuskać je z otrzymanej tablicy bajtów, niż realizować wiele mniejszych odczytów. Zyska na tym szybkość i optymalność komunikacji. W przypadku biblioteki S7netplus mamy w zanadrzu świetny mechanizm „mapowania” bloku na strukturę lub klasę, o którym wspominam w dalszej części postu.

WAŻNA UWAGA. Jeżeli zdarzy się sytuacja, w której uda się poprawnie nawiązać połączenie a odczyt jednak nie będzie działał poprawnie to warto sprawdzić czy w konfiguracji hardware sterownika włączona jest funkcja zezwalająca na realizację komunikacji PUT/GET.
Metodę parametryzacji sterownika opisałem w tym poście

W przypadku wykorzystania metody Read w jej uproszczonej wersji, w której zapisujemy format zmiennej w zapisie sterownikowym otrzymamy od razu odpowiednią wartość. Jeżeli czytamy większą ilość danych i otrzymamy tablicę bajtów należy zadbać o konwersję formatów. Dane w sterowniku S7 (ze względu na historyczne zaszłości) przechowywane są w notacji BigEndian, natomiast w przypadku architektury komputerów PC mamy do czynienia z notacją LittleEndian.

Konwersji na szczęście nie musimy robić na piechotę. Z pomocą przyjdą nam metody rozszerzone zdefiniowane w bibliotece. Przykłady konwersji znajdziemy w manualu, o którym wspomniałem powyżej.

Po zakończeniu realizacji komunikacji (w przypadku komunikacji cyklicznej np. w momencie zamknięcia aplikacji) należy koniecznie zamknąć połączenie. W przypadku opisywanej biblioteki zrobimy to łatwo za pomocą metody Close();

Warto pamiętać, że jeżeli nie zamkniemy poprawnie połączenia i będziemy go nawiązywać ponownie – to oczywiście uda się nam to zrobić – jednak nie w nieskończoność. Otwarte połączenia będą nadal widziane przez sterownik jako istniejącej i po przekroczeniu liczby dozwolonych jednocześnie połączeń (zwykle 8-miu) sterownik odmówi nam nawiązania kolejnego połączenia. Oczywiście mowa tu o próbach połączenia w trakcie działania aplikacji. Zamknięcie aplikacji (a więc i zwolnienie zasobów zajmowanych przez bibliotekę) resetuje nawiązane połączenia.

Jest jeszcze jedna fajna cecha, o której warto wspomnieć w odniesieniu do tej biblioteki. Istnieją funkcje pozwalające na zapis/odczyt struktur i klas. Układamy wtedy w naszej klasie zmienne dokładnie według takiej kolejności jak mamy je zdefiniowane w bloku DB w sterowniku. Trzeba jedynie pamiętać o tym, aby skrupulatnie dobrać właściwe typy dla danych odwzorowujące zmienne w bloku. Wtedy możemy odczytywać/ zapisywać całą strukturę lub klasę za pomocą jednej metody. W przypadku odczytu otrzymamy również już skonwertowane wartości, które możemy dalej wykorzystywać. Dokładny opis tego rozwiązania znajduje się w manualu, o którym wspomniałem powyżej. Simple as that 🙂

Kod aplikacji do przetestowania jest oczywiście dostępny na github.

Wszystkie posty w tym cyklu:

Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – wstęp
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – protokół S7 i konfiguracja sterownika
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – projekty testowe
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka s7netplus
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka Sharp7 (Snap7)
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka DotNetSiemensPlcToolboxLibrary

Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – projekty testowe

1

Witaj w kolejnej części cyklu o bibliotekach .Net do komunikacji ze sterownikami Siemensa.

Moim zdaniem najlepiej uczyć się nowych rozwiązań za pomocą działających przykładów. W związku z tym, zamiast prezentować „na sucho” działanie bibliotek zdecydowałem się przygotować trochę kodu, który pozwoli je przetestować w praktyce. W związku z tym przygotowałem projekt prostego programu dla sterownika oraz szkic prostej aplikacji WinForms, która posłuży nam do testów.

Program sterownika przygotowany jest dla PLC S7-1200 w środowisku TIA Portal V14 SP1. Zdecydowałem się na takie rozwiązanie, ponieważ jest to najpopularniejsza seria przystępnych cenowo sterowników oferowanych przez Siemens-a. Projekt taki bardzo łatwo można przekształcić też na projekt dla sterownika S7-1500. Nie mam w tej chwili niestety dostępu do najprostszego sterownika LOGO!, który jest programowany za pomocą innego narzędzia.

Powstaje w ten sposób pewne ograniczenie, które wymaga posiadania sterownika do przetestowania komunikacji, ale zakładam że osoby zainteresowane tym cyklem postów czytają go raczej z założeniem, że taką komunikację będą wcześniej czy później realizować – a więc posiadają samo urządzenie.

Sterownik S7-1200 można kupić stosunkowo niedrogo w formie zestawu startowego np. w sklepie Kamami

Do załadowania programu w zupełności wystarczy wersja Trial oprogramowania TIA Portal.

PROGRAM STEROWNIKA

Do wglądu/pobrania z https://github.com/pstrejczek/PlcNetLibrariesS7TestProject

W projekcie wykorzystałem samo CPU 1212 w wersji AC/DC/RLY (zasilane z 230V). W przypadku wykorzystania innego sterownika trzeba dokonać podmiany w konfiguracji hardware projektu.

Trzeba również przypisać odpowiedni adres IP, aby sterownik był dostępny w sieci w której chcemy się z nim komunikować.

Sam program jest bardzo prosty. W bloku danych DB10 znajdują się parametry, które będziemy wymieniać ze sterownikiem.

Program inkrementuje licznik przechowywany w zmiennej CurrentValue aż do osiągnięcia wartości SetPoint a następnie resetuje się do wartości 0. Ustawienie bitu Start spowoduje rozpoczęcie odliczania, natomiast ustawienie bitu Stop powoduje zakończenie odliczania i wyzerowanie CurrentValue. Zmienna ProcessInProgress będzie nas informować czy proces odliczania trwa, czy też nie.

APLIKACJA .NET

Znajduje się na github: https://github.com/pstrejczek/PlcNetLibraries

To będzie prosta aplikacja w Windows Forms, która zapewni nam podstawowe GUI pozwalające testować komunikację. Warstwę komunikacyjną bazującą na różnych bibliotekach będziemy podłączać w formie bibliotek dll. Wydaje mi się, że takie rozwiązanie będzie tutaj najlepsze. Póki co, repozytorium zawiera jedynie wstępny szkic, który będzie rozwijany wraz z opisami kolejnych bibliotek.

W następnej części zajmiemy się (nareszcie 🙂 ) konkretnie pierwszą z bibliotek.

Wszystkie posty w tym cyklu:

Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – wstęp
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – protokół S7 i konfiguracja sterownika
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – projekty testowe
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka s7netplus
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka Sharp7 (Snap7)
Biblioteki .Net do komunikacji ze sterownikami PLC Siemens – biblioteka DotNetSiemensPlcToolboxLibrary

Programistów historie prawdziwe

0

Dzisiaj zapraszam na zaprzyjaźnionego bloga stormit.pl.

Tomek Woliński, który prowadzi tego bloga wyszedł z bardzo ciekawą inicjatywą przeprowadzenia „wywiadu” z grupą wybranych programistów na tematy związane z początkami i rozwojem programistycznej kariery.

Ja również miałem przyjemność wziąć udział w tym przedsięwzięciu i na zaproszenie Tomka podzieliłem się swoją historią i przemyśleniami.

Materiału jest bardzo dużo, został więc podzielony na części.

W chwili obecnej możemy przeczytać o:

Początkach w branży IT

Skąd wziął się pomysł, by zostać programistą.

Kolejne części pojawią się wkrótce.

Serdecznie polecam lekturę tych wpisów. Z założenia mają one być kierowane do osób zastanawiających się nad rozpoczęciem pracy jako junior developer, ale muszę przyznać że ja sam czytałem wypowiedzi innych z niekłamanym zainteresowaniem i z niecierpliwością czekam na kolejne części.