ArduShop.ro

ArduShop.ro
cod tehnic.go.ro_02 reducere 5%, pentru vizitatorii paginilor mele !

marți, 14 mai 2013

Ceas de timp real (RTC) cu DS1307 si Arduino

   Deoarecea placa de dezvoltare Arduino se bazeaza pe un microcontroler ATmega 328 (sau cele mai vechi pe ATmega168 sau ATmega8), nu au incorporat un "ceas de timp real", care sa "numere si sa memoreze" timpul trecut, secunde, ore, zile, luni, ani si in cazul cand placa de dezvoltare a fost deconectata de la sursa de alimentare.
   Un integrat care sa faca acest lucru este DS1307 produs de MAXIM INTEGRATED, dupa cum se poate afla din fisa tehnica (datasheet).

   Am desenat cu ajutorul programului EAGLE PCB DESIGN SOFTWARE o schema, pentru a realiza si o varianta proprie de cablaj:
 
   Acest modul are modul de comuncare prin protocol i2c (2 fire active, SDA = intrare/iesire date, respectiv SCL = intrare seriala ceas), ceasul intern se bazeaza pe un cristal de cuart de 32,768kHz (cum sunt cele din ceasurile de mana), iar partea de alimentare de rezerva (in cazul intreruperii alimentarii) se realizeaza cu o baterie de 3V tip CR2302 (cum sunt cele de pe placile de baza ale calculatoarelor (PC), dar s epot folsi si 2 inseriate de 1,5V...
   Pe site-ul Arduino se gasesc informatii despre libraria RTC-ului, dar si la ROBOFUNO prezentare pas cu pas a modulul de asamblare a unui kit RTC cu DS1307 si conectare la un Arduino se gaseste la Adafruit Learning System.
   Prezentare in limba romana am gasit in articolul http://www.electronicstefan.ro/2013/02/ceas-de-timp-real-rtc-cu-ds1307-si-arduino/ de pe blogul Electronic Stefan.

   Schema "clasica" de conectare pentru modulul RTC folosind protocolul de communicare i2c este:
   In articolul Using the ATMEGA168/Arduino with a DS1307 Real Time Clock scris de Lewis Loflin gasim o schema si un sketch care soloseste 3 butoane pentru reglajul orelor si minutelor:
// http://www.bristolwatch.com/arduino/arduino_ds1307.htm

#include <Wire.h> // specify use of Wire.h library.

byte blinkPin = 13;
byte SW0 = 4;
byte SW1 = 5;
byte SW2 = 6;


void setup()

{
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);
  pinMode(blinkPin, OUTPUT);
  digitalWrite(blinkPin, 0);

  pinMode(SW0, INPUT);  // for this use a slide switch
  pinMode(SW1, INPUT);  // N.O. push button switch
  pinMode(SW2, INPUT);  // N.O. push button switch

  digitalWrite(SW0, HIGH); // pull-ups on
  digitalWrite(SW1, HIGH);
  digitalWrite(SW2, HIGH);
}

void loop()
{
  Wire.beginTransmission(0x68);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(0x68, 7);
  byte secs = Wire.read();
  byte mins = Wire.read();
  byte hrs = Wire.read();
  byte day = Wire.read();
  byte date = Wire.read();
  byte month = Wire.read();
  byte year = Wire.read();

  // hours, minutes, seconds

  Serial.print("The time is "); 
  if (hrs < 10) Serial.print("0");
  Serial.print(hrs,HEX);    
  Serial.print(":");
  if (mins < 10) Serial.print("0");
  Serial.print(mins, HEX);
  Serial.print(":");
  if (secs < 10) Serial.print("0");
  Serial.println(secs, HEX);

  // use MM-DD-YYYY

  Serial.print("The date is "); 
  if (month < 10) Serial.print("0");
  Serial.print(month,HEX);    
  Serial.print("-");
  if (date < 10) Serial.print("0");
  Serial.print(date, HEX);
  Serial.print("-");
  Serial.print("20");
  if (year < 10) Serial.print("0");
  Serial.println(year, HEX);
  Serial.println();


  if (!(digitalRead(SW0))) set_time(); // hold the switch to set time
  delay(1000);    //wait a second before next output
  toggle(blinkPin);


// toggle the state on a pin
void toggle(int pinNum) 
{  
  int pinState = digitalRead(pinNum);
  pinState = !pinState;
  digitalWrite(pinNum, pinState); 
}

void set_time()   {
  byte minutes = 0;
  byte hours = 0;

  while (!digitalRead(SW0))  // set time switch must be released to exit
  {
    while (!digitalRead(SW1)) // set minutes
    { 
      minutes++;          
      if ((minutes & 0x0f) > 9) minutes = minutes + 6;
      if (minutes > 0x59) minutes = 0;
      Serial.print("Minutes = ");
      if (minutes >= 9) Serial.print("0");
      Serial.println(minutes, HEX);

      delay(750);
    }

    while (!digitalRead(SW2)) // set hours
    { 
      hours++;          
      if ((hours & 0x0f) > 9) hours =  hours + 6;
      if (hours > 0x23) hours = 0;
      Serial.print("Hours = ");
      if (hours <= 9) Serial.print("0");
      Serial.println(hours, HEX);
      delay(750);
    }

    Wire.beginTransmission(0x68); // activate DS1307
    Wire.write(0); // where to begin
    Wire.write(0x00);          //seconds
    Wire.write(minutes);          //minutes
    Wire.write(0x80 | hours);    //hours (24hr time)
    Wire.write(0x06);  // Day 01-07
    Wire.write(0x01);  // Date 0-31
    Wire.write(0x05);  // month 0-12
    Wire.write(0x09);  // Year 00-99
    Wire.write(0x10); // Control 0x10 produces a 1 HZ square wave on pin 7. 
    Wire.endTransmission();
  }    
}

   Am completat schema modululului cu un LED care clipeste cu frecventa de 1Hz:
 
17.mai.2013
   O varianta care nu mai contine bateria de 3V, ci doar un conector cu 2 pini:


03.06.2013
   Am realizat, spre rusinea mea, ca tutoriale sau articole, despre ceas cu DS1307 si Arduino, in limba romana se mai gasesc pe net, asa ca o sa le enumar:
- tutorialul intitulat KitDS1307 de la ROROID;
- articolul intitualt DS1307 RTC - ceas de timp real de pe blogul Arduino in Romania;