Fuktmåler med Wifi til potteplanter – DIY


Reklame - Artikkelen inneholder annonselenker

Hvem har vel ikke tatt liv av en plante eller to? Her er steg for steg på hvordan en fuktmåler til jord kan lages.

Kun fantasien setter grenser på hvordan denne IOT måleren (Internet of Things) kan kobles opp mot smarthuset.

Beskrivelsen her vil beskrive hvordan den bygges, programmeres og kobles opp mot Home Assistant. Varsling til Sonos og push varsel til mobiltelefon er også med.

Deler til fuktmåler

For å bygge denne trenger du følgende (kan kjøpes i min nettbutikk)

Andre varianter av batteri kan brukes, men det må være mellom 3,3V og 5V. Er også en fordel at det har en god kapasitet slik man slipper å bytte for ofte.

Sammenstilling av fuktsensoren

1. Lodde på ledninger på batteriet

Dupont ledninger er loddet fast på batteriet. En liten bit nikkelstrips er punktsveiset til batteriet for at det skal være lettere å lodde fast ledningene uten å skade batteriet.

2. Tape på batteriet

Elektriker tape er brukt for å dekke til de ledende flatene på batteriet, samtidig som ledningene holdes fint på plass.

3. Batteriet plasseres i boksen

Batteriet passer perfekt ned i boksen, og må presses lett på plass.

4. Kutte hull i lokk og sette inn sensor

Det må lages et hull i lokket som passer til fuktsensoren. For å få dette til brukte jeg en multikuttsag. Det bør også være mulig å skjære det ut med kniv.

Dersom man ønsker at det skal være vanntett, må sensoren festes med silikon rundt hullet.

5. Lodde Wemos

Tilkoblingsledningene loddes på plass iforhold til koblingskjema. Det som ikke vises på bildet her loddingen som ble gjort på undersiden av kortet. Det må loddes i feltet som heter «sleep». Alternativt kan en ledning mellom D0 og RST loddes på. NB! Det er en fordel å lodde «sleep» etter kortet er programmert, ellers kan det være vanskelig å få det programmert.

Over er et skjematisk koblingskjema.

Det grafiske koblingskjema over, stemmer ikke utseende på komponentene helt med hva som benyttes, men konseptet er helt likt.

Fuktsensor kode

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// WIFI
const char* ssid = "Nettverksnavn";
const char* password = "123456";


// MQTT
const char* mqtt_server = "192.168.1.02";
const int mqtt_port = 1883;
const char *mqtt_user = "Plante";
const char *mqtt_pass = "hemmeligpassord";
const char *mqtt_client_name = "Fukt_Plante"; // Hver klient må ha eget navn
WiFiClient espClient;
PubSubClient client(espClient);

//Jordsensor
int sensorPower = D6; 
int sensorPin = A0; 
int sensorValue;
char jordfukt[50];  

//Deep Sleep
const int sleepSeconds = 62*30;


char jordfuktrssi[50]; //Wifi signalstyrke


void setup() {
 Serial.begin(115200);
 Serial.println("");
 Serial.println("Startet!");
 
pinMode(sensorPower, OUTPUT);
digitalWrite(sensorPower, HIGH);

WIFI();

client.setServer(mqtt_server, mqtt_port);

while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqtt_user, mqtt_pass )) {
      Serial.println("connected"); 
    } else {

      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
}
client.publish("checkIn/Fukt_Plante", "hello"); //Topic name    
sjekkFukt();
client.publish("Fukt_Plante", jordfukt);
client.publish("RSSI/Fukt_Plante", jordfuktrssi);
delay(100);
Serial.println("Går i dvale!");

ESP.deepSleep(sleepSeconds * 1000000);
}

void loop() {}

void sjekkFukt(){
String sens_str; 
  Serial.println("Sjekker fuktsensor");
   delay(100);
  sensorValue = analogRead(sensorPin); 
 Serial.println(sensorValue);
 sens_str = String(sensorValue);
 sens_str.toCharArray(jordfukt, sens_str.length() + 1);
 Serial.println("Avslutter sjekk av fuktsensor!");
}

Koden over skal være å bare laste opp på din Wemos D1 mini, men først må Wifi navn og passord redigeres. I tillegg må MQTT server innstillinger redigeres.

Node Red

Over er en grafisk fremstillingen av koden i Node-Red. Koden kan kopieres fra lenger nede i artikkelen, så kan den limes direkte i NodeRed

I MQTT Inn boksen angis hvilke MQTT setninger som skal lyttes etter. I dette tilfelle er det Fukt_Plante. Meldingen som kommer angir rådata fra fuktsensoren.

For å få dataen over i prosent, må man vite hvilke verdi man leser av på tør jord og fuktig jord. Gjennom «Subtract», «Multiply» og «Divide» regnes det ut i prosent, som igjen publiseres til Home Server. I mitt tilfelle her er Subtract = 531, Multiply = -47 og Divide = 100.

For enkelhetsskyld fylte jeg opp en glasskrukke med tør jord, og målte verdien, før jeg fuktet jorden for en ny måling.

«Switch» angir på hvilke nivå melding skal sendes til mobiltelefon og Sonoshøyttaler. Klokkeslettene angir når meldingen skal sendes. Dette for å forhindre den blir sendt på natten. Limit er satt til 1 gang pr dag, slik at det ikke skal varsles hver gang måleren rapporterer en lav fuktighet.

Melding til mobilen angir hva som skal sendes til mobiltelefonen, og hvilke lyd skal spilles av. Det samme gjelder melding til Sonos.

NodeRed kode til fuktmåler

[
    {
        "id": "20eb9435.2eadec",
        "type": "mqtt in",
        "z": "be373486.908688",
        "name": "",
        "topic": "Fukt_Plante_1",
        "qos": "2",
        "datatype": "auto",
        "broker": "4f5a2e41.d1076",
        "nl": false,
        "rap": true,
        "rh": 0,
        "x": 250,
        "y": 100,
        "wires": [
            [
                "33ee64fe.1053bc",
                "f646b151fe6c40b1"
            ]
        ]
    },
    {
        "id": "4b4d52f0.0fda8c",
        "type": "ha-entity",
        "z": "be373486.908688",
        "name": "Fukt_Plante_1",
        "server": "a90d8c7c.e094a",
        "version": 1,
        "debugenabled": false,
        "outputs": 1,
        "entityType": "sensor",
        "config": [
            {
                "property": "name",
                "value": "Fukt_Plante_1"
            },
            {
                "property": "device_class",
                "value": ""
            },
            {
                "property": "icon",
                "value": ""
            },
            {
                "property": "unit_of_measurement",
                "value": "%"
            }
        ],
        "state": "payload",
        "stateType": "msg",
        "attributes": [],
        "resend": true,
        "outputLocation": "",
        "outputLocationType": "none",
        "inputOverride": "allow",
        "outputOnStateChange": false,
        "outputPayload": "$entity().state ? \"on\": \"off\"",
        "outputPayloadType": "jsonata",
        "x": 900,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "33ee64fe.1053bc",
        "type": "switch",
        "z": "be373486.908688",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "lte",
                "v": "300",
                "vt": "str"
            },
            {
                "t": "nnull"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 450,
        "y": 100,
        "wires": [
            [
                "877cd991.813a88"
            ],
            []
        ]
    },
    {
        "id": "caa51c16.74a04",
        "type": "delay",
        "z": "be373486.908688",
        "name": "",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "day",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "x": 790,
        "y": 60,
        "wires": [
            [
                "4bae7057.b10a4",
                "b4e7002a.f59cd"
            ]
        ]
    },
    {
        "id": "319858ac.4a2a08",
        "type": "api-call-service",
        "z": "be373486.908688",
        "name": "Tom",
        "server": "a90d8c7c.e094a",
        "version": 3,
        "debugenabled": false,
        "service_domain": "notify",
        "service": "mobile_app_tom",
        "entityId": "",
        "data": "{}",
        "dataType": "json",
        "mergecontext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 1210,
        "y": 60,
        "wires": [
            []
        ]
    },
    {
        "id": "4bae7057.b10a4",
        "type": "function",
        "z": "be373486.908688",
        "name": "Melding til mobilen",
        "func": "var beskjed = \"Jorden har en fuktighet på\" + msg.payload;\n\n\n\nmsg.payload = \n{\n  \"data\": \n  {\n    \"title\": \"Banyantreet trenger vann \",\n    \"message\": beskjed,\n    \n    \"data\": \n    {\n      \"push\": \n      {\n        \"category\": \"Fuktighet\",\n\n      }\n     \n    }\n  }\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 990,
        "y": 60,
        "wires": [
            [
                "319858ac.4a2a08"
            ]
        ]
    },
    {
        "id": "877cd991.813a88",
        "type": "time-range-switch",
        "z": "be373486.908688",
        "name": "",
        "lat": "58.94308",
        "lon": "5.67869",
        "startTime": "17:00",
        "endTime": "22:30",
        "startOffset": 0,
        "endOffset": 0,
        "x": 630,
        "y": 100,
        "wires": [
            [
                "caa51c16.74a04"
            ],
            []
        ]
    },
    {
        "id": "384dd2e3.ba8e7e",
        "type": "ttsultimate",
        "z": "be373486.908688",
        "name": "",
        "voice": "sv-SE",
        "ssml": false,
        "sonosipaddress": "192.168.1.127",
        "sonosvolume": "20",
        "sonoshailing": "Hailing_Hailing.mp3",
        "config": "16cb8f96.b50dd",
        "property": "payload",
        "propertyType": {},
        "rules": [],
        "x": 1230,
        "y": 120,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "b4e7002a.f59cd",
        "type": "function",
        "z": "be373486.908688",
        "name": "Melding til Sonos",
        "func": "\nmsg.payload = \"Hei! Poppelfiken trenger vann!\";\nmsg.volume=\"50\";\nreturn msg;\n\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 990,
        "y": 120,
        "wires": [
            [
                "384dd2e3.ba8e7e"
            ]
        ]
    },
    {
        "id": "3402ec2934a944a2",
        "type": "calculator",
        "z": "be373486.908688",
        "name": "",
        "inputMsgField": "payload",
        "outputMsgField": "payload",
        "operation": "mult",
        "constant": "-47",
        "x": 620,
        "y": 200,
        "wires": [
            [
                "57eb0a0c8d53419e"
            ]
        ]
    },
    {
        "id": "f646b151fe6c40b1",
        "type": "calculator",
        "z": "be373486.908688",
        "name": "",
        "inputMsgField": "payload",
        "outputMsgField": "payload",
        "operation": "sub",
        "constant": "531",
        "x": 480,
        "y": 200,
        "wires": [
            [
                "3402ec2934a944a2"
            ]
        ]
    },
    {
        "id": "57eb0a0c8d53419e",
        "type": "calculator",
        "z": "be373486.908688",
        "name": "",
        "inputMsgField": "payload",
        "outputMsgField": "payload",
        "operation": "div",
        "constant": "100",
        "x": 750,
        "y": 200,
        "wires": [
            [
                "4b4d52f0.0fda8c"
            ]
        ]
    },
    {
        "id": "4f5a2e41.d1076",
        "type": "mqtt-broker",
        "name": "",
        "broker": "192.168.1.45",
        "port": "1883",
        "clientid": "",
        "usetls": false,
        "compatmode": false,
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "willTopic": "",
        "willQos": "0",
        "willPayload": ""
    },
    {
        "id": "a90d8c7c.e094a",
        "type": "server",
        "name": "Home Assistant",
        "version": 1,
        "rejectUnauthorizedCerts": true,
        "ha_boolean": "y|yes|true|on|home|open",
        "connectionDelay": true,
        "cacheJson": true
    },
    {
        "id": "16cb8f96.b50dd",
        "type": "ttsultimate-config",
        "name": "Config",
        "noderedipaddress": "192.168.1.1",
        "noderedport": "1980",
        "purgediratrestart": "leave",
        "ttsservice": "googletranslate"
    }
]

Fuktsensor Home Assistant

Gauge symbolet er godt egnet i Home Assistant til å vise informasjonen fra fuktmåler. I visningen over, er planten akkurat vannet, og har fått i overkant mye vann. Dette kan kalibreres ved å endre tallene som legges inn i Node Red.

I tillegg til Gauge, kan for eksempel «History Graph Card» for å vise utviklingen over tid. (Det er inkludert i koden under)

path: planter
title: Planter
icon: mdi:flower
panel: false
cards:
  - type: gauge
    name: 'Fikenpoppel'
    entity: sensor.nodered_4b4d52f0_0fda8c
    severity:
      red: 0
      yellow: 40
      green: 60
  - type: history-graph
    name: 'Fikenpoppel'
    hours_to_show: 96
    entities:
    -  sensor.nodered_4b4d52f0_0fda8c

For flere grafiske visninger, anbefaler jeg å se mer på de offisielle Home Assistant sidene om Lovelace

Dersom du har spørsmål er det bare å stille det i kommentarfeltet, så skal jeg forsøke å svare etter beste evne.



3 kommentarer til “Fuktmåler med Wifi til potteplanter – DIY

  1. Hei 🙂

    Bruker du en Raspberry Pi for å kjøre Home Assistant på? Eller har du en annen device som brukes som base for Home Assistant?

    Mvh Hanne

  2. Hei igjen 🙂 Kalibrerte du sensoren ved å sette den ned i tørr jord (0%) og så jord som nettopp var blitt vannet (100%)?

    Mvh Hanne

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *