Go Down

Topic: LED clock with different time speed (Read 4396 times) previous topic - next topic

Graynomad

#15
Sep 19, 2010, 04:32 pm Last Edit: Sep 19, 2010, 04:44 pm by graynomad Reason: 1
Oops, should have been

Code: [Select]
shiftOut(datapin, clockpin, MSBFIRST, segdisplay[digits[x]]);

Note the segdisplay[] instead of segdisplay(), the compiler thought segdisplay was a function not an array. I think that will work.

Sorry I can't work from fuzzy photos and youtube clips, did I miss something on those links because I don't see enough info there to build this, just some vague descriptions. Anyway an actual correct schematic is needed.

I know it's frustrating, welcome to the embedded programming world.

Rob
Rob Gray aka the GRAYnomad www.robgray.com

sinuslinus

#16
Sep 20, 2010, 01:44 am Last Edit: Sep 20, 2010, 01:45 am by sinuslinus Reason: 1
Quote
Sorry I can't work from fuzzy photos and youtube clips, did I miss something on those links because I don't see enough info there to build this, just some vague descriptions. Anyway an actual correct schematic is needed.

The last two are wired the same. And there are resistors on all segments.

sinuslinus

I tried changing as below and now the seconds are counting alright but at 24 it stops counting. So solved one problem, but created another.

Code: [Select]
void loop()

{
   seconds++;                      // counting
  if (seconds > 59){
     seconds = 0;
     minutes++;
  if (minutes > 59) {
     minutes = 0;
     hours++;
  if (hours > 23) {
    hours = 0;
  }
  if(hours == 0) hours = 24;
  if(hours > 24) hours -= 24;
{

Graynomad

Hi linus,

The circuit looks good.

You've removed half of the braces, if you properly indent the result you get this

Code: [Select]

  seconds++;                      // counting
  if (seconds > 59) [glow]{[/glow]
     seconds = 0;
     minutes++;
     if (minutes > 59) {
        minutes = 0;
        hours++;
        if (hours > 23) {
          hours = 0;
        }
        if(hours == 0) hours = 24;
        if(hours > 24) hours -= 24;
     }


Note the highlighted }, how on earth did it compile with the unmatched braces, or is there one further down in the code, in which case anything could be happening.

This I don't think you need

Code: [Select]
if(hours == 0) hours = 24;
        if(hours > 24) hours -= 24;


If it works it's just covering up another fault somewhere.

Try your modified version with correct braces

Code: [Select]
  if (seconds > 59) {
     seconds = 0;
     minutes++;
     if (minutes > 59) {
        minutes = 0;
        hours++;
        if (hours > 23) {
          hours = 0;
        }
      }
   }


And if you get a compiler error remove any extra braces below this.
Rob Gray aka the GRAYnomad www.robgray.com

sinuslinus

This is what I am running now. It counts seconds from 00 to 23 and then starts again from 00. No shiftdown on the other displays.
I don't get why it counts to 24.

Code: [Select]
#define SECONDS 4
#define MINUTES 2
#define HOURS   0


unsigned int latchpin = 8;  // connect to pin 12 on the '595
unsigned int clockpin = 12; // connect to pin 11 on the '595
unsigned int datapin  = 11; // connect to pin 14 on the '595

unsigned int speed = 1000;    // used to control speed of counting
unsigned int seconds = 0;
unsigned int minutes = 0;
unsigned int hours = 0;
unsigned int digits[6];

unsigned int segdisp[10] = {63,6,91,79,102,109,125,7,127,111};

void setup() {

  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);

}

void loop(){
   seconds++;                      // counting
  if (seconds > 59){
     seconds = 0;
     minutes++;
  if (minutes > 59) {
     minutes = 0;
     hours++;
  if (hours > 23) {
    hours = 0;
  }
  digits[SECONDS] = seconds / 1  ;
  digits[SECONDS+1] = seconds % 10;
  digits[MINUTES]   = minutes / 10;
  digits[MINUTES+1] = minutes % 10;
  digits[HOURS]     = hours   / 10;
  digits[HOURS+1]   = hours   % 10;
 
  digitalWrite(latchpin, LOW);
  for (int x = 0; x < 6; x++)
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
  digitalWrite(latchpin, HIGH);


  delay (speed);
}
}
}


If I move up the brachets above
Code: [Select]
digits[SECONDS] = seconds / 1  ;

it mishaves as before.

Graynomad

Quote
digits[SECONDS] = seconds / 1  ;

There's an error, what happens to / 10? As it is when you do the
Code: [Select]
shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]); it will index out of the segdisp array once seconds exceeds 9 and get any old crap.

Here's your code properly indented

Code: [Select]
void loop(){
  seconds++;                      // counting
  if (seconds > 59) [glow]{
     seconds = 0;
     minutes++;
     if (minutes > 59) {
        minutes = 0;
        hours++;
        if (hours > 23) {
          hours = 0;
        }

     digits[SECONDS]   = seconds / 10;
     digits[SECONDS+1] = seconds % 10;
     digits[MINUTES]   = minutes / 10;
     digits[MINUTES+1] = minutes % 10;
     digits[HOURS]     = hours   / 10;
     digits[HOURS+1]   = hours   % 10;
 
     digitalWrite(latchpin, LOW);
     for (int x = 0; x < 6; x++)
          shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
     digitalWrite(latchpin, HIGH);


     delay (speed);
     }
  }[/glow]
}


Note that the majority of the code is inside the  "if (seconds > 59) {}" block and therefore only gets executed every time seconds > 59. That in itself isn't a bad thing, but the delay is inside this block as well and therefore only get run when seconds > 59.

Try moving the delay out of that block.

Code: [Select]
     
     digitalWrite(latchpin, HIGH);
     }
  }
  delay (speed);
}



Now, if it still doesn't do something sensible it's time to ignore the counting, comment shiftout line out, and write a quick test line like

Code: [Select]
     for (int x = 0; x < 6; x++)
          shiftOut(datapin, clockpin, MSBFIRST, segdisp[x]);


This should show the numbers from 0-6.

Rob Gray aka the GRAYnomad www.robgray.com

sinuslinus

Hi Rob, thanks so much for helping out but it still doesn't want to work.

Quote
digits[SECONDS] = seconds / 1  ;

There's an error, what happens to / 10? As it is when you do the

Sorry, missed copying the 0 to the post.

I tried your code and then the seconds count up to 23 and restarts (as before) and if I move out the delay it counts to 23 but much slower.

And if I test
Code: [Select]
void loop(){

     digitalWrite(latchpin, LOW);
     for (int x = 0; x < 6; x++)
          shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
     digitalWrite(latchpin, HIGH);

delay (speed);
}

all zeros are displayed.

Graynomad

#22
Sep 20, 2010, 11:03 am Last Edit: Sep 20, 2010, 11:04 am by graynomad Reason: 1
Quote
but much slower


Presumably at about 1Hz.

Quote
count up to 23 and restarts (as before)


There must be a problem in the counting such as the hours going into the seconds part of the array, but first let's get the display working.

Quote
segdisp[digits
  • ]);


That will show 0s because the digits array was probably initialised to all 0s. So that's good.

Now try adding

Quote
digits[0] = 1;
digits[1] = 2;
digits[2] = 3;
digits[3] = 4;
digits[4] = 5;
digits[5] = 6;


In the init() func and running the same test code.
Rob Gray aka the GRAYnomad www.robgray.com

sinuslinus

#23
Sep 20, 2010, 11:10 am Last Edit: Sep 20, 2010, 11:21 am by sinuslinus Reason: 1
Quote
In the init() func and running the same test code.


Yes, now 123456 is shown.

1,2 is the digits that the it previously count 0-23 on.

Graynomad

OK that's good, the basic logic works, we just have a problem with the counting, and part of that problem is the way you changed the bracing from what I had a few posts back to

Code: [Select]
if (seconds > 59) {
     seconds = 0;
     minutes++;
     if (minutes > 59) {
        minutes = 0;
        hours++;
        if (hours > 23) {
          hours = 0;
        }


The trouble is that if say minutes is < 59 the rest of the code doesn't get executed, including the display stuff. So try this where the tests are not nested.


Code: [Select]
void loop(){
  seconds++;                      // counting
  if (seconds > 59) {
     seconds = 0;
     minutes++;
  }
  if (minutes > 59) {
     minutes = 0;
     hours++;
  }
  if (hours > 23) {
     hours = 0;
  }

  digits[SECONDS]   = seconds / 10;
  digits[SECONDS+1] = seconds % 10;
  digits[MINUTES]   = minutes / 10;
  digits[MINUTES+1] = minutes % 10;
  digits[HOURS]     = hours   / 10;
  digits[HOURS+1]   = hours   % 10;
 
  digitalWrite(latchpin, LOW);
  for (int x = 0; x < 6; x++)
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
  digitalWrite(latchpin, HIGH);

  delay (speed);
}


It's not very efficient but that doesn't matter here.
Rob Gray aka the GRAYnomad www.robgray.com

sinuslinus

It works! I was starting to loose faith here. Thanks again.
Hopefullly all these difficulties won't scare me off from doing other projects in the future ;)
Oh, I have a counter again anyway. And it must be much more efficient than my first code..

Is there a way to get all 6 displays show the same thing or do I need other wiring then than daisychainging efterthing? Getting back to the interactivity part of this and change what is shown on the display when a button is pressed.
And I will be satisfied with not showing correct time as long as the actual interactivity works since time is running out on me.

Graynomad

Quote
It works! I was starting to loose faith here. Thanks again.

Programming can be very frustrating even when you're experienced. As a beginner it's even worse. Still it's worth it when you get something working.

Quote
Is there a way to get all 6 displays show the same thing or do I need other wiring then than daisychainging efterthing?

Do you mean the 6 7-seg displays we're already working with? If so then it's easy

Code: [Select]
for (int x = 0; x < 6; x++)
       shiftOut(datapin, clockpin, MSBFIRST, some_value);


Quote
change what is shown on the display when a button is pressed.


Wire up a button connecting a pin to GND with a 10k pullup resistor to 5v. Then

Code: [Select]
for (int x = 0; x < 6; x++)
  if (digitalRead (buttonpin) == LOW)
       // button pressed, show something different
       shiftOut(datapin, clockpin, MSBFIRST, some_other_data);
  else
       // show the time
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);


Next question is what to you want to display when the button is pressed?
Rob Gray aka the GRAYnomad www.robgray.com

sinuslinus

Yes, still working the same 6 displays.

I was going to try writing something similar but this is better to get it right from the start.

I want it to count quickly on all 6 display simultaneously, delay of 100 ms.
Its almost so quick that you hardly see what is displayed.
This is what I want it to show when the button is not pressed and when pressing the button it should show the timer we just made for 10 seconds and then back to the quick counter again.

Graynomad

Play with this

Code: [Select]
#define SECONDS 4
#define MINUTES 2
#define HOURS   0

#define TRUE 1  // these may cause an error if already defined
#define FALSE 0


unsigned int latchpin = 8;  // connect to pin 12 on the '595
unsigned int clockpin = 12; // connect to pin 11 on the '595
unsigned int datapin  = 11; // connect to pin 14 on the '595

unsigned int speed = 1000;    // used to control speed of counting
unsigned int ticks = 0;
unsigned int seconds = 0;
unsigned int minutes = 0;
unsigned int hours = 0;
unsigned int digits[6];
unsigned int button_state = HIGH;
unsigned long time_but_pressed;


unsigned int segdisp[10] = {63,6,91,79,102,109,125,7,127,111};

void setup() {

  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);

}

void loop(){
  ticks++;
  if (ticks > 10) {
     ticks = 0;
     seconds++;
     slow_display = TRUE;
  }
  if (seconds > 59) {
     seconds = 0;
     minutes++;
  }
  if (minutes > 59) {
     minutes = 0;
     hours++;
  }
  if (hours > 23) {
     hours = 0;
  }

  // detect falling edge of button
  // record the time and set flag to indicate we are timing for 10 secs
  if (digitalRead (buttonpin) == LOW && button_state == HIGH) {
        time_but_pressed = millis()
        button_state == LOW
       timing = TRUE;
  }

  // if it's been 10secs since we started timing reset the flag
  if (millis () > time_but_pressed + 10 * 1000)) {
     timing = FALSE;
  }
 
  digits[SECONDS]   = seconds / 10;
  digits[SECONDS+1] = seconds % 10;
  digits[MINUTES]   = minutes / 10;
  digits[MINUTES+1] = minutes % 10;
  digits[HOURS]     = hours   / 10;
  digits[HOURS+1]   = hours   % 10;
 
 
  if (timing == FALSE) {
     digitalWrite(latchpin, LOW);
     for (int x = 0; x < 6; x++)
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
     digitalWrite(latchpin, HIGH);  
  } else {
     if (ticks = 0) {
        digitalWrite(latchpin, LOW);
        for (int x = 0; x < 6; x++)
           shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
        digitalWrite(latchpin, HIGH);  
     }
  }  


  delay (100);
}


It won't do everything but should do the fast/slow thing.

It's 1AM here, we'll carry on tomorrow.
Rob Gray aka the GRAYnomad www.robgray.com

sinuslinus

Okay its really late here now...
It didn't compile and I tried to change it but no luck. It doesn't start counting.

Code: [Select]

#define SECONDS 4
#define MINUTES 2
#define HOURS   0


#define TRUE 1  // these may cause an error if already defined
#define FALSE 0
[glow]#define BUTTON 5 // push button on pin 5[/glow]


unsigned int latchpin = 8;  // connect to pin 12 on the '595
unsigned int clockpin = 12; // connect to pin 11 on the '595
unsigned int datapin  = 11; // connect to pin 14 on the '595

unsigned int speed = 1000;    // used to control speed of counting
unsigned int ticks = 0;
unsigned int seconds = 0;
unsigned int minutes = 0;
unsigned int hours = 0;
unsigned int digits[6];
unsigned int button_state = HIGH;
unsigned long time_but_pressed;
[glow]unsigned int  slow_display;
unsigned int timing;[/glow]

unsigned int segdisp[10] = {63,6,91,79,102,109,125,7,127,111};

void setup() {

  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);

}

void loop(){
  ticks++;
  if (ticks > 10) {
     ticks = 0;
     seconds++;
     slow_display = TRUE;
  }
  if (seconds > 59) {
     seconds = 0;
     minutes++;
  }
  if (minutes > 59) {
     minutes = 0;
     hours++;
  }
  if (hours > 23) {
     hours = 0;
  }

  // detect falling edge of button
  // record the time and set flag to indicate we are timing for 10 secs
  if (digitalRead (BUTTON) == LOW && button_state == HIGH) {
        time_but_pressed = millis();
        button_state == LOW;
       timing = TRUE;
  }

  // if it's been 10secs since we started timing reset the flag
  if (millis () > time_but_pressed + 10 * 1000) {
     timing = FALSE;
  }
 
  digits[SECONDS]   = seconds / 10;
  digits[SECONDS+1] = seconds % 10;
  digits[MINUTES]   = minutes / 10;
  digits[MINUTES+1] = minutes % 10;
  digits[HOURS]     = hours   / 10;
  digits[HOURS+1]   = hours   % 10;

  if (timing == FALSE) {
     digitalWrite(latchpin, LOW);
     for (int x = 0; x < 6; x++)
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
     digitalWrite(latchpin, HIGH);  
  } else {
     if (ticks = 0) {
        digitalWrite(latchpin, LOW);
        for (int x = 0; x < 6; x++)
           shiftOut(datapin, clockpin, MSBFIRST, segdisp[digits[x]]);
        digitalWrite(latchpin, HIGH);  
     }
  }  


  delay (100);
}


Go Up