Water Salinity-meter

by bdvbart in Circuits > Arduino

13770 Views, 4 Favorites, 0 Comments

Water Salinity-meter

WhatsApp Image 2021-09-19 at 17.38.28.jpeg

Hello,

In this Instructable we will explain in detail how to build a water salinity-meter. This was a project for the minor Delta Expert at the Delft University of Technology. It is a relatively low cost and easy sensor to build. We made it to look nice, but it can be done in any other way, as long as the circuit and code are the same.

The sensor works by measuring the resistance between two electrodes. It also measures temperature to compensate for temperature changed resistance.

Good luck on this adventure!

Supplies

- Arduino Uno (Any brand will do)

- Breadboard, welding clamps or perfboard

- (Jumper) cables

- Three resistors (10k Ohm, 1k Ohm and 4.7k Ohm)

- Temperature sensor (for example DS18B20 waterproof)

- Two copper electrodes (like nails or pins)

- Button

- LCD display for Arduino (for example I2C)

- Soldering

- Hot glue gun

- Laptop for coding

Optional:

- Powerbank for use without laptop

The Resistivity Sensor

Schermafbeelding 2021-09-19 113439.png
Schermafbeelding 2021-09-19 115148.png

The first step in making the salinometer is the wiring. There are 4 seperate parts to the sensor; the resistivity sensor, the thermometer, the button and the display.

Wiring

Let's start with the resistivity sensor. For this we need the following:

  • Two electrodes
  • 1k Ohm resistor
  • (Jumper) cables
  • Arduino UNO
  • Breadboard / welding camps / perfboard and soldering equipment

Since the aim is to measure seawater, we want to avoid electrolysis which makes the electrodes oxidize and that in turn will make the resistance increase rapidly over the first second of the measurement. To avoid electrolysis we put an AC current over the electrodes. Since an Arduino is DC we have to use a trick to make something that is close to AC; we use two digital pins between which we rapidly switch around the polarity. A HIGH pin will be the positive and a LOW pin will be the negative.

See the schematic for the wiring. Note that we use a "known" resistance which is being used to measure the "unknown" resistance of the water.

Coding

We use a relatively simple code to measure the resistivity. It consists of two parts. One part switches around the polarity and the other takes a measurement when the 8-pin is HIGH and the 7-pin is LOW.

The code for the sensor alone to work is below. This can be used to test if it is working.

Tip: Use a known resistor on the electrodes to see if the values from the serial monitor are correct

int analogPin = 0;
int dtime = 500;
int raw = 0;
int Vin = 5;
float Vout = 0;
float R1 = 1000;
float R2 = 0;
float buff = 0;
float avg = 0;
int samples = 5000;

void setup(){
  pinMode(8,OUTPUT); // define ports 8 and 7 for AC 
  pinMode(7,OUTPUT);
  Serial.begin(9600); // start serial
}

void loop(){
  float tot = 0;
  for (int i =0; i<samples; i++) {
    digitalWrite(7,HIGH);
    digitalWrite(8,LOW);
    delayMicroseconds(dtime);
    digitalWrite(7,LOW);
    digitalWrite(8,HIGH);
    delayMicroseconds(dtime);
    raw = analogRead(analogPin);
    if(raw){
      buff = raw * Vin;
      Vout = (buff)/1024.0;
      buff = (Vin/Vout) - 1;
      R2= R1 * buff;
      //Serial.print("Vout: ");
      //Serial.println(Vout);
      //Serial.print("R2: ");
      //Serial.println(R2);
      tot = tot + R2;
    }
  }
  avg = tot/samples;
  Serial.print("The average resistance is: ");
  Serial.print(avg);
  Serial.println(" Ohm");
}<br>

Wiring the Button

Schematic with button.png

Now to we add a button to start a measurement. We need the following components:

  • Button
  • 10k Ohm resistor
  • (Jumper) cables

The wiring is above.

Adding the Thermometer

Schematic with temp.png

For this example the DS18B20 waterproof digital thermometer was used. Any other thermometer can be used, but in this guide only the wiring for the DS18B20 will be provided.

Required components:

  • Thermometer
  • 4.7k Ohm resistor(or any other if specified by other manufacturer)
  • (Jumper) cables

The wiring is above.

LCD Display

Schematic with LCD.png

Finally we add the LCD display. We used the I2C display, which only has 4 pins. In this guide only the wiring for that display will be shown(Please note that in the schematic another LCD display was used. This is only for visuals).

Required components:

  • LCD display
  • (Jumper) cables

The wiring is shown above.

Coding

We already showed a bit of code after the wiring of the resistance sensor to find out if everything was working. Now we will add the full code to work with the entire sensor.

#include <Wire.h> //These two libraries are for the LCD
#include <LiquidCrystal_I2C.h>
#include <OneWire.h> //These two libraries are for the temp sensor
#include <DallasTemperature.h>

//Data wire from thermometer is plugged into digital pin 12 on the Arduino
#define ONE_WIRE_BUS 12
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

LiquidCrystal_I2C lcd(0x27, 16, 2); 

int analogPin = 0;
int dtime = 500;
int raw = 0;
int Vin = 5;
float Vout = 0;
float R1 = 1000;
float R2 = 0;
float buff = 0;
float avg = 0;
int samples = 5000;
int state = 0;
int button = 0;
int buttonPin = 5;

float CalibrationTemp = 21.0;	//This is the temperature from which calibration is done. Change if needed
float CorrectionFactor = 1.02;	//Correction factor found by us. Change if needed
float dTemp = 0;		//Initial value for temperature difference

//State 0 = rest
//State 1 = measure
//State 2 = print


void setup(){
  sensors.begin(); // start up temperature library
  pinMode(8,OUTPUT); // define ports 8 and 7 for AC 
  pinMode(7,OUTPUT);
  pinMode(12,INPUT);		//Setup the thermometerpin as input
  pinMode(buttonPin,INPUT);	//Setup buttonpin as input
  Serial.begin(9600); // start serial

  lcd.begin(); //start up LCD
  lcd.clear(); //clear LCD memory
  
}

void loop(){
  //REST
  button = digitalRead(buttonPin);
  if (button == HIGH) {		//Check is the button is pressed and go to another state to start measuring
    lcd.clear();
    lcd.setCursor(4,0);
    lcd.print("Starting");
    lcd.setCursor(2,1);
    lcd.print("measurement");
    state = 1;
  }
  
  
  //MEASURE
  if (state == 1) {
    float tot = 0;
    for (int i =0; i<samples; i++) {
      digitalWrite(7,HIGH);
      digitalWrite(8,LOW);
      delayMicroseconds(dtime);
      digitalWrite(7,LOW);
      digitalWrite(8,HIGH);
      delayMicroseconds(dtime);
      raw = analogRead(analogPin);
      if(raw){
        buff = raw * Vin;
        Vout = (buff)/1024.0;
        buff = (Vin/Vout) - 1;
        R2= R1 * buff;
        //Serial.print("Vout: ");
        //Serial.println(Vout);
        //Serial.print("R2: ");
        //Serial.println(R2);
        tot = tot + R2;
      }
    }
    avg = tot/samples;
    Serial.print("Average resistance is: ");
    Serial.print(avg);
    Serial.println(" Ohm");
    state = 2;

    // Send the command to get temperatures
    sensors.requestTemperatures(); 
    float temp = sensors.getTempCByIndex(0);
    //print the temperature in Celsius
    Serial.print("Temperature: ");
    Serial.print(temp);
    Serial.print("C  |  ");
    dTemp = temp - CalibrationTemp;
    avg = avg * pow(CorrectionFactor, dTemp);
    Serial.print("Corrected resistance is: " + String(avg));
  
  }

  //PRINT
  if (state == 2) {	//Here the value found is printed and the values for different sorts of water are defined
    if (avg > 2000) {
      Serial.println("This is demineralised water.");
      lcd.clear();
      lcd.setCursor(1,0);
      lcd.print("Demi water");
      lcd.setCursor(1,1);
      lcd.print("AVG: " + String(avg));
      
      delay(1000);
      state = 0;
    }
    else if (avg > 1000) {
      Serial.println("This is fresh/tap water.");
      
      lcd.clear();
      lcd.setCursor(1,0);
      lcd.print("Tap water");
      lcd.setCursor(1,1);
      lcd.print("AVG: " + String(avg));
      
      delay(1000);
      state = 0;
    }
    else if (avg > 190) {
      Serial.println("This is brackish water.");
      lcd.clear();
      lcd.setCursor(1,0);
      lcd.print("Brackish water");
      lcd.setCursor(1,1);
      lcd.print("AVG: " + String(avg));
      
      delay(1000);
      state = 0;
    }
    else if (avg < 190) {
      Serial.println("This is seawater.");
      lcd.clear();
      lcd.setCursor(1,0);
      lcd.print("Sea water");
      lcd.setCursor(1,1);
      lcd.print("AVG: " + String(avg));
      
      delay(1000);
      state = 0;
    }
  }
}<br>

Calibrating

Since the measured resistivity could not immediately give the salinity level of the water, it is required to calibrate the sensor. The very first important step in this process is to have the electrodes at a fixed distance from eachother. The measured resistance will change when the distance between the electrodes changes.

Calibrating was done by taking multiple samples of demineralised water and adding different amounts of salt to them. The resistance was measured. The process was fairly easy, but is necessary to have a working sensor which can also say something about the salinity

The temperature might also need calibrating. Our sensor was already calibrated, so will not discuss calibrating the thermometer in this guide.

Calibrating the correction factor is a bit more work. The correction factor generally lies between 2-4% change in resistance for each degree temperature change. This is however not always correct. The method to find the correction factor is by taking a sample of water and changing the temperature while measuring the resistance. The easiest way to do this is by taking hot water and measuring the resistance while it cools down. From this data a correction factor can be computed. You know your correction factor is correct when the "Corrected resistance" does not change while the water cools down.

Housing and Finishing

WhatsApp Image 2021-09-19 at 17.38.28 (1).jpeg
Gardalux_Stekkersafe___Gardalux_Groen_170740040_K150305315_big.jpg
Behuizing_86_Arduino_LCD.jpg
result.jpg

Since this sensor will be used in water, it is important to shield all electrical components from the water. For this sensor we built three seperate housings; for the electrodes, for the Arduino and wiring and for the LCD display with the button.


The electrodes were put in a black plastic casing with two holes in the front and one in the back. A hot glue gun was used to make everything waterproof. As said in previous step, it is very important to have the electrodes at a fixed distance from eachother. Make sure they are tighly glued or fixed in place.

The Arduino and wiring were put in a protective box for plugs. This was an exact fit and waterproof at once. You might find something else like this, but for us this was perfect. From one side the power cable could be let in and from the other side the electrodes and thermometer cables could be let out.

The LCD and button were put in a case made for the LCD display we conviently had lying around.

With some hot glue everything was "neatly" put together and made into one sensor.


P.S. Any of these housings could of course also be self-designed and manufactured(3D printed).