Projekt k repozitáru - Github: Hasičské stopky
Arduino LCD Stopwatch Firesport Schematics Code Eagle

Programová implementácia pre projekt Hasičské stopky - Arduino


Knižnica pre LCD znakový displej 16x2, 20x4 s I2C prevodníkom

Nahratie strojového kódu do Arduina - vzorovo pre COM21 - nástroj avrdude - program sketch.ino.hex (spustený cez CMD)

  • AVRDUDE je nutné spustiť cez CMD (príkazový riadok) je nainštalované s prostredím Arduino IDE. Nachádza sa v C:/Users/User/Documents/ArduinoData/packages/arduino/tools/avrdude/6.X.X-arduino/bin
  • avrdude -CC: avrdude.conf -v -patmega328p -carduino -PCOM21 -b115200 -D -Uflash:w:sketch.ino.hex:i
  • Ak sa v konzolových programoch neorientujete a potrebuje GUI rozhranie, využite nástroj XLoader.
  • Strojový kód (.hex) zaručuje, že daný program je kompatibilný a má totožnú funkčnosť na všetky zariadenia, do ktorých sa nahrá a spustí. Kód je tak univerzálny a poskytuje možnosť na ukážku poskytnúť autorovi záujemcom o vyskúšanie projektu jeho build bez prístupu ku zdrojovému (.ino) kódu.
  • Pre nahratie strojového kódu do Arduina je možné využiť nástroj AVRDUDE, ktorý pre nahrávanie skompilovaného programu využíva i prostredie Arduino IDE. Nástroj je možné spúšťať priamo z príkazového riadku, ale je nutné správne nastaviť všetky konfigurovateľné údaje a tak nie je vhodný pre menej skúsených programátorov, či laikov. XLoader je Windows aplikácia (spusiteľný .exe nástroj) s jednoduchým grafickým rozhraním, ktoré umožňuje výber firmvéru - strojového kódu (.hex), cieľovej platformy a vie dynamicky ukázať COM port, na ktorom sa zariadenie nachádza. Umožňuje vypalovať firmvér do AVR platforiem t.j. Arduino Uno, Nano, Duemilanove (AtMega328 / AtMega168), Arduino Mega (AtMega1280 / AtMega2560). Jednoduchým kliknutím na Upload je možné strojový kód automatizovane nahrať (XLoader využíva podobne ako Arduino IDE nástroj AVRDUDE). Okno XLoadera informuje o úspešnom uploade formou výpisu počtu uploadovaných bajtov. Po nahratí firmvéru z Github repozitáru projektu Hasičské stopky sú stopky ihneď pripravené na prevádzku. Firmvér stopiek je rozlíšený na základe I2C adresy znakového LCD displeja - štandardne 0x27 / 0x3F. Firmvér zo strojových kódov umožňuje pre stopky s počítaním na stotiny sekundy v Shareware verzii dokáže merať max 15 sekúnd. Slúži na overenie funkčnosti, testovanie rýchlosti reakcie, odozvy systému - kompilované z kompletnej .ino aplikácie (nedostupná zdarma).

    Firmvér je dostupný v priečinku firmwave projektu: PROJEKT
    XLoader - Arduino - AVRDUDE - Termostat - Ethernet

    Stopky na desatiny sekundy - INTERNAL PULLUP

    /*|------------------------------------------------------------------------------------------|*/
    /*|VYHOTOVIL: MARTIN CHLEBOVEC                                                               |*/
    /*|HASICSKE STOPKY - VERZIA ZDARMA - NA DESATINY SEKUNDY S CASOM PRE DVA UTOKY - LAVY/PRAVY  |*/
    /*|FUNGUJE NA PRINCIPE FUNKCIE MILLIS() A VYKONAVANI KRATKYCH PROGRAMOVYCH CYKLOV            |*/
    /*|INPUT PULLUP ZAPOJENIE S 50kohm INTERNAMY REZISTOROM (PODLA SCHEMY)                       |*/
    /*|PROGRAM FUNGUJE PRE ZASTAVENIE A SPUSTENIE OBOCH CASOV JEDNYM TLACIDLOM                   |*/
    /*|PROGRAMOVU LOGIKU SI MOZETE UPRAVIT PRE OVLADANIE CASOV SAMOSTATNYMI KONTAKTMI NA TERCOCH |*/
    /*|Doska: Arduino Uno, Nano, Mega, ATmega328P (Hardware I2C)                                 |*/
    /*|WEB: http://arduino.clanweb.eu/hasicske-stopky.php                                        |*/
    /*|------------------------------------------------------------------------------------------|*/
    
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    //I2C adresa, stlpce, riadky, pouziva sa i 0x3F pre displej 20x4, 0x27 pre 16x2, skontruj cez I2C scanner https://playground.arduino.cc/Main/I2cScanner/
    LiquidCrystal_I2C lcd(0x3F, 20, 4);
    
    //DEKLARACIA KONŠTÁNT S NASTAVENÍM POČIATOCNÝCH HODNÔT
    const int start_tlacidlo = 12;
    const int lavy_terc_kontakt = 11;
    const int pravy_terc_kontakt = 10;
    const int vynulovat_cas_tlacidlo = 9;
    
    boolean run = false;         //bezi cas pre LAVY UTOK?
    boolean run2 = false;         //bezi cas pre PRAVY UTOK?
    
    //STAVY NACITANYCH LOGICKYCH HODNOT TLACIDIEL
    int start_tlacidlo_stav = HIGH;
    int lavy_terc_kontakt_stav = HIGH;
    int pravy_terc_kontakt_stav = HIGH;
    int vynulovat_cas_tlacidlo_stav = HIGH;
    
    unsigned long timer = 0; //timer
    
    //PREMENNE PRE PRVY CAS - LAVY UTOK
    int second = 0;
    int minute = 0;
    int tenth = 0;
    
    //PREMENNE PRE DRUHY CAS - PRAVY UTOK
    int second2 = 0;
    int minute2 = 0;
    int tenth2 = 0;
    
    void setup() {
      lcd.begin(); //incializacia displeja na I2C zbernici
      lcd.backlight(); //zapnutie podsvietenia
      pinMode(start_tlacidlo, INPUT_PULLUP); //nastav ako vstup proti internemu 50kohm pullup rezistoru
      pinMode(lavy_terc_kontakt, INPUT_PULLUP);
      pinMode(pravy_terc_kontakt, INPUT_PULLUP);
      pinMode(vynulovat_cas_tlacidlo, INPUT_PULLUP);
      lcd.setCursor(0, 0); //nastav kurzor pre zapis na 1. riadok, 1. stlpec
      lcd.print("   AUTOR PROJEKTU");
      lcd.setCursor(0, 1); //nastav kurzor pre zapis na 2. riadok, 1. stlpec
      lcd.print("  MARTIN CHLEBOVEC");
      delay(2500);
      lcd.setCursor(0, 0); //nastav kurzor pre zapis na 1. riadok, 1. stlpec
      lcd.print("00:00:0 L. PRUD    ");
      lcd.setCursor(0, 1); //nastav kurzor pre zapis na 2. riadok, 1. stlpec
      lcd.print("00:00:0 P. PRUD    ");
    }
    
    void tickClock() {
      Serial.println(millis() / 10);
      if ((timer - millis() / 100) >= 100 || timer == 0) {
        tick();
        timer = millis() / 100;
      }
    }
    
    void loop() {
      tickClock();
      start_tlacidlo_stav = digitalRead(start_tlacidlo);
      lavy_terc_kontakt_stav = digitalRead(lavy_terc_kontakt);
      pravy_terc_kontakt_stav = digitalRead(pravy_terc_kontakt);
      vynulovat_cas_tlacidlo_stav = digitalRead(vynulovat_cas_tlacidlo);
      checkStart();
    }
    
    void checkStart() {
      if (start_tlacidlo_stav == LOW ) {
        run = true; //aktivuj cas pre lavy prud
        run2 = true; //aktivuj cas pre pravy prud
      }
      if (lavy_terc_kontakt_stav == LOW ) {
        run = false;
      }
      if (pravy_terc_kontakt_stav == LOW ) {
        run2 = false;
      }
      if (vynulovat_cas_tlacidlo_stav == LOW ) {
        run = false;
        run2 = false;
        second = 0;
        minute = 0;
        tenth = 0;
        second2 = 0;
        minute2 = 0;
        tenth2 = 0;
        updateLCD();
        updateLCD2();
      }
    }
    
    
    void tick() { //tick sa vykonava kazdych 100 miliseund, teda kazdu desatinu sekundy
      //LOGIKA BEZIACEHO CASU PRVEHO UTOKU (UTOK LAVY)
      if (run) {
        updateLCD();
        if (tenth == 9) {
          tenth = 0;
          if (second == 59) {
            second = 0;
            minute++;
          } else {
            second++;
          }
        } else {
          tenth++;
        }
      }
    
      //LOGIKA BEZIACEHO CASU DRUHEHO UTOKU (UTOK PRAVY)
      if (run2) {
        updateLCD2();
        if (tenth2 == 9) {
          tenth2 = 0;
          if (second2 == 59) {
            second2 = 0;
            minute2++;
          } else {
            second2++;
          }
        } else {
          tenth2++;
        }
      }
    }
    
    //VYPIS PRVEHO UTOKU NA DISPLEJ (UTOK LAVY)
    void updateLCD() {
      lcd.setCursor(0, 0);
      if (minute < 10) {
        lcd.print("0");
      }
      lcd.print(minute, DEC);
      lcd.print(":");
      if (second < 10) {
        lcd.print("0");
      }
      lcd.print(second, DEC);
      lcd.print(":");
      lcd.print(tenth, DEC);
    }
    
    //VYPIS DRUHEHO UTOKU NA DISPLEJ (UTOK PRAVY)
    void updateLCD2() {
      lcd.setCursor(0, 1);
      if (minute2 < 10) {
        lcd.print("0");
      }
      lcd.print(minute2, DEC);
      lcd.print(":");
      if (second2 < 10) {
        lcd.print("0");
      }
      lcd.print(second2, DEC);
      lcd.print(":");
      lcd.print(tenth2, DEC);
    }
    					

    Stopky na stotiny sekundy - INTERNAL PULLUP

    /*|--------------------------------------------------------------------------------------------|*/
    /*|VYHOTOVIL: MARTIN CHLEBOVEC                                                                 |*/
    /*|HASICSKE STOPKY - PLATENA VERZIA - NA STOTINY SEKUNDY S CASOM PRE DVA UTOKY - LAVY/PRAVY    |*/
    /*|FUNGUJE NA PRINCIPE FUNKCIE MILLIS() A VYKONAVANI KRATKYCH PROGRAMOVYCH CYKLOV              |*/
    /*|INPUT PULLUP ZAPOJENIE S 50kohm INTERNAMY REZISTOROM (PODLA SCHEMY) - MOZNO ZNIZIT EXTERNYM |*/
    /*|PROGRAM FUNGUJE PRE ZASTAVENIE A SPUSTENIE OBOCH CASOV JEDNYM TLACIDLOM                     |*/
    /*|Doska: Arduino Uno, Nano, Mega, ATmega328P (Hardware I2C)                                   |*/
    /*|WEB: https://arduino.php5.sk/hasicske-stopky.php                                            |*/
    /*|--------------------------------------------------------------------------------------------|*/
    
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    //I2C adresa, stlpce, riadky, pouziva sa i 0x3F pre displej 20x4, 0x27 pre 16x2, skontruj cez I2C scanner https://playground.arduino.cc/Main/I2cScanner/
    LiquidCrystal_I2C lcd(0x3F, 20, 4);
    
    //DEKLARACIA DIGITALNYCH PINOV NA KTORE SU NAPOJENE TLACIDLA
    const int start_tlacidlo = 12;
    const int lavy_terc_kontakt = 11;
    const int pravy_terc_kontakt = 10;
    const int vynulovat_cas_tlacidlo = 9;
    
    boolean run = false;         //bezi cas pre LAVY UTOK?
    boolean run2 = false;         //bezi cas pre PRAVY UTOK?
    
    //STAVY NACITANYCH LOGICKYCH HODNOT TLACIDIEL
    int start_tlacidlo_stav = HIGH;
    int lavy_terc_kontakt_stav = HIGH;
    int pravy_terc_kontakt_stav = HIGH;
    int vynulovat_cas_tlacidlo_stav = HIGH;
    
    unsigned long timer = 0; //timer
    
    //PREMENNE PRE PRVY CAS - LAVY UTOK
    int second = 0;
    int minute = 0;
    int tenth = 0;
    
    //PREMENNE PRE DRUHY CAS - PRAVY UTOK
    int second2 = 0;
    int minute2 = 0;
    int tenth2 = 0;
    
    void setup() {
      Serial.begin(115200);
      lcd.begin(); //incializacia displeja na I2C zbernici
      Wire.setClock(400000); //400 kHz clock na I2C zbernici
      lcd.backlight(); //zapnutie podsvietenia
      pinMode(start_tlacidlo, INPUT_PULLUP); //nastav ako vstup proti internemu 50kohm pullup rezistoru
      pinMode(lavy_terc_kontakt, INPUT_PULLUP);
      pinMode(pravy_terc_kontakt, INPUT_PULLUP);
      pinMode(vynulovat_cas_tlacidlo, INPUT_PULLUP);
      lcd.setCursor(0, 0); //nastav kurzor pre zapis na 1. riadok, 1. stlpec
      lcd.print("00:00:00 L. PRUD ");
      lcd.setCursor(0, 1); //nastav kurzor pre zapis na 2. riadok, 1. stlpec
      lcd.print("00:00:00 P. PRUD  ");
    }
    
    void loop() {
      checkStart();
      if ((micros() - timer) >= 10000 || timer == 0) {
        timer = micros();
        Serial.println(micros());
        tick();
      }
    }
    
    void checkStart() {
      if (!digitalRead(start_tlacidlo)) {
        run = true; //aktivuj cas pre lavy prud
        run2 = true; //aktivuj cas pre pravy prud
      }
      if (!digitalRead(lavy_terc_kontakt)) {
        run = false;
      }
      if (!digitalRead(pravy_terc_kontakt)) {
        run2 = false;
      }
      if (!digitalRead(vynulovat_cas_tlacidlo)) {
        run = false;
        run2 = false;
        second = 0;
        minute = 0;
        tenth = 0;
        second2 = 0;
        minute2 = 0;
        tenth2 = 0;
        lcd.setCursor(0, 0);
        lcd.print("00:00:00 L. PRUD");
        lcd.setCursor(0, 1);
        lcd.print("00:00:00 P. PRUD");
      }
    }
    
    
    void tick() { //tick sa vykonava kazdych 10 miliseund, teda kazdu stotinu sekundy
      //LOGIKA BEZIACEHO CASU PRVEHO UTOKU (UTOK LAVY)
      if (run) {
        if (tenth == 99) {
          tenth = 0;
          if (second == 59) {
            second = 0;
            lcd.setCursor(3, 0);
            lcd.print("00");
            minute++;
            lcd.setCursor(0, 0);
            if (minute < 10) {
              lcd.print("0");
            }
            lcd.print(minute, DEC);
          } else {
            second++;
            lcd.setCursor(3, 0);
            if (second < 10) {
              lcd.print("0");
            }
            lcd.print(second, DEC);
          }
        } else {
          tenth++;
          lcd.setCursor(6, 0);
          lcd.print(tenth, DEC);
        }
      }
    
      //LOGIKA BEZIACEHO CASU DRUHEHO UTOKU (UTOK PRAVY)
        if (run2) {
        if (tenth2 == 99) {
          tenth2 = 0;
          if (second2 == 59) {
            second2 = 0;
            lcd.setCursor(3, 1);
            lcd.print("00");
            minute2++;
            lcd.setCursor(0, 1);
            if (minute2 < 10) {
              lcd.print("0");
            }
            lcd.print(minute2, DEC);
          } else {
            second2++;
            lcd.setCursor(3, 1);
            if (second2 < 10) {
              lcd.print("0");
            }
            lcd.print(second2, DEC);
          }
        } else {
          tenth2++;
          lcd.setCursor(6, 1);
          lcd.print(tenth2, DEC);
        }
      }
    }