Forum: Mikrocontroller und Digitale Elektronik Stoppuhr Programm


von Sebastian C (Gast)


Lesenswert?

Hallo,

ich hab jetzt mit dem Arduino eine Stoppuhr gebaut. Dazu habe ich 
folgenden Code gefunden. Dieser zählt aber leider runter. Ich hab es 
zwar schon hinbekommen, dass er hoch zählt, dann bemerkt er aber nicht, 
dass 60 Sekunden eine Minute sind. Deshalb bitte ich darum, dass mir 
jemand den Code so umschreibt, dass er hochzählt und auf richtige 
Minuten umschaltet.
Außerdem wäre es schön, wenn mir jemand einen Tipp gibt, wie ich in 
andere Zeitformate z.b. Sekunden:Milisekunden umprogrammieren kann.

Gruß Sebastian.

Hier noch der Code:

/*
Arduino 4 digits 7 segments LED countdown timer with buzzerm from
electronicsblog.net. If You share/use this code elsewhere on the 
internet
please meantion this code source.
*/

// segment | Arduino board PIN number

#define G 13
#define F 12
#define A 11
#define B 10
#define E 9
#define D 8
#define C 7
#define DP 6

// Commonn cathodes control
#define GND1 5
#define GND2 4
#define GND3 3
#define GND4 2

// buttons
/*
Button_start - start/pause timer and in setup mode inreases minutes
and seconds values
Button_set - if timer is paused it resets timer to start. Long press
activates setup mode in which button is for going through minutes, 
seconds setup
and leaving setup mode.

*/

#define Button_start 1
#define Button_set 0

///
#define Buzzer 46
#define LED 47 // or relay insted

int i=0;
char run=0; // shows if timer is runnig
int b=0;  //for buttons
int c=0;
int d=0; // for buzzer
char set_mode=0; // shows if timer is in setup mode
char alarm =0;  // if "1" buzzer is on

//timer variables

// user setted and "turn on" values
int default_Sec=59;
int default_Min=99;

// current values
int Sec;
int Min;

//timer interrupt

ISR(TIMER1_OVF_vect) {
Sec--; // timer values decreases
TCNT1=0x0BDC;

}

// functions to display digits

void digit0 () {
// for 0 needed to turn ON F A B C D E segments, so:

digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);

//////////////////////// G segment should be turn OFF
digitalWrite(G, LOW);

};

void digit1 () {

digitalWrite(A,LOW);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
};

void digit2 () {

digitalWrite(A,HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, LOW);
digitalWrite(G, HIGH);
};

void digit3 () {

digitalWrite(A,HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, HIGH);
};

void digit4 () {

digitalWrite(A,LOW);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
};

void digit5 () {

digitalWrite(A,HIGH);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
};

void digit6 () {

digitalWrite(A,HIGH);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
};

void digit7 () {

digitalWrite(A,HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
};

void digit8 () {

digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);

};

void digit9 () {

digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);

};

//function to display digit from inputed int

void showdigit (int digit)

{

 switch (digit) {

 case 0:
 digit0 ();
 break;

 case 1:
 digit1 ();
 break;

 case 2:
 digit2 ();
 break;

 case 3:
 digit3 ();
 break;

 case 4:
 digit4 ();
 break;

 case 5:
 digit5 ();
 break;

 case 6:
 digit6 ();
 break;

 case 7:
 digit7 ();
 break;

 case 8:
 digit8 ();
 break;

 case 9:
 digit9 ();
 break;

 default:



 break;



 };

};

// showing 4 digits
//  not only shows 4 digit number, but also there is option to turn on
//only selected digits and decimal point.

void showdigits (int number, char digit_on, char  decimal_point)
{



digitalWrite(GND4, LOW);
  // e.g. we have "1234"
showdigit(number/1000);  // segments are set to display "1"
if (decimal_point&8) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, 
LOW);};
 if (digit_on&8) {
digitalWrite(GND1, HIGH); // first digit on,
digitalWrite(GND2, LOW); // other off
digitalWrite(GND3, LOW);
 }
 delay (1);

number = number%1000;  // remainder of 1234/1000 is 234
digitalWrite(GND1, LOW); // first digit is off
 showdigit(number/100); //// segments are set to display "2"
if (decimal_point&4) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, 
LOW);};
 if (digit_on&4) {
digitalWrite(GND2, HIGH); // second digit is on
  } delay (1);// and so on....

number =number%100;
digitalWrite(GND2, LOW);
showdigit(number/10);
if (decimal_point&2) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, 
LOW);};
 if (digit_on&2) {
digitalWrite(GND3, HIGH);
 }
 delay (1);

number =number%10;
digitalWrite(GND3, LOW);
showdigit(number);
if (decimal_point&1) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, 
LOW);};
 if (digit_on&1) {
digitalWrite(GND4, HIGH);
  }
  delay (1);

};

void setup()

{


pinMode(A, OUTPUT);
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT);
pinMode(E, OUTPUT);
pinMode(F, OUTPUT);
pinMode(G, OUTPUT);
pinMode(DP, OUTPUT);

pinMode(GND1, OUTPUT);
pinMode(GND2, OUTPUT);
pinMode(GND3, OUTPUT);
pinMode(GND4, OUTPUT);

pinMode(Button_start, INPUT);
digitalWrite(Button_start, HIGH); //pull up resistor

pinMode(Button_set, INPUT);
digitalWrite(Button_set, HIGH); //pull up resistor

pinMode(Buzzer, OUTPUT);
pinMode(LED, OUTPUT);

TIMSK1=0x01; // enabled global and timer overflow interrupt;
TCCR1A = 0x00; // normal operation 148 page (mode0);

TCNT1=0x0BDC;

TCCR1B = 0x00; // stop hardware timer

// loading default timer values

Sec = default_Sec ;
Min = default_Min ;

};
void loop ()

{
 //////////// button_start//////////
  if (!digitalRead(Button_start)&&!b) {

  if (!set_mode) { if (run) {TCCR1B=0x00; run=0;} else {TCCR1B=0x04; 
run=1;}}

  if (set_mode==1) {Min++;}

   if (set_mode==2) {Sec++;}

   if (set_mode) {b=25;} else b=100;

         };

 if (!digitalRead(Button_start)&&b==1) {

        };

if (!b==0) b--;

 //////////// button_set/////////
 if (!digitalRead(Button_set)&&!c) {

   if(!run&&!set_mode) {Min=default_Min; Sec=default_Sec;}

  if (set_mode>0) set_mode++;

  if (set_mode==3) {set_mode=0;  default_Sec = Sec ;
default_Min = Min; }

   c=100;      };

 if (!digitalRead(Button_set)&&c==1&&!run) {

     set_mode=1;

     c=100;

        };

if (!c==0) c--;
////////////////////////////

if (set_mode) {if (Sec==60) {Sec=00;}

 if (Min==100) {Min=0;} }


       else {

 if (Sec==-1) {Min--;Sec=59;}

 }


//decimal point indication control

if (!set_mode) {


  if (!(Sec%2)) { showdigits (Min*100+Sec,0x0F,0x04); } //0X00

else  {showdigits (Min*100+Sec,0x0F,0x00); }; //0000

} else {

  if (set_mode==1) {

  showdigits (Min*100+Sec,0x0F,0x0C);   //XX00
                                } else {



                     showdigits (Min*100+Sec,0x0F,0x03);      } //00XX

}
if (run) {  // to do while timer is running; e.g. control relay

digitalWrite(LED, HIGH);

} else digitalWrite(LED, LOW);

if ((Min==0)&&(Sec==0)&&run) {
run=0;
TCCR1B=0x00; //stop timer

//// to do after count down is finished e.g. start alarm as in this 
example

alarm=1;
d=500;

}

// Alarm part
if (alarm) { if (!(d%100)) { // sound 500/100= 5 times ;
  tone(Buzzer, 440, 200); }
  d--;
  if (d==0) {alarm=0; Sec = default_Sec ;
  Min = default_Min ; // After alarm is off, timer goes to start
          }
    }

};

von Floh (Gast)


Lesenswert?

Längere Quellcodes als Anhang -> Nettiquette
So ist das nicht schön zu lesen.

Übrigends, für eine Stoppuhr hast du das falsche kopiert. Das ist ein 
Timer, der mit Sekundenauflösung zählt, Millisekunden gehen da nur über 
Umwege.
Warum fängst du also nicht an, das Programm selbst zu entwickeln? Da 
lernt man was ;-)

von Sebastian C (Gast)


Lesenswert?

Jetzt gehts mir erstmal drum, dass er hochzählt.

von Kai B. (tekasiko)


Angehängte Dateien:

Lesenswert?

Hallo Sebastian,

fals es dir Hilft,

habe im anhang de Quellcode für eine Stopuhr, programmiert in Bascom,

aber die funktioniert.

Evtl kannst ja was damit anfangen

Lg Kai

von Helfer (Gast)


Lesenswert?

Sebastian C schrieb:
> Jetzt gehts mir erstmal drum, dass er hochzählt.

Dann wirst du wohl in der Funktion loop () alles einmal genau durchsehen 
müssen, insbesondere die Anweisungen zum Erhöhen oder Verringern von Sec 
und Min Zähler. Beim Überlauf, d.h. bei 59/60 wirst du dir dann 
überlegen müssen, was passieren soll.

von Helfer (Gast)


Lesenswert?

Nachdem du die ganzen Dinge in loop() verstanden hast, ist dir 
sicherlich klar geworden, dass es da hauptsächlich um die Bedienung mit 
den Tasten geht. Ziemlich am Ende kommt dann die Ausgabe auf dem Display 
und die Alarmfunktion (if ((Min==0)&&(Sec==0)&&run){}.
Der eigentliche Zeitablauf wird über den Timer1 kontrolliert, der in der 
ISR(TIMER1_OVF_vect) {} die Sekunden herunterzähl. Hier mußt du also 
eingreifen, um eine Stopuhr draus zu machen. Wenn die Sekunden richtig 
hochzählen, mußt du dich als nächstes um den Minuten-übertrag kümmern. 
Nachdem du die Stelle im Programm gefunden hast, ist das ein Klacks. Im 
Simulator kannst du dazu z.B. die Sekunden auf 59 stellen, setzt 
Breakpoints an die entscheidenden Stellen und verfolgst dann Schritt für 
Schritt wo's passieren muß.

Erstmal kannst du es ja beim Sekundentakt lassen und später die Schritte 
für eine bessere Zeitauflösung verkleinern.

von Karl H. (kbuchegg)


Lesenswert?

Wahnsinn!

Wirf den Code weg und schreib dir selber eine.
Der ist doch grauenhaft!


(Aber mach nicht denselben Quark, den dieser Autor da mit der 7-Seg 
Ansteuerung verbrochen hat. Man kann auch beim Arduino einen Port als 
Ganzes ansteuern und muss da nicht jedes Digit einzeln setzen. Zusammen 
mit einem Array fallen dann schon mal runde 60 Zeilen Programmcode weg.
Das Multiplexing der Anzeige ist auch Müll. Das macht man mit einem 
Timer, der dann auch Millisekunden zählen kann.

von Sebastian C (Gast)


Angehängte Dateien:

Lesenswert?

Hochzählen tut, aber immernoch nicht bis 60. Kann mir des jemand genau 
erklären. Hier mal der Stand der Dinge.

von Sebastian C (Gast)


Lesenswert?

Kann mir das niemand erklären?

von Karl H. (kbuchegg)


Lesenswert?

Schreib den Code neu.
Der Code ist fuchtbar.


Und diesmal baust du die komplette Uhrenfunktionalität an einer Stelle 
ein und zerreist sie nicht über das halbe Programm.

Die ISR ist eine gute Stelle dafür. Anstelle von nur Sekunden kann man 
dort ruhig die komplette Uhrezeit hochzählen. Und anstelle von dem 
dämlichen Vorladen das Timers nimmst du eine CTC, stellst die ISR auf 
ca. 1 Millisekunde ein und machst dort das Multiplexen mit. Anstelle 
dieser 10 Funktionen für jedes Digit, überlegst du dir eine Systematik, 
wie du die ein/auszuschaltenden Segmente für ein bestimmtes Digit in 
einem Array unterbringen kannst.

Bei diesem Programm stimmt so gut wie gar nix bzw. ist so gemacht wie 
man es NICHT macht. Dass es davon abgesehen auch noch grauslich 
formatiert ist, tut ein Übriges dazu bei, dass es ein scheusliches 
Programm ist, das so keinesfalls als ein Lehrbeispiel für irgendjemanden 
dienen sollte. Ausser zur Abschreckung natürlich.

von Sebastian C (Gast)


Lesenswert?

Kann mir jemand eines schreiben?

von Helfer 2 (Gast)


Lesenswert?

Sebastian C schrieb:
> Kann mir jemand eines schreiben?
Nee, aber gibt's doch alles schon fertig:
http://www.online-stopwatch.com/german/

von Sebastian C (Gast)


Lesenswert?

Das was du da gepostet hast ist in PHP geschrieben, hat also nix mit dem 
Arduino zu tun.

von Sebastian C (Gast)


Lesenswert?

Also derjenige der mir die beiden Programmme für den Arduino schreibt 
(also einmal m:ss:ms und einmal ss:msts ) bekommt 15€ von mir.

von Philip Ouistar (Gast)


Lesenswert?

Selber essen macht fett... :)
Für lumpige 15,- Euro setzt sich da niemand hin.

von Seb C. (dark-seb)


Angehängte Dateien:

Lesenswert?

Ich hab jetzt den Code gefunden, nur leider zählt der viel zu schnell.
Findet jemand den Fehler?

von Seb C. (dark-seb)


Angehängte Dateien:

Lesenswert?

So ich habs jetzt geschafft nen Code zusammen zu basteln. Was ich nicht 
hingekriegt hab, ist das es mit nem Button startet.
Ich hab ihn im Code oben schon definiert. Jetzt bräuchte ich noch nen 
Tipp, wie ich des in den Teil:

void loop ()

{
showdigits (i);
};

reinkriege.

von Irgendjemand (Gast)


Lesenswert?

include <fDigitsSegtPin.h>
//https://www.arduinolibraries.info/libraries/f-digits-segt-pin

fDigitsSegtPin Display(1, 2, 3, 4, 5,6, 7, 8, 9, 10, 11, 12);


int sekunde;

void setup() {

Display.begin();
Display.doPrint_lastDot = 1;
Display.doPrint_firstZero = 1;
Display.doReport_overRange = 1;

}
void loop() {
int test;
  sekunde = (millis()/1000);

  Display.print(sekunde);

}

von Irgendjemand (Gast)


Lesenswert?

include <fDigitsSegtPin.h>
//https://www.arduinolibraries.info/libraries/f-digits-segt-pin

fDigitsSegtPin Display(1, 2, 3, 4, 5,6, 7, 8, 9, 10, 11, 12);


int sekunde;

void setup() {

Display.begin();
Display.doPrint_lastDot = 1;
Display.doPrint_firstZero = 1;
Display.doReport_overRange = 1;

}
void loop() {

  sekunde = (millis()/1000);

  Display.print(sekunde);

}

von Johannes S. (Gast)


Lesenswert?

Seb ist jetzt schon groß und hat hoffentlich dazu gelernt.

von Percy N. (vox_bovi)


Lesenswert?

Johannes S. schrieb:
> Seb ist jetzt schon groß und hat hoffentlich dazu gelernt.

Du meinst, er weiß jetzt, wie man andere für lau für sich arbeiten 
lässt?

von STK500-Besitzer (Gast)


Lesenswert?

Percy N. schrieb:
> Du meinst, er weiß jetzt, wie man andere für lau für sich arbeiten
> lässt?

Oder er hat es aufgegeben.
Manche Projekte werden vom Lauf der Zeit überholt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.