Live R&D Log

The Build Log

Live R&D, hardware iterations, testing, and progress from the bench. Written by Aki Suda as the project evolves.

Started Oct 2025
Current phase Phase 1 โ€” Active Prototype
Location Dublin, CA
Entries 13 entries ยท 12 months
2025
The problem, properly defined

I started this project asking a simple question: why do cooking fires still happen so often? Smoke detectors clearly aren't the answer โ€” they respond after something is already burning. I spent a few weeks going through NFPA data and reading incident reports. The finding that stuck: unattended cooking is the leading behavioral cause of home cooking fires, and the average empty pan can reach dangerous temperatures in under five minutes.

That told me the intervention window exists. The hazard develops over minutes, not seconds. You don't need to stop a fire โ€” you need to catch the conditions that lead to one. That reframing is what HomeHalo is built on.

Key insight: 158,400 home cooking fires per year in the US (NFPA 2017โ€“2021 avg). Unattended cooking is the #1 behavioral factor. Ranges and cooktops are involved in 53% of those fires. The problem is behavioral, not technological โ€” and behavior can be monitored.
First sensor experiments โ€” Arduino Nano + thermal array

First prototype: an Arduino Nano connected to a low-resolution thermal array sensor in a 3D-printed enclosure I designed myself. The goal at this stage wasn't detection accuracy โ€” it was understanding what thermal data above a real cooktop actually looks like. Where is the heat concentrated? What happens to the temperature profile when a pan empties out?

I mounted the enclosure above my own stove and ran a series of controlled tests: empty pan heating, full pan to boil, pan left unattended with water boiling off. The data was noisier than expected at low resolution, but the shape of the hazard was already visible in the raw readings.

What worked: Even at low resolution, an empty pan heating curve looks distinctly different from a pan with contents. Rapid, uniform temperature rise with no internal thermal structure is a detectable signature.
What didn't: Arduino processing speed wasn't enough for frame-by-frame trajectory analysis. I needed a more capable edge processor. Also: the 3D-printed enclosure placement above the stove was inconsistent โ€” field-of-view geometry needed to be locked before anything else.
Defining the detection logic before writing a line of real code

Before upgrading the hardware, I wanted to define exactly what I was trying to detect and how. I wrote out the detection rules in plain English first โ€” no code, no implementation. The question: what physical signatures indicate a hazardous cooking state?

I landed on four fundamental measurements: rate of temperature rise (dT/dt), area change rate (dA/dt), fill ratio (liquid surface area relative to vessel area), and absolute temperature thresholds. From those four variables, you can construct rules for most of the hazard states I care about.

# Core detection variables (pseudocode, December 2025) dT_dt = (current_temp - prev_temp) / frame_interval # ยฐC/sec dA_dt = (current_area - prev_area) / frame_interval # pxยฒ/sec fill_ratio = liquid_area / vessel_area # 0.0 โ€“ 1.0 avg_temp = mean(vessel_pixels) # ยฐC # Empty pan rule (draft) if dT_dt >= 3.0 and fill_ratio < 0.15 and duration >= 5: trigger_alert("empty_pan_heating")

Writing this out before implementing it forced me to think about false positives. A high dT/dt alone is not enough โ€” oil heats fast too, and that's fine. The fill ratio is the key discriminator.

2026
Switching to Raspberry Pi 4 + Thermal Master P2

Moved from the Arduino to a Raspberry Pi 4 as the edge processing unit, paired with the Thermal Master P2 โ€” a 256ร—192 IR sensor with ยฑ1.5ยฐC accuracy. The resolution jump was significant. At 256ร—192, you can actually see the internal structure of a pot โ€” the cooler rim versus the hotter liquid surface.

Sensor:Thermal Master P2 โ€” 256ร—192 IR array, ยฑ1.5ยฐC, 25Hz
Processor:Raspberry Pi 4 Model B โ€” 4GB RAM, quad-core ARM Cortex-A72
Interface:USB-C (sensor to Pi), Python via Thermal Master SDK
Mount:Revised 3D-printed bracket, fixed 45ยฐ angle above rear burners

Also added the Pi NoIR Camera V2 as a development reference โ€” not for detection, but for positional calibration. Having a visible-light reference frame alongside the thermal made it much easier to verify that the thermal blobs were actually aligning with the cookware I was testing.

How I detect liquid in a pot using thermal imaging and Otsu's method

The hardest part of cooktop hazard detection isn't finding the pot. It's distinguishing a pot with something in it from an empty one โ€” and doing it reliably across different cookware materials, burner types, and cooking states.

The core problem

When you look at a thermal image of a cooktop, a hot pan is easy to spot โ€” it's the brightest blob. But "bright" means hot, and hot can mean many things: full pan cooking normally, half-empty pan, or completely empty pan running dry. The average temperatures might not differ much at first. The internal structure does.

A pan with liquid in it has a characteristic thermal profile: a slightly cooler rim (the metal walls absorbing heat) and a hotter center (the liquid surface, especially near boiling). An empty pan heats more uniformly โ€” the whole surface climbs together, with no cool liquid mass to absorb energy unevenly.

Otsu's method as a thermal segmentation tool

Otsu's method is a classic image processing technique for finding the optimal threshold to separate two classes of pixels based on their intensity distribution. It finds the threshold that minimizes within-class variance โ€” in other words, it finds the natural dividing line in your histogram.

I'm using it here differently from its typical application. Instead of thresholding a grayscale image into foreground and background, I'm applying it to the temperature histogram of just the pixels inside the detected vessel blob. That gives me the dividing temperature between the cooler rim structure and the hotter liquid surface.

# Otsu threshold applied to vessel interior pixels vessel_pixels = extract_blob_pixels(thermal_frame, vessel_mask) threshold = otsu_threshold(vessel_pixels) # Segment into rim (cool) vs liquid (hot) rim_mask = vessel_pixels < threshold liquid_mask = vessel_pixels >= threshold fill_ratio = np.sum(liquid_mask) / np.sum(vessel_mask) liquid_temp = np.mean(vessel_pixels[liquid_mask])

What this tells me

If Otsu finds a clean split โ€” a meaningful cooler region and a meaningful hotter region โ€” that's evidence of liquid. The fill ratio (liquid area / total vessel area) tells me how full the pot is. A high fill ratio near boiling temperature triggers a boil-over prediction. A fill ratio that was high and is now dropping fast indicates liquid is boiling off. A fill ratio consistently below 0.15 with a rising temperature means the pan is probably empty.

The elegance of this approach is that it's self-calibrating. I don't need to know the cookware material or the burner power setting. The threshold is computed fresh from each frame's own temperature distribution โ€” so it adapts to whatever is in front of the sensor.

Failure modes I've found so far

  • Very small amounts of liquid (less than ~10% fill ratio) can be misclassified as empty โ€” the thermal contrast isn't strong enough for Otsu to find a clean split
  • Cast iron cookware heats so slowly and uniformly that the rim/liquid contrast is low even with normal liquid content
  • Oil doesn't behave like water โ€” it heats more uniformly and doesn't boil in the conventional sense. Boil-over prediction for oil isn't reliable yet

These are documented limitations, not hidden ones. The system is designed to fail conservatively โ€” if the classification is ambiguous, it defaults to a lower-severity alert rather than no alert.

Training on pots and pans โ€” starting with the Kaggle Kitchenware Classification dataset

If the system needs to understand what's in the thermal frame โ€” specifically, what type of cookware is present โ€” it needs training data. I found the Kaggle Kitchenware Classification competition dataset as a starting point. It covers cups, glasses, plates, spoons, forks, and knives โ€” not exactly pots and pans, but a useful baseline for understanding how classification models handle kitchen objects.

The more important work was collecting my own thermal data above a real cooktop. Different cookware types have distinct thermal signatures: a stainless steel pan heats differently from cast iron, which heats differently from non-stick. A model that doesn't account for cookware type will produce inconsistent results across households.

# Cookware classes being trained (current) COOKWARE_TYPES = [ "stainless_pan", "cast_iron_skillet", "non_stick_pan", "stainless_pot", "ceramic_pot", "wok", ] # Each type needs its own dT/dt baseline calibration

The goal is cookware-aware detection: the system recognizes what it's looking at and adjusts its baseline expectations accordingly. A cast iron skillet heating at 1.5ยฐC/sec is normal; a thin stainless pan at the same rate may already be a hazard.

Systematic cooktop tests โ€” 40+ sessions, documented results

Spent most of March running structured test sessions above my stove. I designed a test matrix covering the hazard states I'd defined in December: empty pan heating, boiling onset, boil-over risk, liquid boiling off, sustained high temperature. Each state was tested at different burner power levels and with different cookware (stainless, non-stick, cast iron).

I logged every session: sensor readings, detection events, false positives, missed events. The goal was to find where the detection rules broke down, not to confirm they worked. That mindset change โ€” actively trying to break the system rather than demonstrate it โ€” improved the rules significantly.

March outcome: Empty pan detection became reliable above stainless and non-stick with gas and electric burners. Boiling onset detection (predicting imminent boil before it happens) achieved consistent early warning at ~15โ€“30 seconds ahead of visible boiling in water-based liquids.
Still needs work: Cast iron false-positive rate too high (slow heat distribution confuses the rate-of-rise detector). Oil detection is its own problem. Induction burner thermal signature differs enough from gas/electric that it needs its own tuning pass.
Moving inference to the Nvidia Jetson โ€” what local compute actually means

Local inference compute means running AI models directly on your own hardware instead of relying on remote cloud APIs. In HomeHalo's case, that means the Nvidia Jetson โ€” a purpose-built edge AI board from Nvidia that includes a GPU alongside the CPU, making it capable of running small neural networks at real-time frame rates without a cloud connection.

The Jetson replaced the Raspberry Pi 4 as the primary processing unit for inference workloads. The Pi 4 is fine for rule-based detection (the physics-based logic runs fine on CPU), but as I started adding learned components โ€” cookware classification, environment calibration โ€” GPU acceleration became important for hitting acceptable latency targets.

What "local inference" means in practice: A thermal frame comes off the Thermal Master P2 sensor. It gets processed entirely on the Jetson โ€” blob detection, Otsu segmentation, cookware classification, state machine update, alert decision โ€” and a result is returned in under 100ms. No data ever leaves the device. The Jetson's internet connection is only used for push notifications, not for inference.

The Jetson's power consumption is also manageable for a range-hood installation โ€” it can be powered from the hood's existing wiring in Phase 2, which simplifies the enclosure design significantly.

Experimenting with Vision-Language Models on Jetson โ€” can a VLM reason about cooking scenes?

Found this LearnOpenCV guide on running a VLM on Jetson Nano and started experimenting. The idea: instead of (or alongside) explicit physics-based rules, could a small vision-language model reason about a cooking scene in natural language? "Is this pan empty?" "Does this look like it's about to boil over?"

Running a VLM locally on Jetson is genuinely possible at smaller model sizes, but the latency is significant โ€” several hundred milliseconds per query at useful quality levels. For HomeHalo's application, where I need frame-by-frame analysis at 25Hz, that's not viable as the primary detection path. But it opens up something more interesting: using a VLM for context understanding on lower-frequency checks, while the physics-based rules handle the real-time hazard detection.

Current thinking: Two-tier architecture. Fast physics-based rules run every frame for real-time hazard detection. A lightweight VLM runs every 10โ€“30 seconds for broader scene understanding โ€” "is anyone at the stove?", "has the cookware type changed?" โ€” and feeds context back into the state machine. Still exploratory, not implemented in the prototype yet.
Refactoring detection: from rules to a proper state machine

The detection logic had grown into a tangle of nested if-statements. A single frame's reading could trigger a rule, then contradict it in the next frame, producing alert flicker that was confusing and unreliable. I needed a cleaner architecture.

I refactored everything around a finite state machine. Each burner slot tracks a state (IDLE โ†’ HEATING โ†’ NORMAL_COOKING โ†’ HAZARD โ†’ ALERT) with defined transition conditions and hysteresis. A hazard state can only be entered if the evidence persists across multiple frames โ€” not just a single anomalous reading. This eliminated most of the false-positive flicker.

# State machine transition (simplified) class BurnerState: IDLE = "idle" HEATING = "heating" NORMAL = "normal_cooking" HAZARD = "hazard" # Require 3 consecutive frames to enter HAZARD if hazard_evidence_count >= 3 and current_state == BurnerState.NORMAL: current_state = BurnerState.HAZARD trigger_alert(hazard_type, severity)

The hysteresis principle also applies on exit: a hazard state clears only after several consecutive normal-reading frames. This prevents the system from being fooled by a momentary dip in temperature.

What I learned from presenting HomeHalo to the San Ramon Valley Fire Protection District

I presented early HomeHalo prototypes to members of the San Ramon Valley Fire Protection District and asked them to assess whether the problem I was solving was real, whether my understanding of how cooking fires develop was accurate, and where my prototype's assumptions might be wrong.

This was not a validation session. I was not there to have them endorse the device. I was there to be corrected.

What they confirmed

Unattended cooking is genuinely one of the most common call types they respond to โ€” and often one of the most preventable. The feedback was direct: most of these calls happen because something was left on and the resident wasn't alerted early enough. Smoke detectors, by design, only trigger when smoke is already present. The idea of detecting the thermal precursor to a fire โ€” the overheating stage before any smoke forms โ€” was something they found credible and worth pursuing.

What they pushed back on

They raised the question of false alarms. Any device that alerts too frequently trains the user to ignore it โ€” the same problem that made early car alarms useless. If HomeHalo produces alerts for normal cooking events (searing, high-heat stir-frying), it will get disabled or ignored. That feedback directly shaped the progressive alert model: a gentle reminder first, a louder alert only if the situation worsens and time passes.

They also noted that the most dangerous scenarios are often the ones that develop slowly โ€” a pot left on a low simmer for hours. My detection logic at the time was optimized for rapid temperature events. I added an unattended-cooking timer specifically because of that conversation: if a burner stays active with no detected user interaction for an extended period, that alone should trigger a low-level alert regardless of temperature state.

What I changed after

  • Added duration-based unattended detection (not just temperature-based)
  • Introduced the progressive alert model (reminder โ†’ push alert) based on their false-alarm concern
  • Revised the sensor mounting height recommendations based on their input on how cooking smoke actually develops and rises

This kind of feedback loop โ€” talking to people who see the problem in its real-world context โ€” is something I want to do more of as the project develops.

Applied to Y Combinator and Founders Inc โ€” waiting on results

Applied to Y Combinator and to Founders Inc (San Francisco Lab) startup school programs. Both applications focus on HomeHalo at its current prototype stage โ€” the goal is to get structured feedback on the product direction, the go-to-market approach, and the engineering roadmap from people who've seen many early-stage hardware projects.

Writing the applications was useful in itself. The process of articulating the problem, the technical approach, the current state of the prototype, and the honest gaps in what's been built forces a clarity that you don't always maintain when you're heads-down in the lab. I tried to be direct about what works, what's still open, and what the next 12 months need to accomplish.

Regardless of outcome, the discipline of explaining HomeHalo to people who have no prior context โ€” and doing so accurately rather than optimistically โ€” is something worth practising regularly. Results pending.
Beginning Phase 2 โ€” GU10 form factor and hardware partner

Phase 1 proved the detection methodology works on real cookware in real conditions. Phase 2 is about putting that methodology into a form that can actually be deployed โ€” specifically, a GU10 light bulb socket form factor that installs in a range hood without any new wiring or modifications.

I've begun working with Cosmo Products, LLC to explore what the miniaturization requirements look like. The Raspberry Pi 4 is obviously far too large โ€” the Phase 2 module needs to fit into a GU10 footprint while still providing enough processing power to run the detection algorithms locally. This is a genuine engineering constraint, not a solved problem yet.

Phase 2 design goals (current thinking): GU10 form factor ยท On-device inference (no cloud dependency) ยท Wi-Fi connectivity for push alerts ยท Smart-home integration (HomeKit, Alexa, Google Home) ยท Optional appliance shutoff for plug-in cooktops ยท No new wiring, no installation professional required

The GU10 enclosure also needs to handle the heat environment of a range hood โ€” temperatures, airflow, grease particles. These aren't thermal sensing problems; they're mechanical and materials problems. Working with an experienced hardware partner is the right approach here.

September 2026
Where the detection logic stands today โ€” and what's still open

Twelve months in, here's an honest account of where the software is:

Working reliably: Empty pan detection on stainless and non-stick cookware (gas and electric). Boiling onset prediction (15โ€“30 sec advance warning for water-based liquids). Duration-based unattended cooking detection. State machine alert logic with hysteresis โ€” false-positive rate is acceptable for non-cast-iron scenarios.
Partially working: Boil-over prediction for water-based liquids (reliable above stainless, less reliable above cast iron). Multi-burner tracking (tested with 2 simultaneous burners; 4-burner scenarios need more work).
Still open problems: Oil and high-fat liquid detection (thermal behavior is fundamentally different from water). Cast iron calibration (slow, uniform heat distribution confuses rate-of-rise logic). Induction burner tuning (the cooktop surface itself doesn't heat โ€” only the cookware โ€” which changes the thermal scene significantly).

The open problems are documented, not hidden. Knowing exactly where a system fails is as important as knowing where it works โ€” and it's the foundation for the next phase of testing.