6 digit 7 segment 2812 clock/stopwatch

I have created a 6-digit 7 segment display using a string of 2812 LEDs. I have taken code from projects that have 4 digits.

I am battling to achieve an end point for this project. all the hardware works well and lights are fine. Im trying to get some help with the coding to create a stopwatch that counts up from zero
there are 168 addressable LED all connected together. i dont need a RTC however it would be nice add.

Any help would be appreciated.

Segements are as follows (tried drawing with 4 LED per segment but forum didnt like the post

.....3.....

4.........2

......1....

5.........7

....6.....

Is that diagram a variant of the standard 7 segment labelling pattern:

image

Anyway, how far have you got ? Show a schematic and show a simple example sketch where you light one segment, say the top segment of the first digit.

EDIT

I guess if you have 168 addressable positions and you have 6 digits each made up of seven segments and each segment consists of 4 of the addressable leds, the first step is to devise a structure to represent the whole display. Maybe a 3 dimensional array such as uint8_t digit [6] [7] [4]
where the first dimension is the digit position 0 to 5, the second dimension is the segment number 0 to 6 and the third dimension is the four addresses of the leds which make up the segment.

I have tried to do this:

as a new user i cant upload attachments - segment points are when referencing your image.
G=1, B=2, A=3, F=4, E=5, D=6, C=7
HH:MM.SS
hours are first digits in line.
you are correct with the number of lights per segments

const uint32_t digits[10] = {
0b00001111111111111111111111110000, // 0
0b00001111000000000000000011110000, // 1
0b00000000111111110000111111111111, // 2
0b00001111111100000000111111111111, // 3
0b00001111000000001111000011111111, // 4
0b00001111111100001111111100001111, // 5
0b00001111111111111111111100001111, // 6
0b00001111000000000000111111110000, // 7
0b00001111111111111111111111111111, // 8
0b00001111111100001111111111111111, // 9

Im pretty green with coding, not too bad with building electronics and basic level to reading what others write

So it looks like you have got quite far.
You have a representation of leds which have to be on to form each of the numbers 0 to 9.
So you have to show the code which reads that table to say write a number 7 in the first digit position on your display.

You tell something works and LEDs are shining. As already requested, schematics would be helpful but especially the code. Most helpers don't have chrystal balls.

Hi, @gingergod
Welcome to the forum.

Your code and schematic would make this a whole lot easier.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

@TomGeorge thanks for the direction.
I believe that i have uploaded both a pic of the schematic and the code that i have gotten to currently (borrowed from a source with some edits.


ModularLEDDisplay_168_led_28_LED_per_number.ino (7.5 KB)

thanks for the pointers @Railroader . i have added a few elements below in a reply to tom.

@6v6gt thanks for that. i have been able to upload my code now in a reply in one of the comments now

If you mean that snippet of an array definition in post #3 that is not enough. It has to be a complete and runnable program (sketch).
If you have nothing else, post a link to the code you are using as a basis for your project.

ModularLEDDisplay_168_led_28_LED_per_number.ino (7.5 KB)
I uploaded this a little higher up be here it is again

Thanks again

Pleasd read the advice how to get the best from this forum.
Including .INO files is not the way to do it. Phones, tablets are often used by helpers. Then such links are useless as those devices can read .INO files. Also no helper enjoys filling up disc space with files from members.

apologies @Railroader , i thought i was following guidelines by uploading the file below is the text of the code

/**
 * Modular 7-segment display using (WS2812B) programmable LED strip
 * Copyright (c) 2022 Playful Technology
 */

// INCLUDES
// Interfacing to programmable LED strips, see https://fastled.io/
#include <FastLED.h>
// For debouncing button input, see https://github.com/thomasfredericks/Bounce2
#include <Bounce2.h>

// DEFINES
// How many LEDs are used in each digit
#define NUM_LEDS_PER_DIGIT 28
// Total number of LEDs in the strip
#define NUM_LEDS 168
// The pin which is connected to the DataIn of the LED strip
#define DATA_PIN 12
// If defined, timer shows minutes and seconds MM:SS, rather than seconds SSSS
#define DISPLAY_HHMMSS

// CONSTANTS
// The following array defines the sequence of LEDs that should be lit to represent each digit 0-9
// This will vary depending on the order in which the strip has been physically wired through
// the segments, the number of LEDs in each segment, whether there are any unused LEDs in the strip
// (e.g. between digits) etc.
// Segments of a 7-segment display are generally labelled as follows:
//    /-A-\
//    F   B
//    --G-/
//    E   C
//    \-D-/
// The way I've wired the strips is:
// - Strip is fed through the segments in the order G->B->A->F->E->D->C (then onto the next digit)
// - There are 4 LEDs in each segment
// - There is a single unused LED in the strip between segments F and E
// - This makes the total length of 29 LEDs in the strip for each digit
// - I'm packing these into a single 32-bit integer, and since bitwise operations are MSB, this will
// be counted from the right-hand side, and then padded at the front with 3x0s up to 32 bits.
// e.g. 0b000ccccddddeeee0ffffaaaabbbbgggg
// If you have an even bigger display containing more LEDs, it might be necessary to pack them into a
// 64-bit integer instead, i.e. uint64_t.
const uint32_t digits[10] = {
  0b00001111111111111111111111110000, // 0
  0b00001111000000000000000011110000, // 1
  0b00000000111111110000111111111111, // 2
  0b00001111111100000000111111111111, // 3
  0b00001111000000001111000011111111, // 4
  0b00001111111100001111111100001111, // 5
  0b00001111111111111111111100001111, // 6
  0b00001111000000000000111111110000, // 7
  0b00001111111111111111111111111111, // 8
  0b00001111111100001111111111111111, // 9
};
// Input pins
const byte leftPin = 6;
const byte startPin = 13;
const byte rightPin = 4;

// GLOBALS
// The array of RGB values assigned to each LED in the strip
CRGB leds[NUM_LEDS];

// Bounce objects to read debounced button input
Bounce2::Button btnStart = Bounce2::Button();
Bounce2::Button btnLeft = Bounce2::Button();
Bounce2::Button btnRight = Bounce2::Button();

// The time at which the counter was (most recently) started
unsigned long startTime;

// Duration is specified in ms. So 1000 = 1 second, 60000 = 1 minute, etc.
unsigned long timerDuration = 0;

// Keep track of elapsed time from previous start/stop cycles
unsigned long cumulativeElapsedTime;

// Keep track of the current state of the device
enum State {Inactive, Active};
State state = State::Inactive;
// Count direction
enum Mode {CountUp, CountDown};
Mode mode = Mode::CountUp;

// FUNCTIONS
// Set the values in the LED strip corresponding to a particular display/value 
void setDigit(int display, int val, CHSV colour){
  for(int i=0;i<NUM_LEDS_PER_DIGIT; i++){
    colour.v = bitRead(digits[val], i) * 255;
    leds[display*NUM_LEDS_PER_DIGIT + i] = colour;
  }
}

void Start(){
  Serial.println(F("Timer activated!"));
  state = State::Active;
  startTime = millis();
}

void Stop() {
  Serial.println(F("Timer stopped"));
  // Add the length of time elapsed since the timer was last started to the total time elapsed
  cumulativeElapsedTime += (millis() - startTime);
  state = State::Inactive;
}

void Reset(){
  Serial.println(F("Timer reset"));
  cumulativeElapsedTime = 0;
  state = State::Inactive;
}
// This function runs once when the program first starts
void setup() {

  // Initialise a serial connection, used only for debugging
  Serial.begin(115200);
  Serial.println(__FILE__ __DATE__);
 
// Initialise the LED strip
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);

  // Configure the debounced inputs
  btnStart.attach(startPin, INPUT_PULLUP);
  btnLeft.attach(leftPin, INPUT_PULLUP);
  btnRight.attach(rightPin, INPUT_PULLUP);

  state = State::Inactive;
}


// This function runs over and over
void loop() {

  // Check whether any buttons have been pressed
  btnStart.update();
  btnLeft.update();
  btnRight.update();

  // Grab the current timestamp
  unsigned long currentTime = millis();

  // Calculate the value to be displayed
  static long timeValue = 0;
  // The colour hue in which the time will be displayed
  int timeHue = 170;

  // What to do next depends on the current state of the device
  if(state == State::Active) {

    if(mode == Mode::CountDown) {
      // The time remaining is the total game duration, less the time spent during the
      // current period of play, less the time elapsed during any previous sessions
      // or other deductions
      timeValue = timerDuration - (currentTime - startTime) - cumulativeElapsedTime;
     
      // Map colour hue from green -> red based on fraction of time remaining
      timeHue = map(timeValue, 0, timerDuration, 0, 100);
     
      // Countdown has reached zero
      if(timeValue <= 0) {
        timeValue = 0;
        state = State::Inactive;
      }
    }
    else if(mode == Mode::CountUp) {
      // Time is however long since we started counting, plus any previous existing time
      timeValue = (currentTime - startTime) + cumulativeElapsedTime;
     
      // Constant colour
      timeHue = 0;
    }

    // Toggle whether timer is active
    if(btnStart.pressed()) {
      Stop();
    }    
  }
 
  else if(state == State::Inactive){

    // Cycle colour hue while paused (BPM, from_value, to_value)
    timeHue = beatsin8(20, 0, 40);

    // Subtract from countdown duration
    if(btnLeft.pressed()) {
      if(timerDuration >= 60000) { timerDuration -= 60000; }
      timeValue = timerDuration;
      Reset();
    }
    // Add to countdown duration
    if(btnRight.pressed()) {
      timerDuration += 60000;
      timeValue = timerDuration;
      Reset();
    }
    // Start timer
    if(btnStart.pressed()) {

      // Set mode depending on whether duration had been set
      if(timerDuration == 0) { mode = Mode::CountUp; }
      else { mode = Mode::CountDown; }

      // Activate the counter
      Start();
    }
  }

  // Display as mm:ss
  #ifdef DISPLAY_MMSS
    // Use modulo to calculate "remainder" seconds
    int seconds = (timeValue / 1000) % 60;
    int minutes = timeValue / 60000;
    // Units
    setDigit(3, seconds%10, CHSV(timeHue, 255, 255));
    // Tens
    setDigit(2,(seconds/10)%10, CHSV(timeHue, 255, 255));
    // Hundreds
    setDigit(1, minutes%10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(0,(minutes/10)%10, CHSV(timeHue, 255, 255));
  // Display in seconds
  #else
    // Units
    setDigit(3, (timeValue / 1000) % 10, CHSV(timeHue, 255, 255));
    // Tens
    setDigit(2, (timeValue / 10000) % 10, CHSV(timeHue, 255, 255));
    // Hundreds
    setDigit(1, (timeValue / 100000) % 10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(0, (timeValue / 1000000) % 10, CHSV(timeHue, 255, 255));
  #endif

  // Send the updated values to the LED strip
  FastLED.show();
 
  delay(20);
}

Perfect.

OK. Does that code work at all with your 168 leds or maybe explain what goes wrong ?
Can you, for instance, show the first 4 digits correctly with the original code ?

How have you handled this and is your display the same with an unused led ? :

This is how i tried to change things and i have success in getting 4 digits to show but it seem buggy as the Arduino continues to disconnect when the code is uploaded

// DEFINES
// How many LEDs are used in each digit
#define NUM_LEDS_PER_DIGIT 28
// Total number of LEDs in the strip
#define NUM_LEDS 168
// The pin which is connected to the DataIn of the LED strip
#define DATA_PIN 12
// If defined, timer shows minutes and seconds MM:SS, rather than seconds SSSS
#define DISPLAY_HHMMSS

You say you only see 4 digits, right? And you want 6, right? Well, then you have to program that extra 2 digits here:

  // Display as mm:ss
  #ifdef DISPLAY_MMSS
    // Use modulo to calculate "remainder" seconds
    int seconds = (timeValue / 1000) % 60;
    int minutes = timeValue / 60000;
    // Units
    setDigit(3, seconds%10, CHSV(timeHue, 255, 255));
    // Tens
    setDigit(2,(seconds/10)%10, CHSV(timeHue, 255, 255));
    // Hundreds
    setDigit(1, minutes%10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(0,(minutes/10)%10, CHSV(timeHue, 255, 255));
  // Display in seconds
  #else
    // Units
    setDigit(3, (timeValue / 1000) % 10, CHSV(timeHue, 255, 255));
    // Tens
    setDigit(2, (timeValue / 10000) % 10, CHSV(timeHue, 255, 255));
    // Hundreds
    setDigit(1, (timeValue / 100000) % 10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(0, (timeValue / 1000000) % 10, CHSV(timeHue, 255, 255));
  #endif

Something like:
setDigit(4,(timeValue/100)%10,CHSV(timeHue,255,255));
etc..

6 digits light up now thanks so much - this is the new code
once i upload top the board it will DC from pc almost instantly


  // Display as mm:ss
  #ifdef DISPLAY_MMSS
    // Use modulo to calculate "remainder" seconds
    int hours = (timeValue / 3,600,000);
    int seconds = (timeValue / 1000) % 60;
    int minutes = timeValue / 60000;
    // Units
    setDigit(5, seconds%10, CHSV(timeHue, 255, 255));
    // Tens
    setDigit(4,(seconds/10)%10, CHSV(timeHue, 255, 255));
    // Hundreds
    setDigit(3, minutes%10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(2,(minutes/10)%10, CHSV(timeHue, 255, 255));
     // Hundreds
    setDigit(1, hours%10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(0,(hours/10)%10, CHSV(timeHue, 255, 255));
  // Display in seconds
  #else
    // Units
    setDigit(5, (timeValue / 1000) % 10, CHSV(timeHue, 255, 255));
    // Tens
    setDigit(4, (timeValue / 10000) % 10, CHSV(timeHue, 255, 255));
    // Hundreds
    setDigit(3, (timeValue / 100000) % 10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(2, (timeValue / 1000000) % 10, CHSV(timeHue, 255, 255));
    
    setDigit(1, (timeValue / 100000) % 10, CHSV(timeHue, 255, 255));
    // Thousands
    setDigit(0, (timeValue / 1000000) % 10, CHSV(timeHue, 255, 255));
  #endif

  // Send the updated values to the LED strip
  FastLED.show();
 
  delay(20);

Disconnect ? Power issue? Post a link to the led strip data sheet.

@6v6gt i think that it was a bad loop somewhere in there as when i can finally get it reset and a different program on the board then its ok again

when you say data sheet do you mean the specs on the led strip? this is the specs on the strip that i use if that's what you were after

https://www.jaycar.com.au/medias/sys_master/images/images/9700136517662/XC4390-dataSheetMain.pdf