Water level alarm that uses a pressure sensor, sends SMS

Hi!

This is the first version of my "water level alarm".
It is monitoring the water level in a dam.

If the water level gets to high or to low it sends a alarm SMS with the current water level.

The alarm also respond to SMS that is sent to it.
If the message text contains the right command it will respond with a SMS to the sending phonenumber that include the current water level in cm.

All settings (including HIGH level, LOW level, Alarm ON/OFF, phonenumber to send alarm to, clock, calibration) is configured in the menu.

Components used:

ATMEGA8 - acts as a serial LCD and serial keypad. Sends keypresses to master MCU. Master MCU controls the LCD by serial commands.
I used an extra ATMEGA8 because they cost <1$ on ebay.

ATMEGA328 - Master MCU. Checks waterlevel every 5 minute and reads/sends SMS.

MCP3201 - 12bit ADC. The internal 10bit ADC that the ATMEGA MCU has was not good enough for my sensor.

DS1307 - The RTC is used because I save 24h history. By pressing a key you can go back in time and see the water level.

Pressure sensor 4-20ma, 0-0,3bar (0-3m) Realy good sensor!

GSM module TC35 - The module is basic (no GPRS) but has a low price. It works good, I wrote some simple functions to read/send SMS.
I used transistors to convert the modules 2.65v signals to 5v.

I think I will make a version 2 that include a SD-card for long term logging of the water level.
Version 2 will use DS1302 RTC instead of DS1307 because it can trickle charge a supercap or battery.

It would also be fun if I could learn to use Eagle and make a more professional PCB.

I do not hava a picture "in action" but the only thing on the LCD is time & date and the current water level in cm.

Here is two pictures of the project.

Where did you get the sensor from?

Looks great (multi-mcu FTW!) - would be interested to know how much the GSM module was?

What are the limits of water level (in cm) you are measuring?
Was it difficult / can you describe your calibration process?
Is it possible for overflow of the water container to occur?

Nick: I bought the sensor from http://holykell.com/
My sensor is: HPT604

aarondc:

30$, bought it from electrodragon.com (you can also buy it on ebay but electrodragon is great)
This sensor is calibrated to 0-3m but you can get the sensor calibrated any way you want.

My "calibration" is not nessesery. It is a simple function where you can adjust the level in software.
Say the sensor is reporting 95cm but you want it to be 90cm, then you can enter -5 in the "calibration" menu.
Short answer, calibration is not nessesery. The sensor outputs the correct level.

"Is it possible for overflow of the water container to occur?"
I am not sure of your question but the sensor will output 4mA minimum and 20mA maximum.
If the sensor is put 4m below the water level I think the sensor would output 20mA = 3m in my case.
When you order a sensor you can get it in any configuration (eg 0-100m).

What I meant was: you are measuring water going into a water container. What happens when the water container overflows :wink:

I thought the sensor would be for measuring how full a water tank / dam is. Once it's full it's full. Presumably the sensor returns the "highest" measurement. The sensor wouldn't know water is spilling out the side.

I'm also curious how you fixed the sensor in place?

The sensor is placed in a pipe (with holes in) that is fixed.
That way the sensor is protected from objects floating in the water.

Ah nice. Was wondering how you'd place it down the bottom when there was water already in there - this allows you to retrieve it etc too.

how did you manage to "talk" with the tc35 module?? i cant make it.. i tried the "Receive Call" example with no luck..
in Serial monitor i only see "Receive call" and the gsm doesnot do anything... i call the gsm the line seems active but nothing appears in the serial monitor...
Any ideas?

And what the price was for HPT604?

Hi!

The price was 150$ + shipping.

The only way I "talked" to the GSM module was with standard AT commands. I only send and receive SMS with the module.

/Olof

i'm trying for more than 3 weeks now to make/receive calls or sms with tc35 through arduino uno with no luck.
The only success i had was with the TC35 gsm connected to pc via serial and make/receive calls and sms via Hyperterminal..
Any ideas of how to make a call or send sms by using PC-Arduino uno-TC35 gsm?
Thanks!

soulhealer: Here are some of the functions I used.
The code is not pretty but it works. I made a quick translate (was in swedish) of my comments in the code, hope they make sense :slight_smile:

edit: I use AltSoftSerial (AltSoftSerial Library, for an extra serial port) to send commands to TC35 (hardware UART is used for communication with "slave MCU")

void readSMS(byte bSMSpos)
{
  char phonenumber[12];
  //Text mode
  altSerial.print("AT+CMGF=1");
  altSerial.write(13);
  delay(500);
  //clear buffer, we are only intresed in the text message
  altSerial.flushInput();
  delay(500);
  //Read SMS on position 1-5
  //Does not matter if it exist a sms or not
  altSerial.print("at+cmgr=");
  altSerial.print(bSMSpos);
  altSerial.write(13);
  //Takes some time to get answer?
  delay(500);
  memset(&phonenumber[0], '\0', sizeof(phonenumber));
  char command[4];
  char bPhone=0;
  char bDone=0;
  char bRead;

  command[0]='N';
  command[1]='O';
  command[2]='N';
  int i=0;

  //Skip the first 13 characters
  for (byte i=0; i<13; i++)
  {  
    if (altSerial.available()) altSerial.read();
  }
  i=0;
  while(altSerial.available())
  {
    bRead=altSerial.read();
    //Om phone>1 save text as command
    if (bPhone>1)
    {
      //A command is 3 chars long
      if (i<4) command[i]=toupper(bRead);
      i++;
    }
    //Om phone=1 save as phonenumber
    if (bPhone==1)
    {
       
      if (bPhone<sizeof(phonenumber))
      {
        //newline? set phone>1 
        if (bRead==10)
        {
          bPhone=i;
          i=0;
        }
        else
        {
          //" = end of phonenumber
          if (bRead=='"' && bDone==0)
          {
            phonenumber[i]='\0';
            bDone=1;
          }
          else
          {
            if (i<sizeof(phonenumber) && bDone==0)         
            {
              phonenumber[i]=bRead;
              i++;
            }
          }
        }
      }
    }
    //+ = start of phonenumber
    if (bRead=='+')
    {
      bPhone=1;
      phonenumber[0]='+';
      i++;
    }
  }
  //Terminate command
  command[sizeof(command)-1]='\0';
  //Delete SMS after it is read
  altSerial.print("AT+CMGD=");
  altSerial.print(bSMSpos);
  altSerial.write(13);    
  delay(500);
  //If the command is right send SMS
  if (strcmp(command,"XXX")==0)
  {
     sprintf(sMessage,"Water level:%dcm\0",iCurrentNiva);
     sendSMS(phonenumber); 
  }  
}


//---------------------------------------------------------------------------------------------//
//Message in global variabel sMessage
void sendSMS(char phonenumberSMS[12])
{
  Serial.println("$setCursor 0,1");	
  Serial.println("$print Sending SMS  ");
  char sTemp[15];
   memset(&sTemp[0], '\0', sizeof(sTemp));
  //Text mode
    altSerial.print("AT+CMGF=1");
  altSerial.write(13);
  delay(500);
  //number to messagecenter
  //Global variabel sSMSTele
  altSerial.print("AT+CSCA=\"");
  strcpy(sTemp,"+46");
   for (int i=1; i<strlen(sSMSTele); i++)
  {
     sTemp[2+i]=sSMSTele[i];
    
  }
  altSerial.print(sTemp);
  altSerial.print("\"");
  altSerial.write(13);
  delay(500);
  //Phone number to sent to
  altSerial.print("AT+CMGS=\"");
  altSerial.print(phonenumberSMS);
  altSerial.print("\"");
  altSerial.write(13);
  delay(500);
  //Message
  altSerial.print(sMessage);
  //Ska avslutas med ctrl+
  altSerial.write(26);
  delay(5000);
}
//---------------------------------------------------------------------------------------------//
//For loop only check the first 5 messages
void checkSMS()
{
  Serial.println("$setCursor 0,1");	
  Serial.println("$print Checking SMS  ");
  int i=0;
  while (checkIfRegistrated()==0 && i<10)
  {
    delay(5000);
    i++;
  }
  if (i<10)
  {
    for (byte i=1; i<=5; i++)
    {  
      readSMS(i);
    } 
  }
}
//---------------------------------------------------------------------------------------------//
byte checkIfRegistrated()
{
  altSerial.flushInput();
  delay(100);

  altSerial.print("AT+CREG?");
  altSerial.write(13);
  delay(200);
  int i=0;
  char line[10];
  line[0]='X';
  byte bRead;
  byte bStatus=0;
  while(altSerial.available() && i<sizeof(line))
  {
    bRead=altSerial.read();
    if (bStatus==1)
    {
      line[i]=bRead;
      i++;
    }
    if (bRead==10)
    {
      bStatus=1;
    }
  }  
  line[i]='\0';
  if (strcmp(line,"+CREG: 0,1")==0 || strcmp(line,"+CREG: 0,5")==0)
  {
    return 1;
  }
  return 0;
}

Thank you for your reply,
i finally make it work.. i used the pins D2, D3 for Rx,Tx and it worked :D..
Now if you could help me cause i cannot understand your code..
So far i succeed to start a pump via call.. how can i control the gsm ONLY through my phone number??
i want to reject all other phone numbers..
Any ideas? thanks in advance

olof_n:
Hi!

This is the first version of my "water level alarm".
It is monitoring the water level in a dam.

If the water level gets to high or to low it sends a alarm SMS with the current water level.

The alarm also respond to SMS that is sent to it.
If the message text contains the right command it will respond with a SMS to the sending phonenumber that include the current water level in cm.

All settings (including HIGH level, LOW level, Alarm ON/OFF, phonenumber to send alarm to, clock, calibration) is configured in the menu.

Components used:

ATMEGA8 - acts as a serial LCD and serial keypad. Sends keypresses to master MCU. Master MCU controls the LCD by serial commands.
I used an extra ATMEGA8 because they cost <1$ on ebay.

ATMEGA328 - Master MCU. Checks waterlevel every 5 minute and reads/sends SMS.

MCP3201 - 12bit ADC. The internal 10bit ADC that the ATMEGA MCU has was not good enough for my sensor.

DS1307 - The RTC is used because I save 24h history. By pressing a key you can go back in time and see the water level.

Pressure sensor 4-20ma, 0-0,3bar (0-3m) Realy good sensor!

GSM module TC35 - The module is basic (no GPRS) but has a low price. It works good, I wrote some simple functions to read/send SMS.
I used transistors to convert the modules 2.65v signals to 5v.

I think I will make a version 2 that include a SD-card for long term logging of the water level.
Version 2 will use DS1302 RTC instead of DS1307 because it can trickle charge a supercap or battery.

It would also be fun if I could learn to use Eagle and make a more professional PCB.

I do not hava a picture "in action" but the only thing on the LCD is time & date and the current water level in cm.

Here is two pictures of the project.

would you like to share the sketch and how to use the HPT604 Sensor ?

Hi Havizul!

To read the sensor I use two functions.
One function to get a value from the external ADC MCP3201 and one function to convert the value to cm.

//---------------------------------------------------------------------------------------------//
unsigned short read_adc(void)
{
  // select ADC  and then read two bytes
  digitalWrite(cs,LOW); //Select adc
  unsigned char one = SPI.transfer(0xFF);
  unsigned char two = SPI.transfer(0xFF);
  digitalWrite(cs, HIGH); //turn off device
  // 12 bits of ADC value is bottom 5 bits of first
  // byte and top 7 bits of second, move into 16 bit int
  return ((0x1F & one) << 7) | (two >> 1);
}
//---------------------------------------------------------------------------------------------//
unsigned short get_waterlevel(void)
{
  int iADCvalue=read_adc();
  //819.2000 = Remove 1V of reading 4-20ma with 250ohm = 1-5V
  //ADC reading * 0.9158 = mm (sensor range 0-3m)
  float fLevelCalc=(((float)iADCvalue-819.2000)*0.9158)/10.0000;
  //iCal = variable to calibrate the water level in software.
  return (int)fLevelCalc+ iCal;
}

To get the current water level I just call get_waterlevel.
CurrentLevel = get_waterlevel();

The complete code for the "master mcu" are 867 rows with a lot of swedish comments :), maybe it is better that I just post the "core" functions.

/Olof

Hi olof_n,

Thanks for your response.
Your ADC module is 12 bit, so it has 4096 resolution. Your sensor's range is 0 - 3 m = 0 - 3000mm, so ideally this sensors measurement level should be able to measure the level >= 3000mm/4096 = 0.732mm, and 1mm of level measurement should be sufficient precision.
Is it true that this sensor is sufficient precision to measure the water level per 1mm ?
How to convert the values range of 4-20mA to be a value of a distance (mm/cm) ?
How many of range ??that can be measured by this sensor from 4-20mA output with measurements range 0-3m ?

I assume that this sensor's resolution is 300, so it can measure the changes in water level every 1cm (--> 20mA - 4mA = 16, --> 16/300 = 0.05333), is it true that the changes in current for each 0.05333mA represents 1cm of water level / distance ? Is it true that the 4mA represents 0cm, 4.05333mA represents 1cm, 4.10666mA represents 2cm, 4,15999mA represents 3cm ..... 20mA represents 300cm ?

Thanks

Hi!

The ADC outputs 0-5V.
The sensor outputs 4-20ma and if you use a 250ohm resistor you get an output of 1-5V.
Therefore 1V or 20% of the ADC resolution is "lost". Else I think you got it right.

I have not tried to measure more accurate than 1 cm, It was not important in my project.
Here is a link to the sensor: http://www.holykell.com/en/product/Pressure/Pressure_Transmitters/Level%20Pressure_Transmitters/210.html

You can choose configuration when you order the sensor (pressure range, signal output etc.)

To read 4-20ma with a ADC you can use the attatched circuit. I replaced the 220ohm resistor with 250ohm. I also added a 5.1V zener diod for over voltage protection but that is optional.

4-20 ma.png

Hi Brother,

Thank you very much for the explanations.
It is very helpfull.

Thanks