The most useful thing I can tell you about controlling a sealed vertical farm is that a grow room has no undo. A wrong decision is not a failed request you can retry. It is three weeks of lettuce that will never be diagnosable again unless you can say exactly why the environment moved.
That one property decided the architecture of the control layer I built for Interfarm, a TÜBİTAK-funded closed vertical-farming venture I volunteered on for two years alongside full-time work. I also think the decision pattern generalises well beyond agriculture, because most teams reach for the opposite default.
The fashionable answer, and why it was unavailable
The modern reflex for "control this environment well" is to learn a policy from data. It is a good reflex, later. The module I was controlling was the thing being built. There was no logged dataset of this rack, growing this crop, under this lighting, because the first crop was the first data. Learning a controller from operational history puts the learning step at the end of the sequence, and the module still has to be operated from the day it is powered on.
What existed instead of data was expertise. The agronomists could tell you, in exactly these words, that slightly warm and quite humid means back the misting off. That sentence is not a threshold. It is graded, it overlaps, and it is comfortable with two conditions being partially true at once. In other words it is already fuzzy logic wearing casual clothes. Membership functions and a rule base are a machine for compressing that kind of knowledge without pretending it is more precise than it is.
Why traceability won the argument
Fuzzy control had three properties the project needed. It encodes a rule base without a training set. It degrades gently across boundaries instead of snapping between states the way independent thresholds do, and coupled variables punish snapping: light moves transpiration, which moves humidity, which moves the HVAC, which moves the reservoir's concentration, which moves what the plants can absorb under that same light.
The property that settled the argument was the third one. Every action the controller takes can be traced back to the rules that fired and the degrees to which they fired. When a tray goes wrong, the question is why did the environment move, and a controller that can be read is the difference between diagnosing a growing cycle and repeating it. A learned policy, at the fidelity we could have afforded, answers that question with a weight matrix.
I have come to treat this as the dividing line, ahead of accuracy: in systems where a bad decision destroys the evidence, explainability is the debugging strategy.
Making wrong rules cheap
The rule base and membership functions were modelled and swept in MATLAB before a line of the running Python existed. This is slower than writing the implementation first and tuning against the module. It is also the only version where a wrong rule is cheap. Tuning against real hardware means every experiment costs a piece of a growing cycle, on a rig other people need, and a mistake is a plant. Because I modelled first, the implementation was a transcription of something already argued about, and the argument did not have to happen on the rack.
The cost is a second representation to keep honest. Two descriptions of one controller drift unless somebody makes sure they do not. If I were continuing the work, the first addition would be a harness that replays recorded sensor traces through both and fails when they disagree.
The expiry date
None of this is an argument that rules beat models. It is an argument about ordering. A fuzzy controller cannot discover a policy nobody thought of, and its ceiling is the quality of the rules it was given. The honest statement is conditional. With no data and a domain expert in the room, the readable controller wins. Once several seasons of logged history exist, the logged behaviour of this controller becomes exactly the training set for the model that should replace it. The choice ships with its own expiry date, and writing that date down is part of the design.
That ordering is now how I build AI systems generally: build the legible, constrained thing first, and let its operation produce the evidence its successor learns from. It is why LILA's delivery gate is twelve ordered, inspectable checks rather than a scorer nobody can interrogate. Cendra's notification system taught me the same lesson from the other direction. The ordering of a system's concerns is itself a design decision, and the restraint half comes first.
Limits
Fairness requires the other side. I have no measured evaluation of the controller against a baseline, because building the baseline would have cost growing capacity the project did not have. I believe it behaved well, and I cannot show you that it did. The generalisation above is drawn from one module, one crop programme and a volunteer's hours. Treat it as a well-worn heuristic with one strong case study rather than a law.