Forum Rule: Always post complete source code & details to reproduce any issue!

# Thread: converting total seconds to hours, minutes and seconds...

1. ## converting total seconds to hours, minutes and seconds...

I would appreciate some assistance with this seemingly trivial thing.. I'm trying to convert a seconds time variable to corresponding hours, minutes and seconds. Its a countdown timer. Here's the code I found:

Code:
```float h = 0;
float m = 0;
float s = 0;
long unsigned int remainingSeconds = 39600;

void loop();{

TimeCalc(remainingSeconds);

Serial.print(h); Serial.print(" ");Serial.print(m); Serial.print(" ");Serial.print(s);
remainingSeconds --
}

void TimeCalc( long unsigned int seconds ) {
uint32_t t = seconds;

s = t % 60;

t = (t - s) / 60;
m = t % 60;

t = (t - m) / 60;
h = t;
}```
it seems to work fine starting with anything up to 9 hours 59 mins 59 seconds... counts down smoothly.. but start at 10 hours or more, and things get screwy.

I suspect my problem is some sort of variable mistyping.. but I'm new to arduino coding, and not sure how to track down the issue.

Appreciate the help.

2. you can google convert seconds to hours minutes seconds, maybe

Code:
```    uint32_t h,m,s,rem,secs;
secs = 39867;
h = secs/3600;
rem = secs%3600;
m = rem/60;
s = rem % 60;```
or change your float's to int's

EDIT: The sketch you provided would not compile, so I assumed your function TimeCalc() was also broken. Later I fixed your sample sketch so it would compile, and the TimeCalc() function (even with float's) seems to properly print h,m,s on a T3.2 and UNO

3. Thanks manitou, but using your code snippet, I"m still having the same problem... counting down from 9 hours 6 minutes works fine.. but 9 hours and 7 minutes and above, and printing to the OLED gives me garbage...

BTW.. I'm printing with those same h, m, s variables..

Originally Posted by manitou
you can google convert seconds to hours minutes seconds, maybe

Code:
```    uint32_t h,m,s,rem,secs;
secs = 39867;
h = secs/3600;
rem = secs%3600;
m = rem/60;
s = rem % 60;```
or change your float's to int's

4. countdown starting at 9 hours 6 minutes..

Attachment 12571

countdown starting at 9 hours 7 minutes..

Attachment 12572

perplexing....

5. Might help to see your code: hint: 9 hours and 6 minutes is: 32760 seconds which which is fine for in a int16_t where as 9 hours 7 minutes is 32828 which does not fit in int16_t (would go negative)...
Should work with uint16_t which goes up to 65535...

6. Originally Posted by KurtE
Might help to see your code:..
I posted the code in my first post.. I've modified it now with Manitou's suggestion.. but it didnt seem to help. I'm aware that that trouble threshold is at the 32760 point - that was my first clue that it must be a variable typing issue. But now, as Manitou suggested, I've defined them as uint32_t... which should be more than enough, no?

7. Maybe I am missing something, but if I take the program and modify it and make it such that it compiles:
Code:
```uint32_t h = 0;
uint32_t m = 0;
uint32_t s = 0;
long unsigned int remainingSeconds = 39600;
void setup(){
while (!Serial)
Serial.begin(115200);
}
void loop() {

TimeCalc(remainingSeconds);

Serial.print(h); Serial.print(" "); Serial.print(m); Serial.print(" "); Serial.println(s);
remainingSeconds --;
delay(50);
}

void TimeCalc( long unsigned int secs ) {
uint32_t rem;
h = secs / 3600;
rem = secs % 3600;
m = rem / 60;
s = rem % 60;
}```
I appear to be getting the results:
Code:
```11 0 0
10 59 59
10 59 58
10 59 57
10 59 56
10 59 55
10 59 54
10 59 53
10 59 52
10 59 51
10 59 50
10 59 49
10 59 48
10 59 47
10 59 46
10 59 45
10 59 44
10 59 43
10 59 42
10 59 41
10 59 40
10 59 39
10 59 38
10 59 37
10 59 36
10 59 35
10 59 34
10 59 33
10 59 32
10 59 31
10 59 30
10 59 29
10 59 28
10 59 27
10 59 26
10 59 25
...```

8. Originally Posted by KurtE
Maybe I am missing something, but if I take the program and modify it and make it such that it compiles:

I appear to be getting the results:
Kurt,

You are correct.. the serial monitor will show the correct values, however, the OLED will not (pictures posted). As stated earlier, uint16 variables seem to have gotten me past the 9 hour 7 minute barrier, where, long unsigned int or uint32 types will not.

Unfortunately, I seem to be overflowing around 19 hours now...

I find this confusing, as 32 is double 16.. why can I not go to higher values with uint32 variables?

9. have you tried specifying uint32_t instead of unsigned long int? you didnt specify your mcu.

10. Originally Posted by tonton81
have you tried specifying uint32_t instead of unsigned long int? you didnt specify your mcu.
Yes... uint32_t errors out above 9hrs 6min. uint16_t is the only thing that got me to 18hrs 12mins. I'm developing on two platforms: Teensy 3.6 will be the target platform. Its currently being used to develop the stepper motor control algorithms, but I'm developing the menu system and front-end framework on a mega.. hoping to migrate over to the teensy next week. The issues I'm having at the moment are with the menu on the mega.

11. The compiler is stupid. It does what you tell it to do. You told it to multiply/divide ints and put that into an unsigned long.
also replace “unsigned long int” with uint32_t as well, as ints are different size between arduino and teensy, best to specify the type for portability purposes
Tony

12. Try the following:
Code:
```static uint16_t days;
static uint8_t hours, minutes, seconds;

static void TimeCalc(uint32_t  secs)
{
seconds = secs % (uint32_t)60;
secs /= (uint32_t)60;
minutes = secs % (uint32_t)60;
secs /= (uint32_t)60;
hours = secs % (uint32_t)24;
days = secs / (uint32_t)32;
}

uint32_t  remainingSeconds = 70000; /* 0d 19h 26m 40s */

void setup(){
while (!Serial)
Serial.begin(115200);
}

void loop() {

TimeCalc(remainingSeconds);

Serial.print(days);
Serial.print("d ");
Serial.print(hours);
Serial.print("h ");
Serial.print(minutes);
Serial.print("m ");
Serial.println(seconds);

remainingSeconds --;
delay(50);
}```
The variable containing the number of seconds remaining, remainingSeconds, also has to be of sufficient size (i.e, uint32_t).

The explicit casts to (uint32_t) should not be necessary for sane C compilers, but they are safe, and are harmless (no slowdown or any other cost).

13. okay, 90% of that is completely over my head, but I'll try it and feedback...

14. Nominal Animal,

I tried your approach. Here's the code now.. (excerpts from the main code)
Code:
```//                                        Countdown variables

uint32_t remainingSeconds = 0;
uint8_t h   = 0;
uint8_t m   = 0;
uint8_t s   = 0;
uint8_t rem = 0;

TimeCalc(remainingSeconds);

display.setCursor(5, 62);
display.println(h);    // Hours
display.setCursor(54, 62);
display.println(m);      // Minutes
display.setCursor(97, 62);
display.println(s);      // Seconds

static void TimeCalc(uint32_t  secs)
{
s = secs % (uint32_t)60;
secs /= (uint32_t)60;
m = secs % (uint32_t)60;
secs /= (uint32_t)60;
h = secs % (uint32_t)24;

}```
It runs right up to the same limit as the first iteration, but different - no garbage, just complete inaccuracy.

If I start the countdown at 9hrs 6min.. I get an accurate countdown... all the way to zero. Start at 9hrs 7min.. and the countdown starts at 21 hours 22 minutes??????

There's obviously some kind of rollover happening... but where?

15. Originally Posted by vfxwolf
There's obviously some kind of rollover happening... but where?
If you do not give the WHOLE code, how can we find the problem?
Don't say it is the same. Also, code in post #1 is not complete (setup() is missing) .

have you copied Normal Animal's or KurtE's code exactly as presented (cut and past)? Does t work for you? AFAIK, a Mega has a different architecture than a Teensy.

At one post you are saying serial monitor gives correct values but display not. So, it is a problem with display interface, right?

can you give screen shots (pictures) of serial monitor and display values from the same program?

As Paul always says, we cannot see you screen and details matter.

16. WXMZ,

I have posted pictures of the screen in a previous post in this thread. Are they not showing for you?

As for posting the code, I didn’t think it necessary to post the other 400 lines of code when the issue could only involve the variables and functions that are involved in calculating and displaying the time - that code I’ve posted.

I have applied every suggestion posted thus far - and given updates on the results. If I’ve been unclear, please let me know what other information I could provide.

As for the architecture - no doubt there are differences - but I thought both were Arduino compatible - within reason. Understand that the problem I’m having is happening on the Mega - I will be moving the code over to the teensy in a few days. I believe the issue is logic, not hardware related - but I may be wrong.

17. Originally Posted by vfxwolf
WXMZ,

I have posted pictures of the screen in a previous post in this thread. Are they not showing for you?

As for posting the code, I didn’t think it necessary to post the other 400 lines of code when the issue could only involve the variables and functions that are involved in calculating and displaying the time - that code I’ve posted.

I have applied every suggestion posted thus far - and given updates on the results. If I’ve been unclear, please let me know what other information I could provide.

As for the architecture - no doubt there are differences - but I thought both were Arduino compatible - within reason. Understand that the problem I’m having is happening on the Mega - I will be moving the code over to the teensy in a few days. I believe the issue is logic, not hardware related - but I may be wrong.
clicking on the attachments says "Invalid Attachment specified"

400 lines? that is exactly the problem. somewhere in there is an error.

So,
the standard procedures in these cases are
- start from working example, here serial.printf and augment functionality, here add display.printf
or if you want help finding you problem
- remove all non problem relevant code to a bare minimum.
doing this, you will in most cases find you problem yourself, otherwise, someone else can
a) reproduce the issue (Forum rule)
b) find a solution.

as fo architecture:
Paul did a great job to make teensy compatible to Arduino-avr, but it cannot be said that Arduino avr is maintaining or even aiming for compatibility to 32 bit arm. (I'm not worried about the sketch SW but the display lbrary)

18. if serial monitor reports fine, and display rolls over, your display library must be processing the 32bit ints as 16bits, or chunking on 8bit data instead, who knows.... lack of display info, lack of library, all we have here are working time snippets for serial monitor

19. WMXZ and tonton81, points taken.

tonton81, I suspect you may be on to something there.. the display library may be the culprit. Here is the complete code for the GUI, currently being compiled on the Mega. As stated earlier, I'm also developing motor control on the Teensy, and the plan is to merge the GUI onto the Teensy later this week.

The functions of interest are: TimeCalc() and LapseModeRun() which gets its variables set in LapseModeSet().
Code:
```

/*

If you have the 128x64 version, you need to edit the file called Adafruit_SSD1306.h that is on the
Adafruit_SSD1306-master folder. The library comes by default set to use the 128x32 display.
For this reason you need to define the correct resolution like this:
Quote:
#define SSD1306_128_64
//   #define SSD1306_128_32
//   #define SSD1306_96_16
Unquote.
Notes the "//" before each line to comment the other resolutions that we are not going to use.

*/

#include <Adafruit_GFX.h>  // Include core graphics library for the display
#include <Metro.h>
#include <Encoder.h>
#include <Bounce2.h>
#include <Fonts/FreeSans9pt7b.h>  // Add a custom font

int Variable1;  // Create a variable to have something dynamic to show on the display

//                                        Countdown variables

long unsigned int TotalSeconds = 0;
uint16_t remainingSeconds = 0;
uint16_t h   = 0;
uint16_t m   = 0;
uint16_t s   = 0;
uint16_t rem = 0;

boolean hlight = 0;
Metro debounce = Metro(10);

//                                          Keyframe Variables

char StartingKey;
char EndingKey;

//                                          Encoder Variables

Encoder myEnc(2, 3);
int encState;

const int EncButton = 4;                  //Pin # to which SW line is connected
byte oldButtonState = HIGH;               // set previous buttonestate to HIGH because of pull-up resistor
const unsigned long debounceTime = 10;    // milliseconds
unsigned long buttonPressTime;            // when the switch last changed state
boolean buttonPressed = 0;                // a flag variable

//                                          Graphic variables
int progress = 0;

//                                          Mode variables

// timelapse
int TL_hours = 0;
int TL_mins = 0;

#define SMLFONT FreeSans9pt7b

Metro nextfunc = Metro(4000);

class FlashBox
{
int OnTime;
int OffTime;
int x;
int y;
int w;
int h;
int highlight;
unsigned long previousMillis;

// constructor
public:
FlashBox(int xx, int yy, int width, int height, int on, int off)
{
x = xx;
y = yy;
w = width;
h = height;
OnTime = on;
OffTime = off;
highlight = 0;
previousMillis = 0;
}

void Flasher()
{
unsigned long currentMillis = millis();

//        if ((blinkon.check())  && (highlight == 0))
if ((currentMillis - previousMillis >= OnTime)  && (highlight == 0))
{

display.drawRect(x, y, w, h, WHITE);
display.display();
highlight = 1;
previousMillis = currentMillis;

//delay (1000);
}
//          else if ((blinkoff.check()) && (highlight == 1))
else if ((currentMillis - previousMillis >= OffTime) && (highlight == 1))
{

display.drawRect(x, y, w, h, BLACK);
display.display();
highlight = 0;
previousMillis = currentMillis;
//delay(1000);
}

}
};

void setup()  // Start of setup
{
// Encoder setup
pinMode(EncButton, INPUT);
digitalWrite(EncButton, HIGH); // Pull-Up resistor for switch

// Display Setup
delay(100);  // This delay is needed to let the display to initialize
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Initialize display with the I2C address of 0x3C
display.clearDisplay();  // Clear the buffer
display.setTextColor(WHITE);  // Set color of the text
display.setRotation(0);  // Set orientation. Goes from 0, 1, 2 or 3
display.setTextWrap(false);  // By default, long lines of text are set to automatically “wrap” back to the leftmost column.
// To override this behavior (so text will run off the right side of the display - useful for
// scrolling marquee effects), use setTextWrap(false). The normal wrapping behavior is restored
// with setTextWrap(true).

display.dim(0);  //Set brightness (0 is maximun and 1 is a little dim)

}  // End of setup

void loop()  // Start of loop
{

getMenuMode();   // 0: Run Mode A 1: Run Mode B 2: Live Mode

}  // End of loop

int mode = 1;
display.clearDisplay();  // Clear the display so we can refresh
display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);

do {

{
mode--;
if (mode < 1) mode = 1;
}

{
mode++;
}

switch (mode) {
case 1:
display.clearDisplay();  // Clear the display so we can refresh
//drawgrid();
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(10, 50);  // (x,y)
display.println("Run Mode A");
display.display();
//            RunMode('A','B');
break;

case 2:
display.clearDisplay();  //            RecordMode()
//drawgrid();
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(10, 50);  // (x,y)
display.println("Record Mode");
display.display();

break;

case 3:
display.clearDisplay();  // Clear the display so we can refresh
//drawgrid();
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(20, 50);  // (x,y)
display.println("Live Mode");
display.display();
//            LiveMode();
break;

case 4:
display.clearDisplay();  //           SET TimeLapse  menuMode = 4
//drawgrid();
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(48, 38);  // (x,y)
display.println("SET");
display.setCursor(22, 55);  // (x,y)
display.println("Timelapse");
display.display();
checkSwitch();
if (buttonPressed) {
buttonPressed = 0;
display.drawRect(0, 0, 128, 64, WHITE);
display.display();
LapseModeSet();
}
break;

case 5:
display.clearDisplay();  //            RUN Timelapse  MenuMode = 5
//drawgrid();
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(46, 38);  // (x,y)
display.println("RUN");
display.setCursor(22, 55);  // (x,y)
display.println("Timelapse");
display.display();
checkSwitch();
if (buttonPressed) {
buttonPressed = 0;
display.drawRect(0, 0, 128, 64, WHITE);
display.display();
LapseModeRun();
}
break;

}
}

void TimeCalc( uint32_t seconds ) {
uint32_t t = seconds;

h = t / 3600;
rem = t % 3600;
m = rem / 60;
s = rem % 60;
}

void RunMode ( char startKF, char endKF ) {
nextfunc.reset();
TotalSeconds = 740;
do {
Variable1++;  // Increase variable by 1
if (Variable1 > 150) // If Variable1 is greater than 150
{
Variable1 = 0;  // Set Variable1 to 0
}

display.clearDisplay();  // Clear the display so we can refresh

display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);

// Print text:
display.setCursor(0, 12);  // (x,y)
display.print("Running "); display.print(startKF); display.print("<->"); display.print(endKF);  // print start and end keyframes
display.setFont();
display.setCursor(0, 30);  // (x,y)
//        display.println("TIME REMAINING");  // Text or value to print
display.setCursor(0, 29);
display.println(" HOURS   MIN.    SEC.");
display.drawLine(0, 43, 128, 43, WHITE);  // Draw Horizontal line
display.drawLine(42, 43, 42, 64, WHITE);  // Draw Vertictal line
display.drawLine(84, 43, 84, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
TimeCalc(TotalSeconds);
display.setCursor(5, 62);
display.println(h);    // Hours
display.setCursor(54, 62);
display.println(m);      // Minutes
display.setCursor(97, 62);
display.println(s);      // Seconds
--TotalSeconds;

// Draw Progress Bar rectangle:
display.drawRect(0, 22, 128, 1, WHITE);  // Draw rectangle (x,y,width,height,color)
display.fillRect(0, 21, progress, 3, WHITE);  // It draws from the location to down-right
progress++;
if (progress > 127) {
progress = 0;
}

//display.setFont(&FreeMonoBold12pt7b);  // Set a custom font

// Print variable with left alignment:
display.setFont();

display.display();  // Print everything we set previously
checkSwitch();      // check encoder switch
if (buttonPressed) {
Variable1 = 0;
progress = 0;
display.clearDisplay();
display.display();
return;
}
} while (Variable1 < 128);

}

void LiveMode() {
// display.fillRect(0, 0, 128, 64, WHITE);
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.setCursor(10, 20);  // (x,y)
display.setTextColor(WHITE);
while (!buttonPressed) {
display.println("Live Mode");
display.display();
}
return;
}

void RecordMode() {
// display.fillRect(0, 0, 128, 64, WHITE);
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.setCursor(10, 20);  // (x,y)
display.setTextColor(WHITE);
while (!buttonPressed) {
display.println("Recording..");
display.display();
}
return;
}

void LapseModeSet() {

screen_Lapse();

FlashBox hours(1, 36, 63, 27, 200, 200); // Construct flashing box (Hours)
FlashBox mins(65, 36, 62, 27, 200, 200); // Construct flashing box (Minutes)
FlashBox TL_set(0, 0, 128, 64, 300, 300); // Construct TL Done flashing box
int mode = 0;  // 0 = hours selected   1 = minutes selected
int valuechange = 0;

encOld = 0;
buttonPressed = 0;
myEnc.write(0);
do {

do {

{
mode--;
if (mode < 0) mode = 0;
screen_Lapse();
}
{
mode++;
if (mode > 2) mode = 2;
screen_Lapse();
}

switch (mode)
{
case 0:
hours.Flasher();    // flash Hours Box
break;
case 1:
mins.Flasher();     // flash Minutes Box
break;
case 2:
TL_set.Flasher();   // flash whole screen Box
break;
}

checkSwitch();
if (buttonPressed)
{
buttonPressed = 0;
valuechange = 1;
if (mode == 0) myEnc.write(TL_hours);
if (mode == 1) myEnc.write(TL_mins);
screen_Lapse();
}

} while (!valuechange);

do {
if (mode == 0)   // Adjust Hours
{
display.drawRect(1, 36, 63, 27, WHITE);
screen_Lapse();
checkSwitch();
if (buttonPressed)
{
valuechange = 0;
buttonPressed = 0;
}
}

if (mode == 1)   // Adjust Minutes
{
display.drawRect(65, 36, 62, 27, WHITE);
screen_Lapse();
checkSwitch();
if (buttonPressed)
{
valuechange = 0;
buttonPressed = 0;
}
}

if (mode == 2)   // Quit to Main Menu
{

valuechange = 0;
buttonPressed = 0;
remainingSeconds = ((TL_hours * 60) * 60) + (TL_mins * 60);

}

} while (valuechange);

}

void LapseModeRun() {
//  Serial.begin(9600);
TotalSeconds = remainingSeconds;
int percent = 0;

do {

display.clearDisplay();  // Clear the display so we can refresh
display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);
display.setCursor(0, 12);  // (x,y)
display.print("Running ");
display.setFont();
display.setCursor(0, 30);  // (x,y)
//        display.println("TIME REMAINING");  // Text or value to print
display.setCursor(0, 29);
display.println(" HOURS   MIN.    SEC.");
display.drawLine(0, 43, 128, 43, WHITE);  // Draw Horizontal line
display.drawLine(42, 43, 42, 64, WHITE);  // Draw Vertictal line
display.drawLine(84, 43, 84, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
TimeCalc(remainingSeconds);
//Serial.print(h); Serial.print(" ");Serial.print(m); Serial.print(" ");Serial.println(s);
display.setCursor(5, 62);
display.println(h);    // Hours
display.setCursor(54, 62);
display.println(m);      // Minutes
display.setCursor(97, 62);
display.println(s);      // Seconds

// Draw Progress Bar rectangle:
progress = abs((((float)remainingSeconds / (float)TotalSeconds) * 128) - 128);
percent = ((float)progress / 128) * 100;
display.drawRect(0, 22, 128, 1, WHITE);  // Draw rectangle (x,y,width,height,color)
display.fillRect(0, 21, progress, 3, WHITE);  // It draws from the location to down-right

//display.setFont(&FreeMonoBold12pt7b);  // Set a custom font

// Print variable with left alignment:
display.setFont();
display.setCursor(100, 5);
display.print(percent);
display.println("%");
//    display.setCursor(80, 5);
//    display.print(remainingSeconds);

display.display();  // Print everything we set previously

if (remainingSeconds == 0)
{
//display.getTextBounds("Running ",0,12,int x, int y, int ww, int hh);
display.fillRect(0, 0, 70, 20, BLACK);
display.setFont(&SMLFONT);
display.setCursor(0, 12);  // (x,y)
display.print("DONE ");
display.display();
delay(50000);
}

remainingSeconds--;             //          TICK!

checkSwitch();      // check encoder switch
if (buttonPressed) {
buttonPressed = 0;
display.clearDisplay();
display.display();
return;
}

}

void checkSwitch() {
// Check Encoder Switch

if (buttonState != oldButtonState)
{
if (millis () - buttonPressTime >= debounceTime)
{ // debounce
buttonPressTime = millis ();                      // when we closed the switch
oldButtonState =  buttonState;                    // remember for next time
if (buttonState == LOW)
{
//        Serial.println ("Button pressed");               // DEBUGGING: print that button has been closed
buttonPressed = 1;
}
else
{
//        Serial.println ("Button released");               // DEBUGGING: print that button has been opened
buttonPressed = 0;
}
}  // end if debounce time up
} // end of state change
}

void screen_Lapse() {
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.drawRect(0, 0, 128, 64, WHITE);  // Draw Border
display.setCursor(4, 15);  // (x,y)
display.setTextColor(WHITE);
display.println("Set Timelapse");
display.setFont();
display.setCursor(0, 25);
display.println("   HOURS     MINUTES");
display.drawLine(0, 35, 128, 35, WHITE);  // Draw Horizontal line
display.drawLine(64, 35, 64, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
display.setCursor(17, 55);
display.println(TL_hours);
display.setCursor(85, 55);
display.println(TL_mins);
display.display();

}

void drawgrid() {
display.drawRect(0, 0, 128, 64, WHITE);
display.drawLine(64, 0, 64, 128, WHITE);
display.drawLine(0, 32, 128, 32, WHITE);
}

// Adafruit Graphic library code references

// Draw triangle:
// display.drawTriangle(40,40,   50,20,   60,40, WHITE);  // Draw triangle. X, Y coordinates for three corner points defining the triangle, followed by a color

// Draw filled triangle:
//display.fillTriangle(0,35,   15,45,   30,63, WHITE);  // Draw filled triangle. X, Y coordinates for three corner points defining the triangle, followed by a color

// Draw line:
//  display.drawLine(0, 18, 128, 18, WHITE);  // Draw line (x0,y0,x1,y1,color)

// Draw circle:
// display.drawCircle(47, 36, 20, WHITE);  //  Draw circle (x,y,radius,color). X and Y are the coordinates for the center point

// Draw a filled circle:
// display.fillCircle(12, 27, 10, WHITE);  // Draw filled circle (x,y,radius,color). X and Y are the coordinates for the center point

// Draw rectangle:
// display.drawRect(58, 0, 18, 18, WHITE);  // Draw rectangle (x,y,width,height,color)
// It draws from the location to down-right

// Draw rounded rectangle and fill:
// display.fillRoundRect(58, 0, 18, 18, 5, WHITE);  // Draw filled rounded rectangle (x,y,width,height,color)
// It draws from the location to down-right
// Draw rounded rectangle:
//display.drawRoundRect(79, 37, 49, 27, 8, WHITE);  // Draw rounded rectangle (x,y,width,height,radius,color)
// It draws from the location to down-right

// Print variable with right alignment:
//  display.setCursor(83, 60);  // (x,y)
//  display.println(string);  // Text or value to print

//
//
//  // Convert Variable1 into a string, so we can change the text alignment to the right:
//  // It can be also used to add or remove decimal numbers.
//  char string[10];  // Create a character array of 10 characters
//  // Convert float to a string:
//  dtostrf(Variable1, 3, 0, string);  // (<variable>,<amount of digits we are going to use>,<amount of decimal digits>,<string name>)```
I'm also reattaching images of the OLED SSD 1306 module running the sketch. Please let me know if they cant be viewed. Standard JPG.

Again, the problem is the OLED will not display proper countdown starting higher than 18 hrs. 12 minutes.

20. Again simple problem here... Example: your 18 hours and 12 minutes comes out to 65520 seconds... Which is just about as big a number you can fit int uint16_t

Code:
```void TimeCalc( uint32_t seconds ) {
uint32_t t = seconds;

h = t / 3600;
rem = t % 3600;
m = rem / 60;
s = rem % 60;
}```
Yes you are using some uint32_t values which should work, but your intermediate calculations may be done in 16 bits... What happens if you start casting things and use large constants?

Like:
Code:
```void TimeCalc( uint32_t seconds ) {
uint32_t t = seconds;

h =  (uint32_t)t / (uint32_t)3600L;
rem =  (uint32_t)t %  (uint32_t)3600L;
m = rem / 60;
s = rem % 60;
}```

21. Originally Posted by KurtE
Again simple problem here...... What happens if you start casting things and use large constants?

Like:
Code:
```void TimeCalc( uint32_t seconds ) {
uint32_t t = seconds;

h =  (uint32_t)t / (uint32_t)3600L;
rem =  (uint32_t)t %  (uint32_t)3600L;
m = rem / 60;
s = rem % 60;
}```
Kurt, tried your idea... I get the same result. Setting countdown to 18:13 results in a 1 minute countdown..

Code:
```

/*

If you have the 128x64 version, you need to edit the file called Adafruit_SSD1306.h that is on the
Adafruit_SSD1306-master folder. The library comes by default set to use the 128x32 display.
For this reason you need to define the correct resolution like this:
Quote:
#define SSD1306_128_64
//   #define SSD1306_128_32
//   #define SSD1306_96_16
Unquote.
Notes the "//" before each line to comment the other resolutions that we are not going to use.

*/

#include <Adafruit_GFX.h>  // Include core graphics library for the display
#include <Metro.h>
#include <Encoder.h>
#include <Bounce2.h>
#include <Fonts/FreeSans9pt7b.h>  // Add a custom font

int Variable1;  // Create a variable to have something dynamic to show on the display

//                                        Countdown variables

long unsigned int TotalSeconds = 0;
uint16_t remainingSeconds = 0;
uint16_t h   = 0;
uint16_t m   = 0;
uint16_t s   = 0;
uint16_t rem = 0;

boolean hlight = 0;
Metro debounce = Metro(10);

//                                          Keyframe Variables

char StartingKey;
char EndingKey;

//                                          Encoder Variables

Encoder myEnc(2, 3);
int encState;

const int EncButton = 4;                  //Pin # to which SW line is connected
byte oldButtonState = HIGH;               // set previous buttonestate to HIGH because of pull-up resistor
const unsigned long debounceTime = 10;    // milliseconds
unsigned long buttonPressTime;            // when the switch last changed state
boolean buttonPressed = 0;                // a flag variable

//                                          Graphic variables
int progress = 0;

//                                          Mode variables

// timelapse
int TL_hours = 0;
int TL_mins = 0;

#define SMLFONT FreeSans9pt7b

Metro nextfunc = Metro(4000);

class FlashBox
{
int OnTime;
int OffTime;
int x;
int y;
int w;
int h;
int highlight;
unsigned long previousMillis;

// constructor
public:
FlashBox(int xx, int yy, int width, int height, int on, int off)
{
x = xx;
y = yy;
w = width;
h = height;
OnTime = on;
OffTime = off;
highlight = 0;
previousMillis = 0;
}

void Flasher()
{
unsigned long currentMillis = millis();

//        if ((blinkon.check())  && (highlight == 0))
if ((currentMillis - previousMillis >= OnTime)  && (highlight == 0))
{

display.drawRect(x, y, w, h, WHITE);
display.display();
highlight = 1;
previousMillis = currentMillis;

//delay (1000);
}
//          else if ((blinkoff.check()) && (highlight == 1))
else if ((currentMillis - previousMillis >= OffTime) && (highlight == 1))
{

display.drawRect(x, y, w, h, BLACK);
display.display();
highlight = 0;
previousMillis = currentMillis;
//delay(1000);
}

}
};

void setup()  // Start of setup
{
// Encoder setup
pinMode(EncButton, INPUT);
digitalWrite(EncButton, HIGH); // Pull-Up resistor for switch

// Display Setup
delay(100);  // This delay is needed to let the display to initialize
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Initialize display with the I2C address of 0x3C
display.clearDisplay();  // Clear the buffer
display.setTextColor(WHITE);  // Set color of the text
display.setRotation(0);  // Set orientation. Goes from 0, 1, 2 or 3
display.setTextWrap(false);  // By default, long lines of text are set to automatically “wrap” back to the leftmost column.
// To override this behavior (so text will run off the right side of the display - useful for
// scrolling marquee effects), use setTextWrap(false). The normal wrapping behavior is restored
// with setTextWrap(true).

display.dim(0);  //Set brightness (0 is maximun and 1 is a little dim)

}  // End of setup

void loop()  // Start of loop
{

getMenuMode();   // 0: Run Mode A 1: Run Mode B 2: Live Mode

}  // End of loop

int mode = 1;
display.clearDisplay();  // Clear the display so we can refresh
display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);

do {

{
mode--;
if (mode < 1) mode = 1;
}

{
mode++;
}

switch (mode) {
case 1:
display.clearDisplay();  // Clear the display so we can refresh
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(20, 38);  // (x,y)
display.println("REALTIME");
display.setCursor(44, 55);  // (x,y)
display.println("Mode");
display.display();
//            RunMode('A','B');
break;

case 2:
display.clearDisplay();  //            RecordMode()
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(27, 38);  // (x,y)
display.println("RECORD");
display.setCursor(44, 55);  // (x,y)
display.println("Mode");
display.display();

break;

case 3:
display.clearDisplay();  // Clear the display so we can refresh
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(47, 38);  // (x,y)
display.println("LIVE");
display.setCursor(44, 55);  // (x,y)
display.println("Mode");
display.display();
//            LiveMode();
break;

case 4:
display.clearDisplay();  //           SET TimeLapse  menuMode = 4
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(48, 38);  // (x,y)
display.println("SET");
display.setCursor(22, 55);  // (x,y)
display.println("Timelapse");
display.display();
checkSwitch();
if (buttonPressed) {
buttonPressed = 0;
display.drawRect(0, 0, 128, 64, WHITE);
display.display();
LapseModeSet();
}
break;

case 5:
display.clearDisplay();  //            RUN Timelapse  MenuMode = 5
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(46, 38);  // (x,y)
display.println("RUN");
display.setCursor(22, 55);  // (x,y)
display.println("Timelapse");
display.display();
checkSwitch();
if (buttonPressed) {
buttonPressed = 0;
display.drawRect(0, 0, 128, 64, WHITE);
display.display();
LapseModeRun();
}
break;

}
}

void TimeCalc( uint32_t seconds ) {
uint32_t t = seconds;

h =  (uint32_t)t / (uint32_t)3600L;
rem =  (uint32_t)t %  (uint32_t)3600L;
m = rem / 60;
s = rem % 60;

//  h = t / 3600;
//  rem = t % 3600;
//  m = rem / 60;
//  s = rem % 60;
}

void RunMode ( char startKF, char endKF ) {
nextfunc.reset();
TotalSeconds = 740;
do {
Variable1++;  // Increase variable by 1
if (Variable1 > 150) // If Variable1 is greater than 150
{
Variable1 = 0;  // Set Variable1 to 0
}

display.clearDisplay();  // Clear the display so we can refresh

display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);

// Print text:
display.setCursor(0, 12);  // (x,y)
display.print("Running "); display.print(startKF); display.print("<->"); display.print(endKF);  // print start and end keyframes
display.setFont();
display.setCursor(0, 30);  // (x,y)
//        display.println("TIME REMAINING");  // Text or value to print
display.setCursor(0, 29);
display.println(" HOURS   MIN.    SEC.");
display.drawLine(0, 43, 128, 43, WHITE);  // Draw Horizontal line
display.drawLine(42, 43, 42, 64, WHITE);  // Draw Vertictal line
display.drawLine(84, 43, 84, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
TimeCalc(TotalSeconds);
display.setCursor(5, 62);
display.println(h);    // Hours
display.setCursor(54, 62);
display.println(m);      // Minutes
display.setCursor(97, 62);
display.println(s);      // Seconds
--TotalSeconds;

// Draw Progress Bar rectangle:
display.drawRect(0, 22, 128, 1, WHITE);  // Draw rectangle (x,y,width,height,color)
display.fillRect(0, 21, progress, 3, WHITE);  // It draws from the location to down-right
progress++;
if (progress > 127) {
progress = 0;
}

//display.setFont(&FreeMonoBold12pt7b);  // Set a custom font

// Print variable with left alignment:
display.setFont();

display.display();  // Print everything we set previously
checkSwitch();      // check encoder switch
if (buttonPressed) {
Variable1 = 0;
progress = 0;
display.clearDisplay();
display.display();
return;
}
} while (Variable1 < 128);

}

void LiveMode() {
// display.fillRect(0, 0, 128, 64, WHITE);
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.setCursor(10, 20);  // (x,y)
display.setTextColor(WHITE);
while (!buttonPressed) {
display.println("Live Mode");
display.display();
}
return;
}

void RecordMode() {
// display.fillRect(0, 0, 128, 64, WHITE);
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.setCursor(10, 20);  // (x,y)
display.setTextColor(WHITE);
while (!buttonPressed) {
display.println("Recording..");
display.display();
}
return;
}

void LapseModeSet() {

screen_Lapse();

FlashBox hours(1, 36, 63, 27, 200, 200); // Construct flashing box (Hours)
FlashBox mins(65, 36, 62, 27, 200, 200); // Construct flashing box (Minutes)
FlashBox TL_set(0, 0, 128, 64, 300, 300); // Construct TL Done flashing box
int mode = 0;  // 0 = hours selected   1 = minutes selected
int valuechange = 0;

encOld = 0;
buttonPressed = 0;
myEnc.write(0);
do {

do {

{
mode--;
if (mode < 0) mode = 0;
screen_Lapse();
}
{
mode++;
if (mode > 2) mode = 2;
screen_Lapse();
}

switch (mode)
{
case 0:
hours.Flasher();    // flash Hours Box
break;
case 1:
mins.Flasher();     // flash Minutes Box
break;
case 2:
TL_set.Flasher();   // flash whole screen Box
break;
}

checkSwitch();
if (buttonPressed)
{
buttonPressed = 0;
valuechange = 1;
if (mode == 0) myEnc.write(TL_hours);
if (mode == 1) myEnc.write(TL_mins);
screen_Lapse();
}

} while (!valuechange);

do {
if (mode == 0)   // Adjust Hours
{
display.drawRect(1, 36, 63, 27, WHITE);
screen_Lapse();
checkSwitch();
if (buttonPressed)
{
valuechange = 0;
buttonPressed = 0;
}
}

if (mode == 1)   // Adjust Minutes
{
display.drawRect(65, 36, 62, 27, WHITE);
screen_Lapse();
checkSwitch();
if (buttonPressed)
{
valuechange = 0;
buttonPressed = 0;
}
}

if (mode == 2)   // Quit to Main Menu
{

valuechange = 0;
buttonPressed = 0;
remainingSeconds = ((TL_hours * 60) * 60) + (TL_mins * 60);

}

} while (valuechange);

}

void LapseModeRun() {
//  Serial.begin(9600);
TotalSeconds = remainingSeconds;
int percent = 0;

do {

display.clearDisplay();  // Clear the display so we can refresh
display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);
display.setCursor(0, 12);  // (x,y)
display.print("Running ");
display.setFont();
display.setCursor(0, 30);  // (x,y)
//        display.println("TIME REMAINING");  // Text or value to print
display.setCursor(0, 29);
display.println(" HOURS   MIN.    SEC.");
display.drawLine(0, 43, 128, 43, WHITE);  // Draw Horizontal line
display.drawLine(42, 43, 42, 64, WHITE);  // Draw Vertictal line
display.drawLine(84, 43, 84, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
TimeCalc(remainingSeconds);
//Serial.print(h); Serial.print(" ");Serial.print(m); Serial.print(" ");Serial.println(s);
display.setCursor(5, 62);
display.println(h);    // Hours
display.setCursor(54, 62);
display.println(m);      // Minutes
display.setCursor(97, 62);
display.println(s);      // Seconds

// Draw Progress Bar rectangle:
progress = abs((((float)remainingSeconds / (float)TotalSeconds) * 128) - 128);
percent = ((float)progress / 128) * 100;
display.drawRect(0, 22, 128, 1, WHITE);  // Draw rectangle (x,y,width,height,color)
display.fillRect(0, 21, progress, 3, WHITE);  // It draws from the location to down-right

//display.setFont(&FreeMonoBold12pt7b);  // Set a custom font

// Print variable with left alignment:
display.setFont();
display.setCursor(100, 5);
display.print(percent);
display.println("%");
//    display.setCursor(80, 5);
//    display.print(remainingSeconds);

display.display();  // Print everything we set previously

if (remainingSeconds == 0)
{
//display.getTextBounds("Running ",0,12,int x, int y, int ww, int hh);
display.fillRect(0, 0, 70, 20, BLACK);
display.setFont(&SMLFONT);
display.setCursor(0, 12);  // (x,y)
display.print("DONE ");
display.display();
delay(50000);
}

remainingSeconds--;             //          TICK!

checkSwitch();      // check encoder switch
if (buttonPressed) {
buttonPressed = 0;
display.clearDisplay();
display.display();
return;
}

}

void checkSwitch() {
// Check Encoder Switch

if (buttonState != oldButtonState)
{
if (millis () - buttonPressTime >= debounceTime)
{ // debounce
buttonPressTime = millis ();                      // when we closed the switch
oldButtonState =  buttonState;                    // remember for next time
if (buttonState == LOW)
{
//        Serial.println ("Button pressed");               // DEBUGGING: print that button has been closed
buttonPressed = 1;
}
else
{
//        Serial.println ("Button released");               // DEBUGGING: print that button has been opened
buttonPressed = 0;
}
}  // end if debounce time up
} // end of state change
}

void screen_Lapse() {
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.drawRect(0, 0, 128, 64, WHITE);  // Draw Border
display.setCursor(4, 15);  // (x,y)
display.setTextColor(WHITE);
display.println("Set Timelapse");
display.setFont();
display.setCursor(0, 25);
display.println("   HOURS     MINUTES");
display.drawLine(0, 35, 128, 35, WHITE);  // Draw Horizontal line
display.drawLine(64, 35, 64, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
display.setCursor(17, 55);
display.println(TL_hours);
display.setCursor(85, 55);
display.println(TL_mins);
display.display();

}

void drawgrid() {
display.drawRect(0, 0, 128, 64, WHITE);
display.drawLine(64, 0, 64, 128, WHITE);
display.drawLine(0, 32, 128, 32, WHITE);
}

// Adafruit Graphic library code references

// Draw triangle:
// display.drawTriangle(40,40,   50,20,   60,40, WHITE);  // Draw triangle. X, Y coordinates for three corner points defining the triangle, followed by a color

// Draw filled triangle:
//display.fillTriangle(0,35,   15,45,   30,63, WHITE);  // Draw filled triangle. X, Y coordinates for three corner points defining the triangle, followed by a color

// Draw line:
//  display.drawLine(0, 18, 128, 18, WHITE);  // Draw line (x0,y0,x1,y1,color)

// Draw circle:
// display.drawCircle(47, 36, 20, WHITE);  //  Draw circle (x,y,radius,color). X and Y are the coordinates for the center point

// Draw a filled circle:
// display.fillCircle(12, 27, 10, WHITE);  // Draw filled circle (x,y,radius,color). X and Y are the coordinates for the center point

// Draw rectangle:
// display.drawRect(58, 0, 18, 18, WHITE);  // Draw rectangle (x,y,width,height,color)
// It draws from the location to down-right

// Draw rounded rectangle and fill:
// display.fillRoundRect(58, 0, 18, 18, 5, WHITE);  // Draw filled rounded rectangle (x,y,width,height,color)
// It draws from the location to down-right
// Draw rounded rectangle:
//display.drawRoundRect(79, 37, 49, 27, 8, WHITE);  // Draw rounded rectangle (x,y,width,height,radius,color)
// It draws from the location to down-right

// Print variable with right alignment:
//  display.setCursor(83, 60);  // (x,y)
//  display.println(string);  // Text or value to print

//

//  // Convert Variable1 into a string, so we can change the text alignment to the right:
//  // It can be also used to add or remove decimal numbers.
//  char string[10];  // Create a character array of 10 characters
//  // Convert float to a string:
//  dtostrf(Variable1, 3, 0, string);  // (<variable>,<amount of digits we are going to use>,<amount of decimal digits>,<string name>)```

22. you have delcared h,m,s,rem as uint16_t, and remainingseconds. remainingseconds should be uint32_t. is there a reason why h,m,s,rem can not be declared uint32_t? try it

23. Manitou,

Tried it. Seems to make matters worse.. now setting countdown to 10 hours gives garbage on the OLED. Only setting all relevant variables to uint16_t allows me to get to 18hrs 12mins cleanly..

Code:
```

/*

If you have the 128x64 version, you need to edit the file called Adafruit_SSD1306.h that is on the
Adafruit_SSD1306-master folder. The library comes by default set to use the 128x32 display.
For this reason you need to define the correct resolution like this:
Quote:
#define SSD1306_128_64
//   #define SSD1306_128_32
//   #define SSD1306_96_16
Unquote.
Notes the "//" before each line to comment the other resolutions that we are not going to use.

*/

#include <Adafruit_GFX.h>  // Include core graphics library for the display
#include <Metro.h>
#include <Encoder.h>
#include <Bounce2.h>
#include <Fonts/FreeSans9pt7b.h>  // Add a custom font

int Variable1;  // Create a variable to have something dynamic to show on the display

//                                        Countdown variables

long unsigned int TotalSeconds = 0;
uint32_t remainingSeconds = 0;
uint32_t h   = 0;
uint32_t m   = 0;
uint32_t s   = 0;
uint32_t rem = 0;

boolean hlight = 0;
Metro debounce = Metro(10);

//                                          Keyframe Variables

char StartingKey;
char EndingKey;

//                                          Encoder Variables

Encoder myEnc(2, 3);
int encState;

const int EncButton = 4;                  //Pin # to which SW line is connected
byte oldButtonState = HIGH;               // set previous buttonestate to HIGH because of pull-up resistor
const unsigned long debounceTime = 10;    // milliseconds
unsigned long buttonPressTime;            // when the switch last changed state
boolean buttonPressed = 0;                // a flag variable

//                                          Graphic variables
int progress = 0;

//                                          Mode variables

// timelapse
int TL_hours = 0;
int TL_mins = 0;

#define SMLFONT FreeSans9pt7b

Metro nextfunc = Metro(4000);

class FlashBox
{
int OnTime;
int OffTime;
int x;
int y;
int w;
int h;
int highlight;
unsigned long previousMillis;

// constructor
public:
FlashBox(int xx, int yy, int width, int height, int on, int off)
{
x = xx;
y = yy;
w = width;
h = height;
OnTime = on;
OffTime = off;
highlight = 0;
previousMillis = 0;
}

void Flasher()
{
unsigned long currentMillis = millis();

//        if ((blinkon.check())  && (highlight == 0))
if ((currentMillis - previousMillis >= OnTime)  && (highlight == 0))
{

display.drawRect(x, y, w, h, WHITE);
display.display();
highlight = 1;
previousMillis = currentMillis;

//delay (1000);
}
//          else if ((blinkoff.check()) && (highlight == 1))
else if ((currentMillis - previousMillis >= OffTime) && (highlight == 1))
{

display.drawRect(x, y, w, h, BLACK);
display.display();
highlight = 0;
previousMillis = currentMillis;
//delay(1000);
}

}
};

void setup()  // Start of setup
{
// Encoder setup
pinMode(EncButton, INPUT);
digitalWrite(EncButton, HIGH); // Pull-Up resistor for switch

// Display Setup
delay(100);  // This delay is needed to let the display to initialize
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Initialize display with the I2C address of 0x3C
display.clearDisplay();  // Clear the buffer
display.setTextColor(WHITE);  // Set color of the text
display.setRotation(0);  // Set orientation. Goes from 0, 1, 2 or 3
display.setTextWrap(false);  // By default, long lines of text are set to automatically “wrap” back to the leftmost column.
// To override this behavior (so text will run off the right side of the display - useful for
// scrolling marquee effects), use setTextWrap(false). The normal wrapping behavior is restored
// with setTextWrap(true).

display.dim(0);  //Set brightness (0 is maximun and 1 is a little dim)

}  // End of setup

void loop()  // Start of loop
{

getMenuMode();   // 0: Run Mode A 1: Run Mode B 2: Live Mode

}  // End of loop

int mode = 1;
display.clearDisplay();  // Clear the display so we can refresh
display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);

do {

{
mode--;
if (mode < 1) mode = 1;
}

{
mode++;
}

switch (mode) {
case 1:
display.clearDisplay();  // Clear the display so we can refresh
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(20, 38);  // (x,y)
display.println("REALTIME");
display.setCursor(44, 55);  // (x,y)
display.println("Mode");
display.display();
//            RunMode('A','B');
break;

case 2:
display.clearDisplay();  //            RecordMode()
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(27, 38);  // (x,y)
display.println("RECORD");
display.setCursor(44, 55);  // (x,y)
display.println("Mode");
display.display();

break;

case 3:
display.clearDisplay();  // Clear the display so we can refresh
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(47, 38);  // (x,y)
display.println("LIVE");
display.setCursor(44, 55);  // (x,y)
display.println("Mode");
display.display();
//            LiveMode();
break;

case 4:
display.clearDisplay();  //           SET TimeLapse  menuMode = 4
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(48, 38);  // (x,y)
display.println("SET");
display.setCursor(22, 55);  // (x,y)
display.println("Timelapse");
display.display();
checkSwitch();
if (buttonPressed) {
buttonPressed = 0;
display.drawRect(0, 0, 128, 64, WHITE);
display.display();
LapseModeSet();
}
break;

case 5:
display.clearDisplay();  //            RUN Timelapse  MenuMode = 5
//drawgrid();
display.drawRoundRect(0, 0, 128, 64, 8, WHITE);
display.setCursor(48, 12);  // (x,y)
display.setFont();
display.print("SELECT");
//display.print(mode);
display.setFont(&SMLFONT);
display.setCursor(46, 38);  // (x,y)
display.println("RUN");
display.setCursor(22, 55);  // (x,y)
display.println("Timelapse");
display.display();
checkSwitch();
if (buttonPressed) {
buttonPressed = 0;
display.drawRect(0, 0, 128, 64, WHITE);
display.display();
LapseModeRun();
}
break;

}
}

void TimeCalc( uint32_t seconds ) {
uint32_t t = seconds;

//  h =  (uint32_t)t / (uint32_t)3600L;
//  rem =  (uint32_t)t %  (uint32_t)3600L;
//  m = rem / 60;
//  s = rem % 60;

h = t / 3600;
rem = t % 3600;
m = rem / 60;
s = rem % 60;
}

void RunMode ( char startKF, char endKF ) {
nextfunc.reset();
TotalSeconds = 740;
do {
Variable1++;  // Increase variable by 1
if (Variable1 > 150) // If Variable1 is greater than 150
{
Variable1 = 0;  // Set Variable1 to 0
}

display.clearDisplay();  // Clear the display so we can refresh

display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);

// Print text:
display.setCursor(0, 12);  // (x,y)
display.print("Running "); display.print(startKF); display.print("<->"); display.print(endKF);  // print start and end keyframes
display.setFont();
display.setCursor(0, 30);  // (x,y)
//        display.println("TIME REMAINING");  // Text or value to print
display.setCursor(0, 29);
display.println(" HOURS   MIN.    SEC.");
display.drawLine(0, 43, 128, 43, WHITE);  // Draw Horizontal line
display.drawLine(42, 43, 42, 64, WHITE);  // Draw Vertictal line
display.drawLine(84, 43, 84, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
TimeCalc(TotalSeconds);
display.setCursor(5, 62);
display.println(h);    // Hours
display.setCursor(54, 62);
display.println(m);      // Minutes
display.setCursor(97, 62);
display.println(s);      // Seconds
--TotalSeconds;

// Draw Progress Bar rectangle:
display.drawRect(0, 22, 128, 1, WHITE);  // Draw rectangle (x,y,width,height,color)
display.fillRect(0, 21, progress, 3, WHITE);  // It draws from the location to down-right
progress++;
if (progress > 127) {
progress = 0;
}

//display.setFont(&FreeMonoBold12pt7b);  // Set a custom font

// Print variable with left alignment:
display.setFont();

display.display();  // Print everything we set previously
checkSwitch();      // check encoder switch
if (buttonPressed) {
Variable1 = 0;
progress = 0;
display.clearDisplay();
display.display();
return;
}
} while (Variable1 < 128);

}

void LiveMode() {
// display.fillRect(0, 0, 128, 64, WHITE);
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.setCursor(10, 20);  // (x,y)
display.setTextColor(WHITE);
while (!buttonPressed) {
display.println("Live Mode");
display.display();
}
return;
}

void RecordMode() {
// display.fillRect(0, 0, 128, 64, WHITE);
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.setCursor(10, 20);  // (x,y)
display.setTextColor(WHITE);
while (!buttonPressed) {
display.println("Recording..");
display.display();
}
return;
}

void LapseModeSet() {

screen_Lapse();

FlashBox hours(1, 36, 63, 27, 200, 200); // Construct flashing box (Hours)
FlashBox mins(65, 36, 62, 27, 200, 200); // Construct flashing box (Minutes)
FlashBox TL_set(0, 0, 128, 64, 300, 300); // Construct TL Done flashing box
int mode = 0;  // 0 = hours selected   1 = minutes selected
int valuechange = 0;

encOld = 0;
buttonPressed = 0;
myEnc.write(0);
do {

do {

{
mode--;
if (mode < 0) mode = 0;
screen_Lapse();
}
{
mode++;
if (mode > 2) mode = 2;
screen_Lapse();
}

switch (mode)
{
case 0:
hours.Flasher();    // flash Hours Box
break;
case 1:
mins.Flasher();     // flash Minutes Box
break;
case 2:
TL_set.Flasher();   // flash whole screen Box
break;
}

checkSwitch();
if (buttonPressed)
{
buttonPressed = 0;
valuechange = 1;
if (mode == 0) myEnc.write(TL_hours);
if (mode == 1) myEnc.write(TL_mins);
screen_Lapse();
}

} while (!valuechange);

do {
if (mode == 0)   // Adjust Hours
{
display.drawRect(1, 36, 63, 27, WHITE);
screen_Lapse();
checkSwitch();
if (buttonPressed)
{
valuechange = 0;
buttonPressed = 0;
}
}

if (mode == 1)   // Adjust Minutes
{
display.drawRect(65, 36, 62, 27, WHITE);
screen_Lapse();
checkSwitch();
if (buttonPressed)
{
valuechange = 0;
buttonPressed = 0;
}
}

if (mode == 2)   // Quit to Main Menu
{

valuechange = 0;
buttonPressed = 0;
remainingSeconds = ((TL_hours * 60) * 60) + (TL_mins * 60);

}

} while (valuechange);

}

void LapseModeRun() {
//  Serial.begin(9600);
TotalSeconds = remainingSeconds;
int percent = 0;

do {

display.clearDisplay();  // Clear the display so we can refresh
display.setFont(&SMLFONT);  // Set a custom font
display.setTextSize(1);  // Set text size. We are using a custom font so you should always use the text size of 0
display.setTextColor(WHITE);
display.setCursor(0, 12);  // (x,y)
display.print("Running ");
display.setFont();
display.setCursor(0, 30);  // (x,y)
//        display.println("TIME REMAINING");  // Text or value to print
display.setCursor(0, 29);
display.println(" HOURS   MIN.    SEC.");
display.drawLine(0, 43, 128, 43, WHITE);  // Draw Horizontal line
display.drawLine(42, 43, 42, 64, WHITE);  // Draw Vertictal line
display.drawLine(84, 43, 84, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
TimeCalc(remainingSeconds);
//Serial.print(h); Serial.print(" ");Serial.print(m); Serial.print(" ");Serial.println(s);
display.setCursor(5, 62);
display.println(h);    // Hours
display.setCursor(54, 62);
display.println(m);      // Minutes
display.setCursor(97, 62);
display.println(s);      // Seconds

// Draw Progress Bar rectangle:
progress = abs((((float)remainingSeconds / (float)TotalSeconds) * 128) - 128);
percent = ((float)progress / 128) * 100;
display.drawRect(0, 22, 128, 1, WHITE);  // Draw rectangle (x,y,width,height,color)
display.fillRect(0, 21, progress, 3, WHITE);  // It draws from the location to down-right

//display.setFont(&FreeMonoBold12pt7b);  // Set a custom font

// Print variable with left alignment:
display.setFont();
display.setCursor(100, 5);
display.print(percent);
display.println("%");
//    display.setCursor(80, 5);
//    display.print(remainingSeconds);

display.display();  // Print everything we set previously

if (remainingSeconds == 0)
{
//display.getTextBounds("Running ",0,12,int x, int y, int ww, int hh);
display.fillRect(0, 0, 70, 20, BLACK);
display.setFont(&SMLFONT);
display.setCursor(0, 12);  // (x,y)
display.print("DONE ");
display.display();
delay(50000);
}

remainingSeconds--;             //          TICK!

checkSwitch();      // check encoder switch
if (buttonPressed) {
buttonPressed = 0;
display.clearDisplay();
display.display();
return;
}

}

void checkSwitch() {
// Check Encoder Switch

if (buttonState != oldButtonState)
{
if (millis () - buttonPressTime >= debounceTime)
{ // debounce
buttonPressTime = millis ();                      // when we closed the switch
oldButtonState =  buttonState;                    // remember for next time
if (buttonState == LOW)
{
//        Serial.println ("Button pressed");               // DEBUGGING: print that button has been closed
buttonPressed = 1;
}
else
{
//        Serial.println ("Button released");               // DEBUGGING: print that button has been opened
buttonPressed = 0;
}
}  // end if debounce time up
} // end of state change
}

void screen_Lapse() {
display.setFont(&SMLFONT);
display.setTextSize(0);
display.clearDisplay();
display.drawRect(0, 0, 128, 64, WHITE);  // Draw Border
display.setCursor(4, 15);  // (x,y)
display.setTextColor(WHITE);
display.println("Set Timelapse");
display.setFont();
display.setCursor(0, 25);
display.println("   HOURS     MINUTES");
display.drawLine(0, 35, 128, 35, WHITE);  // Draw Horizontal line
display.drawLine(64, 35, 64, 64, WHITE);  // Draw Vertictal line
display.setFont(&SMLFONT);
display.setCursor(17, 55);
display.println(TL_hours);
display.setCursor(85, 55);
display.println(TL_mins);
display.display();

}

void drawgrid() {
display.drawRect(0, 0, 128, 64, WHITE);
display.drawLine(64, 0, 64, 128, WHITE);
display.drawLine(0, 32, 128, 32, WHITE);
}

// Adafruit Graphic library code references

// Draw triangle:
// display.drawTriangle(40,40,   50,20,   60,40, WHITE);  // Draw triangle. X, Y coordinates for three corner points defining the triangle, followed by a color

// Draw filled triangle:
//display.fillTriangle(0,35,   15,45,   30,63, WHITE);  // Draw filled triangle. X, Y coordinates for three corner points defining the triangle, followed by a color

// Draw line:
//  display.drawLine(0, 18, 128, 18, WHITE);  // Draw line (x0,y0,x1,y1,color)

// Draw circle:
// display.drawCircle(47, 36, 20, WHITE);  //  Draw circle (x,y,radius,color). X and Y are the coordinates for the center point

// Draw a filled circle:
// display.fillCircle(12, 27, 10, WHITE);  // Draw filled circle (x,y,radius,color). X and Y are the coordinates for the center point

// Draw rectangle:
// display.drawRect(58, 0, 18, 18, WHITE);  // Draw rectangle (x,y,width,height,color)
// It draws from the location to down-right

// Draw rounded rectangle and fill:
// display.fillRoundRect(58, 0, 18, 18, 5, WHITE);  // Draw filled rounded rectangle (x,y,width,height,color)
// It draws from the location to down-right
// Draw rounded rectangle:
//display.drawRoundRect(79, 37, 49, 27, 8, WHITE);  // Draw rounded rectangle (x,y,width,height,radius,color)
// It draws from the location to down-right

// Print variable with right alignment:
//  display.setCursor(83, 60);  // (x,y)
//  display.println(string);  // Text or value to print

//

//  // Convert Variable1 into a string, so we can change the text alignment to the right:
//  // It can be also used to add or remove decimal numbers.
//  char string[10];  // Create a character array of 10 characters
//  // Convert float to a string:
//  dtostrf(Variable1, 3, 0, string);  // (<variable>,<amount of digits we are going to use>,<amount of decimal digits>,<string name>)```

24. Where in the code did you set 18:13? Is there a contant? If so does it have an L at the end to say it is a long value? Did you try to cast it there?

My guess it has to do with the line:
Code:
`       remainingSeconds = ((TL_hours * 60) * 60) + (TL_mins * 60);`
Which I believe remainingSeconds is defined: uint16_t remainingSeconds = 0;
So it will overflow with your 18:13...

25. Kurt,

Correct. The time is set in the LapseModeSet() function. It has to be a variable I can dial in. I tried setting remaingSeconds to uint32_t, but that causes problems much earlier.. at 9hrs 6minutes

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•