full sketch bellow:
//----------------------------------------------------------------------------------------------------------
// Libraries
//----------------------------------------------------------------------------------------------------------
#include <EEPROM.h>
#include <ezButton.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <Wire.h>
#include <LedControl.h>
#include <SPI.h>
//----------------------------------------------------------------------------------------------------------
#define MAXIMCCLD 16 // output - CS/LOAD - pseudo SPI connection to the Maxim 7219 chip - 7 segment displays
#define MAXIMCCCLK 5 // output - clock - pseudo SPI connection to the Maxim 7219 chip - 7 segment displays
#define MAXIMCCDATA 17 // output - DATA - pseudo SPI connection to the Maxim 7219 chip - 7 segment displays
#define MOSFET_Signal 4
// lc is for the Maxim displays
LedControl MaximCC=LedControl(MAXIMCCDATA, MAXIMCCCLK, MAXIMCCLD, 1); // Define pins for Maxim 72xx and how many 72xx we use
ezButton button(34); // create ezButton object that attach to pin 9 - in this case encoder button;
int hundredsof_pressure, tensofdegrees, singledegrees, millidegrees, tensofpercents, singlepercents, millipercents, tensofcounts, singlecounts, singleHH_powerSave, tensofHH_powerSave,MM_powerSave,singleMM_powerSave,tensofMM_powerSave;
// These variables are for encoder counters. These need to be always declared as VOLATILE
volatile int counter_hour_start;
volatile int counter_minute_start;
volatile int counter_hour_end;
volatile int counter_minute_end;
volatile int sleepWakeCounter;
volatile int counter;
int previousSecond = 0;
// usually the rotary encoders three pins have the ground pin in the middle
enum PinAssignments {
encoderPinA = 18, // right DT
encoderPinB = 23, // left CLK
};
// interrupt service routine vars
bool A_set = false;
bool B_set = false;
// a counter for the dial
signed int lastReportedPos_hour_start = 1; // change management
signed int lastReportedPos_minute_start = 1; // change management
signed int lastReportedPos_hour_end = 1; // change management
signed int lastReportedPos_minute_end = 1; // change management
signed int lastReportedPos_brightness_count = 1; // change management
signed int lastReportedPos_setupMenuCounter = 1;
signed int setupMenuCounter = 1; // counter goes from 1 to 3 or whatever the number of menu items is. Counter cycles so after 3 we get 1 or if we go to less than 1 we get 3
signed int lastReportedPos_sleepWakeCounter = 1;
int tensofhours, singlehours, tensofminutes, singleminutes,tensofhours1, singlehours1, tensofminutes1, singleminutes1;
const int SHORT_PRESS_TIME = 1000; // 1000 milliseconds
const int LONG_PRESS_TIME = 1000; // 2000 milliseconds
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;
// we need to set count0 as true to start with, we will later toggle it if we enter the setup menu.
bool count0 = true;
//Non-Blocking delay code using millis, for encoder - source: https://dzone.com/articles/arduino-using-millis-instead-of-delay
int period = 25;
unsigned long time_now = 0;
int oldEncoderButtonState = LOW;
int encoderButtonState = LOW;
bool selectVar = false;
bool setSleepWakeDisplay = false;
//==============================================================================
// Interrupt Service Routine - ISR Encoder
//==============================================================================
void IRAM_ATTR isr(){
if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
if (count0 == true)
counter +=1;
else if (selectVar == true)
sleepWakeCounter +=1;
else if ((sleepWakeCounter == 0) && (selectVar == false))
counter_hour_start +=1;
else if ((sleepWakeCounter == 1) && (selectVar == false))
counter_minute_start +=1;
else if ((sleepWakeCounter == 2) && (selectVar == false))
counter_hour_end +=1;
else if ((sleepWakeCounter == 3) && (selectVar == false))
counter_minute_end +=1;
}
if ( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if ( B_set && !A_set )
if (count0 == true)
counter -=1;
else if (selectVar == true)
sleepWakeCounter -=1;
else if ((sleepWakeCounter == 0) && (selectVar == false))
counter_hour_start -=1;
else if ((sleepWakeCounter == 1) && (selectVar == false))
counter_minute_start -=1;
else if ((sleepWakeCounter == 2) && (selectVar == false))
counter_hour_end -=1;
else if ((sleepWakeCounter == 3) && (selectVar == false))
counter_minute_end -=1;
}
}
//==============================================================================
// SETUP
//==============================================================================
void setup()
{
// initialize Serial communication - We have to have SERIAL
Serial.begin(115200);
button.setDebounceTime(50); // set debounce time to 50 milliseconds
button.setCountMode(COUNT_FALLING);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
EEPROM.begin(64);
counter_hour_start = EEPROM.read(0);
counter_minute_start = EEPROM.read(2);
counter_hour_end = EEPROM.read(4);
counter_minute_end = EEPROM.read(6);
attachInterrupt(encoderPinA, isr, CHANGE);
attachInterrupt(encoderPinB, isr, CHANGE);
// Initialize RTC and set as SyncProvider.
// Later RTC will be synced with DCF time
setSyncProvider(RTC.get); // the function to get the time from the RTC
// check if RTC has set the system time
if (timeStatus() != timeSet)
{ // Unable to sync with the RTC - activate RTCError LED
}
tensofhours = counter_hour_start / 10;
singlehours = counter_hour_start % 10;
tensofminutes = counter_minute_start / 10;
singleminutes = counter_minute_start % 10;
tensofhours1 = counter_hour_end / 10;
singlehours1 = counter_hour_end % 10;
tensofminutes1 = counter_minute_end / 10;
singleminutes1 = counter_minute_end % 10;
}
//==============================================================================
// LOOP
//==============================================================================
void loop()
{
tasksEverySecond();
// check if there was a short or a long press of a bottom //
button.loop(); // MUST call the loop() function first
if(button.isPressed()){
pressedTime = millis();
isPressing = true;
isLongDetected = false;
}
if(button.isReleased()) {
isPressing = false;
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
}
if(isPressing == true && isLongDetected == false) {
long pressDuration = millis() - pressedTime;
if( pressDuration > LONG_PRESS_TIME ) {
isLongDetected = true;
}
}
if (count0 == true){
if(millis() > time_now + period){
time_now = millis();
encoder_brightness();
}
} else {
if(millis() > time_now + period){
time_now = millis();
encoder_alarm();
}
}
if (isLongDetected == true){
button_press();
}
}
//================================================================================================================
//
// Function name : tasksEverySecond
// called from : <loop>
//
// Purpose : perform tasks that must happen once every SECOND
// Parameters : none
// Return value : none
//
//================================================================================================================
void tasksEverySecond()
{
// check if time is changed
if (second() != previousSecond)
{
// 'reset' variable state
previousSecond = second();
if (count0 == true) {
displayRtcTime();
}
}
}
//================================================================================================================
//
// Function name : displayRtcTime
// called from : <tasksEverySecond>
//
// Purpose : display the Real Time clock time on the RTC display
// Parameters : none
// Return value : none
//
//================================================================================================================
void displayRtcTime()
{
MaximCC.setChar(0, 0, (hour() % 10), true);
MaximCC.setChar(0, 1, (hour() % 10), true);
MaximCC.setChar(0, 2, (minute() / 10), true);
MaximCC.setChar(0, 3, (minute() % 10), false);
MaximCC.setChar(0, 7, (second() / 10), false);
MaximCC.setChar(0, 6, (second() % 10), false);
}
//==============================================================================
// button_press
//==============================================================================
// this loop has a task to convert button.getCount(); to boolean "count0" so we can
// use it in other loops without calling button.getCount(); every time
void button_press (){
unsigned long count = button.getCount();
if (count == 0) {
count0 = true;
} else {
count0 = false;
}
}
//==============================================================================
// ENCODER ALARM
//==============================================================================
void encoder_alarm(){
// toggle boolean state to choose between cycling the setup positions and changing the values
encoderButtonState = digitalRead(34);
if (( encoderButtonState != oldEncoderButtonState ) && (encoderButtonState == HIGH)) {
selectVar = !selectVar;
}
oldEncoderButtonState = encoderButtonState;
//--------------------- sleepWakeCounter ------------------------//
if (lastReportedPos_sleepWakeCounter != sleepWakeCounter) {
if (sleepWakeCounter>4) {(sleepWakeCounter = 0);}
if (sleepWakeCounter<0) {(sleepWakeCounter = 4);}
lastReportedPos_sleepWakeCounter = sleepWakeCounter;
}
//--------------------- HOURS alarm STARTS at ------------------------//
if (lastReportedPos_hour_start != counter_hour_start) {
if (counter_hour_start>23) {(counter_hour_start = 0);}
if (counter_hour_start<0) {(counter_hour_start = 23);}
tensofhours = counter_hour_start / 10;
singlehours = counter_hour_start % 10;
lastReportedPos_hour_start = counter_hour_start;
}
//--------------------- MINUTES alarm STARTS at ------------------------//
if (lastReportedPos_minute_start != counter_minute_start) {
if (counter_minute_start>59) {(counter_minute_start = 0);}
if (counter_minute_start<0) {(counter_minute_start = 59);}
tensofminutes = counter_minute_start / 10;
singleminutes = counter_minute_start % 10;
lastReportedPos_minute_start = counter_minute_start;
}
//--------------------- HOURS alarm ENDS at ------------------------//
if (lastReportedPos_hour_end != counter_hour_end) {
if (counter_hour_end>23) {(counter_hour_end = 0);}
if (counter_hour_end<0) {(counter_hour_end = 23);}
tensofhours1 = counter_hour_end / 10;
singlehours1 = counter_hour_end % 10;
lastReportedPos_hour_end = counter_hour_end;
}
//--------------------- MINUTES alarm ENDS at ------------------------//
if (lastReportedPos_minute_end != counter_minute_end) {
if (counter_minute_end>59) {(counter_minute_end = 0);}
if (counter_minute_end<0) {(counter_minute_end = 59);}
tensofminutes1 = counter_minute_end / 10;
singleminutes1 = counter_minute_end % 10;
lastReportedPos_minute_end = counter_minute_end;
}
//--------------------- 7 Segment display ------------------------//
// this runs only once
if (setSleepWakeDisplay == false)
{
// display current alarm times
MaximCC.setChar(0,7,tensofhours,false);
MaximCC.setChar(0,6,singlehours,false);
MaximCC.setChar(0,5,tensofminutes,false);
MaximCC.setChar(0,4,singleminutes,false);
MaximCC.setChar(0,3,tensofhours1,false);
MaximCC.setChar(0,2,singlehours1,false);
MaximCC.setChar(0,1,tensofminutes1,false);
MaximCC.setChar(0,0,singleminutes1,false);
setSleepWakeDisplay = true;
}
if (sleepWakeCounter == 0) {
MaximCC.setChar(0,7,tensofhours,false);
MaximCC.setChar(0,6,singlehours,true);
} else {
MaximCC.setChar(0,6,singlehours,false);
}
if (sleepWakeCounter == 1) {
MaximCC.setChar(0,5,tensofminutes,false);
MaximCC.setChar(0,4,singleminutes,true);
} else {
MaximCC.setChar(0,4,singleminutes,false);
}
if (sleepWakeCounter == 2) {
MaximCC.setChar(0,3,tensofhours1,false);
MaximCC.setChar(0,2,singlehours1,true);
} else {
MaximCC.setChar(0,2,singlehours1,false);
}
if (sleepWakeCounter == 3) {
MaximCC.setChar(0,1,tensofminutes1,false);
MaximCC.setChar(0,0,singleminutes1,true);
} else {
MaximCC.setChar(0,0,singleminutes1,false);
}
if (sleepWakeCounter == 4) {
// once we press the button from digit selection boolean togles to "false", this then executes everything below
if(selectVar == false) {
// only write to EEPROM once we are exiting the setup menu.
EEPROM.write(0,counter_hour_start);
EEPROM.commit();
EEPROM.write(2,counter_minute_start);
EEPROM.commit();
EEPROM.write(4,counter_hour_end);
EEPROM.commit();
EEPROM.write(6,counter_minute_end);
EEPROM.commit();
sleepWakeCounter = 0; // set sleepWakeCounter to 0 so that when we are back in the setup menu our selection is at position 0 - counter_hour_start
setSleepWakeDisplay = false; // set setSleepWakeDisplay to "false" so that when we are back in the setup menu last alarm setup is displayed on the display
count0 = true; // once we set count0 to "true" we are exiting "encoder_alarm" loop
}
}
}
//==============================================================================
// ENCODER BRIGHTNESS - MANUAL
//==============================================================================
void encoder_brightness(){
if (lastReportedPos_brightness_count != counter) {
if (counter>15) {(counter = 15);}
if (counter<0) {(counter = 0);}
tensofcounts = counter / 10;
singlecounts = counter % 10;
lastReportedPos_brightness_count = counter;
for (int i = 0; i < 8; i++) {
MaximCC.setIntensity(i, counter);
}
MaximCC.setChar(0,0,tensofcounts,false);
MaximCC.setChar(0,1,singlecounts,false);
}
}
many thanks,
Alek