[noob] Help needed for Alarm clock menu - Switching menu using button and confg

I have been trying several methods to make a new menu for configuring the alarm. I tried using the onebutton library to no avail, likely because i also need my modifier button to change the current time when it is held down, hence i had kept the original code which did not use the onebutton library. I also tried using if((digital blah)&&(digitalblah)&&(digitalblah)&&(digitalblah) to activate the second menu but it did not work. I also tried doing the same but by putting it all around my original button code. I tried also having the day up and seconds down buttons (the two centre buttons) activate the menu switch code but this did not work either.
It would be good if someone could look at my menu switch code itself as i am not too confident on how good it might be. I have been testing by using the Buzz(); function as it lets me know if the code went through but otherwise I am not using an LED.

Here is my code:
Code: [Select]

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include "RTClib.h"
#include "OneButton.h"   
#include <OneButton.h>   
#include <LiquidCrystal.h>
#include <Servo.h>

RTC_DS1307 rtc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

//RTC clock - Matthew Lim

//references
//*OLD* library info https://github.com/davidhbrown/RealTimeClockDS1307/blob/master/RealTimeClockDS1307.h ***ditched this library as it was missing features moved to RTCLIB
//RTCLIB library info https://github.com/adafruit/RTClib/blob/master/RTClib.h

//bare source 1: https://www.instructables.com/Arduino-Real-Time-Clock-DS1307/
//interesting idea to move to different library: https://arduino.stackexchange.com/questions/3354/why-is-my-real-time-clock-getting-the-wrong-time-from-my-pc
//https://www.arduino.cc/en/Reference/LiquidCrystal LCD library
//realtime updating rtc time https://forum.arduino.cc/index.php?topic=555628.0
// concept of adding double action buttons https://forum.arduino.cc/index.php?topic=512477.0

//buttons

int PM=6; //button modifier (using pin 6) - will try to make the other buttons change the days and the seconds when held down.
//OneButton onebuttonmodifier(6, true);
int P1=7; //button + hours (using pin 7)
int P2=8; //button - hours (using pin 8)
int P3=9; //button + minutes (using pin 9)
int P4=10; //button - minutes (using pin 10)

//servos
Servo hours; // hours is using pin 1
Servo minutes; // minutes is using pin 0
int hoursdegree = 0;
int minutesdegree = 0;

//buzzer
const int buzzer = 13;

//alarm stuff
bool mondayalarm = false;
bool tuesdayalarm = false;
bool wednesdayalarm = false;
bool thursdayalarm = false;
bool fridayalarm = false;
bool saturdayalarm = false;
bool sundayalarm = false;

int alarmhour = -1;
int alarmminute = -1;
int alarmsecond = -1;

//display
int lcddisplay = 1;
//1 would just be the regular time display
//2 would be the alarm display

void setup () {
  Serial.begin(57600);
lcd.begin(16,2);
  pinMode(A3, OUTPUT);
  digitalWrite(A3, HIGH);
  pinMode(A2, OUTPUT);
  digitalWrite(A2, LOW);

  pinMode(PM, INPUT);
  pinMode(P1, INPUT); //allows program to recognise that we are using buttons
  pinMode(P2, INPUT);
  pinMode(P3, INPUT);
  pinMode(P4, INPUT);

  minutes.attach(A0);
  hours.attach(A1);

  pinMode(buzzer, OUTPUT);

 // onebuttonmodifier.attachDoubleClick(modifierdoubleclick);




#ifndef ESP8266
  while (!Serial); // wait for serial port to connect. Needed for native USB
#endif

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running, let's set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  }

}


void loop () {

   DateTime now = rtc.now();


if (lcddisplay ==1)
{
  lcdPrintdisplay1;
  }

if (lcddisplay ==2)
{
  lcdPrintdisplay2;
  }

alarmAdjustMode();
timeAdjustButtons();
lcdPrintdisplay1();
clockfaceHands();


if ((now.hour() == alarmhour) && (now.minute() == alarmminute)){
      Buzz();
      }


//onebuttonmodifier.tick();
 

     
}

void timeAdjustButtons(){


    if((digitalRead(P1)==HIGH)&&(digitalRead(PM)==HIGH))
  {
    uint32_t deltaT = 86400; // Move time ahead one day (maybe)
rtc.adjust(rtc.now() + TimeSpan(deltaT));
  }
    else{
      if(digitalRead(P1)==HIGH)
      {
   uint32_t deltaT = 3600; // Move time ahead one hour
   rtc.adjust(rtc.now() + TimeSpan(deltaT));
      }
    }

   

     if((digitalRead(P2)==HIGH)&&(digitalRead(PM)==HIGH))
  {
    uint32_t deltaT = -86400; // Move time back one day (maybe)
rtc.adjust(rtc.now() + TimeSpan(deltaT));
  }
    else{
      if(digitalRead(P2)==HIGH)
      {
   uint32_t deltaT = -3600; // Move time back one hour
   rtc.adjust(rtc.now() + TimeSpan(deltaT));
      }

    }





   if((digitalRead(P3)==HIGH)&&(digitalRead(PM)==HIGH))
  {
    uint32_t deltaT = 1; // Move time ahead one second
rtc.adjust(rtc.now() + TimeSpan(deltaT));
  }
    else{
      if(digitalRead(P3)==HIGH)
      {
   uint32_t deltaT = 60; // Move time ahead one minute
   rtc.adjust(rtc.now() + TimeSpan(deltaT));
      }
    }

   

     if((digitalRead(P4)==HIGH)&&(digitalRead(PM)==HIGH))
  {
    uint32_t deltaT = -1; // Move time back one second
rtc.adjust(rtc.now() + TimeSpan(deltaT));
  }
    else{
      if(digitalRead(P4)==HIGH)
      {
   uint32_t deltaT = -60; // Move time back one hour
   rtc.adjust(rtc.now() + TimeSpan(deltaT));
      }

    }

 
 
  }




void clockfaceHands(){
  DateTime now = rtc.now();
hoursdegree = (180-(now.hour()*7.5));

minutesdegree = (180-(now.minute()*3));


    minutes.write(minutesdegree); 
    hours.write(hoursdegree); // tell servo to go to position in variable

}




void Buzz() {
    tone(buzzer, 1000); // Send 1KHz sound signal...
    delay(500);        // ...for 1 sec
    noTone(buzzer);     // Stop sound...
    delay(500);        // ...for 1sec
  }

//void modifierdoubleclick(){

//if (lcddisplay ==3){
 // int lcddisplay = 1;
  //}
 // else
 // {
 // lcddisplay ++;
  // }

//Buzz();

 
  //}

void lcdPrintdisplay1(){

  DateTime now = rtc.now();

    lcd.print(now.hour(), DEC);
    lcd.print(":");
    lcd.print(now.minute(), DEC);
    lcd.print(":");
    lcd.print(now.second(), DEC);
    lcd.setCursor(0, 1);
    lcd.print(now.day(), DEC);
    lcd.print(":");
    lcd.print(now.month(), DEC);
    lcd.print(":");
    lcd.print(now.year(), DEC);
    delay(250);
    lcd.clear();
    lcd.setCursor(0, 0);

 
  }



void lcdPrintdisplay2(){

lcd.setCursor(0, 0);
lcd.print("Set Hrs and Mns");
lcd.setCursor(0, 1);
lcd.print(alarmhour, DEC);     //lcd.print(alarmhour);
lcd.print(":");
lcd.print(alarmminute, DEC);      //lcd.print(alarmminute);

 if(digitalRead(P1)==HIGH)
      {
   alarmhour++;
      }

 if(digitalRead(P2)==HIGH)
      {
   alarmhour-1;
      }

  if(digitalRead(P3)==HIGH)
      {
  alarmminute++;
      }

   if(digitalRead(P4)==HIGH)
      {
  alarmminute-1;
      }
      lcd.clear();

}

void lcdPrintdisplay3() {
lcd.setCursor(0,0);
lcd.print("Mon");
lcd.print(":");
lcd.print("");
 
  }

void alarmAdjustMode() {

//if((digitalRead(P2)==HIGH)&&(digitalRead(P3)==HIGH))
 // {
//if (lcddisplay ==3){
 // int lcddisplay = 1;
  //}
 //else
 //{
 //lcddisplay +1;
 // }
  //  Buzz();
 // }
 
  }

Here are some clips of the clock, they might help you see what I am trying to achieve:

Any help with my code would be greatly appreciated. Thanks!

you should keep your project to only one thread.

What you need is to build a state machine. That's the best way to handle buttons that can have multiple meanings based on context.

to define your state machine, you need to write in plain English (or whatever language) what are the modes of your system and what buttons should do in those modes. Then we can work from there.

J-M-L:
you should keep your project to only one thread.

What you need is to build a state machine. That's the best way to handle buttons that can have multiple meanings based on context.

to define your state machine, you need to write in plain English (or whatever language) what are the modes of your system and what buttons should do in those modes. Then we can work from there.

Mode 1: Date and time display.
in this mode the time is displayed in line 1 and the date is displayed in line 2
both are adjustable in this screen
this mode works already
Mode 2: alarm time adjust
In this mode the time for the alarm is adjusted
this mode does not work. have not been able to find a way to bring up this menu and configure it.
Mode 3: alarm repeat adjust
in this mode the days on which the alarm set in mode 2 will be configured.
this mode does not work.
I need the modes to be cycled through the use of 5 buttons, all of which have pre existing binds.

how are the buttons wired? do you have external pull-up or pull-down?

if there is no external stuff, this is how I would structure the code to handle a state machine using the OneButton library you mention in the code:

#include <OneButton.h>

//buttons
const byte  PM = 6; //button modifier.
const byte  P1 = 7; //button + hours
const byte  P2 = 8; //button - hours
const byte  P3 = 9; //button + minutes
const byte  P4 = 10; //button - minutes

OneButton bModifier(PM, true); // pin, activeLow, ActivateInternalPullup (true by default)
OneButton bHourPlus(P1, true);
OneButton bHourMinus(P2, true);
OneButton bMinutePlus(P3, true);
OneButton bMinuteMinus(P4, true);

enum : byte {DISPLAY_TIME, ADJUST_ALARM, ADJUST_REPEAT} currentMode = DISPLAY_TIME;

void adjustAlarmMode()
{
  Serial.println(F("Adjust Alarm Mode"));
  currentMode = ADJUST_ALARM;
}

void adjustRepeatMode()
{
  Serial.println(F("Adjust Repeat Mode"));
  currentMode = ADJUST_REPEAT;
}

void displayTimeMode()
{
  Serial.println(F("Display Time Mode"));
  currentMode = DISPLAY_TIME;
}

void changeMode()
{
  switch (currentMode) {
    case DISPLAY_TIME: adjustAlarmMode();  break;
    case ADJUST_ALARM: adjustRepeatMode(); break;
    case ADJUST_REPEAT: displayTimeMode(); break;
    default: break;
  }
}

void hourPlus()
{
  switch (currentMode) {
    case ADJUST_ALARM:  Serial.println(F("Alarm Hour +")); break;
    case ADJUST_REPEAT: Serial.println(F("Repeat Alarm Hour +")); break;
    default: break;
  }
}

void hourMinus()
{
  switch (currentMode) {
    case ADJUST_ALARM:  Serial.println(F("Alarm Hour -")); break;
    case ADJUST_REPEAT: Serial.println(F("Repeat Alarm Hour -")); break;
    default: break;
  }
}

void minutePlus()
{
  switch (currentMode) {
    case ADJUST_ALARM:  Serial.println(F("Alarm Minute +")); break;
    case ADJUST_REPEAT: Serial.println(F("Repeat Alarm Minute +")); break;
    default: break;
  }
}

void minuteMinus()
{
  switch (currentMode) {
    case ADJUST_ALARM:  Serial.println(F("Alarm Minute -")); break;
    case ADJUST_REPEAT: Serial.println(F("Repeat Alarm Minute -")); break;
    default: break;
  }
}

void configureButtons()
{
  bModifier.attachClick(changeMode);
  bHourPlus.attachClick(hourPlus);
  bHourMinus.attachClick(hourMinus);
  bMinutePlus.attachClick(minutePlus);
  bMinuteMinus.attachClick(minuteMinus);
}

void tickButtons()
{
  bModifier.tick();
  bHourPlus.tick();
  bHourMinus.tick();
  bMinutePlus.tick();
  bMinuteMinus.tick();
}

// --------------------------

void setup () {
  Serial.begin(115200);
  configureButtons();
  displayTimeMode();
}

void loop ()
{
  tickButtons();
}

you have now specific parts of the code that are being called depending on the current mode when you press the button. It's up to you to add the missing pieces in there. Nothing is blocking, keep it that way.

if you run this and open the console at 115200 bauds, you should be able to change mode and press the H+, H-, M+ and M- buttons and see they are being taken into account

The OneButton library supports long press detection, so you could also have callbacks associated to this event so that you have a fast mode for adding hours or minutes when holding down and not having to click-click-click many times.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.