Servo timer with encoder

Hello everyone,

I premise that I am not very experienced with Arduino, although I have already done a few projects.

Here is the current project:

I would like to make a timer that is controlled by encoder (HW-040). By turning clockwise, seconds and minutes will go up; counterclockwise, they will go down. Instead, pressing the middle button will start the countdown. During this time, a servo motor (SG90) will have to execute this code

#include <Servo.h>

Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0; // variable to store the servo position

void setup() {
  myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos); // tell servo to go to position in variable 'pos'
    delay(15); // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos); // tell servo to go to position in variable 'pos'
    delay(15); // waits 15ms for the servo to reach the position
  }
}

When the timer is finished, the stepper will stop and the buzzer will sound.

Here are the connections:

Buzzer 5
Servo (SG90) 7
Encoder HW-40 ( CLK 2; DT 4; SW 3)
Start button 6

Below is the code realized for now:

/*
FILM ROLLER V 1.0
 */

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display

#define encoder0PinA  2
#define encoder0PinB  4
#define pushButton 3
#define pushButtonSTART 6

volatile int encoder0Pos = 4;
volatile boolean PastB = 0;
volatile boolean update = false;

int minuti = 5;
int secondi = 6;

int contatoreFineTempo;
int lastButtonState = 0;

int lastMSB = 0;
int lastLSB = 0;

int lastEncoded = 0;
long encoderValue = 0;
long encoderValue2 = 0;
long encoderValue3 = 0;

long lastencoderValue = 0;
long lastencoderValue2 = 0;
long lastencoderValue3 = 0;

int timeSEC = 0;
int step_funzione = 0;

int buzzer = 5; // Pulsante Buzzer

void setup() {
  lcd.init();
  lcd.backlight();
  pinMode(pushButton, INPUT);
  pinMode(pushButtonSTART, INPUT);
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);

  digitalWrite(encoder0PinB, HIGH);
  digitalWrite(encoder0PinA, HIGH);

  pinMode(pushButton, INPUT_PULLUP);
  pinMode(pushButtonSTART, INPUT_PULLUP);

  pinMode(buzzer, OUTPUT); // Inizializza il buzzer

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("FILM ROLLER V 1.0");
  lcd.setCursor(0, 1);
  lcd.print("TEMP: ");
  delay(2000);
  lcd.clear();
}

void loop() {
  lcd.setCursor(0, 1);

  if (update) {
    update = false;
    PastB ? encoder0Pos++ : encoder0Pos--;
  }

  minuti = lastencoderValue2;
  secondi = lastencoderValue3;

  switch (step_funzione) {
    case 0:    // STATO INIZIALE
      INIZIO();
      break;
    case 1:    // VAI ALLA FUNZIONE: EDIT TEMPO
      EDIT_TEMPO();
      break;
    case 2:    // VAI ALLA FUNZIONE: CONTO ALLA ROVESCIA
      COUNT_DOWN();
      break;
    case 3:    // VAI ALLA FUNZIONE: TEMPO SCADUTO
      TEMPO_SCADUTO();
      break;
  }
}

void INIZIO() {
  lcd.setCursor(0, 0);
  lcd.print("   PREMI START  ");
  lcd.setCursor(0, 1);
  lcd.setCursor(0, 1);

  lcd.setCursor(4, 1);
  if (minuti < 10) lcd.print("0");  // SE I MINUTI SONO MENO DI 10, SCRIVI LO ZERO A SINISTRA.
  lcd.print(minuti);                // STAMPA I MINUTI
  lcd.print(":");                   // STAMPA I DUE PUNTI

  if (secondi < 10) lcd.print("0");  // SE I SECONDI SONO MENO DI 10, SCRIVI LO ZERO A SINISTRA.
  lcd.print(secondi);                // STAMPA I SECONDI

  int buttonState = digitalRead(pushButton);  //// PER ACCEDERE AL MENU EDITOR CON IL MANTENIMENTO DEL PULSANTE ENCODER
  if (buttonState == LOW) {
    delay (1000);
    Serial.println(timeSEC);
    timeSEC++;
  }
  else {
    timeSEC = 0; //  AZZERAMENTO VARIABILE SEI SECONDI
  }
  delay(100);

  if (timeSEC >= 2) {   //   VAI A EDITOR
    lcd.clear();
    timeSEC = 0;
    step_funzione = 1;
  }

  int pushButtonSTARTstate = digitalRead(pushButtonSTART);
  if (pushButtonSTARTstate == LOW) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Partenza tempo");
    lcd.clear();
    timeSEC = 0;
    step_funzione = 2;
  }
}

void EDIT_TEMPO() {
  lcd.setCursor(0, 1);
  lcd.print("h");
  lcd.setCursor(1, 1);
  if (minuti < 10) lcd.print("0");
  lcd.print(minuti);

  lcd.print(":");
  
  lcd.setCursor(4, 1);
  if (secondi < 10) lcd.print("0");
  lcd.print(secondi);

  int buttonState = digitalRead(pushButton);
  if (buttonState != lastButtonState)
    if (buttonState == LOW) {
      lcd.clear();
    }
  delay(100);
  lastButtonState = buttonState;

  int pushButtonSTARTstate = digitalRead(pushButtonSTART);
  if (pushButtonSTARTstate == LOW) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Partenza tempo");
    lcd.clear();
    timeSEC = 0;
    step_funzione = 2;
  }
}

void COUNT_DOWN() {
  while (secondi > 0) {
    int pushButtonSTARTstate = digitalRead(pushButtonSTART);
    if (pushButtonSTARTstate == LOW) {
      timeSEC++;
    }

    if (timeSEC >= 3) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" reset forzato  ");
      lcd.setCursor(0, 1);
      lcd.print("xxxxxxxxxxxxxxxx");
      lcd.setCursor(1, 1);
      lcd.print("xxxxxxxxxxxxxxxx");
      delay(2000);
      lcd.clear();
      timeSEC = 0;
      step_funzione = 0;
      break;
    }

    lcd.setCursor(0, 0);
    lcd.print(" Tempo residuo: ");
    delay (1000);         // DELAY PER CONTARE STEP DI UN SECONDO...NON TOCCARE
    secondi--;

    lcd.setCursor(0, 0);
    lcd.print(" Tempo residuo: ");
    lcd.setCursor(4, 1);
    if (minuti < 10) lcd.print("0");
    lcd.print(minuti);
    lcd.print(":");
    if (secondi < 10) lcd.print("0");
    lcd.print(secondi);

    if (secondi == 0) {
      step_funzione = 3;  //  VAI AL' ULTIMO STADIO...TEMPO CHE RAGGIUNGE LO ZERO
      break;
    }
  }
}

void TEMPO_SCADUTO() {
  int pushButtonSTARTstate = digitalRead(pushButtonSTART);
  if (pushButtonSTARTstate == LOW) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("   ripristino   ");
    delay(1000);
    lcd.clear();
    timeSEC = 0;
    step_funzione = 0;
  }

  lcd.setCursor(0, 0);
  lcd.print("   Fine tempo   ");
  lcd.setCursor(0, 1);
  lcd.print("Start=Ripristina");
  delay(500);
  lcd.clear();

  // Attiva il buzzer quando il tempo รจ scaduto
  digitalWrite(buzzer, HIGH);

  if (contatoreFineTempo >= 10) {
    contatoreFineTempo = 0;
    timeSEC = 0;
    step_funzione = 0;
  }
}

void doEncoderB() {
  PastB = (boolean)digitalRead(encoder0PinA);
  update = true;

  encoderValue2 = encoder0Pos;
  encoderValue3 = encoder0Pos;
}

At the moment the code doesn't work at all, as soon as I connect arduino, the buzzer starts immediately and it doesn't allow me to set the timer.

I am asking for your help to fix the countdown part with the encoder, once that is done I can enter the code that manages the motor and also the buzzer code

Good idea to take this one step at a time. Here's a suggestion:

  1. Make a sketch that starts the countdown of a fixed number of seconds to zero. Decide what needs to happen if the button is pressed while a countdown is in progress (e.g. reset the number of seconds to the original value, or pause the countdown process until the button is pressed again) and implement that functionality. You'll have to avoid using delay() for the timing. Output the remaining number of seconds to your the serial monitor, only printing each number once during countdown.

2: Now make a sketch that changes the number of seconds. Don't worry about the minutes yet. Ensure that it works well and doesn't make the number of seconds go negative. Output the number of seconds that's set only once whenever it has changed to the serial monitor.

3: Change the sketch of #2 so that you can set the time in minutes and seconds. Tip: the variable holding the time may only need to hold the number of seconds. The question of minutes is really only a matter of displaying the number in terms of minutes and seconds.

4: Now integrate the functionality of exercise #1 and exercise #3 into a system that allows the time to be set, a countdown to be started and the remaining time displayed to the serial monitor in terms of minutes and seconds.

This divides the challenge into more manageable parts that you can tackle one by one.