Inline Digital Hydrometer

20,077

152

7

Posted in TechnologySensors

Introduction: Inline Digital Hydrometer

About: Ugly pirate roaming the seas in search of Treasure.

Many industrial processes require chemical analysis of a fluid and sometimes just knowing it's density is all that is necessary to know what it's main constituents are. This is particularly true in whiskey production, for example.

Here, I am using a very accurate pressure sensor which is connected to some elaborate looking copper pipework to measure the weight of a column of fluid of set height. As long as the ambient pressure and fluid temperature does not change, the density of the fluid will be directly proportional to the pressure generated by the column of fluid. Simple?

Step 1: How It Works

The distillate or 'alcohol' from the condenser enters the top chamber of the gadget and pours down a small internal pipe drawn in green. If this pipe were not here, the alcohol would just flow straight out of the overflow and not circulate into the main body of the device and there would be a large error in the readings.

So, once the device is full of liquid, the flow of fresh liquid down the green pipe causes the 'old' liquid to be pushed out so that we are always measuring the fresh stuff.

The small bore sensor tube is attached to a vertical 'anti capillary' tube, which runs parallel to the main pipework and goes to the HSCDRRN005NDAA5 pressure sensor in the control panel which has barbed fittings on it for very small pipes. If the small flexible pipe was connected directly to the bottom of the gadget it would fill up with fluid and not empty properly due to the forces of capillary action keeping it in the pipe. This capillary action is not a problem in a bigger bore pipe and all we see is a meniscus.

Just to make things even more complicated, there's a solenoid valve at the very bottom of the device which can be automatically opened to dump the contents of the device at different stages of the process.

As the process continues, the 'alcohol', which is actually composed of mostly alcohol and water with a few other weird and wonderful liquids in much lower concentrations, becomes weaker and weaker with more and more water and strange oily chemicals called 'fusils'. It's really useful to be able to measure the concentration of the distillate being produced at all stages of the process as we don't want too much water or too many other heavy chemicals as some of these can give us a bad hangover! (But an interesting taste).

Step 2: Parts

  • 1DS18B20 1-Wire Temperature Sensorpart # DS18B201
  • ADS1115 16-bit ADC Breakout1
  • HSCDRRN005NDAA5chip label HSCDRRN005NDAA5; pins 8; true; hole size 1.0mm,0.508mm; package DIP (Dual Inline) [THT]; pin spacing 300mil1
  • Piezo Speaker1
  • LCD screenpins 16; type Character1
  • Arduino Nano (Rev3.0)type Arduino Nano (3.0)1
  • Rotary Potentiometer (Small)maximum resistance 100kΩ; track Linear; type Rotary Shaft Potentiometer; package THT; size Rotary - 9mm1
  • 100Ω Resistor tolerance ±5%; bands 4; package THT; pin spacing 400 mil; resistance
  • 100Ω14.7kΩ Resistor tolerance ±5%; bands 4; package THT; pin spacing 400 mil; resistance
  • 4.7kΩ11kΩ Resistor tolerance ±5%; bands 4; package THT; pin spacing 400 mil; resistance 1kΩ

Step 3: Arduino Setup

As can be seen, the setup features a ADS1115 16-bit ADC, an Arduino Nano and a HSCDRRN005NDAA5 chip. The 16-bit ADC gives better resolution than the normal Arduino 8 bit, particularly as the pressure sensing chip measures both positive and negative pressures.

Step 4: Arduino Code

There's nothing too fancy about the code, except that I've made a custom LCD character for a delta sign and the nano takes 30 readings from the pressure sensor before calculating an average.

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_ADS1015.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define ONE_WIRE_BUS 12
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress pipeProbe01 = { 0x28, 0x1E, 0x28, 0x08, 0x00, 0x00, 0x80, 0x00  };
float tempC;
float previousTempC =0;
float deltaTempC =0;
Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
// Adafruit_ADS1015 ads;     /* Use this for the 12-bit version */

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
byte delta[8] =
{
  B00000,
  B00100,
  B00100,
  B01010,
  B01010,
  B10001,
  B11111,
  B00000
};
const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

long sensorValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)
int outputValueMin = 1000;
int outputValueMax = -1000;
int i=0;
int c=0;
int x=0;
int z=0;
int y=0;
int tempCount=0;
float av=0;
long totalAdjustedOutputValue=0;
int adjustedOutputValue = 0;
float hrs=1;
void setup() 
{
  lcd.createChar(1, delta);
  lcd.begin(20, 4);
  lcd.setCursor(2,0);  
  lcd.write(1);
    // locate devices on the bus
  Serial.print("Locating devices...");
  sensors.begin();
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");

  if (!sensors.getAddress(pipeProbe01, 0)) Serial.println("Unable to find address for Device 0"); 
  // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(pipeProbe01, 12);
 
  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(pipeProbe01), DEC); 
  Serial.println();
  delay (2000);
  
    pinMode(8, INPUT_PULLUP);   // Momentary switch
    ads.begin();

    
  // initialize serial communications at 9600 bps:
    Serial.begin(9600);
  sensors.requestTemperatures(); // Send the command to get temperatures
  printTemperature(pipeProbe01);
  previousTempC = tempC;
}

void loop() 
{ 
  y=5;
  z=10;
  if (adjustedOutputValue > 1000)
  {
    while (y<z)
    {
    tone (11,200*y,50);
    y++;
    delay(50);
    }
  }

  sensors.requestTemperatures(); // Send the command to get temperatures
  printTemperature(pipeProbe01);
  
  int pushButton = digitalRead(8);
    if (pushButton == HIGH) 
    {
      Serial.print("Switch Off");
    } else
    {
      Serial.print("Switch On");
      x = outputValue;
      outputValueMin = 10000;
      outputValueMax = -10000;
      c = 0;
      totalAdjustedOutputValue =0;
      av=0;
      hrs=0;
    }
      Serial.println(" ");
  int16_t adc0, adc1, adc2, adc3;

 // adc0 = ads.readADC_SingleEnded(0);
 // Serial.print("AIN0: "); Serial.println(adc0);
 // Serial.println(" ");
     
 i=0;
 c++;
 sensorValue =0;
 while (i<30)
 {
  adc0 = ads.readADC_SingleEnded(0);
  i++;
  sensorValue = sensorValue + adc0;
  delay (50);
 }
  sensorValue = sensorValue/30;
 // sensorValue = adc0;
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 0, 21879, -2008,  2000);
  adjustedOutputValue = outputValue - x;
  // change the analog out value:
  analogWrite(analogOutPin, outputValue);

  // print the results to the serial monitor:
  Serial.print("sensor = ");
  Serial.print(sensorValue);
  Serial.print("\t output = ");
  Serial.println(adjustedOutputValue);

if (adjustedOutputValue > outputValueMax)
{
  outputValueMax = adjustedOutputValue;
}
if (adjustedOutputValue < outputValueMin)
{
  outputValueMin = adjustedOutputValue;
}
  
  totalAdjustedOutputValue = adjustedOutputValue + totalAdjustedOutputValue;
  av = 1.000*totalAdjustedOutputValue/c;
  hrs = c*2.00/60.00/60.00;

if (tempCount ==5)
{
  deltaTempC = tempC - previousTempC;
  previousTempC = tempC;
  tempCount=0;
}
  lcd.setCursor(0,0);  
  lcd.print("                    ");   
  lcd.setCursor(0,1);  
  lcd.print("                    "); 
  lcd.setCursor(0,2);  
  lcd.print("                    ");   
  lcd.setCursor(0,3);  
  lcd.print("                    ");  
   
  lcd.setCursor(0,0);    
  lcd.print("P:");     
  lcd.setCursor(2,0);         
  lcd.print(adjustedOutputValue);  
    lcd.setCursor(11,0); 
    lcd.write(1);
    lcd.print("T:");    
    lcd.setCursor(14,0);    
    lcd.print(deltaTempC);         
  lcd.setCursor(0,1); 
  lcd.print("Max:");  
  lcd.setCursor(4,1);       
  lcd.print(outputValueMax);     
  lcd.setCursor(0,2); 
  lcd.print("Min:");  
  lcd.setCursor(4,2);        
  lcd.print(outputValueMin);    
  lcd.setCursor(0,3);    
  lcd.print("Secs:"); 
  lcd.setCursor(5,3);            
  lcd.print(c*2); 
  lcd.setCursor(11,3); 
  lcd.print("hrs:");  
  lcd.setCursor(15,3);            
  lcd.print(hrs,2);  
  lcd.setCursor(11,1);    
  lcd.print("A:"); 

  lcd.setCursor(13,1);  
  lcd.print(av,3);

  lcd.setCursor(11,2);    
  lcd.print("T:");     
  lcd.setCursor(13,2);    
  lcd.print(tempC);  
  lcd.setCursor(18,2);    
  lcd.print("\337C"); 
     
  delay(2000);
  tempCount++;
}
void printTemperature(DeviceAddress deviceAddress)
{
  tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
  Serial.print(" Temp F: ");
  Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}  

Step 5: Real Life Testing

The hydrometer was tested by hooking it up to my Air Still. It worked fairly well and was very reliable, producing results to +- 5% accuracy. Based on these results, eventually it was eventually incorporated into a fully automatic NanoStillery™. Want to know what a NanoStillery is? Next instructable coming soon!

Please in the competitions - top right - Thanks!

2 People Made This Project!

Recommendations

  • Pocket-Sized Contest

    Pocket-Sized Contest
  • Spotless Contest

    Spotless Contest
  • Trash to Treasure

    Trash to Treasure
user

We have a be nice policy.
Please be positive and constructive.

Tips

Questions

7 Comments

I made a device from Motorola air systems back in the 1988 that looks at fresh water and salt water and then turned the salt on if it to little salt. I had to to use 6' towers of salt water and fresh water. They had both tubes with air running at 1 foot a minute. The the differential went to a controller that tuned on the salt water. I used a device for test the weight on the alcohol.

If I were to build this I would eliminate the tube connecting the pressure sensor to the bottom of the unit. Thus eliminating the random innacuracy caused by the random levels of unknown fluids in the tube. Worst case the tube is filled with liquid to the same level as the liquid in the unit causing a zero pressure reading.

1 reply

What ABV are you aiming for?

I guess you can calibrate against sugar solutions for more dense liquids.

Interesting solution. Is it used industrially? I'm guessing that you're brewing up some water-based cleaning fluid.

1 reply

Yes calibration is the answer!

I don't think it's used industrially - I think that a $2,000 inline refractometer would be used.

For us in US 22mm is 3/4" and 15mm is 1/2" CTS (Copper Tube Size) and do not use galvanized or Black Iron as "reducing socket" use Stainless Steel fittings. All threaded pipe has same designation in US as UK, they only call the copper in mm because of EU. And make sure your stand off fittings are brass, copper or SS or you will get galvanic reaction.

1 reply

Hey thanks for the comment. The UK is going to leave the EU soon so hopefully we'll go back to inches for copper pipe? Don't worry about black iron / galvanised as there's none of these in this design :)