Aeroponic Vertical Farming: Environment Control with Data-Driven Crop Advisory · part 1 of 1
Plot Twist: My Dissertation Is Now a Farm
The kernel proposal didn't get approved. Not because the idea was wrong, but because I couldn't sell it. The dissertation is now an aeroponics control system, and the kernel gets slower, not dead.
Keith Gangarahwe 9 min readSo. Remember the whole restructuring post, where I announced that the microkernel was becoming my dissertation, laid out a sixteen-week plan and drew a nice little architecture diagram?
Yeah. That didn’t get approved.
Not “come back with revisions”. Not “narrow the scope”. It just didn’t get enough of my lecturers on board to go ahead as my dissertation project. And before anyone gets defensive on my behalf in the comments: that one is on me.
Why It Didn’t Land
The proposal wasn’t rejected because the idea was bad. It was rejected because I couldn’t explain it.
Every time I tried to pitch it, the explanation went something like: first let me tell you about microkernels, and then about Physical Memory Protection, and then about dynamic binary translation, and then I can tell you why doing all three at once on a chip with no MMU is a gap in the literature. Three prerequisites before the point arrives. By the time I got to the interesting part, the room had reasonably concluded that I was building an emulator for fun.
The honest version is this: I understood why the project was interesting technically, but I never found the sentence that made someone outside my niche care. Everything I had was structured for people who already agreed with me. When I got asked plain questions like “what does it actually do for somebody?”, I reached for the literature gap instead of an answer. A good answer existed, and I couldn’t produce it under pressure.
Lesson, written down here so future me doesn’t get to pretend it didn’t happen:
If you can’t state the value of your project in two sentences, without prerequisites, it doesn’t matter how sound the plan underneath it is. The plan is not the pitch, and you are the one who has to close that distance.
Genuinely annoying. Also genuinely fair.
What Happens to the Kernel
It lives. I’m not stopping.
What changes is the cadence. The dissertation has priority now, which means the kernel gets evenings and whatever weekend survives the week. It was always going to take a while; now it’ll take longer.
Practically, for this blog:
- The kernel series continues. QEMU
virtPart 2 is still coming: trap handling and the context switcher are next, and the Part 1 repo is still where the code lives. - Posts will be less frequent, not less detailed. I’d rather post one proper write-up a month than four filler ones.
- The goal doesn’t change. ARM7TDMI code running under my own kernel on a RISC-V chip. It just isn’t the thing being graded anymore, which, honestly, removes a deadline I was quietly dreading.
There’s an upside I didn’t expect: freed from the dissertation, the kernel gets to be a research notebook again instead of something with a submission date. Weeks 9-16 of that old plan were “write the dissertation”. Now they’re just more kernel.
The New Dissertation
Here it is:
Aeroponic Vertical Farming: Environment Control with Data-Driven Crop Advisory In Zimbabwe
I’ll give you a second to appreciate the distance between “runtime instruction translation for RISC-V microcontrollers” and “farming”.
Now let me explain why I’m not sulking about it, because after two weeks inside the literature I think this problem is actually interesting, and it is much closer to the last one than it looks.
The Problem
Aeroponics means growing plants with no soil at all. The roots hang in a closed chamber and get fed by a fine mist of water and nutrients on a cycle. Stack the chambers vertically and a small floor area holds a lot of plants. It uses something like ninety per cent less water than a field, which matters a great deal in Zimbabwe, where water, not land or sunlight, is the binding constraint on horticulture.
Here’s how a small grower actually operates one today. Misting runs on a mechanical timer set once and rarely revisited. A handheld meter gets dipped in the reservoir maybe once a day to check acidity and nutrient strength. Temperature and humidity are judged by feel. Readings go in a paper book nobody reads again. Problems get discovered by looking at the plants.
And there are three holes in that:
- Detection is retrospective. By the time a crop looks wrong, the conditions that made it wrong have been going for a while. Suspended roots hold no water reserve, so the gap between a fault and permanent damage is short.
- The readings aren’t used. A meter gives you a number at an instant. What carries information is which direction it’s moving, how fast, and how it moves relative to the other numbers. Nobody computes that by hand.
- A blocked nozzle is silent. A nozzle half-clogged with mineral deposit looks like it’s working. The timer still reports the pump ran. The controller has no idea that the mist stopped reaching the roots.
That third one is my favourite, and I’ll come back to it.
The Part That Makes It a Computer Science Project
The components exist, which is a very different claim from the components being cheap. What doesn’t exist at any price is the layer that turns readings into conclusions. That’s the project:
Advisory
A language model writes the sentences.
It is handed the computed indicators, never the raw readings. Every factual claim is checked against the number behind it before display; text that fails the check is logged, not shown.
Indicators
VPD · nutrient trend vs reservoir level · pH drift · accumulated heat hours.
Plain deterministic arithmetic, computed on the device. This is where the judgement happens.
Control
Misting cycle · alerts · SD logging · local web page and touch display.
Hardware
ESP32-S3 · pH · EC · SHT30 · DS18B20 · float switch.
Read it bottom to top: readings become indicators, and only then do indicators become sentences.
The middle layer is where the actual content is. It keeps a short history of every variable and computes things a grower can’t do mentally:
- Vapour pressure deficit, one number combining temperature and humidity that expresses how hard the air is pulling water out of the plant, and therefore whether it’s transpiring at all.
- Nutrient concentration trend against reservoir level, which separates a crop drinking water from a crop eating nutrients. Get this backwards and you “help” by adding concentrate when what the tank lost was plain water, which actively harms the crop.
- The direction acidity is drifting, which tells you which ions are being taken up, and so whether the solution suits the crop’s current stage.
- Accumulated time the solution has spent too warm, because damage here is cumulative, not instantaneous.
All deterministic. All arithmetic. No model, no training set, no cloud.
The Part Where I Put an LLM In a Box
The advisory layer hands those computed indicators to a hosted language model and asks it to write a short plain-language account of what’s going on and what to do about it.
Note what it is not given: the raw sensor readings. And what it is not asked to do: work out what the data means. That determination already happened, arithmetically, one layer down. The model’s entire job is to phrase it.
Then, because the set of indicators is small and fully known to the system, every factual claim in the generated text gets checked automatically against the computed value it refers to before a human sees it. If the text claims something the numbers don’t support, it’s withheld and logged.
This is the part I’d defend hardest. The standard failure of language models in this setting is fluent, confident nonsense. The design answer isn’t a better prompt, it’s not letting the model near the judgement in the first place, and verifying its output against the ground truth you already hold. How often the check rejects the text is a result I intend to report honestly rather than quietly tune away.
And the Blocked Nozzle
Every misting pulse produces a characteristic spike in humidity inside the chamber, followed by a decay. The shape of that curve, how high it goes, how fast it gets there, how quickly it falls, depends on how much mist the nozzles are actually delivering.
So: record that response during commissioning, while the nozzles are known to be clean. Keep it as the baseline. Compare every later pulse against it. A sustained departure means the delivery is deteriorating.
No extra hardware. No flow meter, no pressure sensor, no accelerometer on the pump. The fault is detected from the environmental response the system is already measuring, before the crop shows any symptom. And I get to test it properly, by deliberately blocking nozzles and reporting how many blockages it caught and how many false alarms it raised.
If you squint, it’s the same instinct as the kernel work: watch a signal you already have, model what “correct” looks like, and shout when reality departs from it.
Keeping It Honest About Scope
Also from the proposal, because stating exclusions is half of a defensible project. Not in scope: nutrient chemistry (that’s Chemistry’s department, I consume their formula as config), any claim that this increases yield, comparisons against other growing methods, food safety, cameras and plant disease vision, cloud services or a mobile app, and high-pressure aeroponics.
The Hardware
| Part | Job |
|---|---|
| ESP32-S3-N8R8 | The controller. 8 MB PSRAM, mercifully familiar |
| 3.2” ILI9341 + XPT2046 touch | On-installation display and control panel |
| ADS1115 16-bit ADC | Reads the pH and EC probes. The ESP32’s own ADC is neither linear nor quiet enough for trend detection |
| pH probe (×2) | Acidity. Fragile, fails without warning, hence two |
| EC/TDS probe | Nutrient strength |
| SHT30 | Air temperature and humidity: VPD, and the mist response curve |
| DS18B20 | Solution temperature, so EC can be compensated to 25 °C |
| 12 V diaphragm pump + 0.4 mm nozzles | The misting system, and the subject of the induced-fault testing |
| Float switch | Reservoir level |
Reading that table back, it looks a lot tidier than it felt to put together. Every imported row on it is paid for in forex, spends four to seven weeks in transit, and picks up shipping and duty on the way in. The pH probe costs more than the microcontroller driving it, which is not a sentence I expected to write in a systems blog, and I’m buying two, because they fail without warning and a dead probe in week ten is a dead trial. The budget calls that a contingency line. I call it agreeing in advance to be hurt twice.
So no, this is not the part where I tell you the parts are cheap. The kernel cost me evenings. This costs money, in a currency I don’t earn, on parts I can’t walk into a shop and replace when I break one, and I will break one. Which is exactly why the sensor set is configuration rather than compiled-in code: if a probe doesn’t arrive, or arrives dead, the profile disables that indicator, the system still runs, and the limitation gets reported instead of the whole project stopping. That started out as good architecture. The supply situation turned it into self-defence.
The other thing I notice: same ESP32 family, same “read a datasheet and drive a peripheral” work. The chip selection in the kernel’s hal.zig and the cultivation profile here are the same idea wearing different clothes: swap the crop, the sensor set, or the whole aeroponic tower for a plain soil container, and it should mean supplying a different profile rather than rewriting the program. I have to prove that, too: the system gets run in a second configuration with a different sensor set to demonstrate that the claim is real rather than rhetorical.
The Schedule
Sixteen weeks from approval. Long-lead components get ordered in week one, before any development, because four to seven week import times would otherwise land exactly on top of sensor integration. Construction and instrumentation first, since the indicator, advisory and fault detection layers can’t be built without recorded data from a running rig. The growing trial starts as early as possible so the crop cycle finishes inside the schedule, and the induced-fault evaluation sits deliberately before the end, so that a negative result still leaves time to report it properly.
What This Means For the Blog
Two series now, running in parallel:
- The kernel, continuing at a slower pace, still the long game.
- The aeroponics system, documented from the very beginning, which I’m weirdly excited about. You get to watch me learn what vapour pressure deficit is in public, mis-wire an ADC, and probably drown a batch of lettuce.
Same approach either way: the wrong turns stay in, the numbers get reported as they come out, and when something doesn’t work I’ll say so.
Next up: the parts order goes in, and I start the sensor bring-up on a bench rig long before there’s any plant involved. If it goes anything like the kernel, the first milestone will be “read one believable number off one probe”, and it will take three times longer than it should.