UDP Tilt Hydrometer (my way…)

Floater & stand

Below is a more technical explanation of the Floater. To see the ‘user-manual’ style page, its here

The physical electronics hardware consists of:

  • ESP12S module (WiFi connectivity and computing power)
  • ATtiny1614 (low-power companion processor)
  • DS18B20 (temperature sensor)
  • MPU6050 accelerometer module

Design targets for this were:
Simple circuitry, easy to build at home, readily available parts, no APP required.

I’m not much of a fan of apps so I wanted to be able to do everything using a normal web-browser (setup and configuration).

The electronic components are mounted on a small printed-circuit-board (PCB) that is in turn mounted on a 3D-printed 2-part carrier (see the user manual for pics).

The battery compartment is one part of the carrier and the actual circuit-board mount is the other. The two items are stuck together. This allows for some re-positioning of the PCB mount relative to the battery section for minor weight distribution adjustments.

The main balance adjustment for operational use is by the long screw at the lower (when deployed) end of the carrier.

If the screw is wound into the carrier body (made shorter), this lets the weight move down lower and so moves the tube more towards the vertical.

If the screw is wound out (made longer) the weight moves away from the bottom and so the tube end sits higher in the water, moving towards the horizontal.

This simple adjustment method allows for a surprisingly accurate angle adjustment. Once set, removing and replacing the carrier from the tube has little effect on the angle. The weight of the carrier & batteries always lets the carrier freely find its lowest point in the tube and rests the adjustment screw-head in the curved bottom. The adjustment screw is aligned on the tube axis so naturally sits in the lowest point on the curved end.

The device is powered by two 600mA-h LiFePo4 batteries (in parallel). This particular battery chemistry has advantages in 3.3V electronics.

For a conventional LiPo battery, when fully charged the voltage is a nominal 4.2V. This is too high to use directly for 3.3V electronics so a voltage regulator is required.

Voltage regulators have losses and inefficiencies. Even when the circuit is in low-power ‘sleep’ mode, the voltage regulator consumes power. It might not be a lot, but it adds up over time. These regulators also have a dropout voltage so if you feed it 4.2V in and the WiFi unit starts transmitting, the dropout could be 0.3~0.4V. It sounds like not-much, but it is significant. The high powered pulses used during WiFi transmission could cause the WiFi chip to lock up or reset if the voltage drop in the regulator becomes too much.

LiFePo4 cells have a lower fully-charged voltage. Most chargers consider them fully charged at 3.65V. If you sit them aside for a few hours, this relaxes to a comfortable 3.4-ish volts. These are fine to use directly without a regulator, so no parasitic ongoing drain or voltage drop that is associated with linear regulators.

Another type of regulator is a micropower switching regulator. Some of these are very good now in terms of efficiency but the physical size and style of the actual components make them very unfriendly for DIY home use. It also adds to the component-count and takes up space on the PCB.

I opted for simplicity and low component count. Ease of manufacture.

The electronic components are able to use almost the complete voltage range (charged to discharged) of LiFePo4 batteries.

The low-voltage cut-off I choose is 2.9V (not a full discharge). 2.5V seems to be a common figure for fully discharged but if they are discharged less, they last longer (in terms of charge cycles). Greater than 800 charge-cycles is realistic. That’s a lot of beer!

So what makes this different from other similar offerings?

Others try to do everything in the one device. As far as I understand, they communicate directly to perhaps an online logging site, or a brew-site with logging. They use internet friendly network protocols (TCP/IP) with assured data packet delivery. They are designed to directly communicate over the internet.

The duration of a ‘wake-up and send data’ transaction (start to end) can be multiple seconds. Its very dependant on external conditions on the internet and the site you are sending the data to. If you want to send data to more than one place then the wake time extends to suit. The timing can be fairly fluid, and long.

Direct internet communication can certainly be very useful but there is a power-consumption penalty to pay for the convenience.

This one (the Floater) is more of a ‘component’ in a system.

It uses UDP broadcasts to send its data. The data is ONLY available in the local network. UDP Broadcast packets are not passed-out to the internet by your home router. It is still easy to log stuff to the internet though.. (more on this later).

UDP is fast. The typical complete duration of a Floater ‘wake, get data, send, back to sleep’ is 265~280ms on my very ordinary home network.

This is a typical 12-hour slice of floater wake-to-sleep times. The time stated above is from a reset-pulse (to wake the ESP8266), to the ESP going back to deep-sleep.

Most of the connections are 265~280ms. Now and again a longer one appears, probably due to short term WiFi congestion. Also there is occasional gaps with missing packets.

Using UDP has pros and cons…


  • Its very fast, minimal data overhead. Basically send-and-forget. No receive function used.
  • UDP broadcast packets.


  • No assured data delivery (so occasional lost packets).
  • Not able to directly log/send data to the internet.

So are lost packets actually a problem?… In real use, no.

The floaters are tracking a change in SG that happens over 1~2 weeks so the now-and-again lost packet becomes pretty much irrelevant. If you HAVE to get every transmitted packet, this may not be the device for you.

If you set the reporting rate to 60-min, 3 lost packets in a row would leave a bit of a gap, so not great. Still not actually going to stop you seeing the curve though.

The simple workaround is to increase the report rate. If set to 10-min then a bunch of lost packets would be pretty invisible over 2 weeks.

When set to 5-min and used on a non congested network (so mostly fast connects like above) the projected battery life is about 7~8-months continuous running. At the time of writing this, I have not run one for that long yet. (See the POWER USE section below…)

UDP Broadcast packets: (oversimplification warning…)

Most network/wifi transactions have a source and a destination. Its the backbone of the internet. If the data packets did not have a ‘source/destination’ attached to them, you would not be able to receive web-pages, get you email or use most of the WWW functions we take for granted.

Broadcast packets have a source but no destination.

Perhaps another way to phrase it is everywhere on the local network is the destination. Your home network has lots of broadcast packets floating around on it. The functionality is used widely for certain computer-network background operations.

The underlying (individual device) software that runs network operations usually allows devices on a network to accept broadcast packets. The receiving machine (everything on the local network!) looks at the data packet and checks it for a ‘port’ number. If the receiving machine happens to be expecting data (listening) on the particular port number, it accepts the data packet and passes it in to the relevant software module. If it is not expecting anything with the packet’s port number, the data is simply/silently discarded.

So the data packets transmitted from the floater go to everything on your local network at whatever rate you have configured it for (1 to 60-min). Its not a big deal, occasional data packets, not a flood of data.

Almost everything just discards the data. Only network devices set to ‘listen’ on the particular port number actually take it in.

This is pretty useful.

It means multiple devices can listen to, and then use the data for separate reasons, at the same time.

  • An ESP01 device can read the broadcast packets then post the data to the internet in the format of your choice. Because its removed from the sensor, it no longer matters if its a slow process.
  • A Raspberry-pi can ingest the packets directly into InfluxDB then display with Grafana. Good for long-term data capture and review (I use this a lot).
  • A temperature/angle display can be constructed as a stand-alone indicator where you can conveniently view it.
  • Temperature can be extracted and used as part of your process control (and/or angle).

Once the data is on your local network it can be used in multiple ways. Distributed functionality or perhaps a central controller. Both options are viable.

You are able to get a good feel of how your network is behaving by looking at the connection times (Uptime) and lost packets. Every packet is numbered. From power-on it starts at 1 so you can track how many gaps you get in the count.

Each floater has a unique ID number in its data packet so your not restricted to 1 or 2 or 3 units. There will probably be a maximum number you should use in a small area, but 20~30 or more, reporting at 10-min intervals doesn’t seem unrealistic. It would make sense to dedicate a WiFi network to the floaters for a larger installation.

Packet structure:

Floater data packets are sent as plain text in InfluxDB line-format. This is what a packet looks like…

BBfloater,loc=6 X=-558,Y=129,Z=16545,T=24.0625,V=3.292,XD=-1.92,YD=0.46,N=1340,UT=265,AX=-554,AY=132,AZ=16525,R=1
  • BBfloater,loc=6 This is the floater ID. Its a BrewBoss floater, number-6. The number is on the floater carrier
  • X=-558,Y=129,Z=16545 Sensor axis values
  • T=24.0625 Temperature
  • V=3.292 Battery voltage
  • XD=-1.92,YD=0.46 Roll and Tilt values (in degrees)
  • N=1340 Packet count since powered-on
  • UT=265 Uptime for this packet (in ms). From reset (to wake ESP), till back to sleep
  • AX=-554,AY=13,AZ=16525 X/Y/Z axis rolling average of the configured number of samples (2 to 20)
  • R=1 Run indicator. The last group of packets that get sent before a low battery shut-down have R=0

One of the reasons the Floater is so efficient is because some of the required processing is offloaded to a low power companion processor.

The ESP8266 is more than capable of doing all the processing but the downside of that is it uses a lot of battery power. Keeping the ESP in deep sleep for as long as possible is good!

Since the ESP is only awake for (usually) less than 300ms, it can not use the temperature sensor. A full resolution temperature reading takes about 750ms so this is achieved by the companion processor waking up, initiating the temperature conversion, going back to sleep for 1-sec, waking again and reading the temperature result.

The companion processor (an ATtiny1614) is actually the overall controller for the Floater. It is responsible for timekeeping, running the accelerometer and reading the temperature.

For a reporting rate of 1-min, a simplified timeline is…

  • At 59-sec, ATtiny wakes up, starts temperature conversion, wakes up the accelerometer and starts it running, Attiny goes back to sleep for 1-sec.
  • Attiny wakes up, reads temperature result, reads X/Y/Z axis data, reads the battery voltage, shuts down the accelerometer, sends reset pulse to wake up ESP then waits while ESP boots up.
  • When ESP flags its ready, ATtiny sends its collected data to the ESP then goes back to sleep for the configured report-rate (-1 sec). ATtiny’s job is done for this cycle.
  • ESP is waiting for WiFi connection, while waiting it repackages and formats the data, creates the data packet, still waiting… (if times-out, go back to deep-sleep)
  • WiFi connects, ESP sends UDP broadcast packet then shuts down into deep-sleep mode.
  • That completes the cycle. ESP is only active for (typically) 265~280ms.

Power use:

This is a power-consumption graph of an ESP wake-up event (captured using a Nordic PPK2 power profiler).

The grey area starts with the ESP being woken by the ATtiny. It finishes when the ESP goes back to deep-sleep.

The ESP boot process hands over to the user sketch at the start of the first high current peak.
At the bottom of the picture, the blue horizontal line rises at the sketch start and falls when WiFi is actually connected.
The very last high current peak is the UDP data packet being sent..

A full 5-min cycle…

The power profiler shows the actual charge used for the 5-min cycle so this makes it fairly easy to calculate how long the battery should last.

Charge used is 25.95 milli-Coulombs for the 5 min cycle.

To convert this to mA-h, simply divide by 3.6 so 0.02595/3.6 = 0.007208 mA-h.

So 1 hour uses 0.007208 mA-h x 12 = 0.086496 mA-h

1 day is 2.075904 mA-h

30-days = 62.277 mA-h

Now the bit that gets missed….

Batteries have a self-discharge rate. For these (same as LiPo’s) about 5% a month. Battery capacity is 1200mA-h so 5% is 60mA-h that just vanishes. The self discharge is almost the same as the actual power consumption!

Also, the batteries are not fully discharged in use, only by about 85%. This gives a useable capacity of 1020mA-h

So monthly useage is 62.277 for the electronics and 60 for self discharge so 122.277mA-h

1020/122.277 = 8.3 months.

The assumption here is that all wake-events are the same as above. This is obviously not going to be the case.
Some will be more, some less but the battery life figure should be a reasonable approximation for real life use. It is calculated from real observed data.

A poor network environment could substantially reduce this figure so good WiFi is the main key factor for long battery life.

On WiFi quality, this is what happens to battery voltage when the WiFi dies for 22-min..

A few lost packets noticeable (the small gaps in the lines) but this is not too unusual.

Then the WiFi goes off.

What the floater tries to do is still connect to a now non-existent WiFi network so each time it tries, it times-out.
This wait-time is set when you configure the floater. Between 2 and 4 sec is a reasonable number.
You could set it lower but the price is more missing packets. This setting is network-condition dependant. I mostly use 2500ms.

The repeated timeouts, 22 of them, (periods of higher power draw) causes the battery voltage to droop slightly (by 18mV) but when the WiFi returns you can see the battery recovers to just 4mv below where it started. If the battery is near the end of its working voltage, the droop can be larger and so cause premature shut-down due to low battery voltage.

If its only a small number of fails, the battery voltage droops less (if at-all) and usually rises back up to the original value. After higher rate discharge events, voltage can continue to creep back up for hours.

If your WiFi was off for a day it will have a substantial impact on the battery charge state. (note to self, try it!)

Internet logging:

So how do you get this data to the internet?

Consider a setup where the Floater reports every 5-min. This is probably overkill for reporting to an internet logging service.

Because the broadcast packets are zipping around on your WiFi, it’s fairly trivial to receive this data on another ESP8266 module. An ESP01 is fine for this, or a WeMos mini. I’ll call this device a Logger.

What I do is when a data packet arrives is: I save all the variables and assign a lifespan to the group. Every time new data arrives, it overwrites the last lot and the lifespan is reset. As part of my loop, I check if the data lifespan has expired and set flags appropriately.

If I’m logging to the internet every 30-min, when the logging time comes round, I check the data store and if its lifespan has not expired, use it to post to the internet.

As well as basic logging, the Logger can perform other calculations on the data. The obvious one being angle to SG.

Since its pretty simple to set the reference-angle to within 1-deg I’m hoping (not tried yet) that it can be done with a fixed table, rather than having to mess about with spreadsheets and equations. So far, I just look at angle to see when fermentation has stopped. I’m not that bothered about what the SG actually is. Its not like I’m not going to drink it because I dont know the figure (unless it tastes really bad!)

But for the sake of completeness, I’ve added it to my list of ‘things to do’.

2 thoughts on “UDP Tilt Hydrometer (my way…)

  1. Hi,
    I have been unable to find any way to get one of these. There does not seem to be any files to download or method to purchase/build one.
    Are these actually in production?
    I am quite keen to get one and use it with the BrewPi system. I asked in the forum and it would seem to be compatible but needs a bit of extra work to allow it to properly integrate.
    Is this something you have done or know about? Is there any Arduino examples you are willing to share to make this possible?

    • HI Stewart,
      Thanks for your interest. Its been a slow project for me but things are moving ahead well now.
      This is going to be something I sell rather than a DIY freebie.
      Its a fairly new design and its only in the last couple of months that it has been used ‘in the wild’ so to speak. I have a couple of friends who are trying them out and I’m collecting data to see how things are behaving.
      One of them does pressurised brewing (in a commercial keg) and the other is more old-school in plastic buckets. Both have produced worthwhile learnings for me.
      If you are familiar with the other styles of tilt-hydrometer out there you will see that this one is a bit different.
      This one actually sends the full 3D x/y/z/ data (and more) which (to my surprise) turned out to be quite useful. The X data in particular can be used as an indicator of yeast activity. To my amazement, the bubbles produced by the fermentation actually rock the floater from side to side in a very measurable way. I will post some of the collected data about this soon.
      I had a bit of a read through the BrewPi site docs and in theory it will work but not (as you have discovered) without some tweaking.
      The simplest solution is to collect the broadcast packets using a ESP01 or Wemos-Mini, pick out the data you want and then use MQTT to send to the BrewPi. This means you can run a stock-standard BrewPi and it will (should..) just work.
      The alternative would be to receive the broadcast packets directly on the Pi and ingest the data that way.
      This could be by possibly direct reception into Victoria Metrics which does work, this is something I have tried (using InfluxDb line protocol). This will certainly save the data into the database but not perhaps where you can easily extract it within the existing BrewPi system. I don’t have enough experience (ie none!) with a BrewPi system to give a helpful answer to that.
      The other method (in the Pi) would be to run a service that listens to the relevant port and then posts (internally) to the BrewPi system in a manner that is understood and meaningful. The API docs show how to do this.
      It seems like it should be not-complicated, but again, never done it so don’t know for sure. Probably a python script or similar but I’m just guessing.
      If you are interested in getting one to try the I have a limited number available for ‘testers’. I have 11 built and ready to go and the parts to make another 20.
      These are not going to be free as I’d at least like to cover the hardware cost (and a bit for my effort), but certainly less than the available offerings elsewhere, bearing in mind that its built, tested and calibrated.

      What you need depends on how you brew and your level of expertise. If you know how to deal with (ie receive and process) the broadcast packets and you are not in a metal can (a metal keg) then the floater is all you need (obviously you need WiFi!).
      If you are in a metal keg, which is a fairly good WiFi shield, you will most likely need a local relay.
      My tester who uses the commercial metal beer kegs needed a small relay on top of the keg. It didnt help that his setup is in his shed, quite far away from his WiFi AP.
      Its simply a Wemos-Mini and a basic sketch that runs in AP+STA mode so the floater logs on to the local relay and then it in turn connects to his house WiFi.
      Its a very simple Arduino sketch that listens to the floater then posts the data (some of it) to ThingSpeak.
      He gets the best connection times!, better than mine, Consistently 250~260mS.
      When I get the chance, I will put up a sketch that at least lets you post to ThingSpeak.
      If you would like to be a ‘tester’ then please get in touch.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.