Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * parking.ino
- *
- * 2017 Defitowski Marcin - marcin.defitowski@student.put.poznan.pl
- * Politechnika Poznanska - WBMiZ - Mechatronika 6 semestr
- *
- * Projekt - System Obslugi Parkingu
- * Programowanie Systemow Mechatronicznych
- *
- */
- #include <LiquidCrystal.h>
- #include <Servo.h>
- long nextChange = 0; // wartosc czasu dla ktorej nastapi kolejne wywolanie sprawdzenia czy w obszarze wykrywania sensora istnieje jakis obiekt
- long interval = 1000; // wartosc interwalu dla ktorege nastepuje wywolanie funkcji wymienionej wyzej
- long nextChangeLCD = 0; // wartosc czasu dla kolejnej zmiany wyswietlanego komunikatu
- long intervalLCD = 2000; // 2 sekundy trwania pojedynczego komunikatu na lcd
- long nextRefreshLCD = 0;
- long intervalRefreshLCD = 500;
- long nextChangeOpenClose = 0; // wartosc czasu dla ktorej nastapi wywolanie ruchu serva dla zamkniecia/otwarcia
- int timeStepGate = 100; // 100 ms interwalu pomiedzy kolejnymi krokami ruchu serwa
- long lastTime, currentTime;
- unsigned int numberOfStatement = 0; // rodzaj komunikatu dla lcd -> wiecej w funkcji lcdControl();
- unsigned int freeSites = 10;
- unsigned int maxSites = 10;
- void gatesControl();
- void lcdControl();
- // klasa ktora przechowuje zmienne i metody dla bram jak:
- // piny obslugujace servo i sensor,
- // czas trwania fali i dystans pomiedzy wykrytym obiektem a sensorem,
- // aktualna pozycje serwomechanizmu, zamknieta pozycje, interwaly i statusy
- class CGate
- {
- private:
- const unsigned int stepChange = 5;
- unsigned int status_gate = 0; // 0 - zamknieta, 1 - w trakcie otwierania, 2 - otwarta, 3 w trakcie zamykania
- unsigned int sensorPin, servoPin;
- int actPos, closedPos, openMaxPos;
- long pulseDuration, distanceInCm;
- long timeFound; // czas dla ktorego sensor przestal wykrywac obiekt - po okreslonym czasie nastapi zamkniecie bramy
- bool wasFound = 0; // zmienna przechowuajca dane czy cos bylo lub nie w zakresie wykrywania sensora
- public:
- Servo myServo; // definicja obiektu serwa
- // poczatek konstruktora
- CGate(unsigned int SensorPin, unsigned int ServoPin, unsigned int ClosedPos, unsigned int OpenMaxPos)
- {
- sensorPin = SensorPin;
- servoPin = ServoPin;
- closedPos = ClosedPos; // pozycja zamknieta
- actPos = ClosedPos; // poz aktualna
- openMaxPos = OpenMaxPos; // poz maksymalnie otwarta
- }
- // end of constructor
- void setServo() // funkcja konfigurujaca piny do obslugi serwa oraz automatycznie zamykajaca serwo na start
- {
- myServo.attach(servoPin);
- setActPos(closedPos);
- }
- void setActPos(unsigned int act_pos) // f. nastawiajaca pozycje serwa
- {
- actPos = act_pos;
- myServo.write(actPos);
- }
- void openGate() // funkcja poruszajaca serwem w kierunku otwierania o odpowiedni kat
- {
- if (actPos < openMaxPos)
- {
- actPos += stepChange;
- if (actPos >= openMaxPos)
- {
- actPos = openMaxPos;
- myServo.write(actPos);
- status_gate = 2;
- return;
- }
- else
- {
- myServo.write(actPos);
- status_gate = 1;
- }
- }
- }
- void closeGate() // funkcja poruszajaca serwem w kierunku zamykania o odpowiedni kat
- {
- if (actPos > closedPos)
- {
- actPos -= stepChange;
- if (actPos <= closedPos)
- {
- actPos = closedPos;
- myServo.write(actPos);
- status_gate = 0;
- return;
- }
- else
- {
- myServo.write(actPos);
- status_gate = 3;
- }
- }
- }
- // funkcje get/set
- unsigned int getSensPin() { return sensorPin; }
- unsigned int getServoPin() { return servoPin; }
- unsigned int getActPos() { return actPos; }
- unsigned int getClosedPos() { return closedPos; }
- unsigned int getOpenMaxPos() { return openMaxPos; }
- unsigned int getStepChange() { return stepChange; }
- void setStatusGate(unsigned int StatusGate)
- {
- status_gate = StatusGate;
- }
- unsigned int getStatusGate() { return status_gate; }
- void setTimeFound(long TimeFound) { timeFound = TimeFound; }
- long getTimeFound() { return timeFound; }
- void setWasFound(bool WasFound)
- {
- wasFound = WasFound;
- }
- bool getWasFound() { return wasFound; }
- // koniec funkcje get/set
- // funkcja ktora sprawdza aktywnosc elementow w obszarze wykrywania sensora
- // jesli obiekt jest pomiedzy 0-2.5m w zakresie wykrywania wowczas funkcja zwraca wartosc 'true'
- // jesli nie - return false;
- bool checkGate()
- {
- // PING))) sensor jest wywoływany przez stan WYSOKI co najmniej 2 ms
- // przed tym jednak nalezy wystosowac stan NISKI dla pewności uzyskania przejscia ze stanu NISKIEGO do WYSOKIEGO
- pinMode(sensorPin, OUTPUT);
- digitalWrite(sensorPin, LOW);
- delayMicroseconds(2);
- digitalWrite(sensorPin, HIGH);
- delayMicroseconds(5);
- digitalWrite(sensorPin, LOW);
- // ten sam pin sluzy do odczytania sygnalu z sensora PING)))
- // duration - czas ktory potrzebuje impuls (fala wyslana przez urzadzenie) na dotarcie do przedmiotu i powrot do sensora
- pinMode(sensorPin, INPUT);
- // pulseIn() odczytuje puls (wysoki lub niski) na pinie. Dla przykladu: jesli wartosc jest "wysoki",
- // pulseIn() oczekuje na przejscie pinu w stan wysoki, rozpoczyna odlcizanie, nastepnie oczekuje przejscia stanu pinu w niski
- // i zatrzymuje odliczanie. Zliczony czas jest czasem przebycia fali od sensora do obiektu i z powrotem. Jesli wartosc zwrocona jest rowna 0
- // wowczas nastapilo bledne odczytanie wartosci lub czas ten sie przedawnił (timeout);
- pulseDuration = pulseIn(sensorPin, HIGH);
- // konwertowanie czasu na odleglosc w cm
- distanceInCm = microsecondsToCentimeters(pulseDuration);
- if ((distanceInCm > 0) && (distanceInCm < 250))
- {
- return true; // jakis obiekt znalazl sie w obszarze wykrywania
- }
- else return false; // nic nie zostalo wykryte
- }
- };
- CGate Entrance(6, 9, 0, 75); // sensorPin, servoPin, actualPos (closed = 0), openMaxPos
- CGate Exit(7, 10, 0, 75);
- LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // definicja obiektu dla obslugi lcd
- void setup() {
- // funkcja millis() zwraca wartosc czasu w ms od momentu wystartowania realizacji programu mikroprocesora jako typ long
- lastTime = millis();
- currentTime = millis();
- lcd.begin(16, 2); // inicjalizacja lcd
- Entrance.setServo(); // konfig. serwa
- Exit.setServo();
- }
- void loop() {
- lastTime = currentTime;
- currentTime = millis();
- gatesControl(); // kontrola bramek
- lcdControl(); // kontrola komunikatow na wyswietlaczu lcd
- }
- void gatesControl()
- {
- // wywolanie ponizszego warunku nastepuje co 1 sekunde
- // zrealizowane jest to poprzez porownanie obecnego czasu (czasu uplyniecia od uruchomienia programu) a czasu nastepnej zmiany
- // czas nastepnej zmiany jest rowny czasu obecnemu + interwalowi (1s) - inkrementacja o 1s nastepuje po spelnieniu warunku, zatem co 1s
- if (currentTime >= nextChange || currentTime < lastTime)
- {
- nextChange = currentTime + interval; // inkrementacja czasu nastepnego "wejscia" do warunku o 1s
- // sterowanie brama wjazdowa
- if (Entrance.checkGate()) // funkcja checkGate() zwraca 'true' jesli sensor wykryje cos w swoim obszarze
- {
- Entrance.setWasFound(true); // ustalenie, ze cos znaleziono w obszarze wjazdu
- // jesli status bramy jest inny niz otwarty i sa wolne miejsca to:
- if (Entrance.getStatusGate() != 2 && freeSites > 0) Entrance.setStatusGate(1); // ustawienie statusu jako "w trakcie otwierania"
- }
- // jesli aktualnie czujnik nic nie wykrywa ale w poprzedniej petli (1s temu) wykryto obiekt to:
- else if (Entrance.getWasFound() == true)
- {
- if (Entrance.getStatusGate() == 2) // jesli status bramy jest aktualnie otwarty
- {
- Entrance.setTimeFound(currentTime); // zachowaj czas do porownania
- if (Entrance.checkGate() == false) // jesli sensor nic nie wykrywa
- {
- Entrance.setWasFound(false); // ustaw ze w obecnej petli programu czujnik nic nie wykryl (w danej sekundzie)
- // wniosek - jakis obiekt byl nie krocej niz 1s w obszarze wykrywania sensora zatem ustalam, ze pojazd wjechal
- // ilosc miejsc wolnych jest mniejsza o 1
- freeSites--;
- }
- }
- }
- // jesli nie wykryto obecnie obiektu
- // a roznica obecnego czasu i czasu zapamietanego od ostatniej obecnosci poajzdu przed sensorem wynosi wiecej niz 2s
- // i brama jest otwarta to:
- else if (currentTime - Entrance.getTimeFound() > 2000 && Entrance.getStatusGate() == 2)
- {
- // ten warunek sluzy do tego, aby po 2 sekundach od przejazdu obiektu brama sie zamknela samoczynnie
- // w raize gdyby ponownie jakis obiekt znalazl sie w obrebie obszaru wykrywania sensora,
- // wowczas warunek wyzej zostaje spelniony i brama ponownie sie otwiera, nawet gdy jest w trakcie zamykania
- Entrance.setStatusGate(3); // nadaj bramie status 'w trakcie zamykania'
- }
- // koniec sterowania brama wjazdowa
- // sterowanie brama wyjazdowa - analogicznie do bramy wjazdowej, z tym ze dodaje
- // wolne miejsca po przejechaniu obiektu przez brame
- if (Exit.checkGate())
- {
- Exit.setWasFound(true);
- if (Exit.getStatusGate() != 2) Exit.setStatusGate(1); // ustawienie statusu jako "w trakcie otwierania"
- }
- else if (Exit.getWasFound() == true)
- {
- if (Exit.getStatusGate() == 2)
- {
- Exit.setTimeFound(currentTime);
- if (Exit.checkGate() == false)
- {
- Exit.setWasFound(false);
- freeSites++;
- }
- }
- }
- else if (currentTime - Exit.getTimeFound() > 2000 && Exit.getStatusGate() == 2)
- {
- Exit.setStatusGate(3);
- }
- // koniec sterowania brama wyjazdowa
- }
- // jesli obecny czas jest wiekszy od czasu nastepnej zmiany otwarcia/zamkniecia lub czas sie przedawnil to:
- // (czas ostatniej zmiany otwarcia/zamkniecia, to czas aktualny + interwał o wartości 100ms (0.1s)
- // sluzy to temu, aby ruch serwa nie był nagły do pozycji np. maksymalnej, ale zeby co 0.1s nastapil skok serwa o 5 pozycji
- // zatem caly ruch z pozycji zamknietej do max. otwartej zajmuje 75/5 = 15 -> 15x0.1s = 1.5 sekundy)
- if (currentTime >= nextChangeOpenClose || currentTime < lastTime)
- {
- nextChangeOpenClose = currentTime + timeStepGate; // zwiekszenie nastepnego czasu zmiany
- // jesli status bramy to 'w trakcie otwierania' -> otworz brame (zrob kolejny krok)
- if (Entrance.getStatusGate() == 1) Entrance.openGate();
- // jesli status bramy to 'w trakcie zamykania' -> zamknij brame 9zrob kolejny krok)
- else if (Entrance.getStatusGate() == 3) Entrance.closeGate();
- // analogicznie dla bramy wyjazdowej
- if (Exit.getStatusGate() == 1) Exit.openGate();
- else if (Exit.getStatusGate() == 3) Exit.closeGate();
- }
- }
- void lcdControl() // obsluga lcd
- {
- // podobnie jak w obsludze bram - warunek wykonywany co okreslony czas (2s)
- // pozwala to na zmiane wyswietlanego komunikatu co 2 sekundy
- if (currentTime >= nextChangeLCD || currentTime < lastTime)
- {
- nextChangeLCD = currentTime + intervalLCD;
- numberOfStatement++; // inkrementacja numeru wyswietlanego komunikatu
- if (numberOfStatement > 3) numberOfStatement = 1; // powrot do pierwszego komunikatu
- }
- if (currentTime >= nextRefreshLCD || currentTime < lastTime)
- {
- nextRefreshLCD = currentTime + intervalRefreshLCD;
- // numer komunikatu
- // 1 - stan bramy wjazdowej
- // 2 - stan bramy wyjazdowej
- // 3 - ilsoc wolnych miejsc i zaparkowanych
- // 4 - komunikat o stanie parkingu
- switch (numberOfStatement)
- {
- case 1:
- lcd.clear();
- lcd.setCursor(0, 0);
- lcd.write("Brama wjazdowa");
- lcd.setCursor(0, 1);
- // w zaleznosci od rodzaju statusu bramy wyswietlam kolejne warianty
- switch (Entrance.getStatusGate())
- {
- case 0:
- lcd.write("ZAMKNIETA");
- break;
- case 1:
- lcd.write("OTWIERANA");
- break;
- case 2:
- lcd.write("OTWARTA");
- break;
- case 3:
- lcd.write("ZAMYKANA");
- break;
- default:
- lcd.write("ERROR");
- }
- break;
- case 2:
- lcd.clear();
- lcd.setCursor(0, 0);
- lcd.write("Brama wyjazdowa");
- lcd.setCursor(0, 1);
- switch (Exit.getStatusGate())
- {
- case 0:
- lcd.write("ZAMKNIETA");
- break;
- case 1:
- lcd.write("OTWIERANA");
- break;
- case 2:
- lcd.write("OTWARTA");
- break;
- case 3:
- lcd.write("ZAMYKANA");
- break;
- default:
- lcd.write("ERROR");
- }
- break;
- case 3:
- if (freeSites == 0)
- {
- lcd.clear();
- lcd.setCursor(0, 0);
- lcd.write(" BRAK WOLNYCH");
- lcd.setCursor(0, 1);
- lcd.write(" MIEJSC");
- break;
- }
- else
- {
- lcd.clear();
- lcd.setCursor(0, 0);
- lcd.write("Liczba wolnych");
- lcd.setCursor(0, 1);
- lcd.write(" miejsc ");
- lcd.print(freeSites);
- break;
- }
- default:
- break;
- }
- }
- }
- // funkcja pozwalajaca zmienic otrzymana wartosc z sensora (ms) na cm
- // znajac predkosc dzwieku
- long microsecondsToCentimeters(long microseconds) {
- // predkosc dzwieku to 340 m/s lub 29 ms/cm
- // fala przebiega do przedmiotu i z powrotem, dlatego odleglosc od sensora do przedmiotu
- // to polowa uzyskanej przez sensor wartosci
- return (microseconds / 29 / 2);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement