PIC Vietnam

Go Back   PIC Vietnam > Robotics > Cảm biến

Tài trợ cho PIC Vietnam
Trang chủ Đăng Kí Hỏi/Ðáp Thành Viên Lịch Bài Trong Ngày Vi điều khiển

Cảm biến Camera, siêu âm, hồng ngoại, gyro, la bàn...

Trả lời
 
Ðiều Chỉnh Xếp Bài
Old 09-05-2011, 09:40 PM   #1
luulytim90
Nhập môn đệ tử
 
Tham gia ngày: May 2011
Bài gửi: 3
:
Cảm biến siêu âm SRF02

Chào mọi người,
Em đang có một bài tập sử dụng cảm biến SRF02 với Atmega128 qua giao tiếp I2C. Các pin SCL và SDA lần lượt được nối với PIN D0 và D1 trên vi xử lý (cổng SCL/SDA của TWI). Giữa dây +5V và 2 dây SCL, SDA có nối 2 điện trở 1800ohm.

Em gửi lệnh startRanging với giá trị 0x51 (đo bằng cm) sau đó đọc giá trị trả về từ register 0x02 và 0x03 rồi cộng lại. (Dưới đây là code C viết trong AVR Studio)

Mọi thứ có vẻ như rất ổn ngoại trừ kết quả đo thu được từ cảm biến hầu như vô nghĩa. Nó trả về giá trị random trong khoảng từ 25 đến 40 trong mỗi lần đọc. Các anh chị nếu có con SRF02 hoặc có kinh nghiệm làm việc với cảm biến này giúp em tìm ra lỗi sai với. Cám ơn mọi người!

Code:
#define F_CPU 14745600UL   

#include<avr/io.h>
#include<util/delay.h>
#include<inttypes.h>
#include <string.h>
#include <stdio.h>  
#include <stdint.h>

#include "LCD.c"

#define SRF02		0xE0				// Address of SRF02
 
void i2c_transmit(char address, char reg, char data)
{
	TWCR = 0xA4;                                                  // send a start bit on i2c bus
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
	TWDR = address;                                               // load address of i2c device
	TWCR = 0x84;                                                  // transmit
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
	TWDR = reg;
	TWCR = 0x84;                                                  // transmit
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
	TWDR = data;
	TWCR = 0x84;                                                  // transmit
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
	TWCR = 0x94;                                                  // stop bit
}

void startRanging(void)
{
	i2c_transmit(SRF02, 0, 0x51);					// Cause SRF02 to start a ranging returning results in CM
} 


unsigned char i2cRead(char address, char reg)
{
char read_data = 0;

   TWCR = 0xA4;                                                  // send a start bit on i2c bus
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit  
   TWDR = address;                                               // load address of i2c device
   TWCR = 0x84;                                                  // transmit 
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWDR = reg;                                                   // send register number to read from
   TWCR = 0x84;                                                  // transmit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit

   TWCR = 0xA4;                                                  // send repeated start bit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
   TWDR = address+1;                                             // transmit address of i2c device with readbit set
   TWCR = 0xC4;                                                  // clear transmit interupt flag
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWCR = 0x84;                                                  // transmit, nack (last byte request)
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
   read_data = TWDR;                                             // and grab the target data
   TWCR = 0x94;                                                  // send a stop bit on i2c bus
   return read_data;

}

unsigned int getRange(void) 
{
	unsigned int x;
	x = i2cRead(SRF02,2) << 8;					// Get high and then low bytes of the range
	x += i2cRead(SRF02,3);
	
	return(x);
}

void TWI_init_master(void) // Function to initialize master
{
	TWBR=0x0c;	// Bit rate
	TWDR=0xFF;
	TWCR=(1<<TWEN)|
		 (0<<TWIE)|(0<<TWINT)|
		 (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
		 (0<<TWWC);

	TWSR=(0<<TWPS1)|(0<<TWPS0);	// Setting prescalar bits
	// SCL freq= F_CPU/(16+2(TWBR).4^TWPS)
}

int main(void)
{
	char buffer[16];
	int range;
	TWI_init_master();
	LCD_Init();
	LCD_Clear();
	_delay_ms(500);
	startRanging();

	while(1)
	{		
                startRanging();
                _delay_ms(70);
		range = getRange();
		sprintf(buffer, "s= %3d", range);
		LCD_Position(0,0);
		LCD_WriteString(buffer);
		_delay_ms(200);
	}
}
Mình nghĩ F_CPU có ảnh hưởng đến tần số trên dây SCL, vậy nếu mình define F_CPU sai thì có thể gây ra việc đọc không chính xác không?

Cám ơn mọi người giúp đỡ,
luulytim90 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 27-08-2011, 06:10 PM   #2
duongvt
Nhập môn đệ tử
 
Tham gia ngày: Apr 2011
Bài gửi: 9
:
Trích:
Nguyên văn bởi luulytim90 View Post
Chào mọi người,
Em đang có một bài tập sử dụng cảm biến SRF02 với Atmega128 qua giao tiếp I2C. Các pin SCL và SDA lần lượt được nối với PIN D0 và D1 trên vi xử lý (cổng SCL/SDA của TWI). Giữa dây +5V và 2 dây SCL, SDA có nối 2 điện trở 1800ohm.

Em gửi lệnh startRanging với giá trị 0x51 (đo bằng cm) sau đó đọc giá trị trả về từ register 0x02 và 0x03 rồi cộng lại. (Dưới đây là code C viết trong AVR Studio)

Mọi thứ có vẻ như rất ổn ngoại trừ kết quả đo thu được từ cảm biến hầu như vô nghĩa. Nó trả về giá trị random trong khoảng từ 25 đến 40 trong mỗi lần đọc. Các anh chị nếu có con SRF02 hoặc có kinh nghiệm làm việc với cảm biến này giúp em tìm ra lỗi sai với. Cám ơn mọi người!

Code:
#define F_CPU 14745600UL   

#include<avr/io.h>
#include<util/delay.h>
#include<inttypes.h>
#include <string.h>
#include <stdio.h>  
#include <stdint.h>

#include "LCD.c"

#define SRF02		0xE0				// Address of SRF02
 
void i2c_transmit(char address, char reg, char data)
{
	TWCR = 0xA4;                                                  // send a start bit on i2c bus
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
	TWDR = address;                                               // load address of i2c device
	TWCR = 0x84;                                                  // transmit
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
	TWDR = reg;
	TWCR = 0x84;                                                  // transmit
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
	TWDR = data;
	TWCR = 0x84;                                                  // transmit
	while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
	TWCR = 0x94;                                                  // stop bit
}

void startRanging(void)
{
	i2c_transmit(SRF02, 0, 0x51);					// Cause SRF02 to start a ranging returning results in CM
} 


unsigned char i2cRead(char address, char reg)
{
char read_data = 0;

   TWCR = 0xA4;                                                  // send a start bit on i2c bus
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit  
   TWDR = address;                                               // load address of i2c device
   TWCR = 0x84;                                                  // transmit 
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWDR = reg;                                                   // send register number to read from
   TWCR = 0x84;                                                  // transmit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit

   TWCR = 0xA4;                                                  // send repeated start bit
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
   TWDR = address+1;                                             // transmit address of i2c device with readbit set
   TWCR = 0xC4;                                                  // clear transmit interupt flag
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit
   TWCR = 0x84;                                                  // transmit, nack (last byte request)
   while(!(TWCR & 0x80));                                        // wait for confirmation of transmit 
   read_data = TWDR;                                             // and grab the target data
   TWCR = 0x94;                                                  // send a stop bit on i2c bus
   return read_data;

}

unsigned int getRange(void) 
{
	unsigned int x;
	x = i2cRead(SRF02,2) << 8;					// Get high and then low bytes of the range
	x += i2cRead(SRF02,3);
	
	return(x);
}

void TWI_init_master(void) // Function to initialize master
{
	TWBR=0x0c;	// Bit rate
	TWDR=0xFF;
	TWCR=(1<<TWEN)|
		 (0<<TWIE)|(0<<TWINT)|
		 (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
		 (0<<TWWC);

	TWSR=(0<<TWPS1)|(0<<TWPS0);	// Setting prescalar bits
	// SCL freq= F_CPU/(16+2(TWBR).4^TWPS)
}

int main(void)
{
	char buffer[16];
	int range;
	TWI_init_master();
	LCD_Init();
	LCD_Clear();
	_delay_ms(500);
	startRanging();

	while(1)
	{		
                startRanging();
                _delay_ms(70);
		range = getRange();
		sprintf(buffer, "s= %3d", range);
		LCD_Position(0,0);
		LCD_WriteString(buffer);
		_delay_ms(200);
	}
}
Mình nghĩ F_CPU có ảnh hưởng đến tần số trên dây SCL, vậy nếu mình define F_CPU sai thì có thể gây ra việc đọc không chính xác không?

Cám ơn mọi người giúp đỡ,
Bây giờ Bạn đã làm xong chưa ?? Mình trao đổi chút nhé
theo mình thì thấy mấy con này thướng có hàm khởi tạo "init" nữa ở đây cũng thấy bạn init LCD và I2c nhưng chưa thấy init SRF ...vấn đề là ở đây chăng ??
duongvt vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 28-08-2011, 08:07 PM   #3
luulytim90
Nhập môn đệ tử
 
Tham gia ngày: May 2011
Bài gửi: 3
:
con SRF02 mình làm được rồi, code trên... hoàn toàn đúng, chỉ do nguồn cấp cho con Atmega mình dùng nguồn 'stabilized' nên (hình như) nó không tạo được giao động chuẩn cho giao tiếp I2C. Sau đó mình thay cái adapter mới thì chạy được, hihi.
luulytim90 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 05-09-2011, 05:05 PM   #4
duongvt
Nhập môn đệ tử
 
Tham gia ngày: Apr 2011
Bài gửi: 9
:
Trích:
Nguyên văn bởi luulytim90 View Post
con SRF02 mình làm được rồi, code trên... hoàn toàn đúng, chỉ do nguồn cấp cho con Atmega mình dùng nguồn 'stabilized' nên (hình như) nó không tạo được giao động chuẩn cho giao tiếp I2C. Sau đó mình thay cái adapter mới thì chạy được, hihi.
Thay adapter?? là như thế nào nhỉ nói cụ thể hơn đc k hay là up cái ảnh lên đi .Mình cũng đang làm cái này mà kết quả trả về của nó toàn là 0xFF thôi . Bạn để lại sdt hoặc mail để mình trao đổi đc k
duongvt vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 16-09-2011, 11:30 PM   #5
duongvt
Nhập môn đệ tử
 
Tham gia ngày: Apr 2011
Bài gửi: 9
:
Bao giờ cũng thế mà . K làm đc thì hỏi còn làm đc rồi thì mất tích luôn Haizzzzzzzzzz
Việt Nam
duongvt vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 17-09-2011, 04:40 AM   #6
luulytim90
Nhập môn đệ tử
 
Tham gia ngày: May 2011
Bài gửi: 3
:
Bồ cũng đang dùng con SRF02? Nếu sensor luôn trả về 0xFF thì có thể do bạn đọc ở sai thanh ghi. SRF02 lưu kết quả ở 2 thanh ghi 8bit gọi là HIGH và LOW (góp lại thì tương đương với 1 thanh 16bit). Bạn đọc thanh High, dịch trái 8bit, rồi cộng với thanh Low mới ra kết quả cần đo. Hoặc cũng có thể bạn sử dụng sai 'mode'.

Nếu cần giúp đỡ thì bạn cứ gửi code và sơ đồ nối dây lên đây, mình có thể giúp.
luulytim90 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 29-09-2011, 04:56 PM   #7
duongvt
Nhập môn đệ tử
 
Tham gia ngày: Apr 2011
Bài gửi: 9
:
SRf02

Trích:
Nguyên văn bởi luulytim90 View Post
Bồ cũng đang dùng con SRF02? Nếu sensor luôn trả về 0xFF thì có thể do bạn đọc ở sai thanh ghi. SRF02 lưu kết quả ở 2 thanh ghi 8bit gọi là HIGH và LOW (góp lại thì tương đương với 1 thanh 16bit). Bạn đọc thanh High, dịch trái 8bit, rồi cộng với thanh Low mới ra kết quả cần đo. Hoặc cũng có thể bạn sử dụng sai 'mode'.

Nếu cần giúp đỡ thì bạn cứ gửi code và sơ đồ nối dây lên đây, mình có thể giúp.
Mình đã mất khá nhiều tg với con này mà k đc
Thôi k trình bày gì nhiều cả mình post code nên bạn giúp đc thì tốt quá
Mà mình k hay vào đây lắm vì cũng hơi bận nếu đc bạn mail cho mình nhé,cảm ơn bạn nhiều lắm.Mail của mình là duong.dktd@gmail.com


code pic

#include <16F877A.h>
#FUSES hs,NOWDT, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_D4,rcv=PIN_D3,bi ts=8,stop=2)
#include <PIC16F877A_registers.h>
#include <LCD_EBLOCK.C>

void main()
{
INT16 I;
UNSIGNED CHAR HSB,LSB,TR,CH,DV;
TRISB=0;
TRISA=0;
DELAY_MS(1000);
PORTB=0;
LCD_INIT();

WHILE(1)
{

PUTC(0x00);
PUTC(0x54);
WHILE(!KBHIT());
HSB=GETC();
WHILE(!KBHIT());
LSB=GETC();
I=HSB*256+LSB;

IF(I>300)
{ lcd_gotoxy(1,1);
LCD_PUTC("DISTANCE=ERROR ");
}
ELSE
{
DV=i%10;
TR=i/100;
CH=(I/10)%10;
lcd_gotoxy(1,1);
LCD_PUTC("DISTANCE=");
LCD_PUTC(TR+0x30);
LCD_PUTC(CH+0x30);
LCD_PUTC(DV+0x30);
LCD_PUTC(" CM");
}
DELAY_MS(2000);
}
}


code avr


/************************************************** ***
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date : 21/09/2011
Author :
Company :
Comments:


Chip type : ATmega16
Program type : Application
Clock frequency : 1.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
************************************************** ***/

#include <mega16.h>
#include <delay.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>

#define START_CLK 0x0A // Start 1:8 prescaler CTC mode
#define START_CLK_N 0x02 // Start 1:8 prescaler normal mode
#define STOP_CLK 0x08 // Stop

// Declare your global variables here
void startTimer(unsigned int time)
{
OCR1A = time; // set thoi gian dem
TIFR = 0x10; // Clear co` nho' timer
TCNT1 = 0x00; // Clear timer
TCCR1B = 0x0A; // Start timer 1:8 prescaler
}
void wait(void)
{
while(!(TIFR&0x10)); // doi co` nho' so sanh
TCCR1B = STOP_CLK; // Stop timer
}
void startRange(void)
{
PORTA = ( 1<<PORTA.0 ); // set trigger len 1
startTimer(0x0002); //cho` 10uS
// wait();
PORTA = ( 0<<PORTA.0 ); // clear trigger ve 0
}

unsigned int Doc_kq(void)
{
unsigned int range;

while(!(PINA&0x02)); // cho` xung echo len muc 1 de bat dau do do rong
TCNT1 = 0x00; // Clear timer
TCCR1B = START_CLK_N; // khoi tao timer 1:8 prescaler o normal mode
while((PINA&0x02)); // cho` xung echo ve muc 0 de stop timer
TCCR1B = STOP_CLK; // Stop timer
range = TCNT1/58; // doc gia tri cua timer và chia cho 58 de dc kq la cm
return(range);
}

void disp(int x,int y, unsigned int data)
{
lcd_gotoxy(x,y);
lcd_putchar((data/100)+48);
lcd_putchar(((data/10)%10)+48);
lcd_putchar((data%10)+48);
delay_ms(2);
}


void main(void)
{
DDRA = 0x01;
TCCR1A=0x00;
TCCR1B=0x08;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
TWBR = 0x20;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// LCD module initialization
lcd_init(16);

while (1)
{
unsigned int range;
lcd_putsf("srf05");
startRange(); //gui xung 10uS de bat dau do
range = Doc_kq(); // cho` xung echo va do do rong xung
disp(0,1,range);
wait();
delay_ms(1000);
lcd_clear();
delay_ms(1000);
};
}


còn về kết nối mình làm uart nên k dùng trở ji cả kết nối trực tiếp thôi
nói chung kết nối mình làm như datasheet. mình nghĩ k sai đc vì đọc rất nhiều lần rồi . K biết thực tế có phải mắc khác với datasheet k thì tớ chịu hic
duongvt vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 29-09-2011, 04:58 PM   #8
duongvt
Nhập môn đệ tử
 
Tham gia ngày: Apr 2011
Bài gửi: 9
:
Ak qên Post nhầm code avr là của con srf05 mà con này cũng k chạy.hix ai biết xem dùm/ Mà bạn luulytim90 để lại mail cho mình biết nhé có gì mình trao đổi qua mail sẽ tiện hơn hihi
duongvt vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Trả lời


Quyền Sử Dụng Ở Diễn Ðàn
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is Mở
Smilies đang Mở
[IMG] đang Mở
HTML đang Tắt

Chuyển đến


Múi giờ GMT. Hiện tại là 07:44 AM.


Được sáng lập bởi Đoàn Hiệp
Powered by vBulletin®
Page copy protected against web site content infringement by Copyscape
Copyright © PIC Vietnam