Watermeter

Je kan ook hier één en ander voor kopen. De basis voor de meeste uitlezers is dat het rode wieltje (dat per liter een rondje draait) een magneetje bevat. Daarmee veranderd het magnetisch veld als je water verbruikt en het wieltje draait. Dat kan je meten met een zogenaamde hall (of nabijheids) sensor die gebruik maakt van het Hall effect. Resultaat is een electrisch signaal dat je kan uitlezen. De meeste sensors werken met een transistor die als een soort schakelaar aan/uit gaat. Je krijgt zo bij elke liter verbruik een puls in de vorm van een 0-1 of 1-0 overgang. Ben je bekend met deze sensors, Arduino's en NodeJS kan je direct door naar github om alles te downloaden en installeren. Zo niet, lees verder ...

Uiteraard is het leuker en goedkoper om zelf te knutselen. Hiervoor heb ik een Arduino nano gebruikt. De link gaat naar de officiele site, je hebt ook compatible third party varianten die vriendelijker geprijst zijn. Ben je voor 6-8 euro klaar. En als je lang wilt wachten op China kan het nog goedkoper. Dit zijn kleine computertjes met digitale en analoge in/uitgangen en een USB poort. Die laatste gebruikt je om het programma erop te zetten maar kan je ook gebruiken om met je Raspberry met openHAB te praten. Laatste voordeel, hij is erg energiezuinig.

Wil je exact mijn setup gebruiken moet je er rekening mee houden dat je een NPN sensor nodig hebt die kan werken op 5 Volt. De 5V is namelijk waar de raspberry en Arduino ook op werken en de NPN of PNP bepaald of het contact normaal open of dicht is. Deze heb ik gebruikt maar de keuze is reuze. Pas op met de bedrading, kleuren kunnen afwijken. Zelfs voor hetzelfde type. Dus lees de datasheet of in dit geval staat het op de sensor zelf. Blauw was de min, bruin de plus en zwart het uitgangssignaal. Zoals het hoort verschillen de meningen op het internet maar de consensus lijkt dat het verstandig is een weerstand van 10.000 ohm (meestal 10K genoemd) tussen de uitgang en de positieve spanning aan te brengen (zodat die niet gaan zweven). Nogmaals, let op kleuren van draden verschillen per sensor! En natuurlijk wil je stekkertjes aansluiten die op de arduino passen. Je houdt de boel veilig door te isoleren met krimpkous. De tip is, schuif die al in positie voordat je gaat solderen anders past het achteraf misschien niet meer. Eindresultaat is een Hall Sensor met drie stekkertjes. Twee voor de voedingsspanning (Aarde/Min/Negatief/GND/Bruin en Plus/Positief/VCC/Oranje) en één voor de uitgang (wit). Uiteraard, kleuren mag je zelf bedenken als je achteraf maar weet wat wat is. Zelf probeer ik altijd rood (+) en zwart (-) aan de houden voor de voedingspanning en wit voor het signaal. Maar goed, dan houd je altijd bepaalde kleuren over. Dus daarom speel ik vals en gebruikt ook kleuren die erop lijken zoals oranje en bruin. Maak vooral een afpsraak met jezelf, achteraf zie je niet meer wat wat is.

int pulsePin = 2;//digital pin for pulse sensor, 2 = D2

void setup() {

  //init pulse input
  pinMode(pulsePin, INPUT_PULLUP);
  digitalWrite(pulsePin, HIGH);

}

void loop() {

  //synch clock
  clock=millis();

  //read input
  pulse=digitalRead(pulsePin);
  
  if (pulse != pulseLast){
    //input change
    if (clock-pulseTime>pulseDelay){
      //enough time past (debouncing state changes) and ON only
      pulseLast=pulse;
      
      if (pulse==1){
        //ON only
        water++;
      }
    }
  }
}

Eenmaal aangesloten op een digitale ingang gaat deze één puls geven als het wieltje op de watermeter een rondje van 1 liter draait. Kwestie van tellen, elke puls is er weer een liter verbruikt. Dit kan je gebruiken om het waterverbruik te meten en aan je openHAB door te geven. Dit zou je zelfs rechtstreeks op de raspberry kunnen doen via de GPIO ingangen. Let er dan wel op dat deze 3.3V zijn terwijl de sensor zoals die nu aangesloten is 5V doorgeeft. Dat is één van de nadelen, de andere is dat als de raspberry het druk heeft hij misschien een puls mist. En dan mis je ook een liter waterverbruik. Als je een Arduino gebruikt kan die dat met gemak bijhouden en mist nooit een puls. Bovenstaand het concept van het programma. In de setup vertel je dat je de D2 aansluiting als ingang wilt gebruiken (daar sluit je de sensor op aan). En in de eeuwige lus (loop) ga je kijken of die van 0 naar 1 veranderd (of andersom). Nu kan precies op dat moment de sensor even wiebelen (door ruis in de omgeving), dus een paar keer even snel tussen 0 en 1 wisselen. Die ruis wil je eruit halen, vandaar een bekend concept met een debounce. Er moet tijd genoeg tussen 0-1 of 1-0 overgang zitten. Als laatste ga je op de overgang naar de 0 (of 1 maar niet beide) 1 liter bij je waterverbruik optellen.

//open message
Serial.flush();
Serial.print('[');
Serial.print(speed);
Serial.print(',');
//combine numbers in single string
Serial.print(totalCountH);

long tmp=(10L*totalCountL+5L*accurancy/10L)/accurancy;// So 5678 is (56780 + 5000)/10000 = 61780/10000 = 6 (floored). So printed .6
Serial.print('.');
Serial.print(tmp); //0.6 (with privious 12345 is 12345.6)
Serial.print(',');
Serial.print(round(10.0*pulseCount/accurancy)/10.0);
Serial.print(',');
Serial.print(pulseSpeed);
Serial.print(',');
Serial.print(round(10.0*minTotal/accurancy)/10.0);
Serial.print(',')
Serial.print(round(10.0*lastTotal/accurancy)/10.0);
Serial.print(',');
Serial.print(pulse);
Serial.print(',');
if (lastTotalTime<0){
  Serial.print('0');
}else {
  Serial.print( (clock-lastTotalTime+30000L)/60000L);
}
//close message
Serial.println(']');

Uitvoer over de USB is een kwestie van Serial.print. Ik heb er maar een soort telegram van gemaakt die de electriciteitsmeter ook verstuurd (kan ik een deel van die opzet hergebruiken). Eerst moet natuurlijk het programma op een Arduino gezet worden zodat het actief wordt.

Arduino's zijn heel populair en hebben een uitgebreide community en website. De volgende stap is met de Arduino IDE (ontwikkelomgeving) het programma op de Arduino te zetten. Het programma staat op mijn github en hoe je dat op een Arduino krijgt staat goed op hun startersgids.

Aansluiten is een kwestie van de drie kabeltjes van de sensor met de Arduino te verbinden (GND, 5V en D2) en die vervolgens met een USB kabel met de Raspberry Pi. De sensor moet je boven het magneetwieltje van de watermeter zetten. Hier heb ik op een gegeven moment een truc verzonnen. De meeste oplossingen op internet gebruiken de sensor om een heel rondje van het wieltje (en dus 1 liter) te detecteren omdat dit de makkelijkste opzet is. Wat je ook kan doen is de sensor er een beetje half overheen te zetten. Dan geeft hij de helft van de tijd een 0 en de helft van de tijd een 1 door. Je voelt hem al aankomen, zo kan je per halve liter meten! En je meet zowel de overgang van de 0 naar 1 als die van de 1 naar de 0. Die half-om-half lukt natuurlijk nooit 100% maar daarvoor zit er een calibratie optie in het programma. Daarover later meer, eerst maar de installatie afmaken.

http://[ip of naam van je openHAB]:3002/water
geeft:
{"loop":99,"cpu":0.99,"total":401155.5,"lastPeriod":0.5,"flow":3241,"minTotal":3,"lastTotal":25,"pulse":1,"calibration":"calibrated","p0":"5226","p1":"4774"}

Vanaf hier lijkt één en ander erg op de opzet van mijn slimme meter, waar je dus meer details en informatie kan vinden. Heel kort gebruik ik weer een alias/snelkoppeling voor de USB poort en NodeJS om van dit seriele bericht een JSON webservice te maken. Dit komt niet mee met openHAB dus zal je zelf moeten installeren, de handleiding staat ook op deze site. Het watermeter programma staat naar mijn github code wat je met PM2 weer op de achtergrond op de raspberry kan laten draaien. Eindresultaat is dat je alles via een webservice url kan opvragen. Voorbeeld hierboven.

http://[ip of naam van je openHAB]:3002/water
geeft de 1e keer:
{"loop":99,"cpu":0.99,"total":401155.5,"lastPeriod":0.5,"flow":3241,"minTotal":3,"lastTotal":25,"pulse":1,"calibration":"uncalibrated"}

Start calibratie:
http://[ip of naam van je openHAB]:3002/calibrate
Hierna krijg je met http://[ip of naam van je openHAB]:3002/water de tussenresultaten door:
{"loop":96,"cpu":0.96,"total":1014,"lastPeriod":1,"flow":2847,"minTotal":0,"lastTotal":1,"pulse":0,"calibration":"calibrating","p0":"4922","p1":"5078","t0":"11297","t1":"9775","calCount":2}
Die kan je zo vaak refreshen als je wilt zodat je T0 en T1 zo gelijk mogelijk kan maken.
Uiteindelijk krijg je iets als:
{"loop":98,"cpu":0.98,"total":1019,"lastPeriod":0.5,"flow":2763,"minTotal":2,"lastTotal":1,"pulse":1,"calibration":"calibrated","p0":"5332","p1":"4668","t0":"11502","t1":"10054","calCount":9}

Zoals beloofd de calibratie en de truc om halve liter te zien. Standaard (in stand uncalibrated) meet het programma alleen liters. Je kan ook naar halve liters (stand calibrated) waarbij het programma zowel het moment dat de schakelaar aan als uit gaat meet. Daarmee krijg je per liter 2 keer een waarde, bij uit-aan en aan-uit. Als de de sensor een beetje half over het wieltje plaatst duren beide periodes ongeveerd even lang en meet je op een halve liter nauwkeurig. Dat 'ongeveer' kan je instellen. Plaats de sensor half over het wieltje, zet een kraan open (zorg dat er niks anders water verbruikt zoals een WC of wasmachine) en start de calibratie. Het programma gaat meten hoe lang beide periodes duren (T1 en T2). Verschillen ze veel, verplaats je de sensor een beetje (dit reset de calibratie en je begint weer bij 0). Als de tijdsverschillen min of meer constant blijven telt hij 1 iteratie, zoniet begint hij opnieuw. Na 10 iteraties is de calibratie klaar en zal hij de timings gebruiken om halve liters te meten. Of waar je maar uitkomt. Stel de eerste periode duurt 4 seconden en de tweede 6 seconden dan meet je dus om en om 0.4 en 0.6 liter. Hoe gelijker hoe beter dus! En voor de duidelijkheid, dit is alleen voor de tussenstand van belang. Het wieltje rond (dus elke liter) weet je altijd zeker, zelfs als de calibratie helemaal verkeerd is. Naast het verdubbelen van de nauwkeurigheid zie je ook sneller dat je water verbruikt. Want als je een kraan vol open zet (zeg 10 liter/minuut) en het wieltje is net rond geweest, weet openHAB dus na 60/10=6 seconden dat de kraan open is. Met deze opstelling wordt dat 3 seconden. De winst lijkt klein, maar als je de kraan niet vol open zet worden de verschillen groter.

totaalstand van 492,123 m3 doorgeven:
http://[ip of naam van je openHAB]:3002/totaal/492123

P0 van 4990 doorgeven:
http://[ip of naam van je openHAB]:3002/P0/4990

P1 van 5010 doorgeven:
http://[ip of naam van je openHAB]:3002/P1/5010

Na de calibratie kan je de meterstand doorgeven zodat het totaal op openHAB en je meter gelijk gaan lopen. Als laatste nog hulp bij stroomuitval, je kan ook de calibratie handmatig opvoeren. Scheelt wat waterverbruik want om 10 iteraties te doen moet je weer 10 liter water in de goot laten lopen. Dat kan allemaal ook automatisch, indien je (in de configuratie) USE_DISK op true zet en/of je openHAB naam of ip opgeeft zal het programma bij herstart of stroomuitval zelf zorgen dat de calibratie en totaal weer juist gezet wordt.

Arduino lezen:

//get serial input
if (Serial.available()>0){
  //input available, so command given
  String input=Serial.readString();

  //check for available commands
  if (input.startsWith(F("CALIBRATE"))){
    //reset and start calibration
    calibrated=false;
    calibrating=true;
    calibrationDone=false;
    pulseStable=0;
    pulseTime0T=0L;
    pulseTime1T=0L;
  } else if (input.startsWith(F("CALIBRATION"))){
    ...
  }
}

Raspberry/nodeJS schrijven
serialPort.write('P0:'+myP0);

Als je denkt, hoe werkt dat dan? Zowel in NodeJS als de Arduino kan je serieel 'beide kanten' op. Daarvan maak ik gebruikt. Standaard schrijft de Arduino en leest de raspberry met NodeJS. Maar dat kan bijna net zo gemakkelijk andersom.

UID: http:url:watermeter
label: water meter
thingTypeUID: http:url
configuration:
  authMode: BASIC
  ignoreSSLErrors: false
  baseURL: http://[ip-of-naam]:3002/water
  delay: 0
  stateMethod: GET
  refresh: 10
  commandMethod: GET
  contentType: application/json
  timeout: 3000
  bufferSize: 2048
channels:
  - id: total
    channelTypeUID: http:number
    label: total
    description: null
    configuration:
      mode: READONLY
      stateTransformation: JSONPATH:$.total
      unit: l
  - id: lastPeriod
    channelTypeUID: http:number
    label: lastPeriod
    description: null
    configuration:
      mode: READONLY
      stateTransformation: JSONPATH:$.lastPeriod
      unit: l

Je kan deze service in openHAB aanroepen met de HTTP binding. Installeer deze (als je dat nog niet gedaan hebt) en je kan met behulp van bovenstaande url's een thing maken. Daarbij zul je ook de plugin JSONPATH add-on nodig hebben, installeer die ook als je dat nog niet gedaan had. Daarmee kan je een specifieke variabele uit het JSON bericht in een channel zetten. Dit kan je met de GUI doen of met YAML op het code tabblad. Voorbeeldje hierboven. Je kan ook lui zijn en die van mij gebruiken, hij staat ook op github. Download de yaml code en plak die in het code tabblad van een nieuw thing. Kies daarna in the gemaakte en opgeslagen thing dat je equipements/items wil genereren en daarna komen de gegevens ook in openHAB door voor gebruik in pages en rules.

Je wilt dit natuurlijk mooi weergeven vandaar dat ik er ook een widget bij heb gemaak. Deze toont in een grijze/groene kraan hoeveel water er stroomt en in een emmer hoeveel water er de laatste keer in totaal is gebruikt. De widget (en een uitgebreider verhaal) zijn te vinden op mijn github. Let erop dat je ook een aantal plaatjes moet downloaden en in de openHAB installatiemap moet zetten. Is de kraan groen,stroomt er water. In de kraan staat hoeveel liter met minuut. De emmer toont het laatste volledige verbruik, dus heb je de kraan 5 minuten open gehad en 35 liter verbruikt staat dat in de emmer.

1