0

I am making a 24 hour clock with a four digit seven segment display based on an arduino uno with the SevSeg.h library. Will recreate with a nano later on. Currently, the timer ticks up nicely from 0 to 23.59, but does not reset back to 0 like I want it to. It cuts back to around 21 something for a few cycles before defaulting back to 0 and no longer counting up.

Later, I will implement an actual way to set the clock so I can wear it and actually use it but for now, it's a counter problem.

Also, I am aware that I should use an external RTC if I want it to be accurate over longer periods of time, but this is just a proof of concept and I really do not care about longevity.

Here's the code so far, it's sped up considerably so I don't have to wait 24 hours for testing purposes:

#include "SevSeg.h"
SevSeg sevseg;

int startTime = 0;
int sec;
int minute;

void setup(){
  
  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = true; 
  bool updateWithDelaysIn = true;
  byte hardwareConfig = COMMON_ANODE; 
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(100);

  Serial.begin(9600);
}

void loop(){
    
  sevseg.refreshDisplay();

  long now = millis() - startTime;
  now /= 50; //1000 for seconds, 50 for testing so I don't have to wait fucking forever
  sec = now % 60;
  minute = 100*(now / 60);

  int displayNum = sec + minute;

  if(displayNum > 2359){
    startTime = millis();
    now = millis();
    displayNum = 0;
  }

  sevseg.setNumber(displayNum,2);
  Serial.println(displayNum);
  
}

It is supposed to count from 0 to 2359 before reverting back to zero and counting up again. Just now while writing this I noticed that after about 5 minutes or so, it started counting up again after being stuck at 0 and later "--.--". Still not ideal ¯_(ツ)_/¯

2 Answers2

0

This works fine, just a little simplification

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

void loop(){
  static uint32_t startTime;
  uint32_t now = (millis() - startTime)/100;  //  /1000 for seconds
  
  byte sec = now % 60;
  byte minute = now / 60;
  uint16_t displayNum = 100 * minute + sec;

  if(displayNum > 259){ // 2359 for a whole day
    startTime = millis();
    displayNum = 0;
  }
  static uint16_t olddisplay=9999; 
  if (olddisplay != displayNum) Serial.println(olddisplay=displayNum);
}

All variables can be local (very few are static to keep their values for the next round)

Data types are important in C/C++

datafiddler
  • 1,755
  • 3
  • 17
  • 30
0

I did manage to make it work. I changed the "int startTime" to a uint32_t and I moved "sevseg.refreshDisplay()" to right above setNumber. This seemed to solve the issue and it is now counting correctly multiple times. Underneath is the new code, which works well:

#include "SevSeg.h"
SevSeg sevseg;

uint32_t startTime = 0;
int sec;
int minute;

void setup(){
  
  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = true; 
  bool updateWithDelaysIn = true;
  byte hardwareConfig = COMMON_ANODE; 
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(100);

  Serial.begin(9600);
}

void loop(){

  long now = millis() - startTime;
  now /= 50; //1000 for seconds
  sec = now % 60;
  minute = 100*(now / 60);

  int displayNum = sec + minute;

  if(displayNum > 2359){
    startTime = millis();
    displayNum = 0;
  }

  sevseg.refreshDisplay();
  sevseg.setNumber(displayNum,2);
  Serial.println(displayNum);
  
}