specifications of design:
The design should be useful in liquid level or proximity detection. It should operate by detecting the distance from the target by reflection of an infra-red beam. It should safely detect the level of a liquid in a tank without any contact with the liquid itself. The device's range should be variable, from a couple of cm. to about 50 cm.
It is a continuous liquid level detector.
I must be able to display the results on an LCD screen.
ie. The level of the liquid in cm
tank empty
tank full
error message etc
The device should also be reconfigurable and able to work on any tank
Can the sensor measure the level of water in a vessel, or does it need a colored surface?
Im a girlnot a HE
//*********************************************************
/* Junebug_Serial4.c RomanBlack.com 19th July 2009.
Junebug 18F1320, uses my "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 as a text string to PC
via bitbanged serial out. It also flashes Junebug LED1
everytime it takes a distance sample.
Code for MikroC, config handled by MikroC compiler;
_INTI02_OSC_1H
_WDT_OFF_2H
-MCLRE_ON_3H
_LVP_OFF_4L
_PWRT_ON_2L
*/
//*********************************************************
// functions declared
void calc_distance(void);
void send_serial_message(void);
void send_serial_byte(unsigned char);
#define PIN_SER_OUT LATA.F3 // which pin for serial out (PORTA.F3)
#define SER_BAUD 51 // TMR3 (1Mhz/19200 baud) = 52
// tested; works from 49 to 53, using 51
unsigned char i; // used for looping
unsigned char cm10; //
unsigned char cm; //
unsigned int math; // used for voltage calculations
unsigned long bres; // for bresenham 2-second timer system
//---------------------------------------------------------
void main()
{
// setup the PIC 18F1320
OSCCON = 0x72; // internal osc, 8MHz
PORTA = 0;
[COLOR="Red"]TRISA = 0b10000010; // RA7 high imp, RA3 is serial out,
// RA1 is [/COLOR]ADC input measuring VR1
PORTB = 0;
INTCON2 = 0; // PORTB pullups ON
TRISB = 0b00000000; // PORTB not used
ADCON0 = 0b00000101; // ADC ON, RA1 is ADC input
ADCON1 = 0b01111101; // AN1 is ADC input
[COLOR="RoyalBlue"]ADCON2 = 0b10100010; // right justify, 8Tad, 32Tosc[/COLOR]
T1CON = 0b00010001; // TMR1 is ON, 1:2 prescale, =1MHz
T3CON = 0b00010001; // TMR3 is ON, 1:2 prescale, =1MHz
// main loop here;
while(1)
{
// wait for 2 seconds, uses TMR1 free running at 1Mhz
while(!PIR1.TMR1IF); // wait for TMR1 overflow
PIR1.TMR1IF = 0; // clear overflow flag
LATA = 0; // all LEDs off
bres += 65536; // add 65536uS to bres value
if(bres >= 2000000) // if reached 2 seconds!
{
bres -= 2000000; // subtract 2 seconds, keep error
// flash Junebug LED1, RA0=1 RA6=0 RA7=hiimpedance
LATA.F0 = 1; // LED on
// read the ADC voltage RA1 (Sharp GP2 sensor)
ADCON0.F1 = 1; // set GO bit, start doing ADC
while(ADCON0.F1); // wait until ADC done
calc_distance(); // convert ADC value to distance
send_serial_message(); // send message back to PC!
}
}
}
//---------------------------------------------------------
void calc_distance(void)
{
// from the Sharp datasheet the analog voltage is
// the inverse of distance, so distance can be calculated
// d = (1 / volts) then just scaled to suit the sensor
// 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;
}
//---------------------------------------------------------
void send_serial_message(void)
{
// send message and number to serial port
send_serial_byte('J'); // send ascii text
send_serial_byte('u');
send_serial_byte('n');
send_serial_byte('e');
send_serial_byte('b');
send_serial_byte('u');
send_serial_byte('g');
send_serial_byte(' ');
send_serial_byte('G');
send_serial_byte('P');
send_serial_byte('2');
send_serial_byte('=');
send_serial_byte('0'+ cm10); // send number as ascii text 0-9
send_serial_byte('0'+ cm); // send number as ascii text 0-9
send_serial_byte('c');
send_serial_byte('m');
send_serial_byte(13); // send carriage return/linefeed pair
send_serial_byte(10); // to start a new text line
}
//---------------------------------------------------------
void send_serial_byte(unsigned char data)
{
// this manually sends a serial byte out any PIC pin.
// NOTE! serial is inverted to connect direct to PC serial port.
// baud timing is done by using TMR3L and removing
// timer error after each baud.
i=8; // 8 data bits to send
PIN_SER_OUT = 1; // make start bit
TMR3L = (256 - SER_BAUD); // load TMR3 value for first baud;
while(TMR3L.F7); // wait for baud
while(i) // send 8 serial bits, LSB first
{
if(data.F0) PIN_SER_OUT = 0; // invert and send data bit
else PIN_SER_OUT = 1;
data = (data >> 1); // rotate right to get next bit
i--;
TMR3L -= SER_BAUD; // load corrected baud value
while(TMR3L.F7); // wait for baud
}
PIN_SER_OUT = 0; // make stop bit
TMR3L -= SER_BAUD; // wait a couple of baud for safety
while(TMR3L.F7);
TMR3L -= SER_BAUD;
while(TMR3L.F7);
}
[COLOR="Red"]
TRISA = 0b10000010; // RA7 high imp, RA3 is serial out,
// RA1 is [/COLOR]
[COLOR="RoyalBlue"]ADCON2 = 0b10100010; // right justify, 8Tad, 32Tosc[/COLOR]
I 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.
All I did was try doing a single ADC reading, then tried using multiple readings averaged. There was never much discernable difference between the 2 systems and my readings were stable whenever there was no movement of sensor or target. So that was good enough for me.
I'd love to see your results with different liquids AND different heights of liquid to see if there is a back reflaction from the bottom of the container.
And why use a look up table to correct the nonlinearity?? My version of the Sharp formula dist = (1 / volts)+n worked really nice. I think lookup tables are another reason people get jumpy values, (unless they are using a 1024 entry table).
We are concerned about reflection from surfaces or interfaces other than the liquid's top surface.
In your case, you need to show that the reflective surface being measured is the air-liquid interface ("A" in the above example), not some other surface ("B" in the example).
1)do you have a stable way to position the detector, like a ring stand and clamps, or is it just being hand held?
2) What are the dimensions of your liquid container(s)? Is your detector situated over the center or near an edge? Do your results vary if you move the detector off center? I looked briefly at the datasheet and suspect you may be able to move one direction, but not the other, without an effect from the edge of the container.
4) What was the "green" solution? Was it green-tinted water? Is it colored with a dye or a pigment?
It is great to see someone on these forums who is willing to put forth the effort and is not just an "I want the answer type."
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.
...
1) When you do these experiments, do you have a stable way to position the detector, like a ring stand and clamps, or is it just being hand held?
...
3) The experiment I suggested earlier was designed to detect secondary reflections that might influence your results. In other words, at a set distance from the liquid's surface, the value you get should be exactly the same (within experimental error) regardless of the depth of the liquid. A water depth of 1 to 2 cm was chosen, as that would allow a significant percentage of your IR light to penetrate to the wall.
...
Very nice. I love experimentation. Did you vary the depth of the liquid or just the distance from the liquid's surface? The experiment I would sugest is water in a deep bowl. Add about 3 to 4 cm of water and measure at 10 and 20 cm from the surface. Then increase depth of water 10 cm and repeat.
John
Edit: On reconsideration, make the initial water depth only 2 to 3 cm. Keep the rest the same.
hi Miss Fantabulous
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?