12. 12. 2016

Arduino projekt: Hodiny, část 2

V pokračování z minulého článku se podíváme, jak si k hodinám ještě připojit senzor pohybu PIR a jak s jeho pomocí probudit uspané Arduino. A samozřejmně jak Arduino nejprve uspat aby jsme ho mohli budit.

Co potřebujeme k další práci na projektu?
  1. Arduino se zapojenými obvody z minulas drobnou změnou viz. následující obrázek.
  2.  PIR čidlo HC-SR501 - detekce pohybu

Čidlo PIR si připoj podle obrázku. Všimni si, že modul RTC jsem zapojila na digitální pin 6 to kvůli vypínání modulu aby měl obvod menší spotřebu. Čas je uložený v paměti a je udržován baterií na desce RTC.
Schéma zapojení hodiny v2

Uspávání Arduina je snadné a potřebná knihovna je již přítomná v IDE.
Kód vypadá následovně:
    // Zobrazení času na displeji
    //
    //Zapojení pinů:
    /*** RTC DS3231 > Arduino Nano v3.0
       GND > GND
       Vcc > D6 // digitálním pinem se spouští napájení hodin
       SCL > SCL A5
       SDA > SDA A4
    */
    /*** TM1637 Display > Arduino Nano v3.0
       GND > GND
       Vcc > 5V
       CLK > D4
       DIO > D5
    */
    /*** Pohybové čidlo HC-SR501 > Arduino Nano v3.0
       GND > GND
       Vcc > 5V
       OUT > D2
    */
    
    #include "Wire.h"
    #include <Arduino.h>
    
    //*** uspávání arduina
    #include <avr/sleep.h>
    #include <avr/power.h>
    #include <avr/wdt.h>
    //***/
    //*** nastavení displeje
    #include "SevenSegmentTM1637.h"
    #include "SevenSegmentExtended.h"
    //***/
    // nastavení čísel pinů pro propojení s Arduinem
    
    //*** TM1637 Display
    const byte PIN_CLK = 4;   // define CLK pin (any digital pin)
    const byte PIN_DIO = 5;   // define DIO pin (any digital pin)
    SevenSegmentExtended      display(PIN_CLK, PIN_DIO);
    //***/
    
    //*** Modul RTC
    const int RTCpinVcc = 6;
    #define DS3231_I2C_ADDRESS 0x68
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    // Convert normal decimal numbers to binary coded decimal
    byte decToBcd(byte val) {
      return ( (val / 10 * 16) + (val % 10) );
    }
    // Convert binary coded decimal to normal decimal numbers
    byte bcdToDec(byte val) {
      return ( (val / 16 * 10) + (val % 16) );
    }
    //***/
    
    //*** Pohybové čidlo HC-SR501
    const int cidloPin = 2;
    //***/
    
    void setup() {
      Serial.begin(9600);
    
      //*** modul RTC
      pinMode(RTCpinVcc, OUTPUT);
      digitalWrite(RTCpinVcc, HIGH);
      Wire.begin();
      // set the initial time here:
      // sec, min, hod, č. dne v týdnu (ne=0,po=1...so=6), den, měs, rok
      //  setDS3231time(0, 50, 22, 4, 1, 12, 16); //************************************** nastaví čas
      //***/
    
      //*** Display
      display.setBacklight(50);  // set the brightness to 100 %
      display.begin();
      //***/
    
      //*** Pohybové čidlo HC-SR501
      // inicializace digitálního vstupu
      pinMode(cidloPin, INPUT);
      // nastavení přerušení na pin 2 (int0)
      // při rostoucí hraně (logO->log1) se vykoná program detekce
      attachInterrupt(0, detekce, RISING);
      //***/
    }
    
    // sets time and date data to DS3231
    void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
      Wire.beginTransmission(DS3231_I2C_ADDRESS);
      Wire.write(0); // set next input to start at the seconds register
      Wire.write(decToBcd(second)); // set seconds
      Wire.write(decToBcd(minute)); // set minutes
      Wire.write(decToBcd(hour)); // set hours
      Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
      Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
      Wire.write(decToBcd(month)); // set month
      Wire.write(decToBcd(year)); // set year (0 to 99)
      Wire.endTransmission();
    }
    
    // read time and date from DS3231
    void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) {
      Wire.beginTransmission(DS3231_I2C_ADDRESS);
      Wire.write(0); // set DS3231 register pointer to 00h
      Wire.endTransmission();
      Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
      // request seven bytes of data from DS3231 starting from register 00h
      *second = bcdToDec(Wire.read() & 0x7f);
      *minute = bcdToDec(Wire.read());
      *hour = bcdToDec(Wire.read() & 0x3f);
      *dayOfWeek = bcdToDec(Wire.read());
      *dayOfMonth = bcdToDec(Wire.read());
      *month = bcdToDec(Wire.read());
      *year = bcdToDec(Wire.read());
    }
    
    //*** uspání arduina
    void enterSleep(void) {
      //nastavení nejúspornějšího módu
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      // spánkový režim je povolený
      sleep_enable();
      // spuštění režimu spánku
      sleep_mode();
      //*** tady bude program pokračovat když se probudí
      // spánek zakázán
      sleep_disable();
      //znovu zapojení všech funkcí
      power_all_enable();
      // a skok do Loop
    }
    //***/
    
    // probuzení Arduina
    void detekce() {
      //Serial.println("Detekce pohybu pomoci HC-SR501!");
    }
    
    void loop() {
      byte stavPIR;
      byte a;
      for (a = 0; a < 10; a++) {
        //*** čtení z RTC DS3231
        readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
    
        //*** výpis času na displej
        display.printTime(hour, minute, true);
    
        //*** restart počítadla vypnutí při detekci pohybu
        stavPIR = digitalRead(cidloPin);
        if (stavPIR == 1)
        {
          a = 1;
        }
      }
    
      //*** vypnutí hodin, displeje a uspání arduina
      digitalWrite(RTCpinVcc, LOW);
      display.clear();
      enterSleep();// uspat
      //*** zapnout napájení hodin po probuzení
      digitalWrite(RTCpinVcc, HIGH);
    }
    
    
    Ke stažení opět tady.
    Pokračování někdy příště.

    1 komentář:

    1. Moc mi to pomohlo. Mám podobné hodiny akorát místo displaye mám led neopixel. Máš pěkně vysvětlený sleep.

      OdpovědětVymazat