Pomiar zużycia gazu przez Raspberry Pi i eBUS

Pierwszy sezon grzewczy z nowym kotłem gazowym powoli dobiega końca. O kosztach ogrzewania pisałem ostatnio i obiecałem opowiedzieć, skąd wiem, ile gazu zużywa kocioł i w jaki sposób to badam. Techniczne aspekty łączenia kotła z Raspberry Pi i odczytu parametrów jego pracy, były już poruszane na blogu. Dzisiaj skupimy się wyłącznie na rejestracji zużycia gazu przez kocioł Vaillant.

Poszukiwanie drogi

Jak już wiecie, do odczytu danych kotła używam programu ebusctl z pakeitu ebusd . Przeglądając listę dostępnych parametrów i szukając jakiegoś punktu zaczepienia do pomiaru zużycia gazu, zwróciłem uwagę na cztery z nich: PrEnergySumHc1, PrEnergyCountHc1, PrEnergySumHwc1 i PrEnergyCountHwc1. Patrząc na nazwy łatwo się zorientować, że Hc odnosi się do centralnego ogrzewania, a Hwc do ogrzewania wody. Ponieważ obserwacje zaczynałem tuż przed sezonem grzewczym, prosto było zaobserwować, że rosną wyłącznie liczniki Hwc. Notowanie wartości i wskazań licznika doprowadziło mnie to stwierdzenia, że warto skupić się na wskaźnikach PrEnergySum i był to strzał w dziesiątkę.

Zbieranie danych

Uznałem, że najlepszą drogą do dalszych analiz będzie zbieranie danych. Postawiłem wszystkie 4 wskaźniki zapisywać co godzinę w dwóch miejscach - w logu tekstowym i w bazie rrd, na potrzeby przejrzystych wykresów. Do pobierania danych służy prosta funkcja w PHP:

function getregister( $reg )
{
 global $ip;
 exec("/usr/bin/ebusctl -s $ip read -m 30 $reg", $output, $retcode);

 if($retcode==0 && substr($output[0],0,3)!="ERR" && substr($output[0],0,3)!="err" ) return($output[0]);
   else return("error");
}

Ebusctl łączy się w tym wypadku z drugim Raspberry Pi, na którym chodzi ebusd. Oczywiście wszystko może działać na jednym systemie, ale u mnie tak jest wygodniej. Za zapisywanie danych odpowiada natomiast taki fragment kodu:

if( date("i")=="00" )
{
  $prenergysumhc1=getregister("PrEnergySumHc1");
  $prenergycounterhc1=getregister("PrEnergyCountHc1");
  $prenergysumhwc1=getregister("PrEnergySumHwc1");
  $prenergycounterhwc1=getregister("PrEnergyCountHwc1");
  exec("echo ".date("Y-m-d H")."\;".$prenergysumhc1."\;".$prenergysumhwc1."\;".$prenergycounterhc1."\;".$prenergycounterhwc1." >> $counterlog");

  exec("/usr/bin/rrdtool update $rrdcounterfile ".time().":$prenergysumhc1:$prenergycounterhc1:$prenergysumhwc1:$prenergycounterhwc1", $eoutput, $ecode);
  if( $ecode>0 ) { echo "RRD update problem ($rrdpcounterfile)\n"; print_r($eoutput); }
}

Banalnie proste, prawda? Jako wynik, w pliku o nazwie przechowywanej w zmiennej $counterlog, pojawia się kolejna linia z odczytanymi wartościami liczników i aktualnym czasem (data i pełna godzina). Dane dodawane są też do bazy rrd $rrdcounterfile. Być może gromadzenie danych co godzinę na dłuższą metę nie jest konieczne,  ale plik csv z danymi, to po pół roku zajmuje on 200kB, więc pomijalnie mało, jak na dzisiejsze standardy.

Kalibracja

Liczniki kotła to jedno, a licznik gazu od gazowni, to drugie. Skoro już mamy odczyty, to należałoby je jakoś powiązać. W tym celu stworzyłem prosty mechanizm, który pozwala mi podać aktualny stan licznika gazu i zapisuje w pliku csv aktualny czas, timestamp, podany przeze mnie stan licznika (przemnożony przez 1000, żeby pozbyć się przecinka) oraz pobrane cztery, opisane wyżej wartości rejestrów kotła. Następnie sprawdzam o ile przyrosły od pierwszego odczytu wartości PrEnergySumHc1 i PrEnergySumHwc1, a o ile fizyczny licznik gazu. Na tej podstawie wyliczam stosunek między sumą przyrostów parametrów PrEnergySum a fizycznym licznikiem gazu. Wynosi on w moim przypadku 976.171242912. Od czego zależy? Od egzemplarza? Stabilności jakości gazu? Nie wiem, ale działa to dużo dokładniej, niż się spodziewałem.

Skrypt do kalibracji i przewidywania aktualnego stanu licznika jest prosty. Odczytuje on aktualne rejestry wprost z kotła, sprawdza wszystkie wpisy w pliku kalibracyjnym, podając kolejne wartości w celach diagnostycznych, a następnie wylicza aktualny stan licznika, na podstawie pobranego odczytu.

#!/usr/bin/php5
<?php

$ip="192.168.1.32"; //zdalny ebus
$log='/mojdom/licznik-gazu.log'; //plik kalibracyjny

// pobieranie rejestrów przez ebusctl
function getregister( $reg )
{
  global $ip;
  exec("/usr/bin/ebusctl -s $ip read -m 30 $reg", $output, $retcode);
  if($retcode==0 && substr($output[0],0,3)!="ERR" && substr($output[0],0,3)!="err" ) return($output[0]);
  else return("error");
}

//pobranie danych z kotła przez eBUS
$prenergysumhc1=getregister("PrEnergySumHc1");
$prenergysumhwc1=getregister("PrEnergySumHwc1");

$lines=file($log);

if( sizeof($lines)>1 )
{
  for( $w=0; $w<sizeof($lines); $w++ ) $pola[$w]=split(";",$lines[$w]);

  for( $w=1; $w<sizeof($lines); $w++ )
  {
    $czas=($pola[$w][1]-$pola[0][1]);
    $licznik=($pola[$w][2]-$pola[0][2]);
    $energyhw=($pola[$w][3]-$pola[0][3]);
    $energyhwc=($pola[$w][4]-$pola[0][4]);
    $kalibracja=($energyhw+$energyhwc)/$licznik;
    echo "Czas: ".$czas."\n";
    echo "Licznik: ".($licznik/1000)."\n";
    echo "Energy: ".($energyhw+$energyhwc)."\n";
    echo "Kalibracja: ".$kalibracja."\n";
    echo "\n";

    $ostlicznik=($pola[$w][2]);
    $ostsuma=($pola[$w][3]+$pola[$w][4]);
  }
}

$aktsuma=$prenergysumhc1+$prenergysumhwc1;
$aktlicznik=($ostlicznik+($aktsuma-$ostsuma)/$kalibracja)/1000;

echo "\n\nAktualny stan licznika: ".$aktlicznik."\n";
?>

Natomiast plik z danymi do kalibracji, opisany wcześniej, wygląda tak:

2017-10-27 09:39:47;1509089986;126317;43474893;64973467;460045;228077
2017-10-27 11:59:42;1509098381;126515;43661714;64973467;462009;228077
2017-10-28 09:36:14;1509176173;130908;47181835;65703665;500437;230631
2017-10-30 08:17:46;1509347865;139323;53246974;67189283;560202;235624
2017-11-08 08:01:26;1510124485;177775;84520571;72577883;893364;254024
2017-11-16 08:02:54;1510815773;218850;118810371;78203438;1263387;273414
2017-12-07 17:26:22;1512663980;347452;233511542;90820186;2486487;318324
2018-01-06 10:26:59;1515230818;515355;381400712;106815356;4025920;373482

Dokładność

Jak już przy dokładności jesteśmy. Po pierwszych kalibracjach, po kilku godzinach od uruchomienia dokładność była taka sobie - kilka procent błędu. Niby do zorientowania się w trendach wystarczająco, ale liczyłem na więcej. Wystarczyło jednak trochę cierpliwości i jest bardzo dobrze. Po trzech miesiącach od ostatniego odczytu, przewidywana przez skrypt wartość różni się od realnego wskazania licznika o około 0,5m³. Przy różnicy stanów licznika 500m³. To zaledwie 1 promil błędu! Znacznie większy błąd byłby nadal w pełni akceptowalny.

Przy kalibracji warto zwrócić uwagę, że liczniki kotła Vaillant są zwiększane dość skokowo. Nie wiem do końca od czego to zależy, natomiast pewnie najlepiej odczytywać wartości, gdy kocioł jest już pewien czas w spoczynku. Przy dłuższych okresach nie ma to znaczenia, bo nawet godzina czy dwie to niewiele w skali miesiąca, ale pewnie z tego powodu pierwsze pomiary były u mnie obarczone dużym błędem (z kalibracją po kilku lub kilkunastu godzinach). Warto też zwrócić uwagę, że u mnie kalibracja jest bardzo prosta - kocioł gazowy jest jedynym odbiornikiem gazu. W przypadku posiadania kuchenki gazowej, nie byłoby już tak  łatwo.

Wykresy zużycia gazu

Dzięki rrdtool możemy dodatkowo rysować wykresy zużycia gazu. Osobiście lubię wykresy, bo pozwalają szybko zorientować się w sytuacji i trendach.

Po co to wszystko?

Przede wszystkim bo jestem ciekawy i lubię wiedzieć. Poza tym dla oszczędności - robiąc cokolwiek, żeby zmniejszyć zużycie gazu, warto wiedzieć, czy przynosi to jakikolwiek efekt. Nic nie jest pewniejsze niż twarde dane… Bez tego nawet dyskusje typu “czy warto obniżać temperaturę w domu przy nieobecności” mają mały sens, gdy swojego zdania nie można poprzeć dowodami. Nie bez znaczenia jest też fakt, że dzięki wykresom, od razu widać, gdy ze zużyciem gazu dzieje się coś niepokojącego. Natomiast proste obliczenia pozwalają od razu zweryfikować wysokość wystawionego rachunku za gaz.

Przykład aktualnych wyliczeń ze strony systemu automatyki domowej:

Ostatni szacowany stan licznika gazu: 1091.273 Zużycie na 24h: 1.888m3 (miesięcznie: 58.558m3 = 155zł) Zużycie na tydzień: 25.711m3 (miesięcznie: 114m3 = 256zł) Zużycie na miesiąc: 167.046m3=352zł Zużycie na dwa miesiące: 374.779m3=778zł

Widać wyraźnie, że mamy ostatnio cieplejsze dni a koniec sezonu grzewczego nadchodzi wielkimi krokami. Optymistyczne.