Hi everyone,
I’m working on an industrial project for milk silos and I’d like some help understanding a measurement issue with a 4–20mA pressure sensor (Vegabar) and also some advice about alternative sensors / approaches for silo level.
1. Hardware / Setup
- Central device: Heltec WiFi LoRa 32 (V3) – ESP32 + SX1262 LoRa
- Remote nodes (per silo):
- ESP32 board
- Vegabar 28 (4–20mA pressure transmitter, range 0–2.5 bar)
- ADS1115 16-bit ADC
- Shunt resistor: 150 Ω, 0.1%, 0.5 W (metal film) to convert 4–20mA → voltage
- Extra resistors: 10 kΩ and 1 kΩ (pull-downs / dividers, etc.)
- Power:
- 24 V supply for the Vegabar (current loop)
- 5 V / 3.3 V supply for ESP32 and ADS1115
- Communication:
- Each node reads the Vegabar via ADS1115, computes / sends:
- Raw voltages (V0, V1)
- Optional pre-computed P / h / L / T
- Data is sent by LoRa to the Heltec central, which uploads everything to Blynk.Cloud.
- Each node reads the Vegabar via ADS1115, computes / sends:
- Smartphone: Android 16
- Blynk app: latest Blynk IoT app from Play Store
- Blynk Library: latest version from GitHub / Library Manager
- Server: Blynk.Cloud (I’m in Argentina, not sure which exact region)
2. What I’m doing with the Vegabar / ADS1115
On the remote node, the Vegabar 28 (4–20mA) current loop goes through a 150 Ω shunt resistor, so:
- 4 mA → about 0.6 V on the shunt
- 20 mA → about 3.0 V on the shunt
This voltage is measured by the ADS1115 and sent via LoRa as V0 (pressure channel) and V1 (temperature channel, with a second 4–20mA loop).
On the central (Heltec WiFi LoRa 32 V3) I receive this payload:
<ID>;P=...;h=...;L=...;T=...;V0=...;V1=...
And I recalculate the physical values using:
- A per-silo zero in volts (
blynkZeroV[slot]) coming from a Blynk numeric input (V130…V134, etc.) - A per-silo area in m² (
blynkAreaM2[slot]) also from Blynk
The formula is:
// V0 = raw volts from ADS1115 (pressure channel)
// zV = "zero" volts (when silo is empty), configured from Blynk
float V0corr = v0_raw - zV;
if (V0corr < 0) V0corr = 0;
// Rshunt per slot (default 147 Ω, or measured value like 147.9 Ω, 149.9 Ω, etc.)
float I0_mA = 4.0f + mA_from_V_slot(V0corr, idx); // ΔI + 4 mA base
I0_mA = clamp_mA(I0_mA); // 4..20 mA
// Pressure in bar
float Pbar = ((I0_mA - 4.0f) / 16.0f) * P_MAX_BAR; // P_MAX_BAR = 2.5 bar
// Height in meters (using milk density + g)
float h_m = (Pbar * 100000.0f) / (RHO_MILK * G_ACC); // RHO_MILK = 1030 kg/m³
// Liters = h (m) * area (m²) * 1000
float L_L = h_m * area * 1000.0f;
I also use individual Rshunt per silo (measured with a multimeter):
static const float RSHUNT_DEFAULT = 147.0f; // ohms
float rshuntSlot[MAX_NODES]; // NaN => use default
static float mA_from_V_slot(float V, int slotIdx){
float R = (!isnan(rshuntSlot[slotIdx]) && rshuntSlot[slotIdx] > 1.0f)
? rshuntSlot[slotIdx]
: RSHUNT_DEFAULT;
return (V / R) * 1000.0f;
}
And the zeros / areas are set from Blynk virtual pins, one per silo.
3. What works and what is the problem
Things that work well:
- LoRa communication ESP32 node → Heltec central is stable.
- Blynk connection is stable (with watchdogs and timers).
- The Blynk dashboard shows P, h, L, T, RSSI for each silo.
- The web UI (local port 8080) shows all silos and a “wash mode” (where I temporarily force level to zero during cleaning).
The problem is with the Vegabar measurement vs. real silo level:
- I’ve zeroed the silo when empty (using the raw
V0value, stored as zero in Blynk). - I’ve configured a precise silo area (for example: Silo 9 → 19.500 m²; Silo 8 → 16.400 m²).
- I’ve measured the shunt resistors and set the exact value for each slot (
rshuntSlot[1] = 147.9f; rshuntSlot[8] = 149.9f, etc.).
However, I still see a difference between:
- What the Vegabar should be reporting according to its datasheet / pressure range, and
- The actual liters in the silo (based on real usage / truck unloads, etc.).
Sometimes the error is small, but in some operating ranges the liters don’t match what we expect (especially near the top or in certain levels). I know some of this can be due to:
- Silo geometry (not a perfect cylinder, conical bottoms, etc.)
- Milk density variations with temperature
- Possible non-linearity of the pressure transmitter or mounting height
But before I redesign the whole thing, I’d like to check with the community:
- Does the way I’m converting 4–20mA → pressure → height → liters look OK to you?
- Would you do the math directly on the node instead of the central?
- Any better way to handle zero / span in code?
- Has anyone used Vegabar (or similar 4–20mA pressure transmitters) for silo level with ESP32 + Blynk?
- Any typical tricks (filtering, averaging, calibration steps) I’m missing?
- Would you recommend a different type of sensor for this use case (milk silos, several meters high), that plays well with ESP32/Blynk? For example:
- Ultrasonic level sensors
- Radar level sensors
- Load cells at silo legs
- Other digital (Modbus/RS-485) transmitters that you’ve successfully used with Blynk
4. Example serial output
Here is an example of the serial output from the central when receiving data (just as a reference):
[RAW] SILO-9 V0=0.57600 V zero=0.56889 V area=19.500 m2
[RX] SILO-9 RSSI= -93 SNR= 10 P=0.175 bar h=1.728 m L=34221 L T=4.5 C (slot 8) [recalc]
[RAW] SILO-8 V0=0.57000 V zero=0.56377 V area=16.400 m2
[RX] SILO-8 RSSI= -90 SNR= 9 P=0.160 bar h=1.580 m L=25912 L T=4.3 C (slot 1) [recalc]
(If needed I can post a longer log showing the discrepancy between expected vs. measured liters.)