Advertisement
defit

Projekt Parking

Sep 20th, 2017
755
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.73 KB | None | 0 0
  1. /*
  2. * parking.ino
  3. *
  4. * 2017 Defitowski Marcin - marcin.defitowski@student.put.poznan.pl
  5. * Politechnika Poznanska - WBMiZ - Mechatronika 6 semestr
  6. *
  7. * Projekt - System Obslugi Parkingu
  8. * Programowanie Systemow Mechatronicznych
  9. *
  10. */
  11.  
  12. #include <LiquidCrystal.h>
  13. #include <Servo.h>
  14.  
  15. long nextChange = 0; // wartosc czasu dla ktorej nastapi kolejne wywolanie sprawdzenia czy w obszarze wykrywania sensora istnieje jakis obiekt
  16. long interval = 1000;  // wartosc interwalu dla ktorege nastepuje wywolanie funkcji wymienionej wyzej
  17. long nextChangeLCD = 0; // wartosc czasu dla kolejnej zmiany wyswietlanego komunikatu
  18. long intervalLCD = 2000; // 2 sekundy trwania pojedynczego komunikatu na lcd
  19. long nextRefreshLCD = 0;
  20. long intervalRefreshLCD = 500;
  21. long nextChangeOpenClose = 0; // wartosc czasu dla ktorej nastapi wywolanie ruchu serva dla zamkniecia/otwarcia
  22. int timeStepGate = 100; // 100 ms interwalu pomiedzy kolejnymi krokami ruchu serwa
  23. long lastTime, currentTime;
  24. unsigned int numberOfStatement = 0; // rodzaj komunikatu dla lcd -> wiecej w funkcji lcdControl();
  25. unsigned int freeSites = 10;
  26. unsigned int maxSites = 10;
  27.  
  28. void gatesControl();
  29. void lcdControl();
  30. // klasa ktora przechowuje zmienne i metody dla bram jak:
  31. // piny obslugujace servo i sensor,
  32. // czas trwania fali i dystans pomiedzy wykrytym obiektem a sensorem,
  33. // aktualna pozycje serwomechanizmu, zamknieta pozycje, interwaly i statusy
  34. class CGate
  35. {
  36. private:
  37.     const unsigned int stepChange = 5;
  38.     unsigned int status_gate = 0; // 0 - zamknieta, 1 - w trakcie otwierania, 2 - otwarta, 3 w trakcie zamykania
  39.     unsigned int sensorPin, servoPin;
  40.     int actPos, closedPos, openMaxPos;
  41.     long pulseDuration, distanceInCm;
  42.     long timeFound; // czas dla ktorego sensor przestal wykrywac obiekt - po okreslonym czasie nastapi zamkniecie bramy
  43.     bool wasFound = 0; // zmienna przechowuajca dane czy cos bylo lub nie w zakresie wykrywania sensora
  44.  
  45.  
  46. public:
  47.     Servo myServo; // definicja obiektu serwa
  48.     // poczatek konstruktora
  49.     CGate(unsigned int SensorPin, unsigned int ServoPin, unsigned int ClosedPos, unsigned int OpenMaxPos)
  50.     {
  51.         sensorPin = SensorPin;
  52.         servoPin = ServoPin;
  53.         closedPos = ClosedPos; // pozycja zamknieta
  54.         actPos = ClosedPos; // poz aktualna
  55.         openMaxPos = OpenMaxPos; // poz maksymalnie otwarta
  56.     }
  57.     // end of constructor
  58.  
  59.     void setServo()  // funkcja konfigurujaca piny do obslugi serwa oraz automatycznie zamykajaca serwo na start
  60.     {
  61.         myServo.attach(servoPin);
  62.         setActPos(closedPos);
  63.     }
  64.     void setActPos(unsigned int act_pos)  // f. nastawiajaca pozycje serwa
  65.     {
  66.         actPos = act_pos;
  67.         myServo.write(actPos);
  68.     }
  69.  
  70.     void openGate()  // funkcja poruszajaca serwem w kierunku otwierania o odpowiedni kat
  71.     {
  72.         if (actPos < openMaxPos)
  73.         {
  74.             actPos += stepChange;
  75.             if (actPos >= openMaxPos)
  76.             {
  77.                 actPos = openMaxPos;
  78.                 myServo.write(actPos);
  79.                 status_gate = 2;
  80.                 return;
  81.             }
  82.             else
  83.             {
  84.                 myServo.write(actPos);
  85.                 status_gate = 1;
  86.             }
  87.  
  88.         }
  89.     }
  90.  
  91.     void closeGate() // funkcja poruszajaca serwem w kierunku zamykania o odpowiedni kat
  92.     {
  93.         if (actPos > closedPos)
  94.         {
  95.             actPos -= stepChange;
  96.             if (actPos <= closedPos)
  97.             {
  98.                 actPos = closedPos;
  99.                 myServo.write(actPos);
  100.                 status_gate = 0;
  101.                 return;
  102.             }
  103.             else
  104.             {
  105.                 myServo.write(actPos);
  106.                 status_gate = 3;
  107.             }
  108.  
  109.         }
  110.     }
  111.     // funkcje get/set
  112.     unsigned int getSensPin() { return sensorPin; }
  113.     unsigned int getServoPin() { return servoPin; }
  114.     unsigned int getActPos() { return actPos; }
  115.     unsigned int getClosedPos() { return closedPos; }
  116.     unsigned int getOpenMaxPos() { return openMaxPos; }
  117.     unsigned int getStepChange() { return stepChange; }
  118.     void setStatusGate(unsigned int StatusGate)
  119.     {
  120.         status_gate = StatusGate;
  121.     }
  122.     unsigned int getStatusGate() { return status_gate; }
  123.     void setTimeFound(long TimeFound) { timeFound = TimeFound; }
  124.     long getTimeFound() { return timeFound; }
  125.     void setWasFound(bool WasFound)
  126.     {
  127.         wasFound = WasFound;
  128.     }
  129.     bool getWasFound() { return wasFound; }
  130.     // koniec funkcje get/set
  131.  
  132.     // funkcja ktora sprawdza aktywnosc elementow w obszarze wykrywania sensora
  133.     // jesli obiekt jest pomiedzy 0-2.5m w zakresie wykrywania wowczas funkcja zwraca wartosc 'true'
  134.     // jesli nie - return false;
  135.     bool checkGate()
  136.     {
  137.         // PING))) sensor jest wywoływany przez stan WYSOKI co najmniej 2 ms
  138.         // przed tym jednak nalezy wystosowac stan NISKI dla pewności uzyskania przejscia ze stanu NISKIEGO do WYSOKIEGO
  139.         pinMode(sensorPin, OUTPUT);
  140.         digitalWrite(sensorPin, LOW);
  141.         delayMicroseconds(2);
  142.         digitalWrite(sensorPin, HIGH);
  143.         delayMicroseconds(5);
  144.         digitalWrite(sensorPin, LOW);
  145.  
  146.         // ten sam pin sluzy do odczytania sygnalu z sensora PING)))
  147.         // duration - czas ktory potrzebuje impuls (fala wyslana przez urzadzenie) na dotarcie do przedmiotu i powrot do sensora
  148.         pinMode(sensorPin, INPUT);
  149.  
  150.         // pulseIn() odczytuje puls (wysoki lub niski) na pinie. Dla przykladu: jesli wartosc jest "wysoki",
  151.         // pulseIn() oczekuje na przejscie pinu w stan wysoki, rozpoczyna odlcizanie, nastepnie oczekuje przejscia stanu pinu w niski
  152.         // i zatrzymuje odliczanie. Zliczony czas jest czasem przebycia fali od sensora do obiektu i z powrotem. Jesli wartosc zwrocona jest rowna 0
  153.         // wowczas nastapilo bledne odczytanie wartosci lub czas ten sie przedawnił (timeout);
  154.         pulseDuration = pulseIn(sensorPin, HIGH);
  155.         // konwertowanie czasu na odleglosc w cm
  156.         distanceInCm = microsecondsToCentimeters(pulseDuration);
  157.  
  158.         if ((distanceInCm > 0) && (distanceInCm < 250))
  159.         {
  160.             return true; // jakis obiekt znalazl sie w obszarze wykrywania
  161.         }
  162.         else return false; // nic nie zostalo wykryte
  163.     }
  164.  
  165. };
  166.  
  167. CGate Entrance(6, 9, 0, 75); // sensorPin, servoPin, actualPos (closed = 0), openMaxPos
  168. CGate Exit(7, 10, 0, 75);
  169. LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  // definicja obiektu dla obslugi lcd
  170.  
  171. void setup() {
  172.     // funkcja millis() zwraca wartosc czasu w ms od momentu wystartowania realizacji programu mikroprocesora jako typ long
  173.     lastTime = millis();
  174.     currentTime = millis();
  175.     lcd.begin(16, 2); // inicjalizacja lcd
  176.     Entrance.setServo(); // konfig. serwa
  177.     Exit.setServo();
  178. }
  179.  
  180. void loop() {
  181.     lastTime = currentTime;
  182.     currentTime = millis();
  183.     gatesControl();  // kontrola bramek
  184.     lcdControl(); // kontrola komunikatow na wyswietlaczu lcd
  185. }
  186.  
  187. void gatesControl()
  188. {
  189.     // wywolanie ponizszego warunku nastepuje co 1 sekunde
  190.     // zrealizowane jest to poprzez porownanie obecnego czasu (czasu uplyniecia od uruchomienia programu) a czasu nastepnej zmiany
  191.     // czas nastepnej zmiany jest rowny czasu obecnemu + interwalowi (1s) - inkrementacja o 1s nastepuje po spelnieniu warunku, zatem co 1s
  192.     if (currentTime >= nextChange || currentTime < lastTime)
  193.     {
  194.         nextChange = currentTime + interval; // inkrementacja czasu nastepnego "wejscia" do warunku o 1s
  195.         // sterowanie brama wjazdowa
  196.         if (Entrance.checkGate()) // funkcja checkGate() zwraca 'true' jesli sensor wykryje cos w swoim obszarze
  197.         {
  198.             Entrance.setWasFound(true); // ustalenie, ze cos znaleziono w obszarze wjazdu
  199.             // jesli status bramy jest inny niz otwarty i sa wolne miejsca to:
  200.             if (Entrance.getStatusGate() != 2 && freeSites > 0) Entrance.setStatusGate(1); // ustawienie statusu jako "w trakcie otwierania"
  201.         }
  202.         // jesli aktualnie czujnik nic nie wykrywa ale w poprzedniej petli (1s temu) wykryto obiekt to:
  203.         else if (Entrance.getWasFound() == true)
  204.         {
  205.             if (Entrance.getStatusGate() == 2) // jesli status bramy jest aktualnie otwarty
  206.             {
  207.                 Entrance.setTimeFound(currentTime); // zachowaj czas do porownania
  208.                 if (Entrance.checkGate() == false) // jesli sensor nic nie wykrywa
  209.                 {
  210.                     Entrance.setWasFound(false); // ustaw ze w obecnej petli programu czujnik nic nie wykryl (w danej sekundzie)
  211.                     // wniosek - jakis obiekt byl nie krocej niz 1s w obszarze wykrywania sensora zatem ustalam, ze pojazd wjechal
  212.                     // ilosc miejsc wolnych jest mniejsza o 1
  213.                     freeSites--;
  214.                 }
  215.             }
  216.         }
  217.         // jesli nie wykryto obecnie obiektu
  218.         // a roznica obecnego czasu i czasu zapamietanego od ostatniej obecnosci poajzdu przed sensorem wynosi wiecej niz 2s
  219.         // i brama jest otwarta to:
  220.         else if (currentTime - Entrance.getTimeFound() > 2000 && Entrance.getStatusGate() == 2)
  221.         {
  222.             // ten warunek sluzy do tego, aby po 2 sekundach od przejazdu obiektu brama sie zamknela samoczynnie
  223.             // w raize gdyby ponownie jakis obiekt znalazl sie w obrebie obszaru wykrywania sensora,
  224.             // wowczas warunek wyzej zostaje spelniony i brama ponownie sie otwiera, nawet gdy jest w trakcie zamykania
  225.             Entrance.setStatusGate(3); // nadaj bramie status 'w trakcie zamykania'
  226.         }
  227.         // koniec sterowania brama wjazdowa
  228.  
  229.         // sterowanie brama wyjazdowa - analogicznie do bramy wjazdowej, z tym ze dodaje
  230.         // wolne miejsca po przejechaniu obiektu przez brame
  231.         if (Exit.checkGate())
  232.         {
  233.             Exit.setWasFound(true);
  234.             if (Exit.getStatusGate() != 2) Exit.setStatusGate(1); // ustawienie statusu jako "w trakcie otwierania"
  235.         }
  236.         else if (Exit.getWasFound() == true)
  237.         {
  238.             if (Exit.getStatusGate() == 2)
  239.             {
  240.                 Exit.setTimeFound(currentTime);
  241.                 if (Exit.checkGate() == false)
  242.                 {
  243.                     Exit.setWasFound(false);
  244.                     freeSites++;
  245.                 }
  246.             }
  247.         }
  248.         else if (currentTime - Exit.getTimeFound() > 2000 && Exit.getStatusGate() == 2)
  249.         {
  250.             Exit.setStatusGate(3);
  251.         }
  252.         // koniec sterowania brama wyjazdowa
  253.     }
  254.  
  255.     // jesli obecny czas jest wiekszy od czasu nastepnej zmiany otwarcia/zamkniecia lub czas sie przedawnil to:
  256.     // (czas ostatniej zmiany otwarcia/zamkniecia, to czas aktualny + interwał o wartości 100ms (0.1s)
  257.     // 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
  258.     // zatem caly ruch z pozycji zamknietej do max. otwartej zajmuje 75/5 = 15 -> 15x0.1s = 1.5 sekundy)
  259.     if (currentTime >= nextChangeOpenClose || currentTime < lastTime)
  260.     {
  261.         nextChangeOpenClose = currentTime + timeStepGate;  // zwiekszenie nastepnego czasu zmiany
  262.         // jesli status bramy to 'w trakcie otwierania' -> otworz brame (zrob kolejny krok)
  263.         if (Entrance.getStatusGate() == 1) Entrance.openGate();
  264.         // jesli status bramy to 'w trakcie zamykania' -> zamknij brame 9zrob kolejny krok)
  265.         else if (Entrance.getStatusGate() == 3) Entrance.closeGate();
  266.        
  267.         // analogicznie dla bramy wyjazdowej
  268.         if (Exit.getStatusGate() == 1) Exit.openGate();
  269.         else if (Exit.getStatusGate() == 3) Exit.closeGate();
  270.     }
  271. }
  272.  
  273. void lcdControl() // obsluga lcd
  274. {
  275.     // podobnie jak w obsludze bram - warunek wykonywany co okreslony czas (2s)
  276.     // pozwala to na zmiane wyswietlanego komunikatu co 2 sekundy
  277.     if (currentTime >= nextChangeLCD || currentTime < lastTime)
  278.     {
  279.         nextChangeLCD = currentTime + intervalLCD;
  280.         numberOfStatement++; // inkrementacja numeru wyswietlanego komunikatu
  281.         if (numberOfStatement > 3) numberOfStatement = 1; // powrot do pierwszego komunikatu
  282.     }
  283.  
  284.     if (currentTime >= nextRefreshLCD || currentTime < lastTime)
  285.     {
  286.         nextRefreshLCD = currentTime + intervalRefreshLCD;
  287.         // numer komunikatu
  288.         // 1 - stan bramy wjazdowej
  289.         // 2 - stan bramy wyjazdowej
  290.         // 3 - ilsoc wolnych miejsc i zaparkowanych
  291.         // 4 - komunikat o stanie parkingu
  292.         switch (numberOfStatement)
  293.         {
  294.         case 1:
  295.             lcd.clear();
  296.             lcd.setCursor(0, 0);
  297.             lcd.write("Brama wjazdowa");
  298.             lcd.setCursor(0, 1);
  299.             // w zaleznosci od rodzaju statusu bramy wyswietlam kolejne warianty
  300.             switch (Entrance.getStatusGate())
  301.             {
  302.             case 0:
  303.                 lcd.write("ZAMKNIETA");
  304.                 break;
  305.             case 1:
  306.                 lcd.write("OTWIERANA");
  307.                 break;
  308.             case 2:
  309.                 lcd.write("OTWARTA");
  310.                 break;
  311.             case 3:
  312.                 lcd.write("ZAMYKANA");
  313.                 break;
  314.             default:
  315.                 lcd.write("ERROR");
  316.             }
  317.             break;
  318.         case 2:
  319.             lcd.clear();
  320.             lcd.setCursor(0, 0);
  321.             lcd.write("Brama wyjazdowa");
  322.             lcd.setCursor(0, 1);
  323.             switch (Exit.getStatusGate())
  324.             {
  325.             case 0:
  326.                 lcd.write("ZAMKNIETA");
  327.                 break;
  328.             case 1:
  329.                 lcd.write("OTWIERANA");
  330.                 break;
  331.             case 2:
  332.                 lcd.write("OTWARTA");
  333.                 break;
  334.             case 3:
  335.                 lcd.write("ZAMYKANA");
  336.                 break;
  337.             default:
  338.                 lcd.write("ERROR");
  339.             }
  340.             break;
  341.         case 3:
  342.             if (freeSites == 0)
  343.             {
  344.                 lcd.clear();
  345.                 lcd.setCursor(0, 0);
  346.                 lcd.write("  BRAK WOLNYCH");
  347.                 lcd.setCursor(0, 1);
  348.                 lcd.write("     MIEJSC");
  349.                 break;
  350.             }
  351.             else
  352.             {
  353.                 lcd.clear();
  354.                 lcd.setCursor(0, 0);
  355.                 lcd.write("Liczba wolnych");
  356.                 lcd.setCursor(0, 1);
  357.                 lcd.write("   miejsc ");
  358.                 lcd.print(freeSites);
  359.                 break;
  360.             }
  361.         default:
  362.             break;
  363.         }
  364.     }
  365. }
  366.  
  367. // funkcja pozwalajaca zmienic otrzymana wartosc z sensora (ms) na cm
  368. // znajac predkosc dzwieku
  369. long microsecondsToCentimeters(long microseconds) {
  370.     // predkosc dzwieku to 340 m/s  lub 29 ms/cm
  371.     // fala przebiega do przedmiotu i z powrotem, dlatego odleglosc od sensora do przedmiotu
  372.     // to polowa uzyskanej przez sensor wartosci
  373.     return (microseconds / 29 / 2);
  374. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement