timer with rotay encoder and TM1637

hi..I'm trying to build a digital timer with preset times using a 7-segment display with 4 digits(catalex display with TM1637 ), a rotary encoder and Arduino nano, so you can select a time and start a countown, after which an LED lights for 10 seconds but it doesnìt seem to work ... i am attaching the code

#include "TM1637.h"

#define CLK_PIN  (4)
#define DIO_PIN  (3)
#define NUM_DIGITS    (4)
TM1637 tm1637( CLK_PIN, DIO_PIN, NUM_DIGITS );


int index;
volatile int direction; 
int InterruptPin = 2;
int RotaryEncoder2 = 7;
int PushButton = 8;
int AlarmPin = 9;
int SignalozPin = 10;



void setup() {

  Serial.begin(9600);
  Serial.println("OnFire's Timer");

  uint8_t digits[] = {0, 0, 0, 0};
  char *str = "    ";


  tm1637.setDigits( str );
  tm1637.setDot( 1, false );
  tm1637.update();
  delay(1000);


  // imposta i pin
  pinMode(InterruptPin, INPUT);
  pinMode(RotaryEncoder2, INPUT);
  pinMode(PushButton, INPUT);
  pinMode(AlarmPin, OUTPUT);
  pinMode(SignalozPin, OUTPUT);


}

uint16_t count = 0;


void Direction()
{
  // Questa funzione viene attivata da un interrupt dal coso rotativo sul pin "Interrupt Pin"


  // verificare interrupt, ora controllare l'altro pin dal coso rotativo per stabilire la direzione
  if (digitalRead(RotaryEncoder2))direction = +1;
  else                           direction = -1;
  return;
}
void Alarm(int Signal)
{
  int temp = 500;
  if (Signal == 1) // tono itermittente
  { while (1)
    { tone(AlarmPin, 1000, 500);
      delay(500);
      if (digitalRead(PushButton) == HIGH)break;
      noTone(AlarmPin);
      delay(500);
      if (digitalRead(PushButton) == HIGH)break;
    }
  }
  if (Signal == 2)
  { while (1)
    { tone(AlarmPin, 900);
      delay(temp = (750 - temp));
      //      noTone(AlarmPin);
      if (digitalRead(PushButton) == HIGH)break;
      tone(AlarmPin, 1250);
      delay(500);
      //      noTone(AlarmPin);
      if (digitalRead(PushButton) == HIGH)break;
    }
  }

  noTone(AlarmPin);
  return;
}



void loop() {

  // tempi predefiniti
  int Times[] = {0, 2, 10, 20, 21, 30, 40, 50, 60, 72, // up to 1m
                 75, 90, 105, 120, 144, 150, 180, 210, 240, 270, 300, // up to 5m
                 330, 360, 390, 420, 432, 450, 480, 510, 540, 570, 600, // up to 10m
                 660, 720, 780, 840, 900, 960, 1020, 1080, 1140, 1200, // up to 20m
                 1320, 1440, 1560, 1680, 1800, 2100, 2400, 2700, 3000, 3300, 3600, // up to 1h
                 3900, 4200, 4500, 4800, 5100, 5400
                };
  int nTimes, StartCounting = 0, Time, Count, CountDown, Reset;
  long Delta;

  nTimes = sizeof(Times) / sizeof(Times[0]) - 1;
  Serial.print("tempi: ");
  Serial.println(nTimes);

  // inizia a 00:00
  index = 0;
  Time = Times[index];
  StartCounting = 0;
  CountDown = 0;

  // // la direzione non è definita
  direction = 0;

  // Attendere linput e la visualizzazione dei secondi richiesti
  while (1)
  {
    // Aggiungere +1 o -1 per prevenire ln ritardo dl cambiamento di rotazione
    if (direction != 0)
    { index = index + direction;

      // Verificare di non andare al di la  di limiti di matrice -oveflow-
      if (index < 0)index = nTimes;
      if (index > nTimes)index = 0;
      // mostra il nuovo tempo
      Time = Times[index];
      StartCounting = 0;
    }


    // Resetta, altrimenti aumenta o diminuisce in continuazione
    direction = 0;

    // mostra il tempo corrente
    WriteTime(Time);

    // verifica lo stato HIGH sul pin 8 - ( pulsantozzo per avviare, mettere in pausa e resettare il timer)
    // Una breve pressione corrisponde a  START / pausa, una pressione più lunga, azzera
    if (digitalRead(PushButton) == HIGH)
    {
      // il pulsante è stato premuto ora aspetta fino a quando viene rilasciato
      Count = 0; // Numero di intervalli di 10ms che si preme il pulsantozzo
      Reset = 0; //  reset o start / mette in pausa
      while (digitalRead(PushButton) == HIGH)
      { delay(10);
        Count++;
        // Lasciare 500ms (10ms x 50) il tasto premuto per abilitare il tasto di reset
        if (Count > 50)
        { index = 0;
          Time = 0;
          StartCounting = 0; // stoppato
          WriteTime(Time); // Scrivere il tempo in modo che il display si azzera a 0:00 mentre si preme il pulsante
          CountDown = 0;   // Conteggio fermo
          Reset = 1;       // Così possiamo saltare il prossimo blocco di codice.......#peoplefrompigrizia
          while (digitalRead(PushButton) == HIGH); //ripete in loop finché il pulsante viene rilasciato
          break;
        }
      } // END OF WHILE(DIGITALREAD(8))

      // Basta una rapida pressione per iniziare o mettere  in pausa
      if (Reset == 0)
      { StartCounting = 1 - StartCounting;
        if (index == 0)CountDown = +1;
        else        CountDown = -1;
      }

      Delta = millis() / 1000;
    }

    // Avvia il conteggio ... CountDown dà la direzione
    if (StartCounting == 1)
    { if (millis() / 1000 != Delta)
      { Time = Time + CountDown;
        if (Time == 0)
        { CountDown = 0;
          WriteTime(Time);
          index = 0;
          Alarm(2);
        }
        // quando finisce il countdown, da 5v al pin 10
        if (Time == 0)
          SignalozPin == HIGH;
        delay (10000);

        Delta = millis() / 1000;
      }
    } // END OF IF(STARTCOUNTING...

  } // END OF WHILE(1)

} // END OF loop()
// con molta calma
// WriteTime () il formato di visualizzazione è MM : SS
void WriteTime(int time)
{ int second, minute;
  int d0, d1, d3, d4;

  int digit[11] = {63, // 0
                   6,  // 1
                   91, // 2
                   79, // 3
                   102,// 4
                   109,// 5
                   125,// 6
                   7,  // 7
                   127,// 8
                   111,// 9
                   0
                  }; // space
  second = time % 60;
  minute = time / 60;


  // Impostare dx al valore di ogni cifra
  d0 = 10;
  if (minute >= 10)d0 = minute / 10;
  d1 = minute % 10;
  d3 = second / 10;
  d4 = second % 10;

 tm1637.setDigits( time );
  tm1637.setDigits(1);

  return;

}

where am I wrong ?? thank you :confused:

does anything work ?
Maybe you should go systematically through an test each feature separately and come back when you have better isolated the problem.

can you temporarily hack the code to write something to the display ?
can you temporarily hack the code to read from the rotary encoder and write it's output to the serial console ?
can you temporarily hack the code so a button press writes the countdown sequence to the serial console ?

thanks for your reply..yes..i test display with this code:

#include "TM1637.h"

#define CLK_PIN  (4)
#define DIO_PIN  (3)
#define NUM_DIGITS    (4)
TM1637 tm1637( CLK_PIN, DIO_PIN, NUM_DIGITS );

void setup() {
  uint8_t digits[] = {0,0,0,0};
  char *str="    ";

  tm1637.clear();  
  tm1637.setDigits( digits );
  tm1637.update();
  delay(1000);
  
  tm1637.setDigits( str );
  tm1637.setDot( 1, false );
  tm1637.update();
  delay(1000);
}

uint16_t count = 0;

void loop() {
  tm1637.setBrightness(7);
  tm1637.setDigits( count );
  tm1637.update();
  count = (count-1) % 10000;
  delay(100);
}

and it's work good..

i test the encoder with this code

int encoderPin1 = 2;
int encoderPin2 = 7;
 
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
 
long lastencoderValue = 0;
 
int lastMSB = 0;
int lastLSB = 0;
 
void setup() {
  Serial.begin (9600);
 
  pinMode(encoderPin1, INPUT_PULLUP);
  pinMode(encoderPin2, INPUT_PULLUP);
 
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);
 
}
 
void loop(){
  Serial.println(encoderValue); 
}
 
void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
 
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
 
  lastEncoded = encoded; //store this value for next time
}

and it look ok (maybe) at serial port...i'm stopped here=/

Can you post a link to the TM1637 library you are using?
The following construct in your code which is used to create a parameter for setDigits() looks remarkable and may cause unpredictable behaviour:

char *str="    ";

Have you attached your own button to pin 8, or are you using built-in buttons on the TM1637 display ?

hi...i downloaded library here GitHub - avishorp/TM1637: Arduino library for TM1637 (LED Driver)

I connected directly encoder button of the pin 8 ...

the display that i used is this:

thanks for your reply..

Have you made any changes to the library which you say you downloaded from:
GitHub - avishorp/TM1637: Arduino library for TM1637 (LED Driver) ?
It does not appear, for example, contain the method setDigits() which you are using apparently successfully in statements such as

tm1637.setDigits( time );

Or have I missed some hidden inheritance from somewhere?

andrew_bluefire:
where am I wrong ?? thank you

Using interrupts to read a rotary encoder would be the most obvious blunder.

maybe i've missed some inheritance....i should rewrite all code from zero...

why using interrupt for encoder reading is a mistake? :confused:

Because there is no reason to do so, but on the other hand, since interrupts are intended for very fast events which must be serviced within microseconds (neither of which is remotely true of a hand-driven rotary encoder), the mechanical contact bounce of the encoder is serviced rapidly leading to a barrage of interrupts each time the encoder moves, generating confusing information for the logic, and difficult to debounce.

De-bouncing polled switch events is in contrast, very easy and more effective, since the algorithm may be implemented logically to respond only to a change in state of a switch contact if and when that change is maintained for the entire specified debounce interval.