Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 34

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

  1. #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. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,092
    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
    Last edited by manitou; 01-10-2018 at 11:23 AM.

  3. #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..


    Quote Originally Posted by manitou View Post
    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. #4
    countdown starting at 9 hours 6 minutes..

    Attachment 12571

    countdown starting at 9 hours 7 minutes..

    Attachment 12572

    perplexing....

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,064
    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. #6
    Quote Originally Posted by KurtE View Post
    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. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,064
    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. #8
    Quote Originally Posted by KurtE View Post
    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. #9
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,025
    have you tried specifying uint32_t instead of unsigned long int? you didnt specify your mcu.

  10. #10
    Quote Originally Posted by tonton81 View Post
    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. #11
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,025
    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.
    try doing adding UL to your calculations.. example: 3600UL
    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. #12
    Senior Member
    Join Date
    Feb 2015
    Location
    Finland
    Posts
    120
    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. #13
    okay, 90% of that is completely over my head, but I'll try it and feedback...

  14. #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. #15
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,253
    Quote Originally Posted by vfxwolf View Post
    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. #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. #17
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,253
    Quote Originally Posted by vfxwolf View Post
    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. #18
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,025
    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. #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:
    
    
    
    /*
    
    
      List of fonts: https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts
    
    
    
    
    
    
      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 <Adafruit_SSD1306.h>  // Include Adafruit_SSD1306 library to drive the display
    #include <Metro.h>
    #include <Encoder.h>
    #include <Bounce2.h>
    #include <Fonts/FreeSans9pt7b.h>  // Add a custom font
    
    
    Adafruit_SSD1306 display;  // Create display
    
    
    
    
    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;
    
    
    //                                          Menu Variables
    boolean hlight = 0;
    int menuMax = 5;
    int menuMode = 0;
    int menuDelay = 500;
    Metro blinkon = Metro(1000);
    Metro blinkoff = Metro(1000);
    Metro debounce = Metro(10);
    
    
    //                                          Keyframe Variables
    
    
    char StartingKey;
    char EndingKey;
    
    
    //                                          Encoder Variables
    
    
    Encoder myEnc(2, 3);
    int encState;
    int encRead;                              //current encoder read
    int encOld;                               //previous encoder read
    
    
    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;
          blinkon.interval(OnTime);
          blinkon.reset();
          blinkoff.interval(OffTime);
          blinkoff.reset();
        }
    
    
        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
    
    
    void getMenuMode() {
      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 {
        encRead = myEnc.read() >> 2; // bitwise divide by 4
    
    
        if (encRead < encOld)
        {
          mode--;
          if (mode < 1) mode = 1;
          encOld = encRead;
        }
    
    
    
    
        if (encRead > encOld)
        {
          mode++;
          if (mode > menuMax) mode = menuMax;
          encOld = encRead;
        }
    
    
    
    
    
    
        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();
              delay(menuDelay);
              menuMode = 4;
              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();
              delay(menuDelay);
              menuMode = 5;
              LapseModeRun();
            }
            break;
    
    
        }
      } while (menuMode == 0);
    }
    
    
    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 {
    
    
          encRead = myEnc.read() >> 2; // bitwise divide by 4
          if (encRead < encOld)
          {
            mode--;
            if (mode < 0) mode = 0;
            encOld = encRead;
            screen_Lapse();
          }
          if (encRead > encOld)
          {
            mode++;
            if (mode > 2) mode = 2;
            encOld = encRead;
            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);
            encRead = myEnc.read() >> 2; // bitwise divide by 4
            TL_hours = constrain(encRead, 0, 100);
            screen_Lapse();
            checkSwitch();
            if (buttonPressed)
            {
              valuechange = 0;
              buttonPressed = 0;
            }
          }
    
    
          if (mode == 1)   // Adjust Minutes
          {
            display.drawRect(65, 36, 62, 27, WHITE);
            encRead = myEnc.read() >> 2; // bitwise divide by 4
            TL_mins = constrain(encRead, 0, 59);
            screen_Lapse();
            checkSwitch();
            if (buttonPressed)
            {
              valuechange = 0;
              buttonPressed = 0;
            }
          }
    
    
          if (mode == 2)   // Quit to Main Menu
          {
    
    
            valuechange = 0;
            buttonPressed = 0;
            menuMode = 0;
            remainingSeconds = ((TL_hours * 60) * 60) + (TL_mins * 60);
    
    
          }
    
    
        } while (valuechange);
    
    
    
    
    
    
    
    
    
    
      } while (menuMode == 4);
    
    
    }
    
    
    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);
          menuMode = 0;
        }
    
    
    
    
        remainingSeconds--;             //          TICK!
    
    
    
    
    
    
    
    
    
    
        checkSwitch();      // check encoder switch
        if (buttonPressed) {
          buttonPressed = 0;
          menuMode = 0;
          display.clearDisplay();
          display.display();
          return;
        }
      } while (menuMode == 5);
    
    
    
    
    }
    
    
    void checkSwitch() {
      // Check Encoder Switch
    
    
      byte buttonState = digitalRead(EncButton);
      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.
    Click image for larger version. 

Name:	IMG_5925.jpg 
Views:	24 
Size:	111.4 KB 
ID:	12575Click image for larger version. 

Name:	IMG_7986.jpg 
Views:	28 
Size:	98.3 KB 
ID:	12574

    Again, the problem is the OLED will not display proper countdown starting higher than 18 hrs. 12 minutes.
    Last edited by vfxwolf; 01-10-2018 at 02:43 PM.

  20. #20
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,064
    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. #21
    Quote Originally Posted by KurtE View Post
    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:
    
    
    
    /*
    
    
      List of fonts: https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts
    
    
    
    
    
    
      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 <Adafruit_SSD1306.h>  // Include Adafruit_SSD1306 library to drive the display
    #include <Metro.h>
    #include <Encoder.h>
    #include <Bounce2.h>
    #include <Fonts/FreeSans9pt7b.h>  // Add a custom font
    
    
    Adafruit_SSD1306 display;  // Create display
    
    
    
    
    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;
    
    
    //                                          Menu Variables
    boolean hlight = 0;
    int menuMax = 5;
    int menuMode = 0;
    int menuDelay = 500;
    Metro blinkon = Metro(1000);
    Metro blinkoff = Metro(1000);
    Metro debounce = Metro(10);
    
    
    //                                          Keyframe Variables
    
    
    char StartingKey;
    char EndingKey;
    
    
    //                                          Encoder Variables
    
    
    Encoder myEnc(2, 3);
    int encState;
    int encRead;                              //current encoder read
    int encOld;                               //previous encoder read
    
    
    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;
          blinkon.interval(OnTime);
          blinkon.reset();
          blinkoff.interval(OffTime);
          blinkoff.reset();
        }
    
    
        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
    
    
    void getMenuMode() {
      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 {
        encRead = myEnc.read() >> 2; // bitwise divide by 4
    
    
        if (encRead < encOld)
        {
          mode--;
          if (mode < 1) mode = 1;
          encOld = encRead;
        }
    
    
    
    
        if (encRead > encOld)
        {
          mode++;
          if (mode > menuMax) mode = menuMax;
          encOld = encRead;
        }
    
    
    
    
    
    
        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();
              delay(menuDelay);
              menuMode = 4;
              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();
              delay(menuDelay);
              menuMode = 5;
              LapseModeRun();
            }
            break;
    
    
        }
      } while (menuMode == 0);
    }
    
    
    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 {
    
    
          encRead = myEnc.read() >> 2; // bitwise divide by 4
          if (encRead < encOld)
          {
            mode--;
            if (mode < 0) mode = 0;
            encOld = encRead;
            screen_Lapse();
          }
          if (encRead > encOld)
          {
            mode++;
            if (mode > 2) mode = 2;
            encOld = encRead;
            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);
            encRead = myEnc.read() >> 2; // bitwise divide by 4
            TL_hours = constrain(encRead, 0, 100);
            screen_Lapse();
            checkSwitch();
            if (buttonPressed)
            {
              valuechange = 0;
              buttonPressed = 0;
            }
          }
    
    
          if (mode == 1)   // Adjust Minutes
          {
            display.drawRect(65, 36, 62, 27, WHITE);
            encRead = myEnc.read() >> 2; // bitwise divide by 4
            TL_mins = constrain(encRead, 0, 59);
            screen_Lapse();
            checkSwitch();
            if (buttonPressed)
            {
              valuechange = 0;
              buttonPressed = 0;
            }
          }
    
    
          if (mode == 2)   // Quit to Main Menu
          {
    
    
            valuechange = 0;
            buttonPressed = 0;
            menuMode = 0;
            remainingSeconds = ((TL_hours * 60) * 60) + (TL_mins * 60);
    
    
          }
    
    
        } while (valuechange);
    
    
    
    
    
    
    
    
    
    
      } while (menuMode == 4);
    
    
    }
    
    
    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);
          menuMode = 0;
        }
    
    
    
    
        remainingSeconds--;             //          TICK!
    
    
    
    
    
    
    
    
    
    
        checkSwitch();      // check encoder switch
        if (buttonPressed) {
          buttonPressed = 0;
          menuMode = 0;
          display.clearDisplay();
          display.display();
          return;
        }
      } while (menuMode == 5);
    
    
    
    
    }
    
    
    void checkSwitch() {
      // Check Encoder Switch
    
    
      byte buttonState = digitalRead(EncButton);
      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. #22
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,092
    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. #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:
    
    
    
    /*
    
    
      List of fonts: https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts
    
    
    
    
    
    
      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 <Adafruit_SSD1306.h>  // Include Adafruit_SSD1306 library to drive the display
    #include <Metro.h>
    #include <Encoder.h>
    #include <Bounce2.h>
    #include <Fonts/FreeSans9pt7b.h>  // Add a custom font
    
    
    Adafruit_SSD1306 display;  // Create display
    
    
    
    
    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;
    
    
    //                                          Menu Variables
    boolean hlight = 0;
    int menuMax = 5;
    int menuMode = 0;
    int menuDelay = 500;
    Metro blinkon = Metro(1000);
    Metro blinkoff = Metro(1000);
    Metro debounce = Metro(10);
    
    
    //                                          Keyframe Variables
    
    
    char StartingKey;
    char EndingKey;
    
    
    //                                          Encoder Variables
    
    
    Encoder myEnc(2, 3);
    int encState;
    int encRead;                              //current encoder read
    int encOld;                               //previous encoder read
    
    
    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;
          blinkon.interval(OnTime);
          blinkon.reset();
          blinkoff.interval(OffTime);
          blinkoff.reset();
        }
    
    
        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
    
    
    void getMenuMode() {
      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 {
        encRead = myEnc.read() >> 2; // bitwise divide by 4
    
    
        if (encRead < encOld)
        {
          mode--;
          if (mode < 1) mode = 1;
          encOld = encRead;
        }
    
    
    
    
        if (encRead > encOld)
        {
          mode++;
          if (mode > menuMax) mode = menuMax;
          encOld = encRead;
        }
    
    
    
    
    
    
        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();
              delay(menuDelay);
              menuMode = 4;
              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();
              delay(menuDelay);
              menuMode = 5;
              LapseModeRun();
            }
            break;
    
    
        }
      } while (menuMode == 0);
    }
    
    
    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 {
    
    
          encRead = myEnc.read() >> 2; // bitwise divide by 4
          if (encRead < encOld)
          {
            mode--;
            if (mode < 0) mode = 0;
            encOld = encRead;
            screen_Lapse();
          }
          if (encRead > encOld)
          {
            mode++;
            if (mode > 2) mode = 2;
            encOld = encRead;
            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);
            encRead = myEnc.read() >> 2; // bitwise divide by 4
            TL_hours = constrain(encRead, 0, 100);
            screen_Lapse();
            checkSwitch();
            if (buttonPressed)
            {
              valuechange = 0;
              buttonPressed = 0;
            }
          }
    
    
          if (mode == 1)   // Adjust Minutes
          {
            display.drawRect(65, 36, 62, 27, WHITE);
            encRead = myEnc.read() >> 2; // bitwise divide by 4
            TL_mins = constrain(encRead, 0, 59);
            screen_Lapse();
            checkSwitch();
            if (buttonPressed)
            {
              valuechange = 0;
              buttonPressed = 0;
            }
          }
    
    
          if (mode == 2)   // Quit to Main Menu
          {
    
    
            valuechange = 0;
            buttonPressed = 0;
            menuMode = 0;
            remainingSeconds = ((TL_hours * 60) * 60) + (TL_mins * 60);
    
    
          }
    
    
        } while (valuechange);
    
    
    
    
    
    
    
    
    
    
      } while (menuMode == 4);
    
    
    }
    
    
    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);
          menuMode = 0;
        }
    
    
    
    
        remainingSeconds--;             //          TICK!
    
    
    
    
    
    
    
    
    
    
        checkSwitch();      // check encoder switch
        if (buttonPressed) {
          buttonPressed = 0;
          menuMode = 0;
          display.clearDisplay();
          display.display();
          return;
        }
      } while (menuMode == 5);
    
    
    
    
    }
    
    
    void checkSwitch() {
      // Check Encoder Switch
    
    
      byte buttonState = digitalRead(EncButton);
      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. #24
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,064
    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. #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
  •