Go Down

Topic: Simple Stopwatch (Read 966 times) previous topic - next topic

nitropixie

Hi

I'm after some help please.  I'm trying to produce a lap timer for a car and while i'm not concerned with the hardware as such right now I am trying to get the basic software/program sorted.

What I'm doing is using a 20x4 lcd, which i can communicate with so no problems there, its just the code.  

The code I can't work out is just the timing code. I can count fine with seconds, 10th and 100th's of seconds.  What i am having problems with is 10s of seconds as they count up to 99 and not 60 (or 59).  I would like to get this sorted then i can play with other settings.

If the code i'm using wont suffice, then i'll have to look elsewhere but its the best i have found and to understand at my level at the moment.
Code: [Select]
#include <LiquidCrystal.h>
int long aa ;
boolean b=true;
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
lcd.begin(20,4);
lcd.print("Current Lap");
}

void loop() {
if(b){
lcd.setCursor(12, 0);
aa=millis(); // collecting time from millis function
lcd.print((aa/1000000)%10);
lcd.print((aa/100000)%10);
lcd.print('.');
lcd.print((aa/10000)%10);
lcd.print((aa/1000)%10);
lcd.print('.');
lcd.print((aa/100)%10);
lcd.print((aa/10)%10);
 if(aa>=128000){
delay(20);
lcd.setCursor(0,0);
lcd.print("    IT WORKS, YEY !   ");
for(int i=0;i<3;i++){
lcd.noDisplay();
delay(750);
lcd.display();
delay(750);
}
b=false;
lcd.clear();
}
}
if(!b){
lcd.setCursor(0,0);
lcd.print("www.diymaker.com");
}
}



All help appreciated

AWOL

Quote
What i am having problems with is 10s of seconds as they count up to 99

Maybe if you cut-back a little on all those "% 10" s.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Andy R

Maybe you need something like:

long ea = 133456;  
long totalSeconds = ea/1000; // 133s = 2minutes 13seconds
long seconds = totalSeconds%60; // 13 seconds
long displayLowSeconds = seconds%10; // 3
long displayHighSeconds = seconds/10;  // 1
long displayMinutes = totalSeconds/60; // 2

Hardcode a value for ea and Serial.print() the numbers to check your math. Once you workout the math, remove Serial.print().

nitropixie

Awol, the code i used from someone elses code and i was trying to modify it it to suit what i was aiming for.

Andy R, I can just about understand your code but i must be such a noob i can't quite see how it helps me sorry.  I can understand code to a level but i'm not that great on that great producing my own.


Thanks for the help ;)

nitropixie

After a bit of working out I have come up with this code

Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int hundred;
int sec;
int mins;

void setup(){
lcd.begin(20,4);
int sec=00;
int mins=00;
int hundred=00;
}
void loop(){
 hundred=hundred+1;
 if (hundred==100){
   hundred=00;
 }
 delay(10);
   if (hundred==00){
     sec=sec+1;
   }
   if (sec==60){
 sec=00;
   if (sec==0){
   mins=mins+1;
}}
lcd.setCursor(0,0);
lcd.print("    Current Lap ");
lcd.setCursor(7,1);
lcd.print(mins);
lcd.print(".");
lcd.print(sec);
lcd.print(".");
lcd.print(hundred);
 
}


I'm happy the code works but there are a few niggles I would prefer and there is probably a more efficient code out there but I have managed to get this work by myself.

What I am finding is that when the units are in single figures i.e. 1-9 there is no 0 to prefix e.g 09, 08 which i would prefer.

When the seconds figures go down to single units there seems to be a thousandth figure appearing (but it doesn't count up, like a ghosting).


Any recommendations from anyone would be great, but please be gentle ;)

Ryan

Andy R

I think what you have done is fine.

It sounds like when lcd.print converts the integer 'seconds' to a string, it does not display the initial zero you would like, i.e. it displays "9" instead of "09".

This is just a guess, but to get the extra zero try:

Code: [Select]
if (seconds < 10)
   lcd.print('0');
lcd.print(seconds);


Just play around with it until the lcd displays what you want.


PaulS

You could use sprintf to construct a single string to display. The %.2d format specifier will cause the value to be printed with 2 or more digits, adding leading 0s as required.

The "ghosting" is probably caused by writing a string that is shorter than the previous string.

By using sprintf, the string will always be the same length (as long as the values to be printed don't exceed the reserved space).

nitropixie

Thanks very much for your help guys.  I used AndyR's suggestion and implemented this in my code.

Code: [Select]

unsigned long sec;
int mins;
int hundred;
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup(){
lcd.begin(20,4);
int sec=00;
int mins=00;
int hundred=00;
}
void loop(){
 hundred=hundred+1;
 if (hundred==100){
   hundred=00;
 }
 delay(3);
   if (hundred==00){
     sec=sec+1;
   }
   if (sec==60){
 sec=00;
   if (sec==0){
   mins=mins+1;
}}
lcd.setCursor(0,0);
lcd.print("Current Lap ");

if (mins < 10){
   lcd.print('0');}
lcd.print(mins);
lcd.print(".");
if (sec < 10){
   lcd.print('0');}
lcd.print(sec);
lcd.print(".");
if (hundred < 10){
   lcd.print('0');}
lcd.print(hundred);
}



The next problem i have now is getting an accurate time. After 5 mins its approx 5 secs out of sync (with a stopwatch so only as a guide).

I think i am right in thinking every line of code takes up a finite amount of time and i need to calculate how long all the code would take and adjust the "delay" accordingly.  Also the "if" functions would throw a slight red herring in the code so to say as it would add an extra line of code (if < 10) and a solution would be needed to correct this part of the code when not below 10.

Ryan

AWOL

Have a look at the blink without delay example/tutorial, and see if that helps any.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

nitropixie

Thanks AWOL.  I think i have done it like you meant but it's still not right.
My current code is:-

Code: [Select]

unsigned long sec;
int mins;
int hundred;
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
long interval = 9;
long previousMillis = 0;

void setup(){
lcd.begin(20,4);
int sec=0;
int mins=0;
int hundred=0;
}
void loop(){
   if (millis() - previousMillis > interval) {
   previousMillis = millis();  
 
 hundred=hundred+1;
 if (hundred==100){
   hundred=0;
 }
 if (hundred==0){
   sec=sec+1;
   }
  if (sec==60){
   sec=0;
  if (sec==0){
   mins=mins+1;
}}
lcd.setCursor(0,0);
lcd.print("Current Lap ");

if (mins < 10){
   lcd.print('0');}
lcd.print(mins);
lcd.print(".");
if (sec < 10){
   lcd.print('0');}
lcd.print(sec);
lcd.print(".");
if (hundred < 10){
   lcd.print('0');}
lcd.print(hundred);
}
}



What i also think is happening is if an "if" statement becomes true then there is extra code which increases the time of each cycle.  I guess I could do with some extra code which doesn't do anything to keep things even throughout the code. Am i right??

Again thanks for your help

Go Up