Pages: [1] 2   Go Down
Author Topic: RTC Stopwatch  (Read 3598 times)
0 Members and 1 Guest are viewing this topic.
NY, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Nuovo Arduinisto
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey everyone,

I've been using the Chronodot V2.1, which is based on the DS3231, and I have it up and running. I wound up using
Code:
print(time, HEX);
to the BCD conversion (honestly, I am not sure if it is a true BCD conversion, but it seems to work without flaw). My next step is to add a stopwatch function for the RTC. Currently, I am able to press a button which returns the current second's time, when I press a second button it will return the difference in seconds pass. However, I am having trouble with the rollovers past 59 seconds (when using Macetech's BCD conversion), and printing it out in HEX format is not always correct (again looks like when it rolls pass 59 seconds, it prints out the actual HEX value), due to BCD conversions.

Some edited code snippet:
Code:
byte seconds, init_seconds, elap_seconds;

int Timer() {
  elapsedTime();
  seconds=elap_seconds-init_seconds;
}

int initialTime() {
  /*Wire Code*/
  init_seconds=Wire.read();
}

int elapsedTime() {
  /*Wire Code*/
  elap_seconds=Wire.read();
}

Sorry if the code is brief (right now, going off memory), but it does return some expected values. I think my problem is the BCD conversions, so any help or experience here is appreciated.
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 71
Posts: 3512
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Pretty hard to help with such a small bit of code. Best to post everything, #includes and all.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 71
Posts: 3512
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like you are working with the seconds register value from the RTC directly. This is indeed BCD and will have to be converted to decimal before subtracting. Then some modular arithmetic to ensure a positive result. Of course this code only works if the elapsed time never exceeds 59 seconds. I didn't go and dig up Macetech's code, but the BCD-to-Decimal conversion function that I use is below. I'd bet it's very similar if not identical. Printing the hex value is not what you want. That will show the BCD value but can't do the calculation with it.

Code:
byte seconds, init_seconds, elap_seconds;

int Timer() {
    elapsedTime();
    seconds = ((60 + elap_seconds) - init_seconds) % 60;
}

int initialTime() {
    /*Wire Code*/
    init_seconds=bcd2dec(Wire.read());
}

int elapsedTime() {
    /*Wire Code*/
    elap_seconds=bcd2dec(Wire.read());
}

/*----------------------------------------------------------------------*
 * BCD-to-Decimal conversion                                            *
 *----------------------------------------------------------------------*/
uint8_t bcd2dec(uint8_t n)
{
    return ((n / 16 * 10) + (n % 16));
}
« Last Edit: May 18, 2013, 08:42:04 pm by Jack Christensen » Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12456
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


maybe this code helps to make your stopwatch - http://playground.arduino.cc/Code/StopWatchClass -
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

NY, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Nuovo Arduinisto
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Rob. I did take a look at that, but I'm trying to see if I can implement the RTC.

Thanks Jack. I printed the HEX value since at first I was only interested in seeing the value (I think my attempt was to return a value in HEX and convert it to an int). Macetech, if I'm understanding their conversion correctly, uses bitwise AND (&) to check against each bit:
Code:
seconds = (((seconds & 0b11110000)>>4)*10 + (seconds & 0b00001111)); // convert BCD to decimal

I've seen your BCD-Decimal conversion in a few other posts, but as I'm recalling, I thought there might be another way for it to work. I was able to get a correct time lapse until the 59 second mark and is then restarted, which then gives an incorrect difference. I began to work on this by using an if statement to reset the second time, but haven't gone back to working on it. But here is the code I've been working on. I've have been going back and forth with a few things, so it has gone through some different versions (I was using Macetech's conversion during the last version, seen below).

Code:
#include <Wire.h>

const int button1 = 2;
const int button2 = 3;
const int LED = 13;
boolean butt1State;
boolean butt2State;
byte seconds, init_seconds, elap_seconds;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
 
  // clear /EOSC bit
  // Sometimes necessary to ensure that the clock keeps running on just battery power.
  // Once set, it shouldn't need to be reset but it's a good idea to make sure.
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // select register
  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
  Wire.endTransmission();
  
  //Below was used for decoding and debugging
  //Serial.print("BIN");Serial.print("\t");Serial.print("DEC");Serial.print("\t");Serial.println("HEX");
}
 
void loop() {
  butt1State=digitalRead(button1);
  butt2State=digitalRead(button2);
  if(butt1State==LOW) {
    initialTime();
    Serial.println(init_seconds);
    //Serial.print("\t");Serial.print(init_seconds, DEC);Serial.print("\t");Serial.println(init_seconds, HEX);
    delay(1000);
  }
  if(butt2State==LOW) {
    elapsedTime();
    Timer();  
    digitalWrite(LED, !butt2State);
    Serial.print(elap_seconds);Serial.print("\t");Serial.print(seconds);Serial.print("\t");Serial.print(seconds, BIN);Serial.print("\t");Serial.println(seconds, HEX);
    delay(1000);
  } else {
    digitalWrite(LED, LOW);
  }
}

int Timer() {
  seconds=elap_seconds-init_seconds;
}
int initialTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1);
  
  while(Wire.available()) {
    init_seconds = Wire.read();
    init_seconds = (((init_seconds & 0b11110000)>>4)*10+(init_seconds & 0b00001111));
    return(init_seconds);
  }
}
int elapsedTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1);
  
  while(Wire.available()) {
    elap_seconds = Wire.read();
    elap_seconds = (((elap_seconds & 0b11110000)>>4)*10+(elap_seconds & 0b00001111));
    return(elap_seconds);
  }
}

This is the first time I'm working with BCD and Decimal conversions, and my issue may also be my math after the conversions. I will attempt your conversion tomorrow.
« Last Edit: May 19, 2013, 09:48:11 pm by Osiris » Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 71
Posts: 3512
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm not clear on your requirement, do you need to time intervals longer than 59 seconds? If so, how long? In order to time longer intervals, more than the seconds register from the RTC will need to be used.

The result of Macetech's conversion will be exactly the same as mine. His may be more efficient, I'm not sure that the modulo operator (%) is always the best in that regard. I should have a look into that.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12456
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

macetech's code assumes seconds is in the range 0..59

imho the compiler should be able to optimize this modulo - (n % 16) - as it can also optimize  /16

----
update:
this is almost fastest conversion I can think of. It replaces the /16*10 with 2 shifts and an addition. The masking still exists
Code:
int bcd2dec(uint8_t in)
{
  uint8_t out = (in & 0xF0) >> 1;
  return out + out >> 2 + (in & 0x0F); 
}
« Last Edit: May 20, 2013, 08:20:24 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 71
Posts: 3512
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

imho the compiler should be able to optimize this modulo - (n % 16) - as it can also optimize  /16

Indeed it does, in fact the two approaches turn out to be identical. (I'm always amazed by this compiler when I try to check into something like this, a person really has to jump through some hoops just to ensure everything doesn't get optimized clean away!)

Quote
update:
this is almost fastest conversion I can think of. It replaces the /16*10 with 2 shifts and an addition. The masking still exists
Code:
int bcd2dec(uint8_t in)
{
  uint8_t out = (in & 0xF0) >> 1;
  return out + out >> 2 + (in & 0x0F); 
}

Code:
00000140 <_Z8bcd2dec1h>:
}

uint8_t bcd2dec1(uint8_t n)
{
return ((n / 16 * 10) + (n % 16));
 140: 98 2f        mov r25, r24
 142: 92 95        swap r25
 144: 9f 70        andi r25, 0x0F ; 15
 146: 8f 70        andi r24, 0x0F ; 15
}
 148: 2a e0        ldi r18, 0x0A ; 10
 14a: 92 9f        mul r25, r18
 14c: 80 0d        add r24, r0
 14e: 11 24        eor r1, r1
 150: 08 95        ret

00000152 <_Z8bcd2dec2h>:

uint8_t bcd2dec2(uint8_t n)
{
return ((n & 0b11110000) >> 4) * 10 + (n & 0b00001111);
 152: 98 2f        mov r25, r24
 154: 92 95        swap r25
 156: 9f 70        andi r25, 0x0F ; 15
 158: 8f 70        andi r24, 0x0F ; 15
}
 15a: 2a e0        ldi r18, 0x0A ; 10
 15c: 92 9f        mul r25, r18
 15e: 80 0d        add r24, r0
 160: 11 24        eor r1, r1
 162: 08 95        ret

00000164 <_Z8bcd2dec3h>:

int bcd2dec3(uint8_t in)
{
uint8_t out = (in & 0xF0) >> 1;
 164: 28 2f        mov r18, r24
 166: 20 7f        andi r18, 0xF0 ; 240
return out + out >> 2 + (in & 0x0F);
 168: 30 e0        ldi r19, 0x00 ; 0
 16a: 8f 70        andi r24, 0x0F ; 15
 16c: 90 e0        ldi r25, 0x00 ; 0
 16e: 02 96        adiw r24, 0x02 ; 2
 170: 02 c0        rjmp .+4      ; 0x176 <_Z8bcd2dec3h+0x12>
 172: 35 95        asr r19
 174: 27 95        ror r18
 176: 8a 95        dec r24
 178: e2 f7        brpl .-8      ; 0x172 <_Z8bcd2dec3h+0xe>
 17a: c9 01        movw r24, r18
 17c: 08 95        ret
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12456
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 smiley-red smiley-red smiley-red smiley
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

NY, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Nuovo Arduinisto
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you very much guys. I apologize if my questions were vague, I had a hard time putting into words exactly what I was looking for. The piece of code I was looking for was this:
Code:
seconds = ((60 + elap_seconds) - init_seconds) % 60;

This would allow the "counter" to count up to 60 seconds and reset to 0 at 60. Here, I only worked with seconds to keep it a bit simpler, and not deal with minutes just yet. So yes, this code is only concerned with intervals of 59 seconds. I am now able to focus on the minutes (and hours) for the rollover time. My Timer function now looks like this:
Code:
int Timer() {
  elapsedTime();
  seconds = ((60 + elap_seconds) - init_seconds) % 60;
  if(seconds%60==0) {
    minutes = ((60 + elap_minutes) - init_minutes) % 60;
  }
  if(minutes%24==0) {
    hours = ((24 + elap_hours) - init_hours) % 24;
  }
}
When a full 60 seconds pass, it rolls over to minutes, and continues counting seconds.

The code I know have is below:
Code:
#include <Wire.h>

const int button1 = 2;
const int button2 = 3;
const int LED = 13;
boolean butt1State;
boolean butt2State;
int seconds, minutes, hours, init_seconds, init_minutes, init_hours, elap_seconds, elap_minutes, elap_hours;

void setup() {
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  
  Wire.begin();
  Serial.begin(9600);
  
  // clear /EOSC bit
  // Sometimes necessary to ensure that the clock keeps running on just battery power.
  // Once set, it shouldn't need to be reset but it's a good idea to make sure.
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // select register
  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
  Wire.endTransmission();
  
  Serial.print("Initial Time");Serial.print("\t");Serial.print("Current Time");Serial.print("\t");Serial.println("Elapsed Time");
}

void loop() {
  butt1State=digitalRead(button1);
  butt2State=digitalRead(button2);
  
  if(butt1State==LOW) {
    initialTime();
    Serial.print(init_hours);Serial.print(":");Serial.print(init_minutes);Serial.print(":");Serial.println(init_seconds);
    digitalWrite(LED, !butt1State);
    delay(1000);
  }
  
  if(butt2State==LOW) {
    Timer();
    Serial.print(init_hours);Serial.print(":");Serial.print(init_minutes);Serial.print(":");Serial.print(init_seconds);Serial.print("\t");
    Serial.print(elap_hours);Serial.print(":");Serial.print(elap_minutes);Serial.print(":");Serial.print(elap_seconds);Serial.print("\t");
    Serial.print(hours);Serial.print(":");Serial.print(minutes);Serial.print(":");Serial.println(seconds);
    digitalWrite(LED, !butt2State);
    delay(1000);
  }
}

int Timer() {
  elapsedTime();
  seconds = ((60 + elap_seconds) - init_seconds) % 60;
  if(seconds%60==0) {
    minutes = ((60 + elap_minutes) - init_minutes) % 60;
  }
  if(minutes%24==0) {
    hours = ((24 + elap_hours) - init_hours) % 24;
  }
}

int initialTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3);
  
  while(Wire.available()) {
    init_seconds = Wire.read();
    init_minutes = Wire.read();
    init_hours = Wire.read();
    
    init_seconds = (((init_seconds & 0b11110000)>>4)*10 + (init_seconds & 0b00001111)); // convert BCD to decimal
    init_minutes = (((init_minutes & 0b11110000)>>4)*10 + (init_minutes & 0b00001111)); // convert BCD to decimal
    init_hours = (((init_hours & 0b00100000)>>5)*20 + ((init_hours & 0b00010000)>>4)*10 + (init_hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode)
    return(init_seconds);
  }
}

int elapsedTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3);
  
  while(Wire.available()) {
    elap_seconds = Wire.read();
    elap_minutes = Wire.read();
    elap_hours = Wire.read();
    
    elap_seconds = (((elap_seconds & 0b11110000)>>4)*10 + (elap_seconds & 0b00001111)); // convert BCD to decimal
    elap_minutes = (((elap_minutes & 0b11110000)>>4)*10 + (elap_minutes & 0b00001111)); // convert BCD to decimal
    elap_hours = (((elap_hours & 0b00100000)>>5)*20 + ((elap_hours & 0b00010000)>>4)*10 + (elap_hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode
    return(elap_seconds);
  }
}
« Last Edit: May 20, 2013, 02:38:31 pm by Osiris » Logged

NY, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Nuovo Arduinisto
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just modified the code a bit to include a leading zero for the hour, minute or second < 0
Code:
// Program Size: 6,660/32,256 bytes

#include <Wire.h>

const int button1 = 2;
const int button2 = 3;
const int LED = 13;
boolean butt1State, butt2State;
int seconds, minutes, hours, init_seconds, init_minutes, init_hours, elap_seconds, elap_minutes, elap_hours;

void setup() {
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  
  Wire.begin();
  Serial.begin(9600);
  
  // clear /EOSC bit
  // Sometimes necessary to ensure that the clock keeps running on just battery power.
  // Once set, it shouldn't need to be reset but it's a good idea to make sure.
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // select register
  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
  Wire.endTransmission();
  
  Serial.print("Initial Time");Serial.print("\t");Serial.print("Current Time");Serial.print("\t");Serial.println("Elapsed Time");
}

void loop() {
  butt1State=digitalRead(button1);
  butt2State=digitalRead(button2);
  
  if(butt1State==LOW) {
    initialTime();
    if(init_hours<10) {
      Serial.print("0");Serial.print(init_hours);
    } else {
      Serial.print(init_hours);
    }
    Serial.print(":");
    if(init_minutes<10) {
      Serial.print("0");Serial.print(init_minutes);
    } else {
      Serial.print(init_minutes);
    }
    Serial.print(":");
    if(init_seconds<10) {
      Serial.print("0");Serial.println(init_seconds);
    } else {
      Serial.println(init_seconds);
    }
    digitalWrite(LED, !butt1State);
    delay(1000);
  }
  
  if(butt2State==LOW) {
    Timer();
    if(init_hours<10) {
      Serial.print("0");Serial.print(init_hours);
    } else {
      Serial.print(init_hours);
    }
    Serial.print(":");
    if(init_minutes<10) {
      Serial.print("0");Serial.print(init_minutes);
    } else {
      Serial.print(init_minutes);
    }
    Serial.print(":");
    if(init_seconds<10) {
      Serial.print("0");Serial.print(init_seconds);Serial.print("\t");
    } else {
      Serial.print(init_seconds);Serial.print("\t");
    }
    
    if(elap_hours<10) {
      Serial.print("0");Serial.print(elap_hours);
    } else {
      Serial.print(elap_hours);
    }
    Serial.print(":");
    if(elap_minutes<10) {
      Serial.print("0");Serial.print(elap_minutes);
    } else {
      Serial.print(elap_minutes);
    }
    Serial.print(":");
    if(elap_seconds<10) {
      Serial.print("0");Serial.print(elap_seconds);Serial.print("\t");
    } else {
      Serial.print(elap_seconds);Serial.print("\t");
    }
    if(hours<10) {
      Serial.print("0");Serial.print(hours);
    } else {
      Serial.print(hours);
    }
    Serial.print(":");
    if(minutes<10) {
      Serial.print("0");Serial.print(minutes);
    } else {
      Serial.print(minutes);
    }
    Serial.print(":");
    if(seconds<10) {
      Serial.print("0");Serial.println(seconds);
    } else {
      Serial.println(seconds);
    }
    digitalWrite(LED, !butt2State);
    delay(1000);
  }
}

int Timer() {
  elapsedTime();
  seconds = ((60 + elap_seconds) - init_seconds) % 60;
  if(seconds%60==0) {
    minutes = ((60 + elap_minutes) - init_minutes) % 60;
  }
  if(minutes%24==0) {
    hours = ((24 + elap_hours) - init_hours) % 24;
  }
}

int initialTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3);
  
  while(Wire.available()) {
    init_seconds = Wire.read();
    init_minutes = Wire.read();
    init_hours = Wire.read();
    
    init_seconds = (((init_seconds & 0b11110000)>>4)*10 + (init_seconds & 0b00001111)); // convert BCD to decimal
    init_minutes = (((init_minutes & 0b11110000)>>4)*10 + (init_minutes & 0b00001111)); // convert BCD to decimal
    init_hours = (((init_hours & 0b00100000)>>5)*20 + ((init_hours & 0b00010000)>>4)*10 + (init_hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode)
    return(init_seconds);
  }
}

int elapsedTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3);
  
  while(Wire.available()) {
    elap_seconds = Wire.read();
    elap_minutes = Wire.read();
    elap_hours = Wire.read();
    
    elap_seconds = (((elap_seconds & 0b11110000)>>4)*10 + (elap_seconds & 0b00001111)); // convert BCD to decimal
    elap_minutes = (((elap_minutes & 0b11110000)>>4)*10 + (elap_minutes & 0b00001111)); // convert BCD to decimal
    elap_hours = (((elap_hours & 0b00100000)>>5)*20 + ((elap_hours & 0b00010000)>>4)*10 + (elap_hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode
    return(elap_seconds);
  }
}

If anyone wants to see the output (the initial time and elapsed time are printed in 24 HR time format):
Code:
Initial Time Current Time Elapsed Time
15:22:30
15:22:30 15:22:31 00:00:01
15:22:30 15:22:32 00:00:02
15:22:30 15:22:33 00:00:03
15:22:30 15:22:34 00:00:04
15:22:30 15:22:35 00:00:05
...
15:22:30 15:23:25 00:00:55
15:22:30 15:23:26 00:00:56
15:22:30 15:23:27 00:00:57
15:22:30 15:23:28 00:00:58
15:22:30 15:23:29 00:00:59
15:22:30 15:23:30 00:01:00
15:22:30 15:23:31 00:01:01
15:22:30 15:23:32 00:01:02
15:22:30 15:23:33 00:01:03
15:22:30 15:23:34 00:01:04
15:22:30 15:23:35 00:01:05
...
15:22:30 15:24:25 00:01:55
15:22:30 15:24:26 00:01:56
15:22:30 15:24:27 00:01:57
15:22:30 15:24:28 00:01:58
15:22:30 15:24:29 00:01:59
15:22:30 15:24:30 00:02:00
15:22:30 15:24:31 00:02:01

Thanks again for all your help. English is my native language, but programming is still a bit foreign to me  smiley-lol

You guys have been discussing the accuracy of the BCD conversion, I'm not exactly sure why Macetech's is "more efficient". Is this more of a programming reason, or a mathematical reason (e.g., 10%6 will still return a value, just not an integer)?

My next step with this, is to time different events and add them together. That is;
I walk into a room->timer starts,
I walk out 31 seconds later: T = 00:00:31,
5 minutes later I walk into the room, timer starts again,
I walk out 2 minutes and 14 seconds later: T = 00:02:45
and so on...
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 71
Posts: 3512
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks again for all your help. English is my native language, but programming is still a bit foreign to me  smiley-lol

No problem. Nice job on the code. (BTW, the language that all programmers know best is profanity smiley-wink )

Quote
You guys have been discussing the accuracy of the BCD conversion, I'm not exactly sure why Macetech's is "more efficient". Is this more of a programming reason, or a mathematical reason (e.g., 10%6 will still return a value, just not an integer)?

It's not at all a question of accuracy, I could tell that Macetech's conversion would give the same results as mine. However, I thought that his might be more efficient (fewer instructions). Once I looked at the assembler code, I found that the two were in fact identical.

Choose whichever looks better to you, play rock-paper-scissors to decide, etc. smiley-grin
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

NY, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Nuovo Arduinisto
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No problem. Nice job on the code. (BTW, the language that all programmers know best is profanity smiley-wink )

Thanks and I'm well versed in profanity  smiley

I'm now running into a bit of trouble of getting this work as a start/stop timer. Basically, I'd like to hit a button and the timer starts:
Code:
00:00:00 // Initial Time
// Button press
00:00:01
00:00:02
// Button release
// Wait some time, e.g., 10 seconds
// Button press
00:00:03
00:00:04
...

The above code would continuously count after the initial button press, i.e., as soon as the button is pressed the time is reset and begins and continues counting. I was then able to have it start and stop on button presses and declared a new variable t_seconds += seconds, however, let's say the initial timer ended at 00:00:05, during the second start of the timer (which now makes sense), it is going to compound the time so I would get:
Code:
00:00:06 //+1
00:00:08 //+2
00:00:11 //+3
etc...

and would potentially miss, and continue counting pass the 60 second mark [currently only focusing on the second timer]. I thought I could solve this by dividing seconds into itself: seconds+=(seconds/seconds), but this would sometimes return unexpected numbers.

I have a few ideas of what it might be, but having a bid hard of a time interpreting it I guess (who am I kidding, it's coming down to math again  smiley-lol !). If anyone has any ideas, please. Thanks.
Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A minor fix:
Code:
seconds = ((60 + elap_seconds) - init_seconds) % 60;
That is equivalent to:
Code:
seconds = (elap_seconds - init_seconds) % 60;

The same type of thing applies to the minutes and hours.

Pete
Logged

Where are the Nick Gammons of yesteryear?

NY, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Nuovo Arduinisto
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A minor fix:
Code:
seconds = ((60 + elap_seconds) - init_seconds) % 60;
That is equivalent to:
Code:
seconds = (elap_seconds - init_seconds) % 60;

The same type of thing applies to the minutes and hours.

Pete

Hmm. I thought perhaps the "extra" 60 was to prevent negative values when elap_time resets and then becomes less than init_time?

So i understand a bit more of what is going on here...
I'm just going to deal with the seconds here (and is probably the only thing we have to concern ourselves with). Below is the pasted code, but I'l reference.
Code:
// Program Size: 6,660/32,256 bytes

#include <Wire.h>

const int button1 = 2;
const int button2 = 3;
const int LED = 13;
boolean butt1State, butt2State;
int seconds, minutes, hours,
    init_seconds, init_minutes, init_hours,
    elap_seconds, elap_minutes, elap_hours,
    t_seconds, t_minutes, t_hours;

void setup() {
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
 
  Wire.begin();
  Serial.begin(9600);
 
  // clear /EOSC bit
  // Sometimes necessary to ensure that the clock keeps running on just battery power.
  // Once set, it shouldn't need to be reset but it's a good idea to make sure.
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // select register
  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
  Wire.endTransmission();
}

void loop() {
  butt1State=digitalRead(button1);
  butt2State=digitalRead(button2);
   
  if(butt1State==LOW) {
    initialTime();
    Serial.print(init_hours);Serial.print(":");
    Serial.print(init_minutes);Serial.print(":");
    Serial.println(init_seconds);
    delay(1000);
  }
 
  //Use digitalRead(button2)==LOW for start/stop
  if(digitalRead(button2)==LOW) {
    runTime();
    //Use t_seconds to store each second that passes when button is pressed
    //divide seconds into itself for compound addition of one
    t_seconds+=(seconds/seconds);
   
   
    //Resets the seconds when t_seconds reaches 60
    if(t_seconds%60==0) {
      t_seconds=0;
      t_minutes++;
    }
   
    Serial.print(init_hours);Serial.print(":");Serial.print(init_minutes);Serial.print(":");Serial.print(init_seconds);Serial.print("\t");
    Serial.print(elap_hours);Serial.print(":");Serial.print(elap_minutes);Serial.print(":");Serial.print(elap_seconds);Serial.print("\t");
    Serial.print(hours);Serial.print(":");Serial.print(minutes);Serial.print(":");Serial.print(seconds);Serial.print("\t");
    Serial.print(t_hours);Serial.print(":");Serial.print(t_minutes);Serial.print(":");Serial.println(t_seconds);
    delay(1000);
  }
 
}

int runTime() {
 
  elapsedTime();
  seconds = ((60 + elap_seconds) - init_seconds) % 60;
 
/* This code was an attempt to reset the initial time and avoid the -1 error
  if(elap_seconds%60==0) {
    elap_minutes++;
    initialTime();
  }
*/

}

int initialTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1);
 
  while(Wire.available()) {
    init_seconds = Wire.read();
    init_seconds = (((init_seconds & 0b11110000)>>4)*10 + (init_seconds & 0b00001111)); // convert BCD to decimal
    init_seconds = init_seconds - init_seconds; //set init_seconds to zero
  }
}

int elapsedTime() {
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write(0x00); // start at register
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1);
 
  while(Wire.available()) {
    elap_seconds = Wire.read();
    elap_seconds = (((elap_seconds & 0b11110000)>>4)*10 + (elap_seconds & 0b00001111)); // convert BCD to decimal
  }
}

I am using t_seconds to store the seconds ONLY when the button is pressed. This part works, but there are two problems:
(1) When seconds rolls over from 59 to 0, t_seconds=(seconds/seconds) actually becomes 0 divided by 0 and returns -1. This then subtracts 1 from t_seconds, but will continue adding and repeat this at the same time point. I've tried negating the -1 by multiplication, or adding 2 i.e., ((-1)+1=0+1=1), but it will always subtract the 1.
(2) The use of delay waits for the second to pass, removal of the delay, will add +1 as fast as the MCU can, e.g., if I were to set delay(500); than each passing "actual" second the MCU would actually be adding 2 seconds. The delay here was more for debugging, and I am trying to avoid the use of delay.

Therefore, I seem to be back at square one. Any ideas anyone?
Logged

Pages: [1] 2   Go Up
Jump to: