View Full Version : Cảm biến siêu âm
ahchu
17-11-2007, 01:17 AM
Chào mọi người,
Em đang làm mạch nhận biết vật cản. Mạch của em dùng PIC8F452 và PING))) ultrasonic sensor (http://www.lynxmotion.com/images/data/pingv1.2.pdf).
Hoạt động: nhận tín hiệu từ sensor sau đó sẽ điều khiển motor quay xuôi và quay ngược thông qua đặt giá trị cho 4 input của H-bridge. Mạch của em set up như hình vẽ dưới
Rất đơn giản!!! Thằng bạn em đang dở cái mạch này thì nó có chuyện phải đi một thời gian, giờ nó đi rồi nó kêu em test hộ nó cái mạch.
Sau khi em test thì mọi thứ đều ok cả, nếu không có vật cản thì output của H-bridge cho ra 12V (forward direction), cho vật cản trước sensor thì H-bridge cho ra -12V (reverse direction). Có điều khoảng cách nhận biết vật cản gần quá cỡ 40cm, mà nó cần nhận biết vật cản từ khoảng cách cỡ 1-2m. Nó quăng cho em cái C code mà em đọc xong chẳng hiểu gì cả. Giờ em muốn viết lại bằng ASM. Mọi người giúp em với, em quên sạch bách về con PIC này rồi.... :(. Đã từng dùng nó cách đây khoảng 2 năm, từ đó đến giờ kô đụng nữa nên quên hết.
Theo mọi người em nên đọc lại phần code của nó (phải bắt đầu học C) hay em nên viết lại code bằng assembly (em đã từng có kinh nghiệm viết Assembly)? Em cũng không rành về con cảm biến siêu âm này, đọc về phần hoạt động của con cảm biến này em vẫn chưa rõ làm thế nào để nâng khoảng cách nhận biết của nó? Mọi người giúp em với...lỡ ôm xô nhận lời giúp rồi....
falleaf
17-11-2007, 09:17 AM
Em nên gửi kèm code lên để mọi người xem giúp, cần viết chú thích đầy đủ, vì đọc code không có chú thích mệt lắm.
Chủ yếu là phần code tính toán khoảng cách siêu âm, đọc siêu âm.
Cảm biến này hoạt động giống với con SRF04, 05 của Devantech. Em có thể tham khảo cách hoạt động của nó được mô tả rất rõ, và có cả source code mẫu của Devantech.
Microchip cũng có một application note về đọc cảm biến siêu âm Polaroid với các nguyên lý tương tự.
Chúc vui
ahchu
23-11-2007, 12:10 AM
C code của bạn em đây ạ
/*
Filename: CC5G.c
Generate a PWM signal with 40% duty cycle
on pulse-width = 5us
off pulse-width = 20ms
on CCP1 (RC2 pin) compare
and configure CCP2 (RC1 pin) for capture
*/
#include <p18cxxx.h>
#include <p18f452.h>
#include <timers.h>
#include <capture.h>
#pragma config WDT = OFF
#define PER1_LIMIT 0x0E10
#define PER2_LIMIT 0x0E10
/*
Speed of sound in air = 1130 ft/sec
TMAX = 18.5ms; TMIN = 115us
FOSC = 8MHz; Processor Clock = 2MHz
CCP Clock = 1MHz
Period = Forward + Backward Trip time
0x0E10 -> 1.8ms
0x8CA0 -> 18ms
*/
unsigned int ov_cnt1, cap1_val1, cap1_val2;
unsigned int ov_cnt2, cap2_val1, cap2_val2;
unsigned int period1, period2; // 16-bit value
unsigned int count = 0; // counter used for waiting to turn relays ON
unsigned int count2 = 0; // counter used for waiting to turn relays ON
void high_ISR( void );
void low_ISR( void );
#pragma code high_vector = 0x08 // force the following statement to
void high_interrupt( void ) { // start at 0x08
_asm
goto high_ISR
_endasm
}
#pragma code low_vector = 0x18 // force the following statement to
void low_interrupt( void ) { // start at 0x18
_asm
goto low_ISR
_endasm
}
#pragma code
#pragma interrupt high_ISR
void high_ISR( void ) {
if( PIR2bits.TMR3IF ) {
PIR2bits.TMR3IF = 0;
ov_cnt2++;
}
if( PIR1bits.TMR1IF ) {
PIR1bits.TMR1IF = 0;
ov_cnt1++;
}
}
#pragma code
#pragma interrupt low_ISR
void low_ISR( void ) {
_asm
retfie 0
_endasm
}
void vDelay( void ) {
unsigned const int MAX = 45450;
unsigned int i = 0;
for( i=0; i<MAX; i++ ) ;
}
void vDelay10us( void ) {
unsigned int i = 0;
}
void vDelay5ms( void ) {
unsigned const int MAX = 1150;
unsigned int i = 0;
for( i=0; i<MAX; i++ ) ;
}
// Delay calculations based on 8MHz crystal, 1:1 prescalar for Timer3
void main( void ) {
unsigned int i = 0;
unsigned int odd = 0;
unsigned int flag = 1; // flag for determining boat direction
int num1 = 0;
int num2 = 1;
// Configure registers for Output Compare -- a 5us trigger pulse
TRISCbits.TRISC2 = 0; // configure CCP1 pin for output
T1CON = 0x81; // turn on Timer1 in 16-bit mode, prescalar = 1
// CCP1CON = 0x09; // configure CCP1 pin to set high initially but pull low on match
// CCPR1 = TMR1H + 0x0020; // start CCP1 compare with delay equals 10
// PIR1bits.CCP1IF = 0; // clear CCP1IF flag to prevent false interrupt
OpenTimer1( TIMER_INT_OFF &
T1_16BIT_RW &
T1_PS_1_1 &
T1_OSC1EN_OFF &
T1_SYNC_EXT_OFF &
T1_SOURCE_INT );
OpenTimer3( TIMER_INT_OFF &
T3_16BIT_RW &
T3_SOURCE_INT &
T3_PS_1_1 &
T3_SYNC_EXT_OFF &
T1_CCP1_T3_CCP2 );
T1CON = 0x81; // turn on Timer1 in 16-bit mode, prescalar = 1
TRISD = 0; // set PORTD for output
TRISCbits.TRISC1 = 1; // configure CCP2 pin for input
TRISCbits.TRISC2 = 1; // configure CCP1 pin for input
INTCONbits.GIE = 0; // Disable global interrupts
RCONbits.IPEN = 1; // enable priority interrupts
PIR2bits.TMR3IF = 0;
IPR2bits.TMR3IP = 1; // promote Timer1 rollover interrupt to high priority
INTCONbits.PEIE = 1; // enable preipheral interrupt
PIE2bits.TMR3IE = 0; // disable Timer3 rollover interrupt
PIR1bits.TMR1IF = 0;
IPR1bits.TMR1IP = 1;
PIE1bits.TMR1IE = 0;
TRISB = 0x00; // configure PORTB as output
while( 1 ) {
vDelay5ms();
// if( !odd )
PORTD = 0x01;
vDelay10us();
PORTD = 0x00;
// vDelay10us();
// PORTD = 0x00;
PIE2bits.CCP2IE = 0;
CCP2CON = 0x05;
PIE2bits.CCP2IE = 1;
// PORTD = 0x00;
PIE2bits.CCP2IE = 1; // disable CCP2 capture interrupt
PIR2bits.CCP2IF = 0;
IPR2bits.CCP2IP = 1; // high priority
while( !( PIR2bits.CCP2IF ) ) ;
cap2_val1 = ReadCapture2(); // save the first captured edge
PIR2bits.CCP2IF = 0;
PIR2bits.TMR3IF = 0;
PIE2bits.TMR3IE = 1; // enable Timer3 rollover interrupt
PIE2bits.CCP2IE = 0;
CCP2CON = 0x04;
PIE2bits.CCP2IE = 1;
PORTD = 0x00;
while( !( PIR2bits.CCP2IF ) ) ; // wait for interrupt
CloseCapture2(); // disable CCP2 capture
cap2_val2 = ReadCapture2();
PIR2bits.TMR3IF = 0;
PIE2bits.TMR3IE = 0; // disable Timer3 rollover interrupt
if( cap2_val2 < cap2_val1 ) { // if timer overflows, decrease overflow count by one
ov_cnt2--;
period2 = ov_cnt2*65536 + cap2_val2 + ( 65536 - cap2_val1 );
}
else {
period2 = ov_cnt2*65536 + cap2_val2 - cap2_val1;
}
ov_cnt2 = 0; // Reset overflow counter
// vDelay5ms();
PORTD = 0x02;
vDelay10us();
PORTD = 0x00;
vDelay10us();
// PORTD = 0x00;
PIE1bits.CCP1IE = 0;
CCP1CON = 0x05;
PIE1bits.CCP1IE = 1;
// PORTD = 0x00;
PIE1bits.CCP1IE = 1; // disable CCP2 capture interrupt
PIR1bits.CCP1IF = 0;
IPR1bits.CCP1IP = 1; // high priority
while( !( PIR1bits.CCP1IF ) ) ;
cap1_val1 = ReadCapture1(); // save the first captured edge
PIR1bits.CCP1IF = 0;
PIR1bits.TMR1IF = 0;
PIE1bits.TMR1IE = 1; // enable Timer3 rollover interrupt
PIE1bits.CCP1IE = 0;
CCP1CON = 0x04;
PIE1bits.CCP1IE = 1;
while( !( PIR1bits.CCP1IF ) ) ; // wait for interrupt
CloseCapture1(); // disable CCP2 capture
cap1_val2 = ReadCapture1();
PIR1bits.TMR1IF = 0;
PIE1bits.TMR1IE = 0; // disable Timer3 rollover interrupt
if( cap1_val2 < cap1_val1 ) { // if timer overflows, decrease overflow count by one
ov_cnt1--;
period1 = ov_cnt1*65536 + cap1_val2 + ( 65536 - cap1_val1 );
}
else {
period1 = ov_cnt1*65536 + cap1_val2 - cap1_val1;
}
ov_cnt1 = 0; // Reset overflow counter
if( period1 > PER1_LIMIT & period2 > PER2_LIMIT & flag ) {
count++;
count2 = 0;
num1 &= 0;
num2 = 0;
if( count > 20 ) {
PORTB = 0x0C; // Forward
}
}
if( period1 > PER1_LIMIT & period2 > PER2_LIMIT & !flag ) {
count++;
num2 = 0;
// num1 = 0;
count2 = 0;
if( count > 20 ) {
PORTB = 0x03; // Reverse
}
}
if( period1 > PER1_LIMIT & period2 < PER2_LIMIT ) {
PORTB = 0x00;
flag = 1;
count = 0;
count2++;
if( count2 > 20 )
PORTB = 0x0C; // Forward
}
if( period1 < PER1_LIMIT & period2 > PER2_LIMIT ) {
PORTB = 0x00;
flag = 0;
count = 0;
num2++;
num1+=num2;
if( num1 > 20 ) {
PORTB = 0x03; // Reverse
}
}
if( period1 < PER1_LIMIT & period2 < PER2_LIMIT ) {
PORTB = 0x00; // Shut down
count = 0;
count2 = 0;
}
}
}
nguyendinhtuan
23-11-2007, 10:36 AM
Bạn tham khảo trang web sau nhé:
http://embedded.olin.edu/ultrasonic/links.php
ahchu
28-11-2007, 03:44 AM
Em muốn làm lại cái cảm biến vật cản. Em định sẽ làm một cái mạch cảm biến bằng sóng âm, khi nào có vật cản trong khoảng từ 1-2m nó sẽ cho ra tín hiệu 1 khi nào không có vật cản trong đó sẽ cho ra tín hiệu 0, như mạch cảm biến hồng ngoại cho con line-following robot mà em đã làm hồi trước. Em không biết là có thể làm như vậy được không.
Hồi trước em dùng IR sensor để nhận biết vạch đen trên nền trắng và robot sẽ đi theo vạch đen ấy.
Hoạt động: IR sẽ bị hấp thụ bởi vạch đen và không phản xạ, điều đó làm đầu thu IR bị ngắt và tín hiệu sẽ là 0. Khi phản xạ lại, đầu thu được nối với nhau và sẽ có tín hiệu. Em nối đầu ra của đầu thu vào Hex-Schimitt trigger IC để nó có tín hiệu 1, 0 trước khi di qua PIC.
Em đang nghĩ làm thế nào để có thể áp dụng cách ấy cho ultrasonic sensor. Em muốn tín hiệu trước khi vào PIC (master micro processor) sẽ được xử lý thành 1, 0. Vì em sẽ phải dùng đến 6 con ultrasonic sensor để tránh vật cản. Mà trong khi đó nếu xử lý theo cách bạn em là dùng CCP1 và CCP2 để so sánh khoảng thời gian(rising edge và falling edge)->khoảng cách-> xử lý... thì sẽ phải dùng nhiều hơn 1 con PIC (PIC 18F452 chỉ có 2 chân compare: CCP1 và CCP2). Nếu dùng được như IR sensor trình bày ở trên thì chỉ cần dùng 1 con PIC để xử lý tín hiệu input 1, 0 từ mạch cảm biến (gồm 6 con ultrasonic sensor).
Mong mọi người cho em lời khuyên!!! Mọi người có thể cùng tham gia vào đề tài này cho vui. Em đang làm một cái thuyền để bơi dưới hồ, thuyền sẽ chạy vòng quanh hồ và tránh không bị mắc cạn, bằng cách nhận biết được khoảng cách từ thuyền đến thành hồ, nếu trong khoảng 2m thì thuyền sẽ quay ngược động cơ và đi lùi lại. Thật ra đề tài này của thằng bạn em, nó làm xong rồi, giờ em giúp nó test và định làm lại cái mạch cảm biến cho vui thôi!
Đây là bài về line-following robot của em làm năm ngoái
http://www.picvietnam.com/forum/showthread.php?t=345
và con robot của em (pin bị chết ngay hôm present nên phải cắm dây điện như dắt cún đi dạo vậy :)) )
http://youtube.com/watch?v=ErFmsQKkPy8
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.