Часы на Ардуино своими руками

Мы решили собрать большое руководство о том, как сделать часы на Ардуино, где расскажем о нескольких вариантах реализации такого проекта. Ранее мы уже делали электронные часы на основе этой платы.

Часы на Ардуино на основе ЖК-дисплея и часов реального времени

Цель первого урока показать, как сделать простые часы на основе Arduino с использованием ЖК-дисплея и часов реального времени.

Комплектующие

Для первого урока этого большого руководства нам понадобятся следующие комплектующие для наших часов на Ардуино:

  • Arduino UNO и Genuino UNO
  • PCF8563 (часы реального времени)
  • Кристалл 32 кГц
  • 10К потенциометры
  • Резистор 10k 1/4w
  • Резистор 220 Ом
  • LCD 16x2
  • Макет с набором проводов

В этом уроке будут использованы ЖК-дисплей и часы реального времени. Если вы хотите знать больше теме взаимодействия Arduino и  ЖК-дисплеев - изучите уроки, которые мы публиковали ранее на нашем сайте.

Схема соединения

Схема очень проста. PCF8563 связывается с Arduino с помощью TWI, и когда данные принимаются, ЖК-дисплей обновляется, показывая новое время.

Установка даты и времени

Чтобы установить дату и время, используйте следующий скетч:

/* Демонстрация установки времени Rtc_Pcf8563. 
 * Установите часы на время затем зациклите время чтения 
 * и выведите дату и время на последовательную консоль.
 *
 * Использовали RBBB с Arduino IDE, распиновка 
 * немного отличается. Поменяйте на свои hw
 * SCK - A5, SDA - A4, INT - D3/INT1
 *
 * После загрузки и запуска скетча используйте последовательный монитор
 * для просмотра часов.
 * 
 * настройка:  смотрите тех. спецификацию Pcf8563.
 *         1x 10 КОм на Pin3 INT
 *         Нет соединений на Pin5 или Pin6 (используем внутренние устройства I2C)
 *         1x 0.1pf на питание
 *         1x 32khz кристал
 *
 */ 
 
#include <Wire.h>
#include <Rtc_Pcf8563.h>
 
//инициализировать часы реального времени
Rtc_Pcf8563 rtc;
 
void setup()
{
  //очистить регистры
  rtc.initClock();
  //установка начального времени.
  //день, неделя, месяц, век(1=1900, 0=2000), year(0-99)
  rtc.setDate(14, 6, 3, 1, 10);
  //часы, минуты, секунды
  rtc.setTime(1, 15, 0);
}
 
void loop()
{
  //обе функции форматирования вызывают внутренний метод getTime(), 
  //поэтому форматированные строки соответствуют текущем времени/дате.
  Serial.print(rtc.formatTime());
  Serial.print("\r\n");
  Serial.print(rtc.formatDate());
  Serial.print("\r\n");
  delay(1000);
} 

Код проекта

Теперь вы сможете использовать свои часы, загрузив этот скетч на Arduino:

#include <Wire.h>
#include <Rtc_Pcf8563.h>
// include the RTC library 
#include <LiquidCrystal.h>

//init the real time clock
Rtc_Pcf8563 rtc;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  lcd.print(" Arduino Clock!");
  while(1500 - millis() > 0);
  pinMode(13, OUTPUT);
}

void loop() {
  lcd.setCursor(0, 0);
  lcd.print("Date: ");
  lcd.print(rtc.formatDate());
  
  lcd.setCursor(0, 1);
  lcd.print("Time: ");
  lcd.print(rtc.formatTime());
}

Часы с выводом на экран Nokia 5110

Следующий урок - часы на Arduino, которые также простые для сборки, где вы сможете установить дату и время на последовательном мониторе.

В этом уроке используются лишь несколько компонентов - только перемычки, Arduino и дисплей Nokia 5110/3110.

Комплектующие

Детали, используемые в этом проекте ниже.

Оборудование

  • Arduino UNO и Genuino UNO × 1
  • Adafruit дисплей Nokia 5110 × 1
  • Соединительные провода (универсальные) × 1
  • Резистор 221 Ом × 1

Программное обеспечение

Arduino IDE

Схема соединения

Соединяем детали часов на Ардуино как на схеме выше:

  • контакт pin 3 - последовательный тактовый выход (SCLK) // pin 3 - Serial clock out (SCLK)
  • контакт pin 4 - выход серийных данных (DIN) // pin 4 - Serial date out (DIN)
  • контакт pin 5 - дата / выбор команды (D / C) // pin 5 - date/Command select (D/C)
  • контакт pin 6 - выбор ЖК-чипа (CS / CE) // pin 6 - LCD chip select (CS/CE)
  • контакт pin 7 - сброс ЖК (RST) // pin 7 - LCD reset (RST)

Код урока

Код второй версии часов вы можете скачать или скопировать ниже.

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

Adafruit_PCD8544 display = Adafruit_PCD8544(3,4,5,6,7);

int second,minute, hour, day, mounth,year; 
unsigned long UtlTime; 

void setup() 
pinMode(2,OUTPUT);
UtlTime=0;   {   

minute=0;   
hour=0;   
day=0;   
mounth=0;   
year=0;   
Serial.begin(9600);   
  display.begin();
  display.setContrast(50); // Adjust the display contrast
  display.clearDisplay();   //Apaga o buffer e o display
  display.setTextSize(1);  //Seta o tamanho do texto
  display.setTextColor(BLACK); //Seta a cor do texto      
   
display.print(" date e hour ");   
display.setCursor(0,10);   
display.print(" com Arduino");   
display.display();
delay (5000); 

//Configura o minute   
display.clearDisplay();   
display.setCursor(0,0);   
display.print("minute: ");
display.display();
Serial.print("\nin between minute:");  
while(minute==0)   {     
if (Serial.available() > 0)     
{       
minute= Serial.parseInt();     
}   
}   
display.print(minute);   
display.display();
delay(1000); 

//Configura a hour   
display.clearDisplay();   
display.setCursor(0,0);   
display.print("hour: ");   
display.display();
Serial.print("\nin between hour:"); 
while(hour==0)   
{     
if (Serial.available() > 0)     
{       
hour= Serial.parseInt();     
}   
}   
display.print(hour);   
display.display();
delay(1000);    

//Configura o day   
display.clearDisplay();   
display.setCursor(0,0);   
display.print("day: ");
display.display();   
Serial.print("\nin between day:");   
while(day==0)   
{     
if (Serial.available() > 0)     
{       
day= Serial.parseInt();     
}   
}   
display.print(day);   
display.display();
delay(1000);    

//Configura o mês   
display.clearDisplay();   
display.setCursor(0,0);   
display.print("mounth: "); 
display.display();  
Serial.print("\nin between mounth:");  
while(mounth==0)   
{     
if (Serial.available() > 0)     
{       
mounth= Serial.parseInt();     
}   
}   
display.print(mounth);  
 display.display();
delay(1000);    

//Configura o year   
display.clearDisplay();   
display.setCursor(0,0);   
display.print("year: ");   
display.display();
Serial.print("\nin between year:");   
while(year==0)   
{     
if (Serial.available() > 0)     
{       
year= Serial.parseInt();     
}   
}   
display.print(year);   

display.display();   
delay(1000);
display.clearDisplay(); 

} 

void loop() 
{   

if(millis()-UtlTime<0)   
{     
UtlTime=millis();   
}   
else   
{     
second=int((millis()-UtlTime)/1000);   
}   
if(second>59)   
{     
second=0;     
minute++;     
UtlTime=millis();     
if(minute>59)     
{       
hour++;       
minute=0;       
if(hour>23)       
{         
day++;         
hour=0;         
if(mounth==1||mounth==3||mounth==5||mounth==7||mounth==8||mounth==10||mounth==12)         
{           
if(day>31)           
{             
day=1;             
mounth++;             
if(mounth>12)             
{               
year++;               
mounth=1;             
}           
}         
}         
else if(mounth==2)         
{           
if(year%400==0)           
{             
if(day>29)             
{               
day=1;               
mounth++;             
}           
}           
else if((year%4==0)&&(year%100!=0))           
{             
if(day>29)             
{              
day=1;               
mounth++;             
}           
}           
else           
{             
if(day>28)             
{               
day=1;               
mounth++;             
}           
}         
}         
else         
{           
if(day>30)           
{             
day=1;             
mounth++;           
}         
}       
}     
}   
}    

display.clearDisplay(); 
delay(1000); 
Serial.print(day);   
Serial.print("/");   
Serial.print(mounth);   
Serial.print("/");   
Serial.print(year);   
Serial.println();      

display.setCursor(0,0);   
display.print("date ");   
display.print(day);   
display.print("/");   
display.print(mounth);   
display.print("/");   
display.print(year);

 
display.display();
Serial.print(hour);   
Serial.print(":");   
Serial.print(minute);   
Serial.print(":");   
Serial.print(second);   
Serial.print("\n");   
Serial.println();      

display.setCursor(0,10);   
display.print("hour ");   
display.print(hour);   
display.print(":");   
display.print(minute);   
display.print(":");   
display.print(second); 
display.display();
char tecla;
tecla = Serial.read();
if(tecla=='1'){
digitalWrite(2,LOW);
}
if(tecla=='2'){
  digitalWrite(2, HIGH);
}

}

Часы с будильником, гигрометром и термометром

Эти часы сделаны с использованием платы Arduino Uno, датчика AM2302, модуля RTC DS3231 и TFT-дисплей 1,8" с ST7735.

Комплектующие

Компоненты, используемые в третьей версии часов на Ардуино перечислены ниже.

Компоненты оборудования

  • Arduino UNO и Genuino UNO × 1
  • Часы реального времени (RTC) × 1
  • Датчик температуры DHT22 × 1
  • Кнопочный переключатель 12мм
  • SparkFun Кнопочный переключатель 12 мм × 4
  • Соединительные провода (универсальные) × 1
  • Макет (универсальный) × 1
  • Adafruit ST7735 1,8 "дисплей × 1

Программное обеспечение

  • Arduino IDE

Схема соединения

Соедините все детали часов согласно схеме ниже.

Код урока

Скачайте или скопируйте код часов для Ардуино ниже и загрузите на плату используя Arduino IDE.

Важно! Не забудьте установить нужные библиотеки перед использованием кода для платы, которые вы можете скачать из нашего раздела Библиотеки.

#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>
#include <Wire.h>
#include <SPI.h>
#include "EEPROM.h"

#define TFT_CS     9
#define TFT_RST    7                      
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower!
#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!

float maxTemperature=0;
float minTemperature=200;
char charMinTemperature[10];
char charMaxTemperature[10];
char timeChar[100];
char dateChar[50];
char temperatureChar[10];

float temperature = 0;
float previousTemperature = 0;

String dateString;
int minuteNow=0;
int minutePrevious=0;


#define DS3231_I2C_ADDRESS 104
byte tMSB, tLSB;
float temp3231;
float temperatura, temperatura0;
byte hh, mm, ss;
byte yy, ll, dd, zz;

#define meniu 2 
#define minus 3
#define plus 4
#define alarm 5
#define buzzer 6
int nivel = 0;   // if is 0 - clock
                 // if is 1 - hour adjust
                 // if is 2 - minute adjust

int hh1, mm1, zz1, dd1, ll1, yy1;   
int maxday;
boolean initial = 1;
char chartemp[3];
int hha, mma;   // for alarm
byte al;     // for alarm 
byte xa = 80;
byte ya = 70;

#include "DHT.h"
#define DHTPIN 16     // what pin we're connected to
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11 
#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);
// NOTE: For working with a faster chip, like an Arduino Due or Teensy, you
// might need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// Example to initialize DHT sensor for Arduino Due:
//DHT dht(DHTPIN, DHTTYPE, 30);
//float temperatura;
int umiditate;
int tzeci, tunit, tzecimi, trest;
int tsemn, ttot;
int hzeci, hunit;
int previousHumidity = 0;
char umiditateChar[10];
unsigned long masurare;
unsigned long intervalmasurare = 30000;

void setup () 
{
    dht.begin(); 
    tft.initR(INITR_BLACKTAB);
    tft.fillScreen(ST7735_BLACK);
    Serial.begin(9600);
    Wire.begin();
pinMode(meniu, INPUT); 
pinMode(plus, INPUT); 
pinMode(minus, INPUT); 
pinMode(alarm, INPUT); 
pinMode(buzzer, OUTPUT);
digitalWrite(meniu, HIGH);  // put inputs in high state (when push is to ground -> low state)
digitalWrite(plus, HIGH);
digitalWrite(minus, HIGH);
digitalWrite(alarm, HIGH);
digitalWrite(buzzer, LOW);
    printText("TEMPERATURE", ST7735_GREEN,5,85,1);  // Temperature Static Text
    printText("HUMIDITY", ST7735_RED,5,130,1);

// setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year);
//setDS3231time(0, 45, 13, 0, 25, 11, 2016;

//  hha = 7;
//  mma = 00;
//  al = 1;  // 0 = alarm is off (must put in 1 foar active)

hha = EEPROM.read(100);
mma = EEPROM.read(101);
al = EEPROM.read(102);

if ((hha < 0) || (hha > 23)) hha = 7;
if ((mma < 0) || (mma > 59)) mma = 0;
if ((al < 0) || (al > 1)) al = 0;

//temperature = dht.readTemperature();
//umiditate = dht.readHumidity();
masurare = millis();
}


void loop () 
{

if (nivel == 0)
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  hh1=hh;
  mm1=mm;
  zz1=zz;
  yy1=yy;
  ll1=ll;
  dd1=dd;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,128,160,ST7735_BLACK);
  }

if (((millis() - masurare) > intervalmasurare) || initial)
{
temperature = dht.readTemperature();
umiditate = dht.readHumidity();
delay(500);
masurare = millis();
} 
  readDS3231time(&ss, &mm, &hh, &zz, &dd, &ll,&yy);

    String halarma = "";
    if(hha<10)
    {
         halarma = halarma+" "+String(hha);
    }else  
    halarma = halarma+ String(hha);
    if(mma<10)
    {
        halarma = halarma+":0"+String(mma);
    }else
    {
        halarma = halarma+":"+String(mma);
    }
    halarma.toCharArray(timeChar,100);

if (digitalRead(alarm) == LOW)
  {
  al = al + 1;
  EEPROM.write(102, al%2);
  delay(500);
  }
if (mma == mm & hha == hh & al%2)
{
digitalWrite(buzzer, HIGH);
   tft.drawCircle(xa, ya, 5, ST7735_RED); 
   tft.drawLine(xa, ya, xa, ya-5, ST7735_RED);
   tft.drawLine(xa, ya, xa+4, ya+4, ST7735_RED); 
   printText(timeChar, ST7735_RED,xa+7,ya,1);
}
else
{
if (al%2 == 0)
{
    tft.drawCircle(xa, ya, 5, ST7735_BLUE); 
    tft.drawLine(xa, ya, xa, ya-5, ST7735_BLUE);
    tft.drawLine(xa, ya, xa+4, ya+4, ST7735_BLUE); 
  digitalWrite(buzzer, LOW);
    printText(timeChar, ST7735_BLUE,xa+7,ya,1);
}
if (al%2 == 1)
{
    tft.drawCircle(xa, ya, 5, ST7735_WHITE); 
    tft.drawLine(xa, ya, xa, ya-5, ST7735_WHITE);
    tft.drawLine(xa, ya, xa+4, ya+4, ST7735_WHITE); 
  digitalWrite(buzzer, LOW);
    printText(timeChar, ST7735_WHITE,xa+7,ya,1);
}
}
 
  minuteNow = mm;
  if(minuteNow!=minutePrevious || initial)
  {
    initial = 0;
    dateString = getDayOfWeek(zz)+", ";
    dateString = dateString+String(dd)+"/"+String(ll);
    dateString= dateString+"/"+ String(yy); 
    minutePrevious = minuteNow;
    String hours = "";
    if(hh<10)
    {
         hours = hours+" "+String(hh);
    }else  
    hours = hours+ String(hh);
    if(mm<10)
    {
        hours = hours+" 0"+String(mm);
    }else
    {
        hours = hours+" "+String(mm);
    }
    
    hours.toCharArray(timeChar,100);
    tft.fillRect(0,0,160,65,ST7735_BLACK);
  //  printText(timeChar, ST7735_WHITE,20,25,3);
    printText(timeChar, ST7735_YELLOW,5,25,4);
    dateString.toCharArray(dateChar,50);
    printText(dateChar, ST7735_GREEN,8,5,1);
  }
  
  if ((temperature != previousTemperature) || initial)
  {
    previousTemperature = temperature;
    String temperatureString = String(temperature,1);
    temperatureString.toCharArray(temperatureChar,10);
    tft.fillRect(0,98,128,27,ST7735_BLACK);
    printText(temperatureChar, ST7735_WHITE,10,100,3);
    printText("o", ST7735_WHITE,90,95,2);
    printText("C", ST7735_WHITE,105,100,3);

  if((umiditate != previousHumidity) || initial)
  {
    previousHumidity = umiditate;
    String umiditateString = String(umiditate);
    umiditateString.toCharArray(umiditateChar,10);
    tft.fillRect(55,130,128,27,ST7735_BLACK);
    printText(umiditateChar, ST7735_WHITE,55,130,3);
    printText("%RH", ST7735_WHITE,91,130,2);
  }
  }


delay(500);
//     printText("o", ST7735_WHITE,62,28,1);
//     printText("o", ST7735_WHITE,62,35,1);
     printText("o", ST7735_YELLOW,62,28,1);
     printText("o", ST7735_YELLOW,62,35,1);

delay(500);
     printText("o", ST7735_BLACK,62,28,1);
     printText("o", ST7735_BLACK,62,35,1);
} // end usual case (clock)


if (nivel == 1)   // change hours
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
   delay(500);
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,128,160,ST7735_BLACK);
  }    

printText("SETTING", ST7735_GREEN,10,18,2);  // Temperature Static Text
printText("HOUR:", ST7735_GREEN,10,36,2);  // Temperature Static Text
dtostrf(hh1,3, 0, chartemp); 
      //tft.fillRect(50,50,70,18,ST7735_BLACK);
      tft.fillRect(50,50,70,38,ST7735_BLACK);
      delay(50);
      printText(chartemp, ST7735_WHITE,60,50,2);
      delay(50);
      
if (digitalRead(plus) == LOW)
    {
    hh1 = hh1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    hh1 = hh1-1;
    delay(150);
    }    
if (hh1 > 23) hh1 = 0;
if (hh1 < 0) hh1 = 23;       
     
}  // end loop nivel = 1 (change the hours)

if (nivel == 2)   // change minutes
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,128,160,ST7735_BLACK);
  }    

printText("SETTING", ST7735_GREEN,10,18,2);  // Temperature Static Text
tft.fillRect(10,35,70,18,ST7735_BLACK);
printText("MINUTE:", ST7735_GREEN,10,35,2);  // Temperature Static Text
Serial.println(mm1);
dtostrf(mm1,3, 0, chartemp); 
      tft.fillRect(50,50,70,18,ST7735_BLACK);
      delay(50);
      printText(chartemp, ST7735_WHITE,60,50,2);
      delay(50);
     
if (digitalRead(plus) == LOW)
    {
    mm1 = mm1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    mm1 = mm1-1;
    delay(150);
    }    
if (mm1 > 59) mm1 = 0;
if (mm1 < 0) mm1 = 59;       
     
}  // end loop nivel = 2 (change the minutes)

if (nivel == 3)   // change day in week
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,128,160,ST7735_BLACK);
  }    

printText("SETTING", ST7735_GREEN,10,18,2);  // Temperature Static Text
tft.fillRect(0,35,128,18,ST7735_BLACK);
printText("Day in Week:", ST7735_GREEN,10,40,1);  // Temperature Static Text
//Serial.println(mm1);
dtostrf(zz1,3, 0, chartemp); 
      tft.fillRect(50,50,70,18,ST7735_BLACK);
      delay(50);
      printText(chartemp, ST7735_WHITE,60,50,2);
tft.fillRect(10,80,100,18,ST7735_BLACK);      
if (zz1 == 1) printText("1 - Monday", ST7735_RED,10,80,1);  // Temperature Static Text
if (zz1 == 2) printText("2 - Tuesday", ST7735_RED,10,80,1);  // Temperature Static Text
if (zz1 == 3) printText("3 - Wednesday", ST7735_RED,10,80,1);  // Temperature Static Text
if (zz1 == 4) printText("4 - Thursday", ST7735_RED,10,80,1);  // Temperature Static Text
if (zz1 == 5) printText("5 - Friday", ST7735_RED,10,80,1);  // Temperature Static Text
if (zz1 == 6) printText("6 - Saturday", ST7735_RED,10,80,1);  // Temperature Static Text
if (zz1 == 0) printText("0 - Sunday", ST7735_RED,10,80,1);  // Temperature Static Text  
    delay(50);
     
if (digitalRead(plus) == LOW)
    {
    zz1 = zz1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    zz1 = zz1-1;
    delay(150);
    }    
if (zz1 > 6) zz1 = 0;
if (zz1 < 0) zz1 = 6;       
     
}  // end loop nivel = 3 (change the day of the week)

if (nivel == 4)   // change year
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,128,160,ST7735_BLACK);
  tft.fillRect(10,80,100,18,ST7735_BLACK);    
  }    

printText("SETTING", ST7735_GREEN,10,18,2);  // Temperature Static Text
tft.fillRect(10,35,70,18,ST7735_BLACK);
printText("YEAR:", ST7735_GREEN,10,35,2);  // Temperature Static Text
dtostrf(yy1,3, 0, chartemp); 
      tft.fillRect(40,50,80,18,ST7735_BLACK);
      tft.fillRect(10,80,100,18,ST7735_BLACK);  // erase last explication...
      delay(50);
      printText("20", ST7735_WHITE,45,50,2);
      printText(chartemp, ST7735_WHITE,60,50,2);
      delay(50);

     
if (digitalRead(plus) == LOW)
    {
    yy1 = yy1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    yy1 = yy1-1;
    delay(150);
    }    
if (yy1 > 49) yy1 = 49;
if (yy1 < 16) yy1 = 16;       
     
}  // end loop stare = 4 (change the year)


if (nivel == 5)   // change mounth
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
   tft.fillRect(10,80,100,18,ST7735_BLACK);    
  }    
printText("SETTING", ST7735_GREEN,10,18,2);  // Temperature Static Text
tft.fillRect(10,35,70,18,ST7735_BLACK);
printText("MONTH:", ST7735_GREEN,10,35,2);  // Temperature Static Text
dtostrf(ll1,3, 0, chartemp); 
      tft.fillRect(40,50,80,18,ST7735_BLACK);
      tft.fillRect(10,80,100,18,ST7735_BLACK);  // erase last explication...
      delay(50);
      printText(chartemp, ST7735_WHITE,60,50,2);
      delay(50);
     
if (digitalRead(plus) == LOW)
    {
    ll1 = ll1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    ll1 = ll1-1;
    delay(150);
    }    
   
if (ll1 > 12) ll1 = 1;
if (ll1 < 1) ll1 = 12;       
     
}  // end loop stare = 5 (change the day as data)

if (nivel == 6)   // change day as data
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
 tft.fillRect(10,80,100,18,ST7735_BLACK);      
  }    

printText("SETTING", ST7735_GREEN,10,18,2);  // Temperature Static Text
tft.fillRect(10,35,70,18,ST7735_BLACK);
printText("DAY:", ST7735_GREEN,10,35,2);  // Temperature Static Text
dtostrf(dd1,3, 0, chartemp); 
      tft.fillRect(50,50,70,18,ST7735_BLACK);
      tft.fillRect(10,80,100,18,ST7735_BLACK);  // erase last explication...
      delay(50);
      printText(chartemp, ST7735_WHITE,60,50,2);
      delay(50);
 
if (digitalRead(plus) == LOW)
    {
    dd1 = dd1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    dd1 = dd1-1;
    delay(150);
    }    
    
 // Dawn & Dusk controller. http://andydoz.blogspot.ro/2014_08_01_archive.html
 if (ll == 4 || ll == 5 || ll == 9 || ll == 11) { //30 days hath September, April June and November
    maxday = 30;
  }
  else {
  maxday = 31; //... all the others have 31
  }
  if (ll ==2 && yy % 4 ==0) { //... Except February alone, and that has 28 days clear, and 29 in a leap year.
    maxday = 29;
  }
  if (ll ==2 && ll % 4 !=0) {
    maxday = 28;
  }

if (dd1 > maxday) dd1 = 1;
if (dd1 < 1) dd1 = maxday;       
     
}  // end loop nivel = 6 (change the day as data)

if (nivel == 7)   // change hours alarm
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,128,160,ST7735_BLACK);
  }    
tft.fillRect(10,15,100,38,ST7735_BLACK);
printText("ALARM", ST7735_GREEN,10,18,2);  // Temperature Static Text
printText("HOUR:", ST7735_GREEN,10,36,2);  // Temperature Static Text
dtostrf(hha,3, 0, chartemp); 
      //tft.fillRect(50,50,70,18,ST7735_BLACK);
      tft.fillRect(50,50,70,38,ST7735_BLACK);
      delay(50);
      printText(chartemp, ST7735_WHITE,60,50,2);
      delay(50);
      
if (digitalRead(plus) == LOW)
    {
    hha = hha+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    hha = hha-1;
    delay(150);
    }    
if (hha > 23) hha = 0;
if (hha < 0) hha = 23;       
     
}  // end loop nivel = 7 (change the hours)

if (nivel == 8)   // change minutes for alarm
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,128,160,ST7735_BLACK);
  }    
tft.fillRect(10,15,70,18,ST7735_BLACK);
printText("ALARM", ST7735_GREEN,10,18,2);  // Temperature Static Text
tft.fillRect(10,35,70,18,ST7735_BLACK);
printText("MINUTE:", ST7735_GREEN,10,35,2);  // Temperature Static Text
Serial.println(mm1);
dtostrf(mma,3, 0, chartemp); 
      tft.fillRect(50,50,70,18,ST7735_BLACK);
      delay(50);
      printText(chartemp, ST7735_WHITE,60,50,2);
      delay(50);
     
if (digitalRead(plus) == LOW)
    {
    mma = mma+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    mma = mma-1;
    delay(150);
    }    
if (mma > 59) mma = 0;
if (mma < 0) mma = 59;       
     
}  // end loop nivel = 8 (change the minutes)


 if (nivel >=9)  // readfy to return to main loop
 {
  setDS3231time(0, mm1, hh1, zz1, dd1, ll1, yy1);
  EEPROM.write(100, hha);
  EEPROM.write(101, mma);
  EEPROM.write(102, al%2);
  
  nivel = 0;  
  previousTemperature= 0.0;
  previousHumidity= 0;
  initial = 1;
   printText("TEMPERATURE", ST7735_GREEN,5,85,1);  // Temperature Static Text
   printText("HUMIDITY", ST7735_RED,5,130,1);
 }
}  // end main loop


void printText(char *text, uint16_t color, int x, int y,int textSize)
{
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextSize(textSize);
  tft.setTextWrap(true);
  tft.print(text);
}

String getDayOfWeek(int i)
{
  switch(i)
  {
    case 0: return "Monday";break;
    case 1: return "Tuesday";break;
    case 2: return "Wednesday";break;
    case 3: return "Thursday";break;
    case 4: return "Friday";break;
    case 5: return "Saturday";break;
    case 6: return "Sunday";break;
    default: return "Monday";break;
  }
}


// http://forum.arduino.cc/index.php?topic=398891.0
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
                   dayOfMonth, byte month, byte year)
{
    // sets time and date data to DS3231
    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();
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
    return ( (val / 16 * 10) + (val % 16) );
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
    return ( (val / 10 * 16) + (val % 10) );
}

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());
}

Часы без RTC

Для начала мы должны понимать, что такое RTC. Из Википедии:

Часы реального времени (ЧРВ, RTC — англ. Real Time Clock) — электронная схема, предназначенная для учёта хронометрических данных (текущее время, дата, день недели и др.), представляет собой систему из автономного источника питания и учитывающего устройства. Чаще всего часы реального времени встречаются в вычислительных машинах, хотя на самом деле ЧРВ присутствуют практически во всех электронных устройствах, которые должны хранить время.

В итоге в данной версии мы сделаем часы без RTC с индикатором температуры и влажности на Arduino с помощью модуля DHT11. Также мы используем 3 кнопки для установки часов.

Комплектующие

Вам понадобятся эти кусочки для этого проекта:

  • Arduino Uno плата
  • Кнопки 3 шт.
  • Потенциометр
  • Модуль LCD 1602
  • Модуль температуры и влажности DHT11
  • Макетная плата
  • Перемычки

Схема соединения

Соедините комплектующие часов как на схеме ниже.

Код

Вы можете скопировать или скачать код часов на Ардуино ниже.

#include <LiquidCrystal.h>
#include <SimpleDHT.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
volatile int sec, minute = 0, hour = 0;
int b_h = 5;
int b_m = 6;
int pinDHT11 = 2;
int b_startstop = 3;
bool startstop = false;

SimpleDHT11 dht11;

void setup() {

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  lcd.setCursor(0, 0);
  lcd.print("Ahmad Ordikhani");
  lcd.setCursor(0, 1);
  lcd.print("Clk without RTC");
  delay(3000);
  lcd.clear();

  pinMode(b_h, INPUT_PULLUP);
  pinMode(b_m, INPUT_PULLUP);
  pinMode(b_startstop, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(3), buttons, FALLING);
}

void loop() {

  //Setting the time will stop the clock to set the time
  while (startstop == false)
  {
    lcd.setCursor(0, 1);
    lcd.print("SET");
    delay(100);
    lcd.setCursor(0, 0);
    lcd.print("Time: ");
    if(hour<10)
    {
    lcd.print("0");
    lcd.print(hour);
    }
    else
    lcd.print(hour);
    
    lcd.print(":");
    if(minute<10)
    {
      lcd.print("0");
    lcd.print(minute);
    }
    else
    lcd.print(minute);
    lcd.print(":");
    if(sec<10)
    {
    lcd.print("0");  
    lcd.print(sec);
    }
    else
    lcd.print(sec);
    lcd.print(" ");

    if (digitalRead(b_h) == LOW)
    {
      hour++;
      if (hour > 23)
        hour = 0;
    }

    if (digitalRead(b_m) == LOW)
    {
      minute++;
      if (minute > 59)
        minute = 0;
    }

  }

  //Start the clock
  while (startstop == true)
  {


    // noInterrupts();
    // read with raw sample data.
    byte temperature = 0;
    byte humidity = 0;
    byte data[40] = {0};
    if (dht11.read(pinDHT11, &temperature, &humidity, data)) {
      lcd.setCursor(0, 1);
      lcd.print("Read DHT11 failed");
      return;
    }
    lcd.setCursor(0, 1);
    lcd.print("Temp:");
    lcd.print((int)temperature);
    //lcd.print("*C");
    lcd.print(" ");
    lcd.print("Hum.:");
    lcd.print((int)humidity);
    lcd.print("%");
    //Serial.print((int)temperature); Serial.print(" *C, ");
    // Serial.print((int)humidity); Serial.println(" %");

    lcd.setCursor(0, 0);
    //sec=millis()/1000;
    delay(1000);
    lcd.print("Time: ");
    if (hour < 10)
    {
      lcd.print("0");
      lcd.print(hour);
    }
    else
    {
      lcd.print(hour);
    }
    lcd.print(":");
    if (minute < 10)
    {
      lcd.print("0");
      lcd.print(minute);
    }
    else
    {
      lcd.print(minute);

    } lcd.print(":");
    if (sec < 10)
    {
      lcd.print("0");
      lcd.print(sec);
    }
    else
    {
      lcd.print(sec);
    }
    lcd.print(" ");
    //lcd.print(startstop);
    sec++;
    if (sec > 59)
    {
      minute++;
      sec = 0;
      //lcd.clear();
    }

    if (minute > 59)
    {
      hour++;
      minute = 0;
      //lcd.clear();
    }
    if (hour > 23)
    {
      hour = 0;
      //lcd.clear();

    }
  }
}

//Start/Stop the clock
void buttons()
{
  lcd.clear();
  startstop = !startstop;
}

На этом пока всё. Мы постарались описать все основные варианты реализации часов на Ардуино.

19 декабря 2018 в 01:31 | Обновлено 7 декабря 2019 в 00:09 (редакция)
Опубликовано:
Уроки,

5 комментариев

  1. Евгений
    19 августа 2020 в 21:51

    Не умеете скотч писать так нехрен выкладывать,*censored*.

    Ответить
    1. Администратор
      20 августа 2020 в 00:14

      В статье 4 примера, даже непонятно о каком скетче идет речь. Но, в любом случае, вы всегда можете написать свой скетч, вы же наверняка очень умный и талантливый человек, Евгений?

      Ответить
    2. Сергей Ермилов
      20 августа 2020 в 00:17

      Евгений, ждем скетч от вас. Спасибо

      Ответить
  2. Олег
    2 ноября 2021 в 22:53

    Искал что либо для PCF8563 , поправить часы в устройстве , повторил первый материал , заработало . Из неудобств : для редактирования часиков необходимо применять 2 разных скетча , 2 прошивки ; Без ардуинки правка времени невозможна , изделие (часы) теряет свою автономность , т.е. устанавливать себе время своими кнопками (кей-пад шилд ардуино) . Хотя нужно не так много — добавить кусок кода опроса кнопок аналогового входа и интегрирования в управление редактированием дата-время . Ну и вообще будет супер — просмотр еепром содержимого этих часов . Знаний языков программирования и синтаксиса С++ почти нет , просьба к гуру — пожените оба скетча (PCF85663) , большое спасибо . Олег С.

    Ответить
  3. иван
    24 декабря 2021 в 19:02

    можно получить правильный скетч

    Ответить

Добавить комментарий

Ваш E-mail не будет никому виден. Обязательные поля отмечены *