Arduino MKR 1000 Plant Monitor


The main idea of this device is to track temperature, humidity, light level, and soil moisture, and control a water pump to enable remote watering.

After a nice chat with @alvarolb on this thread, I got the system working.

I did two iterations with an Arduino MKR1000, the first was in a breadboard, and the second in a little more appropriate container (just a little).

First Iteration

The thing was connected to a DHT11 (temperature and humidity sensors), a light sensor, soil moisture sensor, and a Relay module, that activates an aquarium pump. As I was saying, the first iteration looks pretty ugly, but worked and allowed me to be sure that the system worked before starting soldering… here you can see it.

I can’t believe how easy was to integrate everything thanks to library. I hope I can get access soon to the web api part, since there are some things that I’d like to work on, (like keeping a history of the readings, being able to configure a refresh rate on a donut chart, different than the refresh rate of the history chart, for the same device reading type… etc.

Anyway, I’m really happy with the speed I was able to get this working thanks to the library, and how simple and clean the code ended up looking.

#define _DEBUG_

#include <SPI.h>
#include <WiFi101.h>
#include <ThingerWifi.h>
#include <DHT.h>

#define USERNAME "your_user_name"
#define DEVICE_ID "your_device_id"
#define DEVICE_CREDENTIAL "your_device_credential"

#define SSID "your_wifi_ssid"
#define SSID_PASSWORD "your_wifi_ssid_password"


const int LedPin = 6;

// PIN configuration
const int DhtSensorPin = 2;
const int WaterRelayPin = 3;
const int SoilMoistureSensorPin = A5;
const int LightSensorPin = A6;

int ledState = LOW;
int waterRelayState = LOW;

const int DhtType = DHT11;

DHT dht(DhtSensorPin, DhtType);

void setup() {

	// configure wifi network
	thing.add_wifi(SSID, SSID_PASSWORD);

	pinMode(LedPin, OUTPUT);
	pinMode(WaterRelayPin, OUTPUT);

	// Configure the LED
	// Need to track the state separatelly from the real pin, since MKR1000 does not respond the correct value when reading an output pin
	thing["led"] << [](pson & in) {
		if (in.is_empty()) {
			in = ledState;
		else {
			ledState = in ? HIGH : LOW;
			digitalWrite(LedPin, ledState);

	// Configure the Water Relay
	// Need to track the state separatelly from the real pin, since MKR1000 does not respond the correct value when reading an output pin
	thing["water"] << [](pson & in) {
		if (in.is_empty()) {
			in = waterRelayState;
		else {
			waterRelayState = in ? HIGH : LOW;
			digitalWrite(WaterRelayPin, waterRelayState);

	thing["dht11"] >> [](pson & out) {
		out["humidity"] = dht.readHumidity();
		out["celsius"] = dht.readTemperature();
		out["fahrenheit"] = dht.readTemperature(true);

	thing["light"] >> [](pson & out) {
		out = map(analogRead(LightSensorPin), 0, 1023, 0, 100);

	thing["moisture"] >> [](pson & out) {
		out = map(analogRead(SoilMoistureSensorPin), 0, 1023, 0, 100);

void loop() {

Second Iteration

The main purpose here was to make all the hardware fit into a container that I could place into a planter. The electronics are almost the same. The only difference is that I used different pins, since it made easier placing everything together.

I didn’t plan the position of each element, I inserted each of them acording to the space left in the board, so I think I was lucky that everything fitted there…

This would be the board…

And the back side:

Here you can see the soil moisture inserted into the case

Ant how the board fits next to it…

After that, I placed the batteries on the remaining space…

And the relay, goes inverted, on top of the MKR1000, (the only space left…)

Finally, this is how it looks assembled

TODO: upload the code of the second iteration…


Great! Thanks for sharing the project! Good work in the final integration! :smiley:

Did you planned to add a rechargeable battery and a solar panel for extending battery life? Not sure how the two AA batteries will last. Anyway, if there is some kind of sleep mode in the MKR1000, and with the data logging feature available at the end of this month, I think we can extend the battery life much more time.

Thanks again!


To be truth, I think this is the most I’ll do with the MKR1000, since I received the ESP-12E I was waiting for. SO third iteration will be based on ESP8266.

I read MKR1000 has a stand by mode, so it is possible to use that in. I also have 4 AA batteries now, but MKR1000 have an integrated LiPo charger, so it would be a better idea to put the battery it’s expecting, and use all that functionality.

I’m also planning to work on my own server, (accessing the webapi), since I’d like to make it really customized for this project. Anyway, the data logging feature will be awesome to start with :).

You are doing an awesome job with @alvarolb, thanks for helping every project be made a lot faster.


Hey i’m really fascinated of thinger and the possibility to bring the data to the web. Even if this is an older post, i’d like to comment.
I have kind of the same set up running a couple of weeks now only monitoring the temperature and soil moisture. I was also very exited how fast i was able to monitor and log data.

  1. Did you notice that the soil sensor is starting to corrode? I read online that it is possible to trigger the sensor only e.g. every 5 minutes. But i don’t know how to use the thinger.handle in the void loop and some kind of delay for triggering the sensor only ever 5 min. Perhaps you guys have some idea or better solution.

The second idea, did you think about an automatic watering solution?
It is probably not that complicated. At them moment i think some kine of mixture between your setup here and the moisture led alarm from @alvarolb (Moisture Sensor with ESP8266). I could just change the LED Output to a water Pump relais and change the led time.
The only problem i see is that i don’t want that the pump is running in the middle of the night.
And aswell as the first problem, i’m not sure how to integrate some kind of timer.


Hi @sdev, by default, resources are not executed in the loop. For example, if you have defined a resource for reading the soil moisture, and your loop is running only the thing.handle(), your moisture sensor will not be used. However, you can “execute” or read a resource by adding a dashboard widget with some interval reading, or adding a bucket reading the value every x minutes. This way, you can freely adjust the reading on the resource/sensor depending on the interval specified in your dashboards or buckets. A resource is just a callback…

I had also a cheap soil moisture sensor from china, and got corrode in a few weeks. Sure there are better solutions out there…

Regarding your second idea… it is completely possible, using the approach in the led, for example. You could also add a NTP client to synchronize a clock and avoid powering the pump in the night. It should be easy…


Great idea,
i just used this method you described! It worked even better than using an timer interrupt (wich could only handle a couple of seconds) So i used the bucket reading and a function with digital write for the sensor vcc.

I started to use an rtc, it worked but now i have some strange problems. Perhaps i’ll switch to ntp.

If someone is interested i could post my code as a project.