← Back to the notebookTinyML
A working note

I can calculate 46.3 millijoules. What did those millijoules do?

I recorded 14.04 mC at a 3.3 V supply over a 257.8 ms inference window. Multiplying the charge by the supply voltage gave 46.332 mJ, or about 46.3 mJ per inference. I checked the calculation against the average current and duration before writing the result down.

There’s a second route through the arithmetic: 54.44 mA average current multiplied by 0.2578 seconds gives about 14.03 mC, agreeing with the displayed charge after rounding. The maximum current is 87.85 mA, but it cannot replace the average for the entire interval. I find the short calculation satisfying because its units can be followed all the way through. The more demanding question is what activity that interval actually contains.

First, I want the units to make sense. Current is charge per time. Adding current over an interval gives charge. At a constant voltage, multiplying that charge by voltage gives energy. So the milli in millicoulombs carries through to millijoules when I multiply by volts. I don't need a complicated model to do that part correctly, but I do need to keep the prefixes.

There’s another route to check the same result. Average current times duration should give the displayed charge, allowing for rounding. Here, 54.44 mA multiplied by 0.2578 seconds is about 14.03 mC. That agrees closely with 14.04 mC. Multiplying the charge by 3.3 V then gives about 46.3 mJ. The arithmetic is internally consistent with the displayed values.

Inference energy capture: 257.8 ms, 54.44 mA average, 14.04 mC at 3.3 V.
Inference energy capture: 257.8 ms, 54.44 mA average, 14.04 mC at 3.3 V.

The voltage assumption also needs to stay visible. Multiplying the total charge by 3.3 V assumes that voltage describes the supply over the interval. If the voltage varied meaningfully, energy would need the changing voltage and current considered together. I’m not reporting a voltage problem in this setup; I’m keeping the condition behind the simple calculation clear.

That consistency doesn't identify the activity. A current graph can add up everything the supply delivered inside the chosen window, whether the processor was doing feature extraction, running the model or waiting. The measurement answers how much electrical energy passed through this supply boundary during this interval. The name I give the interval has to come from the code and setup.

The maximum current isn't a substitute for the average. If I multiplied 87.85 mA by the entire duration, I would be imagining the board stayed at its peak throughout the displayed window. The trace doesn't say that. A peak is useful for another question, such as the demands on a supply, but it doesn't automatically give the energy total.

The same issue appears when I try to identify a smaller region by eye. A taller section might coincide with processing, but I need the corresponding program timing before assigning it a stage. If the marker includes an extra wait, selecting the whole marker interval includes that wait's energy too. The boundary is doing as much work in the result as the multiplication.

There are several potentially useful measurements I could choose. Energy for the neural network alone. Energy for feature processing and classification together. Energy for a complete cycle including capture and waiting. None is inherently the wrong question. They just describe different pieces of the device, and the labels need to say which piece was measured.

For example, the whole processing call can be more relevant than the network alone if I want to compare the cost of turning the same saved audio into a prediction. A complete-cycle measurement is more relevant if I want to understand the running application's average consumption. I shouldn't choose whichever boundary produces the smallest number and then use a broader name for it.

Subtracting background current adds another decision. In the calculation, the same displayed interval had a justified average baseline of 10 mA under matching conditions. Subtracting that from 54.44 mA would leave an excess average of 44.44 mA. Over 257.8 ms at 3.3 V, that would be about 37.8 mJ above baseline.

If I used an assumed 20 mA baseline instead, the calculated excess would be about 29.3 mJ. Nothing about the original displayed charge changed. My assumption changed the reported answer by around 8.5 mJ. This is why picking one low point on the trace and treating it as the average idle current would be too casual.

The baseline also needs a meaningful definition. Is the microphone still on? Is audio still being collected? Is the processor waiting in the same state? Subtracting a different operating mode could remove consumption that belongs to the task I meant to describe. I need the comparison to fit the question rather than use baseline as another word for an inconvenient part of the graph.

There’s also the count of operations. If a displayed window contains more than one prediction, dividing by their number may answer an average-per-operation question, but only if I know the count and what other work is included. If the interval contains one prediction plus a long deliberate wait, dividing by one doesn't turn the wait into neural-network work. The denominator needs evidence too.

The mentor discussion I want is therefore about the boundary before it is about the final number. Which stage do we want? How do we mark its beginning and end? What does the profiler supply? What comparison, if any, justifies subtraction? Those questions can make a short numerical calculation into a measurement somebody else can understand.

I also want the raw capture and matching firmware kept together. A screenshot records a view, but it may not let me inspect other windows or check the alignment later. If the code changes, the old graph should remain attached to the version that produced it. Otherwise the explanation can drift even while the screenshot stays exactly the same.

I aligned the timing marker with the classifier call and used that boundary for each capture. That gave me the same interval to use when checking the charge against the current trace.

For now, 46.3 mJ stays labelled as the calculated energy for the inference window. That’s already a useful thing to understand. I can explain where it comes from and why a maximum current isn't used in its place.

Leaving this here for next time.All the notes ↗