Używamy plików cookies (tzw. ciasteczka) by spersonalizować treść i ogłoszenia oraz by analizować ruch na stronie.  W sposób automatyczny dzielimy się informacjami o Twoim użyciu tego portalu z dostawcami ogłoszeń, którzy mogą połączyć te informacje z informacjami, które im udzieliłaś/łeś lub, które sami zebrali. Korzystanie z witryny bez zmiany ustawień dotyczących cookies oznacza, że będą one zamieszczane w Państwa urządzeniu końcowym.  Możecie Państwo dokonać w każdym czasie zmiany ustawień dotyczących cookies zmieniając opcje przeglądarki.

Witam!

Zapraszam do zapoznaniu się z najważniejszymi funkcjami ‘inteligentnego’ systemu, który instalowałem w moim nowo wybudowanym domu. Całość oparta jest o sterownik programowalny PLC firmy WAGO, pozwalała w tym czasie sterować 100 obwodami elektrycznymi i wykonywać zdarzenia inicjowane poprzez 90 wejść cyfrowych.

System jest cały czas rozwijany i usprawniany. Na dziś steruje oświetleniem, roletami, zaworami w rozdzielni c.o., podlewaniem ogrodu, bramą wjazdową, piecem i rekuperatorem.

Zapraszam zainteresowanych do przejrzenia opisu kroków projektowania i wykonania oraz elementów składowych systemu. Miejcie jednak dużo dystansu. Wszystko, co tu znajdziecie jest dziełem finansisty, nie elektryka. Moja przygoda z niezaizolowanymi kablami 220V zaczęła się w dniu zakupu sterownika PLC…

Wizualizacja Image 01 NEW Rolety

Sterowanie głosem (Amazon Echo i Alexa)

Po co zajmować się sterowaniem głosem? Bo się da! Odkąd pojawiły się urządzenia pełniące funkcję asystentów głosowych radzących sobie z interpretacją języka mówionego, wykorzystanie ich w automatyce domowej było tylko kwestią czasu.

Wprowadzenie

Codesys oferuje środowisko programistyczne dla sterowników PLC. Autorzy programu przygotowali dla użytkowników wiele ułatwień pozwalających zaoszczędzić czas… pozostawili jednak wiele ‘rozwiązań specyficznych’, które potrafią spowodować wypadanie włosów z głowy. Oto krótka prezentacja głównych funkcji.

Dlaczego Raspberry Pi

Kryteria wyboru rozwiązania umożliwiającego komunikację pomiędzy PLC a siecią 1-wire były następujące: ma być w miarę tanio. Mój dom działa i wszelka rozbudowa jest motywowana bardziej kaprysem i ciekawością niż potrzebą. Rozwiązania oparte o WIRE-CHIP firmy SolidChip (http://www.solidchip.eu/index.php?menu=24) są sprawdzone i działają poprawnie. Wymagają jednak modułu WIRE-CHIP

Czujniki DS18B20 i rozległa sieć 1-Wire

1wire sensor3Nadszedł czas na przetestowanie tego, co moduły "wzmacniające" sieć 1-wire potrafią.  Zakupiłem sporą paczkę czujników i zabrałem sie do pracy. Jako że montaż czujników w obudowach łączników ściennych miałem już przećwiczony, wszystko poszło całkiem sprawnie.  Oto kilka zdjęć i szczegółów...

Pomiar poziomu cieczy

Tytuł brzmi wspaniale by odwrócić uwagę czytelników od faktu, że chodzi o czujnik poziomu nieczystości w szambie. Zdarzyło mi się całkiem niedawno zapomnieć o konieczności sprawdzenia, czy już nie pora wezwać zaprzyjaźnionego szambelana. O zaniedbaniu dowiedziałem się z nienacka, po wejściu do łazienki w piwnicy, gdzie w obniżeniu podłogi pod prysznicem wdzierała się do domu ciecz, rozsiewając zabójczą woń. Był to piątek wieczór, sytuacja fatalna... Taki ze mnie magik od inteligentnych domów, a mam szambo w łazience.

Pierwsze kroki z RPi i DS18B20

Nic, co opisane jest poniżej nie udałoby się bez pomocy Pawła, dzięki któremu podłączenie, instalacja i kodowanie zajęło 1 wieczór. Przy nim zrozumiałem, czemu 'Windows ogranicza'.  Gdy siada do konsoli linuxa, wyrasta mu dodatkowa para rąk i to z 8 palcami każda.  Paweł - wielkie dzięki za pomoc.

Pierwszym wrażeniem po wypakowaniu RPi z pudełka jest zaskoczenie niewielkim rozmiarem.  Komputer ten jest niewiele większy od karty kredytowej.  To naprawdę mało, jeśli przyłoży się do tego wielkość oczekiwań odnośnie funkcji :)

Aby zacząć pracę trzeba:

1. Włożyć kartę SD z obrazem systemu operacyjnego.  Na stronie http://www.raspberrypi.org/downloads znaleźć można najnowszą kompilację Raspbiana (system oparty o Debianie przygotowany do możliwości RPi).  Plik zip trzeba rozpakować i przy pomocy programu Win32DiskImager przenieść na kartę SD.  W moim wypadku była to karta o pojemności 8GB wciśnięta w odpowiednie czytnika w laptopie.  Całość trwała około 15 min.

Win32DiskImager

Źródło: https://wiki.ubuntu.com/Win32DiskImager

2. Wetknąć skrętkę w gniazdo Ethernet i podłączyć ją do switcha.

3. Podłączyć zasilanie - kabel z końcówką microUSB.

Wszystkie powyższe kroki dość szczegółowo i przejrzyście opisane są w instrukcji Getting Started dostępnej na stronach fundacji Raspberry.

Jako że nie posiadam telewizora/monitora z wtyczką hdmi, od samego początku wszelkie czynności na moim RPi wykonywane były przez terminal uruchomiony na laptopie.  Konieczne było znalezienie numeru IP RPi.  Po zalogowaniu do Routera, działającego pod Tomato 1.27, wybraniu Device List, pojawia się lista:

DeviceListTomato

Następnie w Putty trzeba wpisać nr IP: 192.168.1.164 i w Window, Translation, Remote character set wpisać UTF-8.  Sesję można zapisać na potem.  Przycisk OPEN rozpoczyna komunikację z Raspberry Pi.  Login to pi, hasło to raspberry.  Oto rozmawiamy z małym komputerem!

PuttyScreen PuttyScreen2

Aby zobaczyć menu konfiguracyjne, które pojawiłoby się na monitorze (gdyby takowy był podłączony), należy wpisać "sudo raspi-config".

raspi-config

Na ten moment wystarczy uruchomić 'expand_rootfs' aby rozszerzyć partycję na cały obszar karty SD oraz 'change_timezone' by dostosować czas.  Resztę można pozostawić nietknięte.

W międzyczasie jedna uwaga odnośnie komendy 'sudo', którą rozumiem jako 'wykonaj jako super user'.  Może to będą herezje, ale wg mnie nonsensem jest wpisywanie wszystkiego przez sudo.  Sudo i sudo, w każdym tutorialu sudo.  Aby móc wpisywać komendy bez tego sudo, trzeba przyjąć rolę super usera, czyli wykonać 2 kroki:

"sudo passwd" - czyli komenda do zmienienia hasła superusear (roota).  Podać na ten moment można banalne hasło jak pojedyncza spacja, czy litera 'x'.

"su" - czyli komenda, która pozwala przyjąć rolę superusera.  Po wprowadzeniu ustalonego chwilę wcześniej hasła pracować będziemy jako root, czyli darować można sobie wszystkie 'sudo' na początku komend.  Pamiętać trzeba jednak tylko, by po okresie grzebania, zmienić hasło roota na coś trudniejszego...

Teraz czas na podłączenie czujników.  Na adafruit zamieszczony jest bardzo szczegółowy opis co i jak.  Poniższe rysunki pozwolą zapewne rozwiać wszelkie wątpliwości:

sensor connection1 sensor connection2 sensor connection3

W moim wypadku podłączenie wyglądało następująco:

IMAG0424

IMAG0427

 

Czyli 4 czujniki DS18B20 i w związku z brakiem oczekiwanego opornika 4,7K są 2 oporniki 9K połączone równolegle.

Teraz czas na komendy.  W konsoli (Putty) wpisujemy:

modprobe w1-gpio

modprobe w1-therm

co uruchamia procesy odpowiedzialne za wykrywanie czujników.  Aby sprawdzić działanie można wpisać

cd /sys/bus/w1/devices
ls

czyli zmienić katalog na /sys/bus/w1/devices, gdzie 'zamontowane' są wszystkie wykryte czujniki i huby i wyświetlić zawartość tego katalogu.

W moim wypadku pojawia się:

root@raspberrypi:/sys/bus/w1/devices# ls
28-00000067a748 28-00000067ba5a 28-000002ff861f 28-000002fg961f w1_bus_master1

Ok, jeśli widzicie powyższe, znaczy to, że Raspberry Pi gotowe jest do odczytywania temperatur.  Aby jednak dane te dostępne były dla PLC przez zapytania POST/GET, konieczne jest uruchomienie na RPi serwera www z obsługą PHP.  Zainteresowanym polecam Googla (Raspberry Pi webserver PHP); szukający skrótów mogą wpisać komendę:

apt-get install php5

która powinna zainstalować i uruchomić wszystko.  Aby sprawdzić skuteczność powyższego, w przeglądarce internetowej wpisać należy adres Waszego RPi (w moim wypadku http://192.168.1.164/), by zobaczyć komunikat Apache:

apacheWroks 

Wszelki 'content', czyli pliki do wyświetlania, należy umieścić w /var/www.  Na potrzebę pierwszego prostego przykładu umieścić tam należy 2 pliki:

1. test.php

<?php
require_once('OWireTherm.class.php');

error_reporting(E_ALL);
ini_set('display_errors', '1');

$SlaveFile = file("/sys/bus/w1/devices/w1_bus_master1/w1_master_slaves");

if (!$SlaveFile) {
	echo "ERROR with slave-list file";
}
else {
	foreach ($SlaveFile as $line){
		$t1 = new OWireTherm(trim($line));
		if (($temp = $t1->readTemp()) !== false){
			echo $temp.";";
		} else {
			echo "ERROR";
		}
	}
}

2. OWireTherm.class.php (napisany przez Pawła w 3 minuty)

<?php
class OWireTherm {
	protected $id;

	public function __construct($id) {
		$this->id = $id;
	}

	protected function openFile() {
		return fopen("/sys/bus/w1/devices/$this->id/w1_slave", 'r');
	}

	public function readTemp() {
		$fp = $this->openFile();
		if (!$fp) {
			echo "Nie moge otworzyc pliku dla $this->id";
		return false;
	}

	$buff = fgets($fp);
	if (!preg_match('/YES$/', $buff)) {
		echo "Bledna suma CRC podczas odczytu";
		return false;
	}

	$buff = fgets($fp);
	if (!preg_match('/t=(-?[0-9]+)$/', $buff, $matches)) {
		echo "Niepoprawny odczyt temperatury ($buff)"; 
		return false;
	}

	return $matches[1]/1000;
	}
}

Jeśli oba pliki (test.php i OWireTherm.class.php) znajdą się w /var/www, po wpisaniu w przeglądarkę http://192.168.1.164/test.php, pojawią się odczyty temperatur ze wszystkich czujników oddzielone średnikami (np. 14.875;14.75;14.437;).... Dane te zaraz będziemy czytać przez PLC.

Po stronie PLC korzystam z biblioteki WagoLibHttp_02.lib, do działania której potrzebna jest też WagoLibBase64_01.lib. Obie biblioteki można pobrać ze strony WAGO wraz ze szczegółowymi przykładami zastosowania. Polecam w szczególności owe przykłady, gdyż jasno pokazują co (i jak wiele) jest możliwe.

W moim programie stworzyłem nowy proces (Resources->Task configuration, prawy klawisz w nowym oknie i Append Task), któremu nadałem niski priorytet i ustawiłem typ na „freewheeling”. Do nowego procesu dodałem wywołanie programu HttpComm(). Program ten oparty jest w 95% na Przykładzie nr 1 dostarczonym razem z biblioteką Http_02. Oto kod:

- w części definicji zmiennych

PROGRAM HttpComm
VAR
	xDoIt : BOOL; (*to initiate communication*)
	wState : WORD; (*storing the communication status*)
	
	(* HTTP_GET *)
	oHttpGet: HTTP_GET; (*the main function block*)
	sUrl : STRING(250):= '/test.php'; 
	xHttpSend : BOOL;
	diError : DINT;
	sStatus : STRING;
	abResponse : ARRAY [0..MAX_RECEIVE_TCP_CLIENT] OF BYTE;
	uiResponse : UINT;
	
	(* Parsing response data *)
	sTemperature : STRING;
	Temperatues : ARRAY [0..15] OF REAL; (*for storing received temperatures*)
	
	(* Helpers *)
	i : INT;
	TempCount : INT;
	iHelp : INT;
	abHelp : ARRAY [0..180] OF BYTE;
	psHelp : POINTER TO STRING(180);
END_VAR

W programie:

oHttpGet(sServerName:= '192.168.1.164',
	wServerPort:= 80,
	pabUrlData:= ADR(sUrl),
	uiUrlLength:= LEN(sUrl),
	tTimeOut:= t#3s,
	xSend:= xHttpSend,
	diError=> diError,
	sStatus=> sStatus,
	abContentData=> abResponse,
	uiContentLength=> uiResponse);

CASE wState OF
	0: (* IDLE - wait for something to do *)
		IF xDoIt THEN
			xHttpSend := TRUE; (* Send HTTP-GET request *)
			wState := 10;
		END_IF

	10: (* Wait for HTTP-GET response data *)
		IF NOT xHttpSend THEN
			IF diError = 0 THEN
			(* Success *)
				wState := 20; (* Parse response data *)
			ELSE
			(* Error *)
				wState := 999; (* Try again next time *)
			END_IF
		END_IF

	20: (* Parse response data for 'Temperature:'*)
		i:=0; (*Counter of fields in adResponse array*)
		TempCount:=0; (*Counter of found temperatures->fields in Temperatures array*)
		iHelp:=0; (*counter for supportive*)

		WHILE (abResponse[i]>0) DO (*meaning as long as there is data in the adResponse table*)
			IF (abResponse[i]<>59) THEN (*meaning if response char is not = „;”*)
				abHelp[iHelp]:=abResponse[i];
				iHelp:=iHelp+1;
			ELSE (*here is the conversion of data stored in 
				abHelp array to STRING and then to REAL*)
				psHelp := ADR(abHelp);
				sTemperature := psHelp^;
				Temperatues[TempCount]:=STRING_TO_REAL(sTemperature);
				TempCount:=TempCount+1;
				iHelp:=0;
			END_IF
			i:=i+1;
		END_WHILE

		wState := 999;

	999: (* *)
		xDoIt := FALSE;
		wState := 0;
END_CASE

Po stworzeniu prostej wizualizacji z 1 przyciskiem i 4 polami przetestować można działanie programu:

PLC VISU done

 

Komunikacja między PLC a Rpi i odczytywanie temperatur przy zaprezentowanej powyżej konfiguracji i w oparciu o ww. skrypty jest po stokroć ułomna. Serwer Apache w standardowych ustawieniach jest dość powolny i być może wymaga wymiany na inne, lżejsze rozwiązanie. Skrypty – zarówno po stronie serwera, jak i PLC – są zupełnie nieodporne na błędy. Ponadto, co być może najważniejsze, podłączenie czujników 1-wire w sposób tu zaprezentowany nie nadawać się będzie do rozległej struktury mojego domu tj. wielometrowych kabli w układzie gwiazdy prowadzonych blisko przewodów z napięciem 230VAC. Jest to więc jedynie próba uruchomienia pewnej koncepcji.

Jako że testy zakończyły się wstępnym sukcesem, kolejne etapy obejmować będą:

  • budowę rozszerzenia do RPi w oparciu o układy DS2482, który powinien pozwolić obsłużyć dużą sieć, znaczną liczbę czujników (plus dodatkowo dodanie zabezpieczeń przed przepięciami),
  • udoskonalenie konfiguracji samego Rpi i zainstalowanych serwisów, by usunąć to co zbędne i usprawnić to, co pozostanie,
  • poprawę skryptów, by były bezpieczne dla PLC, tj. działały prawidłowo przy wszelkich możliwych do wyobrażenia błędach otrzymanych na zapytanie GET.