Първия робот, който направих беше с инфраред сензори. От начало това ми се струваше много сложно, още навлизах и след като успях да накарам робота да "вижда" препядствия бях много радостен
Постепенно започнах да се чувствам с свои води и вече само "виждането" на препядствия не ми беше достатъчно исках да знам на какво разстояние е предмета. За това започнах да търся начини. Първия метод на който попандах бяха готови инфраред сензори, мерещи до 3м, но както не е трудно да се досетите в бг няма такива. После попаднах на ултразвукови сензори, но за съжеление и тях ги няма в бг и реших да се захвана сам да си направя. Метода за мерене и при ифрареда и при ултразвука е следния : изпраща се сигнал светлина/звук с правилната честота (зависи от сензора) и се мери времето, за което ще отиде, ще се отрази от предмета и ще се върне и според скоростта се намира растоянието. Избрах ултразвука тъй като скоростта му е по-нормална от тази на светлината
и времето не трябва да бъде отмерено с такава голяма точност.
Стига празни приказки да минаваме по съшество
Това е схемата на самия сензор, има 2 оснотвни части - приемник и излъчвател на ултразвук с честота 40кНz. Излъчвателя е една схема 555 която генерира правоъгълни импулси на 40kHz и с транзистор се захранва предавателя. По характеристика максималното му напрежение е 20V и тогава дистанцията е 6м, аз съм го тествал на 12 и достига около 5м, като се раздели на 2 тъй като звука трябва да измине 2 пъти разстоянието до обекта на отиване и връщане, получаваме обхват 2.5м, което доста добре, е не като 3м, но си върши работа
До тук всичко добре, но идва време да пристъпим до приемника, отне ми окло 3месеца докато го подкарам :cry:
Първата стъпка от приемането на сигнала е да се усили. Първата схема е ЛМ358, която е операционен усилвател. С помоща на R1, R2, R3 и R4 се задава коефициента на усилване. На първото стъпало е R2:R1 = 10, а на второто R4:R3 = 100 => усилваме сигнала 1000 пъти. Следващата стъпка е да се пречисти, за целта ползвам ЛМ567. Това интегрална схема, която да кажем, че "сравнява честоти". На входа и се подава, честоа която се "сравнява" с друга, която се генерира от С4, TRIM1 и R7. Тя може да бъде настройвана с помоща на TRIM1. И така когато имаме oпорна честота 40кHz и на входа имаме честота 40kHz то изхода променя логическото си ниво от 1 към 0. Но тъй като ще използваме сигнал с продължителност 200микро секунди, това време няма да е достатъчно за да се свали изхода до абсолютна логическа нула за това слгаме един компарато - ЛМ393. С помоща на TRIM2 настройваме нивото, под което ако слезе сигнала от ЛМ567 на изхода на компаратора илиза логическа 1. И така вече този сигнал може да влезе в миктоконтролера. За засичането изплзвам един capture модул, защото доста по точно от ползване на прекъсване. Пристъпваме към сорса :
#include <16F877A.h>
#device ICD=TRUE
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#priority CCP1, TIMER1
#define send_us PIN_D7
#define receive_us PIN_C2
float temp[10] = {0};
float distance;
float avg_dist;
float time;
float us_speed = 345.123;
int1 echo = 0;
#INT_TIMER1
void overflow()
{
disable_interrupts(GLOBAL);
clear_interrupt(INT_CCP1);
clear_interrupt(INT_TIMER1);
setup_timer_1(T1_DISABLED);
setup_ccp1(CCP_OFF);
distance = 512;
}
#INT_CCP1
void receive()
{
if(!echo)
{
disable_interrupts(GLOBAL);
clear_interrupt(INT_TIMER1);
clear_interrupt(INT_CCP1);
setup_ccp1(CCP_OFF);
setup_timer_1(T1_DISABLED);
time = (CCP_1) * 0.0000004;
distance = time * us_speed;
distance = distance / 2;
distance -= 0.04;
echo = 1;
}
}
void send()
{
int i = 0;
//set ccp and timer module
setup_ccp1(CCP_CAPTURE_RE);
setup_timer_1 (T1_INTERNAL);
//all interrupts on
enable_interrupts(GLOBAL);
echo = 0;
output_bit(send_us, 1);
set_timer1(0);
delay_us(200);
output_bit(send_us, 0);
}
void analyze()
{
int i = 0, cnt_max = 0, max = 0, min = 0, count = 0, dist;
float cur_sum = 0, cur_dist = 0;
for(i = 0; i < 10; i++)
{
if(temp[i] == 512.0) cnt_max++;
if(temp[i] > temp[max]) max = i;
if(temp[i] < temp[min]) min = i;
}
if(cnt_max > 5) avg_dist = 255;
else
{
for(i = 0; i < 10; i++)
if(i != max && i != min && temp[i] != 512.0)
{
cur_sum += temp[i];
count++;
}
cur_dist = cur_sum / count;
cur_dist = cur_dist * 100;
dist = (int)cur_dist;
if((cur_dist - dist) >= 0.5) dist++;
avg_dist = dist;
}
}
main()
{
//define variables
int i = 0, j = 0;
//set IO ports
set_tris_b(0x00);
set_tris_c(0x00);
set_tris_d(0x00);
//enable interrupts
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_CCP1);
clear_interrupt(INT_CCP1);
//clear IO ports
output_b(0x00);
output_c(0x00);
output_d(0x00);
for(j = 0; j < 25; j++)
{
for(i = 0; i < 10; i++)
{
send();
temp[i] = distance;
delay_ms(20);
}
analyze();
}
}
Можете да го свалите от
тукЩе обясня на кратко как работи, а ако имате въпроси питайте. Значи първо инициализарме таймери и кепчър модула. По зададените параметри в сорса таймера ще инкрементира всеки 0,0000004 секунди и ще се напълва за 0,0262144 секунди, за което време звука ще премине приблизително 9м, което ни е напълно достатъчно тъй като ние имаме обхват от 2,5м => при оверфлоу казваме, че няма препядствие. След това викам функцията send(), която сетва таймера на 0, след това вдига пина , който контролира 555 за 200микросекунди, и така изпращаме сигнал с дължина 200микросекунд с честота 40кHz. След това имаме две функции, които са всъщност функци, ползващи интерупт. Първата е overflow(); Тя се активира ако таймера се напълни, тя дезактивира всички прекъсвания, чисти флаговете за такива и задава стойност на distance = 512, което означава оверфлоу. Другия варианt е да се активира receive(), тя пак спира всичките интерупти, чисти флаговете, после зима броя на инкрементиранията на таймера чрез кепчър модула, умножава по 0,0000004 - така намира времето, след това умножава по скоростта на звука и на края дели дистанцият на 2 и вади 0,04 което е корекция, тъй като до като се задейства кепчър модула минава време
И така за едно измерване, мери 10пъти, за по-голяма точност. После получената редица от 10 елемента се обработва- махат се най - малкия и най-големия елемент и ако има по-малко от 5 512 се пренебрегват. И след всичко това крайната стойност е в avr_dist
Това е в общи линии, на теория е лесно, но докато тръгне на практика ми беше много трудно. За малко да забравя ЛМ567 я има в комет, а за предавател и приемника от
тук най-отдолу. Няколко пъти съм си поръчвал и по пощата идват максимум за седмица. Има се предлагат и затворени сензори, но не са достатъчно чувствителни, важно е да отворени.
Очаквам въпроси