Простые часы на семисегментных индикаторах (Arduino)

На рисунке показана схема простых часов на семисегментных индикаторах. Выполнены часы на базе Arduino Nano. В часах можно использовать практически любые (с током свечения сегмента не более 20 мА) семисегментные индикаторы с общим катодом, в частности в проекте используются индикаторы 5161AS.

В часах используется модуль DS3231 который представляет собой часы реального времени.

Как видно на схеме, один из индикаторов перевернут, так его сегмент-точка служит частью двоеточия, которое отображает такт хода секунд. Так как индикатор перевернут необходимо изменить его распайку его контактов.

Управление часами осуществляется тремя кнопка SET, UP и DW. При нажатии на кнопку SET часы переходят в режим коррекции времени, а кнопки UP и DW увеличиваю или уменьшают значение минут или часов. Если не переходить в режим коррекции времени, то кнопки UP и DW позволяют менять яркость свечения индикаторов.

Дополнительно имеется возможность использовать ночной режим работы индикаторов, в нем устанавливается минимально возможная яркость свечения индикаторов с 23 до 7 часов. Для активации этого режима в параметре NIGHT нужно установить 1.

#define NIGHT 1

Скетч:

#define K3 A3
#define K2 A2
#define K1 A1
#define K0 A0

#define SEG_A       8 
#define SEG_B       7 
#define SEG_C       4 
#define SEG_D       5 
#define SEG_E       2 
#define SEG_F       6
#define SEG_G       9 
#define SEG_DP      3 

#define SET  10
#define UP   11
#define DW   12

#define NIGHT 1

#include <EEPROM.h>
#include <Wire.h>
#include <DS3231.h>             // http://rcl-radio.ru/wp-content/uploads/2022/10/DS3231.zip
DS3231 clock;RTCDateTime DateTime;
byte an,segm,a[4],i,dp;
int hour,minut,secon,old_sec,hh,mm,set=0;
unsigned long times,times1;
int brig,br;


void setup(){
  Wire.begin();
  clock.begin();
  Serial.begin(9600);
  cli();
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2 = 0;
// (16000000/((155+1)x256))=400.64102564103 Hz
  OCR2A = 155;
  TCCR2A |= (1 << WGM21);
// Prescaler 256
  TCCR2B |= (1 << CS22) | (1 << CS21);
  TIMSK2 |= (1 << OCIE2A);
  sei();
  pinMode(K3,OUTPUT);
  pinMode(K2,OUTPUT);
  pinMode(K1,OUTPUT);
  pinMode(K0,OUTPUT);
  pinMode(SEG_A, OUTPUT);
  pinMode(SEG_B, OUTPUT);
  pinMode(SEG_C, OUTPUT);
  pinMode(SEG_D, OUTPUT);
  pinMode(SEG_E, OUTPUT);
  pinMode(SEG_F, OUTPUT);
  pinMode(SEG_G, OUTPUT);
  pinMode(SEG_DP, OUTPUT);
  pinMode (SET,INPUT_PULLUP);
  pinMode (UP,INPUT_PULLUP);
  pinMode (DW,INPUT_PULLUP);
  brig = EEPROM.read(100);
  if(brig>20){brig=1;EEPROM.update(100,brig);}
  }

void loop(){
  DateTime = clock.getDateTime();hour = DateTime.hour;minut = DateTime.minute;secon = DateTime.second;

  if((hour<7||hour>=22)&&NIGHT==1){br=20;}else{br=brig;}

  if(digitalRead(SET)==LOW){set++;if(set>2){set=0;}delay(200);}
  hh=hour;mm=minut;
  if(set==1 && digitalRead(UP)==LOW){hh++;if(hh>23){hh=0;}clock.setDateTime(2023, 9, 5, hh, minut, 0);delay(200);}
  if(set==1 && digitalRead(DW)==LOW){hh--;if(hh<0){hh=0;}clock.setDateTime(2023, 9, 5, hh, minut, 0);delay(200);}
  if(set==2 && digitalRead(UP)==LOW){mm++;if(mm>59){mm=0;}clock.setDateTime(2023, 9, 5, hour, mm, 0);delay(200);}
  if(set==2 && digitalRead(DW)==LOW){mm--;if(mm<0){mm=0;}clock.setDateTime(2023, 9, 5, hour, mm, 0);delay(200);}
  if(set==0 && digitalRead(UP)==LOW){brig--;if(brig<1){brig=1;}EEPROM.update(100,brig);delay(200);}
  if(set==0 && digitalRead(DW)==LOW){brig++;if(brig>20){brig=20;}EEPROM.update(100,brig);delay(200);}

  if(set==1&&millis()-times<200){a[0]=10;a[1]=10;}  
    else{a[0] = hour/10%10; a[1] = hour%10; }
  if(set==2&&millis()-times<200){a[2]=10;a[3]=10;}  
    else{a[2] = minut/10%10; a[3] = minut%10; }
  
  if(set==0){ 
    a[0]=hour/10%10;
    a[1]=hour%10;
    a[2]=minut/10%10;
    a[3]=minut%10;
    }
  if(millis()-times>400){times=millis();}
  if(millis()-times1<500){dp=1;}else{dp=0;}
  if(old_sec!=secon){old_sec=secon;times1=millis();}
  delay(100);
  }  

void segment() {
  switch (segm) {
            //  A          B             C              D             E            F            G
    case 0: ch(SEG_A, 1); ch(SEG_B, 1); ch(SEG_C, 1); ch(SEG_D, 1); ch(SEG_E, 1); ch(SEG_F, 1); ch(SEG_G, 0); break; // 0
    case 1: ch(SEG_A, 0); ch(SEG_B, 1); ch(SEG_C, 1); ch(SEG_D, 0); ch(SEG_E, 0); ch(SEG_F, 0); ch(SEG_G, 0); break; // 1
    case 2: ch(SEG_A, 1); ch(SEG_B, 1); ch(SEG_C, 0); ch(SEG_D, 1); ch(SEG_E, 1); ch(SEG_F, 0); ch(SEG_G, 1); break; // 2
    case 3: ch(SEG_A, 1); ch(SEG_B, 1); ch(SEG_C, 1); ch(SEG_D, 1); ch(SEG_E, 0); ch(SEG_F, 0); ch(SEG_G, 1); break; // 3
    case 4: ch(SEG_A, 0); ch(SEG_B, 1); ch(SEG_C, 1); ch(SEG_D, 0); ch(SEG_E, 0); ch(SEG_F, 1); ch(SEG_G, 1); break; // 4
    case 5: ch(SEG_A, 1); ch(SEG_B, 0); ch(SEG_C, 1); ch(SEG_D, 1); ch(SEG_E, 0); ch(SEG_F, 1); ch(SEG_G, 1); break; // 5
    case 6: ch(SEG_A, 1); ch(SEG_B, 0); ch(SEG_C, 1); ch(SEG_D, 1); ch(SEG_E, 1); ch(SEG_F, 1); ch(SEG_G, 1); break; // 6
    case 7: ch(SEG_A, 1); ch(SEG_B, 1); ch(SEG_C, 1); ch(SEG_D, 0); ch(SEG_E, 0); ch(SEG_F, 0); ch(SEG_G, 0); break; // 7
    case 8: ch(SEG_A, 1); ch(SEG_B, 1); ch(SEG_C, 1); ch(SEG_D, 1); ch(SEG_E, 1); ch(SEG_F, 1); ch(SEG_G, 1); break; // 8
    case 9: ch(SEG_A, 1); ch(SEG_B, 1); ch(SEG_C, 1); ch(SEG_D, 1); ch(SEG_E, 0); ch(SEG_F, 1); ch(SEG_G, 1); break; // 9
   case 10: ch(SEG_A, 0); ch(SEG_B, 0); ch(SEG_C, 0); ch(SEG_D, 0); ch(SEG_E, 0); ch(SEG_F, 0); ch(SEG_G, 0); break; // пусто
  }
}


ISR(TIMER2_COMPA_vect){
   switch (i) {
    case 0: segm = 10; segment();an = 10;kat();delayMicroseconds(br*100);segm = a[0];segment();an = 0;kat();ch(SEG_DP, 0);break;
    case 1: segm = 10; segment();an = 10;kat();delayMicroseconds(br*100);segm = a[1];segment();an = 1;kat();ch(SEG_DP, dp);break;
    case 2: segm = 10; segment();an = 10;kat();delayMicroseconds(br*100);segm = a[2];segment();an = 2;kat();ch(SEG_DP, dp);break;
    case 3: segm = 10; segment();an = 10;kat();delayMicroseconds(br*100);segm = a[3];segment();an = 3;kat();ch(SEG_DP, 0);break;
  }
  i++;if (i > 3) {i = 0;}
  }

void kat() {
  switch (an) {
    case 0: ch(K3, 1); ch(K2, 0); ch(K1, 0); ch(K0, 0); break;
    case 1: ch(K3, 0); ch(K2, 1); ch(K1, 0); ch(K0, 0); break;
    case 2: ch(K3, 0); ch(K2, 0); ch(K1, 1); ch(K0, 0); break;
    case 3: ch(K3, 0); ch(K2, 0); ch(K1, 0); ch(K0, 1); break;
   case 10: ch(K3, 0); ch(K2, 0); ch(K1, 0); ch(K0, 0); break;
  }
}  

void ch(int pin, int logic){digitalWrite(pin, logic);}

При подключении индикаторов к плате Arduino не обязательно точно делать по схеме, Вы можете изменить пины подключения поменяв их назначение в скетче:

#define K3 A3
#define K2 A2
#define K1 A1
#define K0 A0

#define SEG_A       8 
#define SEG_B       7 
#define SEG_C       4 
#define SEG_D       5 
#define SEG_E       2 
#define SEG_F       6
#define SEG_G       9 
#define SEG_DP      3 

#define SET  10
#define UP   11
#define DW   12

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=8531#p8531

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

Войти с помощью: