Zachodniopomorski Uniwersytet Technologiczny
w Szczecinie
Projekt z Układów Elektronicznych w Mechatronice
Czujnik parkowania z wykorzystaniem mikrokontrolera STM32F103CBT6
Mechatronika rok II
Semestr 3, 2014/2015
Spis treści str.
1) Cel projektu 3.
2) Założenia projektowe 4.
3) Wybór rozwiązania projektowego 5.
4) Część Hardware 6.
4.1) Schemat blokowy układu 7.
4.2) Schemat ideowy 8.
4.3) Dobór Elementów 9.
5) Część Software 10.
5.1) Funkcje programu 11.
5.2) Schemat blokowy programu 12.
5.3) Program 14.
6) Napotkane Problemy 16.
7) Instrukcja obsługi 17.
8) Wnioski 18.Cel Projektu
Celem projektu było zaprojektowanie i stworzenie czujnika, który włączany jest za pomącą przycisku na płytce a następnie w czasie swojego działania na bieżąco mierzy odległość od przeszkody oraz za pomocą wyświetlacza, głośnika oraz odpowiednich diod informuje użytkownika jak daleko się on od niej znajduje.
Dodatkowo układ ma posiadać dwa ultradźwiękowe czujniki HC - SR04, za pomocą których dodatkowo obliczany będzie kąt pod jakim zbliżamy się do przeszkody.
Założenia Projektu
Zakładamy, że głównym zastosowaniem naszego czujnika będzie mierzenie odległości
między przeszkodą a naszym urządzeniem. Projekt przewiduje użycie dwóch ultradźwiękowych czujników sterowanych za pomocą płytki STM32F103cbt6.Zmierzona odległość ma być wyświetlana na dołączonym do zestawu ekranie alfanumerycznym 2x16 HD44780. Również ma być wysyłany sygnał dźwiękowy adekwatny do zmierzonej odległości, oraz sygnał świetlny z wykorzystaniem diod umieszczonych na płytce bądź też z wykorzystaniem własnych.
Wybór rozwiązania projektowego
Wybraliśmy ultradźwiękowy czujnik odległości HC-SR04.
Przede wszystkim dlatego, że był nam bardzo dobrze znany, pracowaliśmy już nad nim trochę i wiemy czego się po nim spodziewać.
Jego zasięg pracy mieści się w przedziale 2-200 cm, czyli jak na czujnik wykorzystywany przy obliczaniu odległości od przeszkody nadaje się idealnie.
Ma również bardzo duży kąt wysyłania i odbierania sygnału bo jest to aż 30˚, dlatego jest on lepszy od czujnika laserowego, gdzie wiązka jest po prostu linią prostą i jest ona nie czuła mniejsze przeszkody stojące bliżej, a których światło nie wychwytuje.
A poza tym jest do naszego czujnika masa materiałów, które w znaczny sposób pomogły przy naszym projekcie. No i jego główną zaletą jest iż nie jest drogi (inne czujniki były droższe oraz ich maksymalna odległość pomiarowa wynosiła dużo mniej).
W swoim projekcie wykorzystaliśmy dwa takie czujniki.
Część Hardware
Cały projekt opiera się na mikrokontrolerze STM32F103cbt6 oraz dwóch czujnikach ultradźwiękowych.
Korzystanie z czujnika opiera się głównie na sterowaniu napięciami na poszczególnych pinach.
Schemat blokowy układu
Czujnik HC-SR04 odbiera sygnał z ZL30ARM za pomocą pinu trig. Czas trwania sygnału jest proporcjonalna do czasu trwania wysyłanego przez czujnik ultradźwięku. Następnie dźwięk jest odbierany przez czujnik za pomocą odbiornika, który jest przetwarzany na impuls wysyłany do ZL30ARM (z pinu echo). Użytkownik jest informowany o odległości za pomocą diod, wyświetlacza oraz speaker'a.
Schemat
Ewentualnie z zewnętrznymi diodami
Dobór elementów:
Dobrane były trzy diody, których pobór prądu i spadki napięć są takie same dla wszystkich diod.
Wartości oporników były wybierane według poniższego schematu:
Up=Ud+IR gdzie: Up-napięciepinu , Ud-spadek napięcia na diodzie, IR-spadek napięcia na rezystorze
Przekształcając rownanie mamy:
R=Up-Ud/I
Skoro prąd pobierany przez diodę to I=20mA , spadek napięcia na dodzie to 2,3V oraz napięcie na pinie 3,3V więc rezystor powinien mieć ok. 50 om.
Do czujników dobór rezystorów jest niepotrzebny ponieważ potrzebują one napięcia 5V , które jest udostępnione na ZL30ARM.
Część Software Projektu
Projekt był całkowicie pisany na dostarczoną przez prowadzącego ćwiczenia płytkę STM.
Kompilator, jakiego używaliśmy do stworzenia naszego projektu to CooCox oraz Keil.
Program jest pisany w języku C. Instrukcje i parametry są zgodne ze standardami tego języka. Mogą oczywiście w naszym projekcie trafić się wyjątki, gdyż niektóre polecenia są rozróżniane tylko w środowisku danego kompliatora.
Poprawnie napisany program był kompilowany i następnie wgrywany na płytkę za pomocą specjalnego programatora.
Pomysł jest całkowicie naszego autorstwa także rozwiązania jakie wykorzystaliśmy są wynikiem naszego ciężkiego wysiłku, pracy oraz czasu. Faktem jest, że wszystkie biblioteki, z których korzystamy uzyskaliśmy z różnych źródeł, lecz wszystkie instrukcje ich kolejność i przede wszystkim funckjonalność naszego programu jest całkowicie wynikime naszych umiejętności i zdolności.
Funkcje Programu
Program działa w nieskończonej pętli while, dlatego jego działaniue jest ciągłe i pozwala stale monitorować odległość czujnika od potencjalnej przeszkody.
Na początku ustawiamy stan wysoki na jednym z pinów, aby wysłać sygnał na Trig. Sygnał musi trwać 10[us], więc ustawiamy delay_nus(10). Po zadaniu sygnału wyłączamy stan wysoki i czekamy na odpowiedź z czujnika w postaci sygnału wysokiego i zliczamy jego czas trwania, który jest adekwatny do mierzonej odległości.
To samo robimy z drugim czujnikiem.
Gdy pobierzemy oba sygnały, za pomocą funkcji distance [cm] = ( high level time [us] * 34 ) / 1000 / 2 obliczamy mierzoną odległość.
Mając dwie odległości porównujemy je ze sobą i wybieramy tę najmniejszą wartość, gdyż to ona nas najbardziej interesuje.
Na jej podstawie wyświetlamy wartość odległości na ekranie alfanumerycznym, oraz zapalamy odpowiednie diody na płytce.
Ostatnim etapem jest określenie odległości za pomocą speakera.
Schemat blokowy programu
Schemat blokowy programu obejmuje tylko pętlę While, gdyż jest ona tutaj najistotniejsza.
Przedstawiony schemat i tak nie odwzorowuje złożoności naszego kodu obsługującego 2 czujniki, ekran, głośnik oraz diody.
Program
while(1)
{ do
{}while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)==1);
do{
GPIO_ResetBits(GPIOB, GPIO_Pin_13);//wylaczenie pipkacza
GPIO_SetBits(GPIOB, GPIO_Pin_9);//wysylam sygna³ do trig
delay_nus(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_9);//ustawiam poziom niski po 10 [us]
setSysTickCounter(1000000);
do{
}while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==0) && getSysTickCounter()!=0);//Czekaj dopoki nie wczyta stanu wysokiego na echo
setSysTickCounter(1000000);
do{
}while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==1) && getSysTickCounter()!=0);//licz czas d³ugoci trwania stanu wysokiego
int wynik=stoper(getSysTickCounter); //pobranie wyniku czasu
GPIO_SetBits(GPIOB, GPIO_Pin_8);//wysy³am sygna³ do trig
delay_nus(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_8);//ustawiam poziom niski po 10 [us]
setSysTickCounter(1000000);
do{
}while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==0) && getSysTickCounter()!=0);//Czekaj dopóki nie wczyta stanu wysokiego na echo
setSysTickCounter(1000000);
do{
}while((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==1) && getSysTickCounter()!=0);//licz czas d³ugoci trwania stanu wysokiego
int wynik2=stoper(getSysTickCounter); //pobranie wartosci systick
if(wynik>wynik2)
{
dlugosc=wynik2/58;//funkcja matematyczna
dlugosc1=wynik/58;//dluzsza dlugosc
x=(dlugosc*15)/(dlugosc1-dlugosc);
g=dlugosc/x;
}
if(wynik2>wynik)
{
dlugosc=wynik/58;//przyjmowanie krotszej odleglosci
dlugosc1=wynik2/58; //dluzsza
x=(dlugosc*15)/(dlugosc1-dlugosc);
g=dlugosc/x;
}
//dlugosc=wynik2/58;//funkcja matematyczna
if (dlugosc<150)//odleglosc mniejsza niz 150cm, program sie wlacza
{
//w³¹czanie stopniowo diód
if (dlugosc<150 && dlugosc>100)
GPIO_SetBits(GPIOB, GPIO_Pin_6);
if (dlugosc<100 && dlugosc>50)
GPIO_SetBits(GPIOB, GPIO_Pin_7);
if (dlugosc<50)
GPIO_SetBits(GPIOB, GPIO_Pin_14);
//stopniowe wylaczanie diod
if (dlugosc>50)
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
if (dlugosc>100 && dlugosc<150)
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
if (dlugosc>140)
GPIO_ResetBits(GPIOB, GPIO_Pin_6);
if(dlugosc>150)//w razie nag³ego zblizenia przeszkody
{
GPIO_ResetBits(GPIOB, GPIO_Pin_6);
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
}
tan(g);
st=(g*180)/3.14;
char a[]="Odleglosc";
char b[]="kat";
sprintf(b,"%d",st);
sprintf(a,"%d",dlugosc);
LCD_WriteCommand(HD44780_CLEAR);
LCD_WriteTextXY(a,0,0);
LCD_WriteTextXY("cm",6,0);
LCD_WriteTextXY(b,0,1);
LCD_WriteTextXY("stopni",6,1);
}
if (dlugosc<100)
{
sygnal=dlugosc*10;//wzmocnienie sygnalu dzwiêkowego
GPIO_SetBits(GPIOB, GPIO_Pin_13);//wlaczenie pipkacza
delay_nms(sygnal);
GPIO_ResetBits(GPIOB, GPIO_Pin_13);//wylaczenie pipkacza
delay_nms(dlugosc);
}
}while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)==1);}
}
Napotkane problemy:
Pierwszy problem jaki napotkaliśmy był związany z zliczaniem czasu trwania sygnału na pinie w STM odbieranym z czujnika. Został on rozwiązany poprzez zmianę środowiska programistycznego z Kail na Coocox, który jest bardziej znany przez jednego z wykonujących projekt. Następnie została pobrana odpowiednia biblioteka delay.
Drugim problemem było zainicjalizowanie wyświetlacza alfanumerycznego, ponieważ nie mogliśmy skorzystać z bibliotek z przykładów podanych w książce. Nie współpracowały one ze środowiskiem Coocox.
Po długich tygodniach żmudnej pracy, jeden z kolegów podał nam źródło innego zbioru ćwiczeń i przykładów do mikrokontrolera STM32F103cbt6, w których to znajdowała się biblioteka do naszego ekranu kompatybilna z naszym środowiskiem programistycznym, jakim jest CooCox CoIDE®.
Instrukcja Obsługi
1. Podłącz programator do płytki STM32F103cbt6
2. Podłącz zasilanie do mikrokontrolera.
3. Podłącz zasilanie do programatora.
4. Włącz mikrokontroler.
5. Czekaj aż ekran wypisze "Wcisnij Przycisk 0".
6. Wciśnij przycisk 0.
7. Rozkoszuj się działaniem programu.
8. Wciśnij przycisk Reset, aby zakończyć działanie programu.
Wnioski:
Opracowanie projektu uświadomiło nas (w jakimś stopniu) jak działa się w programowaniu mikrokontrolerów. Okazało się , że aby dobrze umieć programować STMy trzeba poświęcić na nie wiele czasu.
Myślę, że gdybyśmy mieli więcej czasu na poświęcenie sie projektowi byłby on bardziej złożony niż jest obecnie.