Here is the simple experiment we ran to determine the specific SPG-30 sensor values used in the code.

The experiment was carried out during February 2021 with the milk shown.

Data was collected February 28, 2021.

Each day, a small amount of milk was poured into a glass and labeled with the current date. This was done for 5 days to produce a series of milk of differing ages.

We used the code to provide a readout of the SGP-30's TVOC and eCO2 - the values shown in the grass at the bottom of the display.

At this point, don't worry about what the cow says.

Do NOT let the SGP-30 touch the milk. It is not a moisture proof sensor.

For each sample, we lowered the sensor into the glass without touching the milk, slowly moved it around, and watched the readings for about 1 minute.

We then wrote down the observed range for each gas reading.

Here is a summary of the readings we obtained:

0 40-60 500-700
1 110-130 600-700
2 160-200 700-900
3 300-900 1500-2100
4 1500-3000 3000-10000

Now we have values we can use in our code to determine milk freshness. We considered there to be three levels:

  • GOOD - low readings very close to fresh milk
  • SUS? - the readings are slightly elevated, milk is sus
  • BAD! - milk that has obviously gone bad

Based on the values we observed, we decided on TVOC <= 80 as the cutoff for GOOD, TVOC <= 120 as the cutoff for SUS, and anything above that as BAD!

However, different milk may age in different ways. Different environmental conditions, like temperature and humidity, may also affect the readings. Further, your personal level of comfort on what constitutes "bad" milk, may be different than others. Therefore, we suggest you repeat the above experiment.

We suggest you repeat this experiment!

Adjusting the Code

You can easily adjust the code to change the cutoff TVOC levels used for freshness detection. You can even customize what the cow says. Just look for these lines at the top of the code:

# --| User Config |-------------------------
TVOC_LEVELS = (80, 120)  # set two TVOC levels
MESSAGES = ("GOOD", "SUS?", "BAD!")  # set three messages (4 char max)
# ------------------------------------------

and change as needed. Note there are only two TVOC levels to specify for a total of three freshness levels.

Other Sensor Values

We decided to keep things simple and just use the SGP-30's TVOC reading. But note in the data above that eCO2 also increased with milk age. This production of CO2 is mentioned in the research papers previously cited. Perhaps a more sophisticated approach could be used that take both readings into account? We leave that up to any intrepid scientist out there that wishes to investigate further.

Other Sensors

We tried a few other sensors as well but they did not seem to have any useful "milk freshness" related signal. At least nothing with as good a signal-to-noise ratio as the SGP-30.

Other Uses

We also thought this idea could be used for detecting dirty laundry. However, that did not seem to work - at least not as easy as the approach above for milk. This may be due to the various dyes used to color clothing producing VOCs that mask any similar signal from "dirty" smells.

This guide was first published on Mar 03, 2021. It was last updated on Mar 03, 2021.

This page (Experiment) was last updated on Feb 28, 2021.

Text editor powered by tinymce.