• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Pomoc w dopisaniu sterowania przyciskami ustawienia godzin minut i sekund w zegarze
#1
Witam.
Szukam osoby chętnej która dopisze mi do programu sterowanie i ustawienie przyciskami godzin minut i sekund.
Zegar zrobiony na bazie arduino nano, DS3231, MAX1719 i sześciu wyświetlaczy 7 segmentowych.
Poniżej kod programu
Kod:
#include <DS3231.h>         

// define pins attached to MAX7219 (and also see notes above)
#define MAX7219_DIN          12
#define MAX7219_CS            10
#define MAX7219_CLK          11

// enumerate the MAX7219 registers
// See MAX7219 Datasheet, Table 2, page 7
enum {  MAX7219_REG_DECODE    = 0x09,
        MAX7219_REG_INTENSITY = 0x0A,
        MAX7219_REG_SCANLIMIT = 0x0B,
        MAX7219_REG_SHUTDOWN  = 0x0C,
        MAX7219_REG_DISPTEST  = 0x0F
    };

// enumerate the SHUTDOWN modes
// See MAX7219 Datasheet, Table 3, page 7
enum  { OFF = 0,
        ON  = 1
      };



// create an instance of the DS3231 called 'rtc',
// and specify the hardware interface PINS
DS3231 rtc(SDA, SCL);


const static byte charTable [] PROGMEM  =
{
  B01111110, B00110000, B01101101, B01111001, B00110011, B01011011, B01011111, B01110000,
  B01111111, B01111011, B01110111, B00011111, B01001110, B00111101, B01001111, B01000111,
};

// ... setup code here, to run once
void setup()
{
  // initialize the serial port:
  Serial.begin(115200);          // initialize serial communication

  // define type of pin
  pinMode(MAX7219_DIN, OUTPUT);  // serial data-in
  pinMode(MAX7219_CS, OUTPUT);    // chip-select, active low
  pinMode(MAX7219_CLK, OUTPUT);  // serial clock
  digitalWrite(MAX7219_CS, HIGH);

  resetDisplay();                // reset the MAX2719 display

  rtc.begin();                    // init. the DS3231 RTC interface

  // Uncomment the following lines to set the RTC
//  rtc.setTime(13, 43, 0);      // Set the time to 4:20pm
}

void loop()
{
  String str;                    // scratch or working string

  // ... display Time, hh-mm-ss
  for ( int i = 0; i < 6; i++ )
  {
    // read the time as a string from the RTC
    str = rtc.getTimeStr(FORMAT_LONG);
    Serial.println(str);        // debug
    displayTime(str);          // display on the 7-segment
    delay(1000);
  }
}

// ... write a value into a max7219 register
// See MAX7219 Datasheet, Table 1, page 6
void set_register(byte reg, byte value)
{
  digitalWrite(MAX7219_CS, LOW);
  shiftOut(MAX7219_DIN, MAX7219_CLK, MSBFIRST, reg);
  shiftOut(MAX7219_DIN, MAX7219_CLK, MSBFIRST, value);
  digitalWrite(MAX7219_CS, HIGH);
}

// ... reset the max7219 chip
void resetDisplay()
{
  set_register(MAX7219_REG_SHUTDOWN, OFF);  // turn off display
  set_register(MAX7219_REG_DISPTEST, OFF);  // turn off test mode
  set_register(MAX7219_REG_INTENSITY, 0x0A); // display intensity
}

// ... display the TIME on the 7-segment display
void displayTime(String timeString)
{
  set_register(MAX7219_REG_SHUTDOWN, OFF);  // turn off display
  set_register(MAX7219_REG_SCANLIMIT, 7);  // scan limit 8 digits
  set_register(MAX7219_REG_DECODE, 0b11111111); // decode all digits

    set_register(5, timeString.charAt(6));  //sekundy
    set_register(6, timeString.charAt(7));  //dziesiątki sekund
    set_register(4, timeString.charAt(4));  //minuty
    set_register(3, timeString.charAt(3));  //dziesiątki minut
    set_register(2, timeString.charAt(1));  //godziny
    set_register(1, timeString.charAt(0));  //dziesiątki godzin
    //  set_register(3, timeString.charAt(2));  //minus po godzinach
    //  set_register(6, timeString.charAt(5));  //minus po minutach

  set_register(MAX7219_REG_SHUTDOWN, ON);  // Turn on display
}
 
Odpowiedź
#2
Zacznij od zastąpienia delay millis, nie musisz sprawdzać czasu z zegara co 1s, można z niego wziąć przerwanie zewnętrzne, albo mierzyć czas millis, synchronizować czas co np. 1h, chyba, że sam zegar to wszystko co ma robić ten układ.
Tu masz przykład jak przy pomocy klawiatury analogowej ustawić godzinę, w kilka sekund ustawiasz dowolną z dokładnością minuty (zmienna 24x60 1440), zegar w układzie 24h.
Podobnie można zrobić ustawienie daty, zmienna na 40 lat zmieści się w int16.
Kod:
#include <AnalogKeypad.h>

// the following table is for this Banggood Analog Keypad
// https://www.banggood.com/AD-Analog-Keyboard-Module-Electronic-Building-Blocks-5-Keys-For-Arduino-DIY-p-1374279.html
// see the AnalogKeypad_CreateConfig.ino sketch example on how to create this table by Makuna
const int KeypadMap[] = {0, 50, 100, 200, 400};

const uint16_t KeypadHoldTimeMs = 1000;
const uint8_t KeypadAnalogPin = A0;

int16_t czasDobowy, czasWduszenia; //int by dalo sie krecic licznikiem przez 0
uint8_t lastbutton;
bool wduszony,update1;
//dla funkcji czas()

uint32_t czasTeraz,czasPoprzedni,tik=10; //tik musi byc mniejszy niz 1000 i dzilic 1000ms na rowne czesci
uint8_t nTik,sekundy,minuty,godziny,dni; //liczniki tikow, sekund, itd.
bool fnTik,fsekundy,fminuty,fgodziny,fdni; //flagi zdarzen nowy tik, nowa sekunda,minuta, godzina, dzien

char napis16[17];

AnalogKeypad keypad(KeypadAnalogPin, KeypadMap, countof(KeypadMap), KeypadHoldTimeMs);

// the button event callback
// this will be called when buttons are pressed and released
void ButtonHandler(const ButtonParam& param)
{

//  Serial.print(param.button);
//  Serial.print(" ");
// 
lastbutton=param.button+1;
  switch (param.state)
  {
    case ButtonState_Up:
//    Serial.print("Up");
wduszony=0;
    break;
   
    case ButtonState_Down:
//    Serial.print("Down");
    break;
   
    case ButtonState_Click:
//    Serial.print("Click");
if(lastbutton==2) czasDobowy++;
else if (lastbutton==3) czasDobowy--;
update1=1;

    break;
   
    case ButtonState_DoubleClick:
//    Serial.print("Double Click");
    break;
   
    case ButtonState_Hold:
//    Serial.print("Hold");
wduszony=1;
    break;
  }
 
//  Serial.println();
}

void setup() {
 
    Serial.begin(115200);
//    while (!Serial); // wait for serial attach

//    Serial.println();
    Serial.println("Initialized");
}

void loop() {
  czas();
if(fnTik) //zamiast dely 10 to mozna sprawdzac stan przyciskow co 10ms
{
  keypad.loop(ButtonHandler); //
  keypadAction();
}

  if(fsekundy or update1)
  {
   update1=0;
//tylko minuty   
   sprintf(napis16,"%02d:%02d",czasDobowy/60,czasDobowy%60); // jak zaminiec liczbe 0-1440 na godziny i minuty
   Serial.println(napis16);
//sekundy w 10
//   sprintf(napis16,"%02d:%02d:%02d",czasDobowy/(60*6),(czasDobowy%(60*6))/6,10*(czasDobowy%(6)) ); // jak zaminiec liczbe   na godziny  minuty sekundy w piatkach
//   Serial.println(napis16);
  }
  // simulate other work happening
  // it also should avoid long delays so loop above can be called
  // at least every 10-20ms
//  delay(10);
}


//wersja dla minut
void keypadAction()
{
//funkcja jest wywolywana co 10ms, ale chcę coś zrobic  co 100ms
if(nTik%10==0) {
if (wduszony)
{     update1=1;
      czasWduszenia++;
 

       switch (lastbutton)
        {
        case 2:
          if(czasWduszenia<30)czasDobowy++;
          else if (czasWduszenia<120)czasDobowy+=10;
          else  czasDobowy+=60;
        break;

        case 3:
          if(czasWduszenia<50)czasDobowy--;
          else if (czasWduszenia<130)czasDobowy-=10;
          else  czasDobowy-=60;
        break;
        }
} else czasWduszenia=0;     
              }


if (czasDobowy>1440-1) czasDobowy=0;
if (czasDobowy<0) czasDobowy=1440-1; 

//if (czasDobowy>(1440*6)-1) czasDobowy=0;
//if (czasDobowy<0) czasDobowy=((1440*6)-1); 
}



void czas()
{
  czasTeraz=millis();
fnTik=fsekundy=fminuty=fgodziny=fdni=0;
if((uint32_t)(czasTeraz-czasPoprzedni)>=tik) //tan napisany warunek jest odporny na "klątwe 50 dni millis()"
{
  czasPoprzedni=czasTeraz;
  fnTik=1;
  nTik++;
  if(nTik>=(1000/tik))
  {
    nTik=0;
    sekundy++;
    fsekundy=1;
     if (sekundy>=60)
    {
      sekundy=0;
      minuty++;
      fminuty=1;
      if (minuty>=60)
      {
        minuty=0;
        godziny++;
        fgodziny=1;
        if (godziny>=24)
        {
          godziny=0;
          fdni=1;
          dni++;
   
        }
      }
    }
  }
}
}
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
(05-08-2022, 16:25)kaczakat napisał(a): Zacznij od zastąpienia delay millis, nie musisz sprawdzać czasu z zegara co 1s, można z niego wziąć przerwanie zewnętrzne, albo mierzyć czas millis, synchronizować czas co np. 1h, chyba, że sam zegar to wszystko co ma robić ten układ.
Tu masz przykład jak przy pomocy klawiatury analogowej ustawić godzinę, w kilka sekund ustawiasz dowolną z dokładnością minuty (zmienna 24x60 1440), zegar w układzie 24h.
Podobnie można zrobić ustawienie daty, zmienna na 40 lat zmieści się w int16.
Kod:
#include <AnalogKeypad.h>

// the following table is for this Banggood Analog Keypad
// https://www.banggood.com/AD-Analog-Keyboard-Module-Electronic-Building-Blocks-5-Keys-For-Arduino-DIY-p-1374279.html
// see the AnalogKeypad_CreateConfig.ino sketch example on how to create this table by Makuna
const int KeypadMap[] = {0, 50, 100, 200, 400};

const uint16_t KeypadHoldTimeMs = 1000;
const uint8_t KeypadAnalogPin = A0;

int16_t czasDobowy, czasWduszenia; //int by dalo sie krecic licznikiem przez 0
uint8_t lastbutton;
bool wduszony,update1;
//dla funkcji czas()

uint32_t czasTeraz,czasPoprzedni,tik=10; //tik musi byc mniejszy niz 1000 i dzilic 1000ms na rowne czesci
uint8_t nTik,sekundy,minuty,godziny,dni; //liczniki tikow, sekund, itd.
bool fnTik,fsekundy,fminuty,fgodziny,fdni; //flagi zdarzen nowy tik, nowa sekunda,minuta, godzina, dzien

char napis16[17];

AnalogKeypad keypad(KeypadAnalogPin, KeypadMap, countof(KeypadMap), KeypadHoldTimeMs);

// the button event callback
// this will be called when buttons are pressed and released
void ButtonHandler(const ButtonParam& param)
{

//  Serial.print(param.button);
//  Serial.print(" ");
// 
lastbutton=param.button+1;
  switch (param.state)
  {
    case ButtonState_Up:
//    Serial.print("Up");
wduszony=0;
    break;
   
    case ButtonState_Down:
//    Serial.print("Down");
    break;
   
    case ButtonState_Click:
//    Serial.print("Click");
if(lastbutton==2) czasDobowy++;
else if (lastbutton==3) czasDobowy--;
update1=1;

    break;
   
    case ButtonState_DoubleClick:
//    Serial.print("Double Click");
    break;
   
    case ButtonState_Hold:
//    Serial.print("Hold");
wduszony=1;
    break;
  }
 
//  Serial.println();
}

void setup() {
 
    Serial.begin(115200);
//    while (!Serial); // wait for serial attach

//    Serial.println();
    Serial.println("Initialized");
}

void loop() {
  czas();
if(fnTik) //zamiast dely 10 to mozna sprawdzac stan przyciskow co 10ms
{
  keypad.loop(ButtonHandler); //
  keypadAction();
}

  if(fsekundy or update1)
  {
   update1=0;
//tylko minuty  
   sprintf(napis16,"%02d:%02d",czasDobowy/60,czasDobowy%60); // jak zaminiec liczbe 0-1440 na godziny i minuty
   Serial.println(napis16);
//sekundy w 10
//   sprintf(napis16,"%02d:%02d:%02d",czasDobowy/(60*6),(czasDobowy%(60*6))/6,10*(czasDobowy%(6)) ); // jak zaminiec liczbe   na godziny  minuty sekundy w piatkach
//   Serial.println(napis16);
  }
  // simulate other work happening
  // it also should avoid long delays so loop above can be called
  // at least every 10-20ms
//  delay(10);
}


//wersja dla minut
void keypadAction()
{
//funkcja jest wywolywana co 10ms, ale chcę coś zrobic  co 100ms
if(nTik%10==0) {
if (wduszony)
{     update1=1;
      czasWduszenia++;
 

       switch (lastbutton)
        {
        case 2:
          if(czasWduszenia<30)czasDobowy++;
          else if (czasWduszenia<120)czasDobowy+=10;
          else  czasDobowy+=60;
        break;

        case 3:
          if(czasWduszenia<50)czasDobowy--;
          else if (czasWduszenia<130)czasDobowy-=10;
          else  czasDobowy-=60;
        break;
        }
} else czasWduszenia=0;    
              }


if (czasDobowy>1440-1) czasDobowy=0;
if (czasDobowy<0) czasDobowy=1440-1; 

//if (czasDobowy>(1440*6)-1) czasDobowy=0;
//if (czasDobowy<0) czasDobowy=((1440*6)-1); 
}



void czas()
{
  czasTeraz=millis();
fnTik=fsekundy=fminuty=fgodziny=fdni=0;
if((uint32_t)(czasTeraz-czasPoprzedni)>=tik) //tan napisany warunek jest odporny na "klątwe 50 dni millis()"
{
  czasPoprzedni=czasTeraz;
  fnTik=1;
  nTik++;
  if(nTik>=(1000/tik))
  {
    nTik=0;
    sekundy++;
    fsekundy=1;
     if (sekundy>=60)
    {
      sekundy=0;
      minuty++;
      fminuty=1;
      if (minuty>=60)
      {
        minuty=0;
        godziny++;
        fgodziny=1;
        if (godziny>=24)
        {
          godziny=0;
          fdni=1;
          dni++;
   
        }
      }
    }
  }
}
}
 
Odpowiedź
#4
Dziękuje za podpowiedź.
Ale jak to powiązać z załączonym na wstępie programem.
 
Odpowiedź
#5
Nie napiszę Ci programu, który sobie wymarzyłeś, co najwyżej naprowadzę, czasami sprowadzę na manowce.
Jak przestaniesz używać delay, to nic nie trzeba wiązać, każdy blok programu wykonuje się czasowo niezależnie od pozostałych niepowiązanych i nie zakłóca czasu ich trwania. Wstawiasz w odpowiednie miejsca swoje zmienne, a gdy nie naciskasz przycisku przez np. 5s wysyłasz nastawę do zegara (albo jak masz więcej przycisków to przy wybraniu tego o funkcji "zapisz"). W samochodzie mam 1 przycisk i nim chodzę po całym menu, długie/krótkie naciśniecie w zależności od kontekstu wybiera opcje lub zmienia jej wartość, a pozostawienie bez działania zapisuje i wychodzi poziom wyżej.
Sprawdziłeś przykład, działa? Jak tak to już wiesz jak mierzyć czas od jakiegoś wydarzenia, jak sprawdzać czy trwało określony czas, jak to wykorzystać.
Z datą w jednej zmiennej jeszcze trzeba wmyślić jak sprawdzać rok przestępny, są o tym informacje w GOOGLE - czy jest podzielny przez 4,100,400, albo można wprowadzić ograniczenie do zakresu 2020-2060 i zostaje podzielność/4. Takie uproszczenie stworzyło "pluskwę milenijną".
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości