Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

infrared Liquid level detector-SharpGP2D12

Status
Not open for further replies.
I am assuming the x-axis is the depth of water in its container. Correct?

Did you keep the distance to the water surface constant? That value should be kept constant...actually, I suggest using 2 distances, like 10 cm and 20 to 30 cm, if it is not too hard to do that. Since your detector is fixed, just lower the vessel. Can you get a "lab jack" to do that?

Nice touch using both a plastic and a glass container. The glass has a very high refractive index, so will reflect differently than the plastic will at the liquid-container interface.

John
 
I am assuming the x-axis is the depth of water in its container. Correct?
Yes it is........uhmmmm no lab jack at my disposal...(use shoe boxes and text books to stack up:))


Tonight i am going to take readings for all those liquids i did b4(its 10:40 now)....but by varying the depth of the liquid...and keeping the distance to the surface fixed.....


i got to practice my presentation and my exams start next month:eek:....
I need to make a study time table...time management!very important
 
Just looked at the datasheet and some other information about the GP2D12 sensor. Based on that, I recommend increasing your minimal fixed distance from 10 cm to 12 to 14 cm. Then, pick a longer distance that is 10 to 13 cm more than your minimum distance for your second point (if you do the experiment as suggested awhile back). The reasons to avoid 10 cm exactly are: 1) it is the minimum distance; 2) there is rapid drop off at shorter distances; and 3) there is variation between devices (devices are characterized for quality control at about 24 cm). So, going to a slightly greater minimal distance will reduce unknown variability due to working at the device's extreme lower limit. You don't want to go too far, because the response curve flattens, which will increase your imprecision, and band spread of the IR beam will make edge effects more prominent. That is, you will have to use a larger diameter container for the liquid. Beam diameter vs. distance is shown in some of the technical sheets.

John
 
the glass vessel and sensor were at a fixed distance apart, took readings of the depth of the water which I varied...I did not move the sensor or the vessel once i started taking readings-the sensor was positioned over the center of the glass vessel.....see attached document...only problem is....the longest glass vessel i got is 21.5cm----so i took 3 readings for each case:

10cm fixed

12cm fixed

14cm fixed
 

Attachments

  • fixed distances.doc
    80 KB · Views: 175
Last edited:
I am very confused by that chart. You say, "10 cm fixed" but show 3 readings at different distances. Distance to what? You did triplicate readings. Does each point represent the average?

What does this mean:
1. Graph of Sensor @ fixed distance of 10cm away from glass vessel
2. Graph of Sensor @ fixed distance of 10cm away from glass vessel
3. Graph of Sensor @ fixed distance of 10cm away from glass vessel

Are you measuring from the top of the glass container, the top of the liquid, or the bottom of the glass container? All three "variations" are identical. Is that a typo?

John
 
thats a typo coz i cut and paste......its 10cm, 12cm and 14cm................let me change that on the document....

The graphs are correctly labled
 
sensor<-------10cm--------->top of glass This was the fixed distance
Then i took 3 readings from the sensor to the surface of the water at THAT fixed distance and plotted a graph

and i repeated this at 12cm.......................then again for 14cm
 
Last edited:
WATER 10*away
[
Code:
distance   output V
30	       0.509
20	       0.724
13	       0.725

Eg.
sensor<-------10cm--------->top of glass This was the fixed distance


Then i took 3 readings from the sensor to the surface of the water at THAT fixed distance and plotted a graph


and i repeated this at 12cm.......................then again for 14cm
 
Last edited:
Oh i have to be going now...its 23:55 and i wake @5:00 to get ready for uni and leave home at 6:15...Take care Jpanhalt....i will see your response at uni tomorrow....thanks for all your input....
 
Can you find a light-gray or white piece of cardboard? Get as big a piece as practical, at least 20 cm X 20 cm. Flat, stiff, card stock would be best.

Take multiple measurements at 12, 20, 30 cm from your detector. let's see what your best-case reproducibility is. I suspect it is pretty good. If not, then you need to look for problems in the basic sensor setup.

Assuming that reproducibility with the cardboard is good, then lets return to your liquid surface. Off hand, those results do not look too good, but don't despair. I think it is the set up you are using, which is why reproducibility seems so poor.

Let's focus only on water for now -- wine is later :D

Do you have a cooking pot or aquarium -- anything -- that is much bigger in diameter than the drinking glass you are using. If you can get something about 20 cm or more in diameter, use it. Hopefully, it will be at least 10 cm high. Place your sensor 20 to 25 cm form the bottom of that container. Take a blank measurement of the empty pot. Then add 2 cm of water, take 3 measurements and average them, if they are relatively close to each other. Otherwise, report what the 3 values are. Then add 5 MORE cm of water and repeat. Keep adding water and taking measurements until the water is at the top of the pot.

For now, be sure to let any ripples in the water settle. If you get an unusual reading, check for ripples, and record your data.

It is getting late for you now, I understand. But, I will check in tomorrow several times.

John
 
That chart doesn't look too good. If the voltage readings are correct for the blue chart it seems to be measuring the bottom of the vessel.

My 80cm Sharp sensor is currently soldered onto a robot and he might get a phobia if I go suspending him head first over a bucket of water...

I do have a few 30cm Sharp sensors spare, if fantabulous can't start to get some logical looking readings (and better labeled charts! :)) I can fill a bucket with water and connect it up.
 
Let's focus only on water for now -- wine is later

lol thats after I PASS....:)

Do you have a cooking pot or aquarium

Pot Yes:D aquarium no.....My cat would eat the fish






better labeled charts! )
:rolleyes::rolleyes::rolleyes::rolleyes:
Sorry i'll improve on that:D....too eager to post my data here:p





Ok im going to get my hands on that cardboard and pot when i get home.......and try again....(But tomorrow i have a practical on SQUIDS....and i get home at 16:30 from uni....uhmmmm i got to do my pre-prac lol or they will kick us out of the lab)....so do forgive me if i dont post any results today....
 
Don't worry. Get what needs to be done, like studying for an exam, done first.

BTW, when is the IR/liquid-level project due? In one of your earliest posts, you indicated it was at least several weeks away.

John
 
have used 3 types of the Sharp GP2 sensors with no real stability problems but I had a good +5v supply and short wiring. Lots of people do report erratic readings, (probably noise?). Putting a 10uF cap right at the sensor power between +5v and ground is supposed to help, and also doing some low pass filtering of the analog voltage out would help especially if you have long wires between the sensor and the PIC.


the attached pic shows put a cap from the i/o line to ground.....


would it really make a difference in my readings that i placed the cap right at the sensor power between +5v and ground .....and not as shown in the pic???
 

Attachments

  • irc.gif
    irc.gif
    3 KB · Views: 303
the attached pic shows put a cap from the i/o line to ground.....


would it really make a difference in my readings that i placed the cap right at the sensor power between +5v and ground .....and not as shown in the pic???

hi,
The caps on the wrong pins.!!:rolleyes:
Should be +V and 0V common
 
Well...we have different phases....1, 2, 3(final)

first phse is done....
second phase is in october and so are exams...........:eek:

2nd phase is a full paper design.....
1. Report
2. Presentation
3. Breadboard version of the design must be working(OR will get zero for demonstration)



But Ill be over with exams in the 1st week then i can give all my attention to design
 
Last edited:
I tried programming the (pic16f690)GP2 sensor with MR RB code for the (pic18F) today and tried displaying just the distance to an object for now....


when i power up the LCD displays random numbers

now when i put a page & hold it steady....i get

EG.

010101010101010
010101010101010

i keep moving it away and...

020202020202020
020202020202020

030303030303030
030303030303030

till.....

090909090909090
090909090909090

THEN
000000000000000
000000000000000

and it repeats the sequence as i move away

010101010101010
010101010101010...............

and so on......

BTW


(it does not go to 111111111111111
111111111111111)

and 1212121212121212
1212121212121212 .....etc)


i just measured manually with a ruler to verify the values....its accurate

meaning....
the sensor has a min range of 10 cm......
so when the page is 10cm away it displays....

000000000000000
000000000000000

and if it 5cm away from the min range(ie. 15cm)

then it display:

050505050505050
050505050505050

and i measured this with a ruler and it gives 15cm

here is the code.....ONLY the Highlighted RED code is the parts dealing with ADC

Could some1 please tell me why its giving me such a long measured value??? Its the 1st time i tried using ADC



Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>	//

void userMenu(char pos); //  
void FloatToStr(float , char[]); 
void DelayMs(unsigned char);
void lcd_cmd(unsigned char);
void lcd_data(unsigned char); 
void lcd_clear(void);
void lcd_puts(const char[]);
void lcd_goto_L1(void);
void lcd_goto_L2(void);
void lcd_cursor(unsigned char);
void lcd_init(void);
void init(void);
char WaitForInput(void);
unsigned char user_input(void);
void home_screen(void);
void EnterHeight(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void calc_distance(void);
void main(void);


unsigned char cm2LCD;

unsigned char cmHigh, cmLow;

      

#define LCD_RS RC0		//LCD RS pin
#define LCD_EN RC1		//LCD EN pin
#define LCD_STROBE()	LCD_EN = 1; asm("nop"); asm("nop"); LCD_EN = 0

unsigned char cm10;		//
unsigned char cm;		//
unsigned int math;		// used for voltage calculations
unsigned char NumDec;
unsigned char NumSep[2];
   
unsigned char i,j,k;
//char temp[8];
//[/b]
unsigned char height=50;
unsigned char range;
unsigned char area;
unsigned char SensorPos=10;
//[/b] New Vars
char input_sw;

  
char mnuPOS;

unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;
unsigned long bres;		// for bresenham 2-second timer system

unsigned char ;

#define HOME_SW RC2				//HOME switch	
#define INCREASE_SW RC3			//INCREASE switch
#define DECREASE_SW RC4			//DECREASE switch
#define ENTERSETTINGS_SW RA4	//ENTERSETTINGS switch



///////////////////////CONVERT FLOAT TO STRING///////////////////
// This function was taken from the CAVR library. It was modified slightly
// to suit our design.
void FloatToStr(float n, char str[])
{
float scale;
unsigned char d,f;
f=0;i=0;
if (n<0.0) {n=-n; str[f]='-'; f++;};
n=n+0.005;
scale=1.0;
while (n>=scale) {scale=scale*10.0; ++i;};
if (i==0) {str[f]='0'; f++;}
else
while (i--)
	  {
      scale=floor(0.5+scale/10.0);
      d=(unsigned char) (n/scale);
      str[f]=d+'0';
      n=n-scale*d;
	  f++;
      };

str[f]='.';
f++;
for (j=0;j<=1;j++) //2 decimal points
      {
      n=n*10.0;
      d=(unsigned char) n;
      str[f]=d+'0';
      n=n-d;
	  f++;
	  };
str[f]='\0';
}
///////////////////END CONVERT FLOAT TO STRING///////////////////

/////////////////////////////DELAY///////////////////////////////
void DelayMs(unsigned char cnt)
{
#if	XTAL_FREQ <= 2MHZ
	do {
		DelayUs(996);
	} while(--cnt);
#endif

#if    XTAL_FREQ > 2MHZ	
	unsigned char	p;
	do {
		p = 4;
		do { 
			DelayUs(250);
		} while(--p);  
	} while(--cnt);
#endif
}

void DelayS(unsigned char cnt)
{
	for (j=0; j<(cnt*10); j++)
		DelayMs(100);
}
///////////////////////////DELAY END/////////////////////////////

//////////////////////////////LCD SETUP//////////////////////////
/* send a command to the LCD */
void lcd_cmd(unsigned char c)
{
	DelayMs(2); //wait for LCD to be ready shorter delay 
	LCD_RS = 0;	 //write instruction
	PORTB = (c & 0xF0); //load upper nibble on LCD data lines
	LCD_STROBE(); //send instruction to LCD
	PORTB = ((c << 4) & 0xF0); //load upper nibble on LCD data lines
	LCD_STROBE(); //send instruction to LCD   	
}

/* send data to the LCD */
void lcd_data(unsigned char c)
{
	DelayMs(2); //wait for LCD to be ready shorter delay 
	PORTB = 0x00;
	LCD_RS = 1; //write data
    PORTB |= (c & 0xF0); //load upper nibble on LCD data lines     
	LCD_STROBE(); //send instruction to LCD
	PORTB &= 0x00; //load upper nibble on LCD data lines
	PORTB |= ( (c << 4) & 0xF0); 
	LCD_STROBE(); //send instruction to LCD
}

/*Clear the LCD*/
void lcd_clear(void)
{
	lcd_cmd(0x01); //command to clear LCD
}

/*write a string of chars to the LCD*/
void lcd_puts(const char s[])
{
	j = -1;
	while(s[++j]!=('\0')) // send characters until null character reached
		lcd_data(s[j]);
}

/*go to beginning of line 1*/
void lcd_goto_L1(void)
{
	lcd_cmd(0b10000000); // command to go to line 1
}

/*go to beginning of line 2*/
void lcd_goto_L2(void)
{
	lcd_cmd(0b11000000); // command to go to line 2
}

/*move cursor "x" positions to the right*/
void lcd_cursor(unsigned char x)
{
	lcd_cmd(((x)&0x7F)|0x80); 
}

/*initialise the LCD - put into 4 bit mode*/
void lcd_init(void)
{
	LCD_RS = 0;	
	LCD_EN = 0;
	DelayMs(20); //wait for LCD startup
	lcd_cmd(0x02);
 
	lcd_cmd(0x28);	// 4-bit mode
	lcd_cmd(0x08);	// display off
	lcd_cmd(0x01);	// clear display
	lcd_cmd(0x0C);	// disp. on, cursor off, cursor blink off
	lcd_cmd(0x06);	// entry mode
	lcd_cmd(0x80);  // initialise DDRAM address to zero
}
//////////////////////////LCD SETUP END//////////////////////////
    

void init(void)
{   
	
	// setup the PIC 16f690
	OSCCON = 0x72;      	// internal osc, 8MHz
	PORTA = 0;
	TRISA = 0b10010010; 	// RA7 high imp, RA3 is serial out, RA4 button input 


	
 	PORTB = 0;          	// PORTB not used
    WPUB = 1;				// PORTB pullups ON		
    RABPU = 0;

[COLOR="Red"]
    /* Init ADC */
    ADCON0 = 0b10000101;	// bit 7 right justify,analogue channel select bits bits5-2  0001=AN1,ADC ON, RA1 is ADC input
	ADCON1 = 0b00100000;	//bits6-4  fosc/32
    ADON=1;	                // turn on the A2D conversion module

	
	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;

        T1CON = 0b00010001;     // TMR1 is ON, 1:2 prescale, =1MHz
	T2CON = 0b00000101;     // TMR2 is ON, 1:4 prescale, =1MHz[/COLOR]



	MyVal = 0; //initializn these variables here
	MyMinVal = 0;
	MyMaxVal = 99;
  
	TRISB=0x00; 
	TRISC=0xFC;
    
	lcd_init(); //call LCD initialisation
}

char WaitForInput(void){
char done;
char temp;
done = 0;

while(!done){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        done = 0xff;
    }

    if(!HOME_SW){
        temp = 2;
        done = 0xff;
    }

    if(!INCREASE_SW){
        temp = 3;
        done = 0xff;
    }

    if(!DECREASE_SW){
        temp = 4;
        done = 0xff;
    }
}//end of while
    DelayMs(150);    //debounce
    return temp;
}//
void userMenu(char pos){
	lcd_clear();
	lcd_goto_L1();

	switch(pos){
		case 0:
			lcd_puts("    HEIGHT    ");
			break;		
		case 1:
			lcd_puts("    RANGE     ");
			break;		
		case 2:
			lcd_puts(" SURFACE AREA ");
			break;		
	}

	lcd_goto_L2();
	lcd_puts("Press Up/Down"); //home screen message (line 2)
}
// New Menu System
void EnterHeight(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER HEIGHT ");
	lcd_goto_L2();
	lcd_puts("Press Up/Down"); //home screen message (line 2)
}

void EnterScreen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" [cm] ");
}

void ShowDigits(unsigned char val){

    MyValLCD[0] = val /10;    //returns the quotient (if temp = 35 the result is 3)
    MyValLCD[1] = val % 10; 	//Returns remainder   (if temp = 35 the result is 5)

	MyValLCD[0] += 0x30;	//to ASCII
	MyValLCD[1] += 0x30;	//to ASCII

	EnterScreen();
	lcd_goto_L2();
	lcd_data(MyValLCD[0]);	//to LCD
	lcd_data(MyValLCD[1]);  //to LCD
}

  
[COLOR="Red"]void calc_distance(void)[/COLOR]
{
	// from the transeiver datasheet the analog voltage is
	// the inverse of distance, so distance can be calculated
	// d = (1 / volts) then just scaled to suit the transeiver

	// load ADC value in 16bit math var
	math = ADRESH;
	math = (math * 256);
	math += ADRESL;

	// now invert it; (1 / volts) use (6050 / volts) for scaling
	math = (6050 / math);
	if(math >= 2) math -=2;		// fix linear error (-2)
	if(math > 99) math = 99;	// max limit at 99cm

	// convert from 0-99 to 2 decimal digits, 0-99cm
	cm10=0;
	while(math >= 10)
	{
		cm10++;
		math -= 10;
	}
	cm = math;
}
 //
unsigned char user_input(void)		//This will return what we want
{
	char done = 0;

	MyVal = 0;			//Start on 0
	while(done == 0){
   	  input_sw = WaitForInput();
		
      switch(input_sw){
		case 1:
			done = 0xff; 			//This tells us the user finished entering
			lcd_goto_L1();
			lcd_puts("     Done!      "); //home screen message (line 1)
			break;
      	case 3:
			if(MyVal < MyMaxVal)
      			MyVal++;
			EnterScreen();
			ShowDigits(MyVal);
			break;
      	case 4:
			if(MyVal > MyMinVal)
      			MyVal--;
			EnterScreen();
			ShowDigits(MyVal);
        	break;
		default: 
			break;
      }
	  
	}
	DelayS(1);
	return MyVal;
}

void home_screen(void){
	mnuPOS = 0;
	lcd_clear();
	lcd_goto_L1();
	lcd_puts("INFRARED LIQUID"); //home screen message (line 1)
	lcd_goto_L2();
	lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)
  
	input_sw = 0;			//Reset the value

	while(input_sw != 1)  	//Wait until enter is pressed
		input_sw = WaitForInput();

	userMenu(0);
	DelayMs(2);				//shorter delay 
    height = user_input();	//The HEIGHT var will have the myVal

	userMenu(1);
	DelayMs(2);				//shorter delay 
    range = user_input();	//The HEIGHT var will have the myVal

	userMenu(2);
	DelayMs(2);				//shorter delay 
    area = user_input();	//The HEIGHT var will have the myVal
/*
"enter height"
call enter/settings (which is now user input function in new code)
height=MyVal

"enter range"
call user_input
range=MyVal

"enter surface area"
call user_input
area=MyVal
*/
}
  
//*********************************************************
/*  Junebug_Serial4.c    RomanBlack.com 19th July 2009.

    uses "zero error 1 second timer"
	system to generate a 2 second interval, then every
	2 seconds it reads an analog voltage from a
	Sharp GP2 distance sensor and converts it to decimal
	distance, then sends that data to a LCD

	Code for MikroC, config handled by MikroC compiler;
	_INTI02_OSC_1H
	_WDT_OFF_2H
	-MCLRE_ON_3H
	_LVP_OFF_4L
	_PWRT_ON_2L
*/
//*********************************************************

void main(void)
{  
    init();	// initialise I/O ports, LCD
    while(1){
 	//	home_screen();

 	[COLOR="Red"]// wait for 2 seconds, uses TMR1 free running at 1Mhz
   	while(!TMR1IF)  // wait for TMR1 overflow
	TMR1IF = 0; 	// clear overflow flag

	bres += 65536;			// add 65536uS to bres value
	if(bres >= 2000000)		// if reached 2 seconds!
	 {
    	bres -= 2000000;	// subtract 2 seconds, keep error
		  	
		// read the ADC voltage RA1 (Sharp GP2 sensor)
		GODONE=1;	// initiate conversion on the channel 0
		while(GODONE) continue;  // Wait convertion done
		calc_distance();		// convert ADC value to distance

//CM is higher than 09 so spilt the variable CM into 2 
cmHigh = ( ( cm >> 4 ) & 0x0F ) + 0x30;
cmLow = ( cm & 0x0F ) + 0x30;

lcd_data(cmHigh);
lcd_data(cmLow);
[/COLOR]


      				         
       }  
            
 
   } 
}
 
Last edited:
Its not giving you a long value lol its looping. Try Clearing the LCD before the loop like:

Code:
void main(void)
{  
    init();	// initialise I/O ports, LCD
    while(1){
 	//	home_screen();

 	// wait for 2 seconds, uses TMR1 free running at 1Mhz
   	while(!TMR1IF)  // wait for TMR1 overflow
	TMR1IF = 0; 	// clear overflow flag

	bres += 65536;			// add 65536uS to bres value
	if(bres >= 2000000)		// if reached 2 seconds!
	 {
    	bres -= 2000000;	// subtract 2 seconds, keep error
		  	
		// read the ADC voltage RA1 (Sharp GP2 sensor)
		GODONE=1;	// initiate conversion on the channel 0
		while(GODONE) continue;  // Wait convertion done
		calc_distance();		// convert ADC value to distance

	//CM is higher than 09 so spilt the variable CM into 2 
		cmHigh = ( ( cm >> 4 ) & 0x0F ) + 0x30;
		cmLow = ( cm & 0x0F ) + 0x30;//[b]
		lcd_clear();	//ADDED THIS[/b]
		lcd_data(cmHigh);
		lcd_data(cmLow);
    				         
     }  //END OF IF
   }//END OF WHILE(1) 
}//END OF MAIN
 
Sorry i made a few mistakes in my PM code:

Code:
void main(void)
{  
  init();		//initialise I/O ports, LCD
  while(1){
    //home_screen();

    //wait for 2 seconds, uses TMR1 free running at 1Mhz
    while(!TMR1IF);             // wait for TMR1 overflow [b] forgot to place ; here[/b]
    TMR1IF = 0; 		// clear overflow flag

    bres += 65536;		// add 65536uS to bres value
    if(bres >= 2000000)		// if reached 2 seconds!
    {
      bres -= 2000000;		// subtract 2 seconds, keep error

    // read the ADC voltage RA1 (Sharp GP2 sensor)
      GODONE=1;		    // initiate conversion on the channel 0
      while(GODONE) continue; // Wait convertion done
      calc_distance();	    // convert ADC value to distance

    //CM is higher than 09 so spilt the variable CM into 2 //[b]
      cmHigh = ( cm / 10 ) + '0'; // My Mistake this will get you true
      cmLow = ( cm % 10 ) + '0';  // values
      lcd_clear();                // ADDED THIS[/b]
      lcd_data(cmHigh);
      lcd_data(cmLow);
     }//END OF IF
   }//END OF WHILE(1)
}//END OF MAIN
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top