1

Тема: Часы-ночник на DS1307

Видео работы:http://www.youtube.com/watch?v=ghEI2i6yKLU


DS1307 это часы реального времени. http://mogalkov.ath.cx/rtc/DS1307.pdf" даташит


Вот схема принципиальная:
http://mogalkov.ath.cx/rtc/Atmega168LcdClockPWMLED.JPG

Очень внимательно надо отнестись к выбору кварца, от этого зависит точность часов. Не каждый кварц подойдет - в даташите указано что внутренняя емкость кварца нужна 12.5pF. Лучше всего использовать кварц от ненужной материнской платы (он на ней для хода системных часов компьютера). Припаивать кварц лучше как можно ближе к мс(я прямо к ножкам паял).
Также для работы часов необходима батарейка на 3В. Я особо не замарачивался, выпаял с той-же мамки что и кварц.

Перечень элементов:
Bat1    = 3V
C1    = 470µ 25v
C2    = 470µ 25v
C3    = 100n
C4    = 100n
HL1    = ARL-5213RGBC/4C
LCD1    = WH1602A-YGH-CTK
R1    = 1k
R2    = 1k
R3    = 50k//потенциометр выбора настройки и скорости мигания
R4    = 50k//потенциометр установки времени
R5    = 100
R6    = 100
R7    = 100
R8    = 1k
R9    = 1k
R10    = 10k
S1    = тумбле //Переключатель установки
S2    = ртактовая кнопка с фиксацией //переключатель лампы
U1    = 7805
U2    = ATMEGA168
U3    = DS1307
Z1    = 32.768kHz
Z2    = 16 MHz

Печатная плата:
http://robocraft.ru/uploads/images/f/7/3/e/281/8dab3e1264.jpg
http://mogalkov.ath.cx/rtc/AT168_RTC_004.layПлата в формате lay

Вникать в протокол I2C не стал, скачал готовую библиотеку:
брал тутhttp://code.google.com/p/sjunnesson/downloads/list Также выложил тут: http://mogalkov.ath.cx/rtc/DS1307.rar

скетч:

//необходимые библиотеки, последнюю надо скачивать
#include <LiquidCrystal.h>
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h> //брал тут “http://code.google.com/p/sjunnesson/downloads/list"
//переменные

int realpot;//Переменная хранения данных потенциометра
int setpot; //Переменная хранения данных потенциометра
int potPinST=2; //потенциометр установки времени
int potPinSE=3;//потенциометр выбора настройки и скорости мигания
int potsec000;//установка времени из потенциометра секунды
int potmin000;//установка времени из потенциометра минуты
int pothor000;//установка времени из потенциометра часы
int potday000;//установка времени из потенциометра дни
int potmon000;//установка времени из потенциометра месяцы
int potyer000;//установка времени из потенциометра годы

LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //пины ЛСД
//хранение времени для чтения с часов и вывода на экран
int hr_00;
int mn_00;
int sc_00;
int DD_00;
int MM_00;
int YY_00;
//хранение времени для установки часов
int hr_01=0;
int mn_01=0;
int sc_01=0;
int DD_01=0;
int MM_01=0;
int YY_01=0;
//делитель времени (:)
char delitel =':';

int ledPinR =  9; //пины светодиода
int ledPinG =  11; //пины светодиода
int ledPinB =  10; //пины светодиода

int swset; //параметр переключателя установки
int swled;//параметр переключателя светодиодной лампы


void btn_read() //Запись состояния переключателей в переменные
{
 swset=digitalRead(12); //Переключатель установки
 swled=digitalRead(8); //переключатель лампы
}

void Var2LCD()//вывод времени на экран
{
lcd.clear(); //очистка экрана
//  координаты      ;     текст
  lcd.setCursor(0,0);lcd.print(hr_00); 
  lcd.setCursor(2,0);lcd.print(delitel); 
  lcd.setCursor(3,0);lcd.print(mn_00); 
  lcd.setCursor(5,0);lcd.print(delitel); 
  lcd.setCursor(6,0);lcd.print(sc_00); 
  lcd.setCursor(0,1);lcd.print(DD_00); 
  lcd.setCursor(2,1);lcd.print('-'); 
  lcd.setCursor(3,1);lcd.print(MM_00); 
  lcd.setCursor(5,1);lcd.print('-'); 
  lcd.setCursor(6,1);lcd.print(YY_00); 
}

void RTC_red2var()//читаем с часов в переменные
{
hr_00=RTC.get(DS1307_HR,true);
mn_00=RTC.get(DS1307_MIN,false);
sc_00=RTC.get(DS1307_SEC,false);
DD_00=RTC.get(DS1307_DATE,false);
MM_00=RTC.get(DS1307_MTH,false);
YY_00=RTC.get(DS1307_YR,false);
}

void RTC_set2var()//Установка часов
{
    do {
  lcd.clear();//очищаем экран
  RTC.stop(); //останавливаем часы
  btn_read();//читаем переключатели в переменные
  setpot=analogRead(potPinSE); //читаем потенциометр выбора настройки от него зависит что настраиваем
  setpot=setpot/128;//Делим показания потенциометра выбора настройки на 128 (1024/128=8) получаем от 0 до 8 вариантов (используются 2-7)
switch (setpot) {
case 2:
//;секунды -Все остальные параметры устанавливаются примерно также
realpot=analogRead(potPinST);//читаем потенциометр установки времени
realpot=realpot/16;//Делим показания потенциометра на 16 (1024/16=64) получаем от 0 до 64 вариантов
if (realpot>=60) {realpot=59;}//ограничиваем до 59 (ни разу не видел у себя на часах 64 секунды, может просто невнимательно смотрел)
potsec000=realpot;//установка времени из потенциометра секунды
lcd.setCursor(0, 0); //координаты отображения
lcd.print("SECONDS");//отображаем текст
lcd.setCursor(1, 1);//координаты отображения
lcd.print(potsec000);//отображаем установки времени из потенциометра секунды
RTC.set(DS1307_SEC,potsec000);//записываем время в часы
break;
case 3:
//;минуты
realpot=analogRead(potPinST);
realpot=realpot/16;
if (realpot>=60) {realpot=59;}
potmin000=realpot;
lcd.setCursor(0, 0);
lcd.print("MINUTES");
lcd.setCursor(1, 1);
lcd.print(potmin000);
RTC.set(DS1307_MIN,potmin000);     //set the minutes
break;
case 4:
//;часы
realpot=analogRead(potPinST);
realpot=realpot/40;
if (realpot>23) {realpot=23;}
pothor000=realpot;
lcd.setCursor(0, 0);
lcd.print("HOURS");
lcd.setCursor(1, 1);
lcd.print(pothor000);
RTC.set(DS1307_HR,pothor000);       //set the hours
break;
case 5:
//;дни
realpot=analogRead(potPinST);
realpot=realpot/32;
if (realpot>31) {realpot=31;}
if (realpot<=0) {realpot=1;}
potday000=realpot;
lcd.setCursor(0, 0);
lcd.print("DAYS");
lcd.setCursor(1, 1);
lcd.print(potday000);
RTC.set(DS1307_DATE,potday000);       //set the date
break;
case 6:
//;месяцы
realpot=analogRead(potPinST);
realpot=realpot/84;
if (realpot>12) {realpot=12;}
if (realpot<=0) {realpot=1;}
potmon000=realpot;
lcd.setCursor(0, 0);
lcd.print("MONTH`S");
lcd.setCursor(1, 1);
lcd.print(potmon000);
RTC.set(DS1307_MTH,potmon000);        //set the month
break;
case 7:
//;годы
realpot=analogRead(potPinST);
realpot=realpot/4;
potyer000=realpot;
lcd.setCursor(0, 0);
lcd.print("YEARS");
lcd.setCursor(1, 1);
lcd.print(potyer000);
RTC.set(DS1307_YR,potyer000);         //set the year
break;
//если показания потенциометра выбора настройки не подпадают под установки времени
//выводит текст SET TIMES AND DATES
default: 
lcd.setCursor(0, 0);
lcd.print("SET TIMES");
lcd.setCursor(1, 1);
lcd.print("AND DATES");
break;
}
 delay(5); 
    }  while (swset==LOW);//если переключатель выключен - повторяем по новой
  RTC.start();//запускаем часы
}

void color_led()//мигаем трехцветным светодиодом
{
      do {
  RTC_red2var();//прочитать время в переменные
  Var2LCD();//отобразить переменные времени на экран
  btn_read();//проверяем переключатели
  setpot=analogRead(potPinSE);//используем потенциометр выбора настройки для установки скорости изменения цвета
  setpot=setpot/128;
  int delayTime = setpot;

  // красный нарастает, синий гаснет
  for (int i=0; i<256; i++)
  {
  btn_read();//проверяем переключатели
  setpot=analogRead(potPinSE);
  setpot=setpot/128;
  int delayTime = setpot;
    analogWrite(ledPinR, i);
    analogWrite(ledPinG, 0);
    analogWrite(ledPinB, 256-i);
    delay(delayTime);
  }
  // красный гаснет, зеленый нарастает
  RTC_red2var();//прочитать время в переменные
  Var2LCD();//отобразить переменные времени на экран
  for (int i=0; i<256; i++)
  {
  btn_read();//проверяем переключатели
  setpot=analogRead(potPinSE);
  setpot=setpot/128;
  int delayTime = setpot;
    analogWrite(ledPinR, 256-i);
    analogWrite(ledPinG, i);
    analogWrite(ledPinB, 0);
    delay(delayTime);
  }
  // зеленый гаснет, синий нарастает
  RTC_red2var();//прочитать время в переменные
  Var2LCD();//отобразить переменные времени на экран
  for (int i=0; i<256; i++)
  {
  btn_read();//проверяем переключатели
  setpot=analogRead(potPinSE);
  setpot=setpot/128;
  int delayTime = setpot;
    analogWrite(ledPinR, 0);
    analogWrite(ledPinG, 256-i);
    analogWrite(ledPinB, i);
    delay(delayTime);
  }
    }  while (swset==LOW);
  RTC_red2var(); //прочитать время в переменные
  Var2LCD(); //отобразить переменные времени на экран
  analogWrite(ledPinR, 0);//выключаем светодиод
  analogWrite(ledPinG, 0);//выключаем светодиод
  analogWrite(ledPinB, 0);//выключаем светодиод
}



void setup()
{
  pinMode(ledPinR, OUTPUT); //пин светодиода у нас выход    
  pinMode(ledPinG, OUTPUT); //пин светодиода у нас выход    
  pinMode(ledPinB, OUTPUT); //пин светодиода у нас выход    
  pinMode(12, INPUT);//Переключатель установки
  pinMode(8, INPUT); //переключатель лампы
  lcd.begin(16, 2);//экран у меня 16 символов на 2е строки
  lcd.home();
}

void loop()
{
btn_read(); //проверяем переключатели
if (swset==LOW){RTC_set2var();} //если переключатель установки 0 запускаем установку даты-времени
else if (swled==LOW){color_led();} //Если переключатель лампы 0 запускаем функцию лампы
else {
RTC_red2var();//прочитать время в переменные
Var2LCD(); //отобразить переменные времени на экран
delay(5);
}
}