Discussion in "Project Doubts" started by    batara    Jan 13, 2013.
Sun Jan 13 2013, 09:06 pm
#1
I want to make a project to measure distance using ultrasonic sensor HC-S*04 and LCD to display the distance in cm. I use AT89C51, the trigger pin for ultrasonic sensor is P3.5 and the echo pin is P3.2. The echo pin is connected to P3.2 because I use interrupt so that whenever there is a HIGH it will activate timer 0 and the duration of HIGH condition (in microsecond) will be converted to cm (divided by 59). I already make sure that the ultrasonic sensor works well. The problem is the LCD always display output the same number 45. It is not varying although the distance between object and ultrasonic sensor change. Can anyone help me to solve this problem?

Code:
#include<REGX51.h>

#include<intrins.h>
// for using _nop_() function
#define port P2
#define dataport P0 
sfr16 DPTR =0x82;
sbit trig=P3^5;
sbit rs=port^0;
sbit rw=port^1;
sbit e=port^2;
 
 
void delay(unsigned int msec)
{
int i,j;
for(i=0;i<msec;i++)
    for(j=0;j<1275;j++);
}
 
void lcd_cmd(unsigned char item) // Function to send command to LCD
{
dataport = item;
rs= 0;
rw=0;
e=1;
delay(1);
e=0;
return;
}
 
void lcd_data(unsigned char item) // Function to send data to LCD
{
dataport = item;
rs= 1;
rw=0;
e=1;
delay(1);
e=0;
return;
}
 
void lcd_data_string(unsigned char *str) // Function to send string to LCD
{
int i=0;
while(str[i]!='\0')
{
  lcd_data(str[i]);
  i++;
  delay(1);
}
return;
}
 
void send_pulse(void) //to generate 10 microseconds delay
{
TH0=0x00;TL0=0x00; 
 trig=1;
 _nop_();_nop_();_nop_();_nop_();_nop_();
 _nop_();_nop_();_nop_();_nop_();_nop_();
 trig=0;
    
} 
 
unsigned int get_range(void)
{
 int range=0;
 int s;
 send_pulse();
 delay(40);//          generate a delay of 40 Milli seconds=40000 micro 
 DPH=TH0;DPL=TL0;  
 TH0=0xFF;TL0=0xFF;
 lcd_cmd(0x81);
 delay(2);
 lcd_data_string("output:");
 lcd_cmd(0x8a);
 if(DPTR<35000)
 {//actually you need to use 38000 but the sensor may not work at higher levels 
  range=DPTR/59;
  s=range/100;
  range=range%100;
  if(s!=0)
  {
  lcd_data(s+48);
  }
  else
  {
  lcd_cmd(0x06);
  s=range/10;
  range=range%10;
  lcd_data(s+48);
  lcd_data(range+48);
  lcd_data(' ');
  }
 }
 else 
 {
 range=0; // indicates that there is no obstacle in front of the sensor 
 lcd_cmd(0x06);
 lcd_data(0);
 }
 return range;
}
 
void main()
{
  lcd_cmd(0x38);
  lcd_cmd(0x0c);
  delay(2);
  lcd_cmd(0x01);
  delay(2);
  lcd_cmd(0x81);
  delay(2);
  lcd_data_string("start");
  delay(20);
  TMOD=0x09;//timer0 in 16 bit mode with gate enable
  TR0=1;//timer run enabled
  TH0=0x00;TL0=0x00;
 
  P3=0x04;//setting pin P3.2 
     
  
 while(1)
 { get_range();
   delay(2);   
 }
}




Tue Jan 15 2013, 12:14 am
#2
@ batara
can you elaborate the logic in your words
why your using DPTR register
how you calculating the distance ?
Tue Jan 15 2013, 12:47 pm
#3
The idea is like this:
The trigger pin P3.5 output HIGH state for 10uS to make the ultrasonic sensor transmit 40KHz sound wave. Then, the echo will be received by echo pin P3.2 which is used as interrupt. Whenever the echo(HIGH state) is received by P3.2, the interrupt will activate timer0 to start. If the echo line goes LOW the timer0 will stop. Therefore, timer0 is used to record the duration of HIGH state from echo line. This duration will be converted to distance (in centimeter) by dividing with 59. When timer0 stops recording the time, the duration is hold by DPTR. You can find in the code above DPH=TH0; DPL=TL0. If DPTR<35000 then it will be divided by 59 to get the distance and the LCD will display that distance. The function to display the distance you can see:
if(s!0)
{
....
...
}
else
{
range=0;
...
...
}
return range;
}

However, the LCD always display output=45 and it is not varying according to distance. I also found that even if I disconnect the trigger wire to ultrasonic sensor, LCD still display output=45. Any idea to fix this problem?
Wed Jan 16 2013, 12:18 am
#4
Whatever the problem is, using the DPTR like this is a bad idea.

It is very likely that Kiel uses the DPTR, so its contents cannot be relied upon.
Just create a 16 bit integer variable to hold your measurement.
Wed Jan 16 2013, 01:40 am
#5
i agree with ExperimenterUK
DPTR is SFR and may be keil using it or may be not
and its values are over written
Mon Jan 21 2013, 05:26 am
#6
you can instead use an intiger for this purpose e.g.

int timerval;

timerval = TH0;
timerval = (timerval << 8) | TL0;

now timerval has 16bit timer value which you can use anywhere in your code. Do not use SFRs in C code as its not recommended. It can break your code without showing any error.
 batara like this.
Mon Feb 04 2013, 02:07 pm
#7
Ajay Bhargav could yo explain the code you write. I don't understand --> timerval=(timerval << 8) | TL0;
Mon Feb 04 2013, 02:20 pm
#8
timerval << 8 //shift timerval 8 bit left.
// e.g. if timerval is 0x43 then shifting it 8-bit gives you
// 0x4300

(timerval << 8) | TL0
// then this value is ORed with TL0
// e.g. if TL0 is 0x22 then
// 0x4300 | 0x22 will give you 0x4322
// which is a 16-bit combined value
 batara like this.
Mon Feb 04 2013, 04:38 pm
#9
Yes, it works. The LCD can display distance correctly. Thank you for your help
Tue Feb 05 2013, 12:16 am
#10
If you can make a simple project on obstacle distance measurement, I can upload it on this website. good luck!
 rammichael like this.

Get Social

Information

Powered by e107 Forum System

Downloads

Comments

Lewisuhakeply
Thu Apr 18 2024, 06:00 pm
Darrellciz
Thu Apr 18 2024, 11:07 am
Charlessber
Thu Apr 18 2024, 09:29 am
BartonSem
Thu Apr 18 2024, 04:56 am
DonaldKnown
Thu Apr 18 2024, 12:24 am
utaletxcyw
Wed Apr 17 2024, 10:21 am
Anthonyvab
Wed Apr 17 2024, 08:48 am
RobertCix
Wed Apr 17 2024, 06:46 am