Wabi-Sabi

Harys Dalvi

July 2022


Wabi-sabi is notoriously difficult to understand. In general, it's a Japanese ideal of the beauty in impermanence, imperfection, and nature. But it might be better shown than explained.

An example of wabi-sabi in a Japanese garden. The rocks are in their natural irregular shapes, and the stone structure shows signs of age. The imperfections in the display give it character.

I appreciate the simplicity and natural elements of this aesthetic, and I wanted to bring some of that to my room. After moving around some things to make more space, I decided the best way to add some wabi-sabi was a plant.

A money plant, like I could have gotten. I think I did better.

Unfortunately, I can't be watering the plants while I'm away in college. One solution to that problem is to get a money plant, which can be grown in aquariums, so I might be able to just put it in water and let it be. However, I found the plant quite boring. Instead, I wanted to design a system that will water a plant automatically.


Concept

I had done Arduino projects before, most recently a failed sailboat, but I didn't want this one to be purely Arduino. I needed to use my Arduino for future projects while this circuit waters my plant. This was my first project built to last.

I found some online Arduino projects for watering plants, but they used soil moisture detectors, which apparently corrode over time. Instead, I simply went with watering the plant at regular intervals. Since I couldn't use my Arduino, I wanted to make a circuit with no code. I sketched a master plan.

My original master plan

Approximately ten seconds after sketching, I realized my master plan was really bad. Building a pump from a motor would be too hard. Water would spill everywhere, and it probably wouldn't even work. Plants need watering on the scale of days or weeks, but the resistances and capacitances needed for that would be far too large: classroom RC circuits work on the scale of seconds. Finally, I would have no way to make adjustments if the plant was getting too little water or not enough.

Realizing why they invented computers in the first place, I decided to use a computer. Specifically, I found the best chip for my needs would be an ATtiny85. It's tiny as the name suggests, but still able to keep track of my plant's watering needs. The chip can be programmed with Arduino and then detached to use in other circuits, leaving the Arduino untouched.

I also replaced the motor with an actual electric pump. After scrapping my old master plan, I designed a new circuit.

My new master plan, made with circuit-diagram.org.

This circuit had the ATtiny chip outputting signals to a transistor, which would then power the pump at the right times. It also had an LED to give me feedback as I set the watering frequency. I planned to change the settings by manually connecting the input pins to ground: I never said this would be user-friendly. However, the design was simple enough that I expected to be done in about a day.

Code

My plant-watering career was full of frustration from the first step.

I carefully followed instructions on how to program an ATtiny from Arduino, double checked my wiring, triple checked my wiring, tried every combination of tweaking the code, and nothing worked. Eventually I found out I had forgotten a capacitor, causing the Arduino to reset every time I tried to upload code. That's just one paragraph now, but it was almost an entire day of annoyance for me. The only thing that stopped me from giving up was that I was confident in my design, and I knew I had the materials. If it wasn't working, I had to be doing something wrong.

When I finally got it working, I uploaded a program that blinked a light at regular intervals and allowed me to change the frequency of the blinking by adding a wire. At this point, I was almost done: I just had to replace the light with a pump, and make it blink every week instead of every second.

Unfortunately, the chip counted time in milliseconds. You can imagine that gets to a big number after a few weeks. After \(2^{32}-1 = 4.29 \times 10^9\) seconds, which is about 50 days, the count resets back to zero. I was worried I would face problems after that reset. Fortunately, the unsigned long data type in C++ works in a way that just as adding 1 to \(2^{32}-1\) gives 0, subtracting 1 from 0 goes back to \(2^{32}-1\). This let me handle any interval less than 50 days with no issues.

There was another problem with my code: say it's been 6 days since I last watered the plant, and it's set to water every 2 weeks. I want to water every 1 week, but the frequency cycles as 0.5, 1, 2, 3, 0.5, 1... per week, so to get from 2 to 1 I would have to cross 0.5. At this point the plant would be watered immediately, which is too soon. I solved this by not watering within a minute of adjusting settings, and adding an option to increase as well as decrease watering frequency.

Pump

When I swapped out the blinking light for the pump, I found it wasn't working properly. At first, it wasn't pumping with enough force.

I changed some things around and at first it seemed to be pumping with too much force: the water wouldn't stop until it had entirely drained from the box. But what gave away the problem is that this continued even when the pump was unplugged. Rather than a code or electrical issue, this was a fluid mechanics issue.

Bernoulli's principle, which looks a little like conservation of energy, is $$\frac{1}{2} \rho v^2 + \rho g h + P = \text{constant}.$$

The key part here is that if height \(h\) of a fluid decreases, the speed will increase, and vice versa. In other words, gravity was pulling down on the water. Combined with the cohesion of water, this was probably enough to pull the water down the tube even without power from the pump.

To solve that, I had to increase \(h\): I placed the tube at a higher elevation, and made it point up at the end instead of down. That solved the issue, and the pump was now behaving predictably. However, now I needed a way to make sure the pump was at the right height when I got the actual plant. I added a feature to send three short test pumps when the program is set up. That last addition got me to the final version of my code.

Code (link to GitHub)
unsigned long lastWater = 0;
unsigned long lastAdjust = 0;
const unsigned long HALFWEEK = 1000UL*43200*7;
//10000UL;
int waterMode = 0; // no watering until an interval is chosen
int interval = 0;
int intervals[5] = {0, 1, 2, 4, 6};
bool tested = false;

#define PUMP 0
#define LIGHT 1

void setup() {
  pinMode(PUMP, OUTPUT);
  pinMode(LIGHT, OUTPUT);
  pinMode(3, INPUT_PULLUP); // pins 3 and 4 can be connected to ground for me to interact with the chip
  pinMode(4, INPUT_PULLUP);
  for (int i = 0; i <= 40; i++) {
    analogWrite(LIGHT, i*5);
    delay(30);
  }
  delay(800);
  for (int i = 20; i > 0; i--) {
    analogWrite(LIGHT, i*10);
    delay(10);
  }
  digitalWrite(LIGHT, LOW);
  delay(300);
}

bool timestamp(unsigned long stamp, unsigned long wait) {
  // checks whether or not a number of milliseconds have passed since a timestamp
  bool pastStamp = (millis()-stamp >= wait);
  return pastStamp;
}

void water() {
  // waters the plant and stores the time of watering
  digitalWrite(PUMP, HIGH);
  delay(8000);
  digitalWrite(PUMP, LOW);
  lastWater = millis()-8000;
}
void setInterval(int dm) {
  // sets the interval at which the plant should be watered and displays the new interval on the LED
  waterMode = (waterMode+dm)%5;
  interval = intervals[waterMode];
  if (waterMode == 0) {
    for (int i = 20; i >= 0; i--) {
      analogWrite(LIGHT, i*10);
      delay(30);
    }
  } else if(waterMode == 1) {
    digitalWrite(LIGHT, HIGH);
    delay(250);
    digitalWrite(LIGHT, LOW);
  }
  else {
    for (int i = 0; i < (waterMode-1); i++) {
      digitalWrite(LIGHT, HIGH);
      delay(900);
      digitalWrite(LIGHT, LOW);
      delay(100);
    }
  }
  lastAdjust = millis(); // stores adjustment time so the plant won't be watered immediately
}

void loop() {
  if (tested) // once the three test pumps are done
  {
    if (timestamp(lastAdjust, 2000)) {
      if (!digitalRead(3) && waterMode < 4)
        setInterval(1); // can water less frequently
      else if (!digitalRead(4) && waterMode > 0)
        setInterval(-1); // or more frequently
    }
    if (waterMode != 0
      && timestamp(lastWater, interval*HALFWEEK)
      && timestamp(lastAdjust, 60000)) {
          water();
    }
  } else {
    analogWrite(LIGHT, 90*sin(millis()*0.001)+100);
    if (!digitalRead(3)) { // only start test when I connect pin 3 to ground
      digitalWrite(LIGHT, HIGH);
      for (int i = 0; i < 3; i++) {
        // send three test water pumps to make sure the tube is at the right height
        digitalWrite(PUMP, HIGH);
        delay(2000);
        digitalWrite(PUMP, LOW);
        delay(4000);
      }
      digitalWrite(LIGHT, LOW);
      lastWater = millis()-4000;
      tested = true;
    }
  }
}

Circuit

Once the code and pump were working, I was ready to solder everything onto a circuit board. I took the chip off the Arduino and put all my components on a prototype board.

The circuit board with some components added

The board was arranged in a regular grid, with the components neatly layed out. It was a beautiful aesthetic, but in many ways it was the antithesis of wabi-sabi. Rather than displaying nature and imperfection, this circuit board was the result of precise manufacturing. I thought it might be interesting to have the board next to a plant with all its natural imperfections.

To add the pump, I first soldered the pump wires to some more wires so I could move it farther away from the circuit board. After that I started soldering the actual circuit. It didn't go entirely smoothly: my wire cutter couldn't come close enough to trim the leads properly, and I almost burned my finger fixing the connections on the transistor. But I was able to get it done in the end, and when I hooked it up to power from the Arduino, the green LED lit up.

Plant

Satisfied that my circuit was working, I went to get a plant. I wanted one that looked interesting but didn't need too much water, so Aloe vera seemed like a good choice. There were rows and rows of Aloe plants at Home Depot, all virtually identical. Yet one was very different from the rest, because it would become mine for the forseeable future. I just had to find which one.

The Aloe plant I picked

It would be nice to say I picked one that spoke to me, but they really looked about the same. I picked the one that I thought would fit best. It wasn't perfect: some leaves were straight up, some were sticking out, a few had small brown spots. But the others weren't perfect either, This one was a good size to fit nicely and still command attention, so I got it.

Batteries

Before adding the battery holder, I connected my circuit to power from Arduino to make sure it was still working. Of course, it wasn't working.

To find out the cause, I built a makeshift multimeter with Arduino to see if the connections were good. By this method, I found the LED was bad, and the wire next to it was fine. Then I tried applying power to the LED to see where it stopped working. By this method, I found the LED was fine, and the wire next to it was bad.

At first, I thought physics was broken. There was no way it made sense to have such a contradiction. Eventually, I found the problem was in the connection between the LED and the wire, so I added extra solder and it worked again.

Now I was ready to add the batteries. Along the way, I soldered the positive end in the wrong place at least twice. I had the negative end at the top of the board when I wanted it at the bottom. The LED lit up, showing me that the circuit was working; but every time I tried to send test pumps, it rebooted. Connecting the reset pin to the VCC pin helped a little, but it still wasn't working.

I spent hours trying to fix that problem only to find it was a problem I had faced earlier with Arduino: I needed a capacitor connecting to ground. I soldered in the capacitor and it finally worked.

My final master plan

I tested it on a glass of water to be sure. I must admit, it took me a few tries to get the tube at the right height, but it worked.

Wabi-Sabi

The Aloe definitely added some wabi-sabi to my room. It has natural dents and spots, but they are what give it character, almost to the point that I can't see myself picking any other from the rows and rows of similar plants at Home Depot. I love the way the leaves are irregular in shape and size, but the small spikes are arranged so regularly and neatly on all of them.

That's nice and all, but it was expected. What I didn't expect is how even the circuit has elements of wabi-sabi. It has random wires sticking out from where I couldn't cut the leads close enough. Some parts of the solder bridges are thicker than others, some parts are more spiky than others. All of it is arranged on that same even grid.

My circuit's small imperfections give it character, just like the Aloe. It represents the hard work I put in over the course of a week for what I expected to be a one-day project. I hope it continues to work, because it's not consumer-ready quality. The connections are handmade rather than professional PCB connections. It doesn't have a box hiding the electronic parts, so consumers can't pretend it's just a magic box. But it's an interesting wabi-sabi decorative piece in its own right, one that represents my interests and learnings.