loading

Problem in arduino code... you'll have to run this one to understand - Word Clock?

I have been writing this code for the Word clock. I am trying to customize the code to fit into an atmega8, and use DS1307 RTC. Both of these is fine, but what is wrong is that when I upload my code and try to set the time by using the buttons, the time is not setting properly. I can increment minutes with the minutes button to 16, but not further. Hours works fine, but if, lets say the time is 6:36 on the arduino, then If I press the hour button, I find that time changes to 7:31. Five minutes less than what I expected.
What am I overlooking here? 
I advise to run the code and understand the problem.

On the other hand Binary sketch size: 7164 bytes (of a 7168 byte maximum), this is just 4 bytes short of max. Can that be a part of the problem

Code:

#include <Wire.h>

// Display output pin assignments
#define MTEN  Display1=Display1 | (1<<0) 
#define HALF Display1=Display1 | (1<<1)
#define QUARTER Display1=Display1 | (1<<2)
#define TWENTY Display1=Display1 | (1<<3)
#define MFIVE Display1=Display1 | (1<<4)
#define MINUTES Display1=Display1 | (1<<5)
#define PAST Display1=Display1 | (1<<6)
#define UNUSED1 Display1=Display1 | (1<<7)

#define TO Display2=Display2 | (1<<0)
#define ONE Display2=Display2 | (1<<1)
#define TWO Display2=Display2 | (1<<2)
#define THREE Display2=Display2 | (1<<3)
#define FOUR Display2=Display2 | (1<<4)
#define HFIVE Display2=Display2 | (1<<5)
#define SIX Display2=Display2 | (1<<6)
#define UNUSED2 Display2=Display2 | (1<<7)

#define SEVEN Display3=Display3 | (1<<0)
#define EIGHT Display3=Display3 | (1<<1)
#define NINE Display3=Display3 | (1<<2)
#define HTEN Display3=Display3 | (1<<3)
#define ELEVEN Display3=Display3 | (1<<4)
#define TWELVE Display3=Display3 | (1<<5)
#define OCLOCK  Display3=Display3 | (1<<6)
#define UNUSED3 Display3=Display3 | (1<<7)

#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address
#if defined(ARDUINO) && ARDUINO >= 100   // Arduino v1.0 and newer
  #define I2C_WRITE Wire.write
  #define I2C_READ Wire.read
#else                                   // Arduino Prior to v1.0
  #define I2C_WRITE Wire.send
  #define I2C_READ Wire.receive
#endif


int  hr=12, mn=00, scnd=0;
static unsigned long msTick =0;  // the number of Millisecond Ticks since we last
                                 // incremented the second counter
int  count;
boolean selftestmode;
boolean  DS1307Present=false;       // flag to indicate that the 1307 is there..    1 = present
char Display1=0, Display2=0, Display3=0;

// hardware constants
static unsigned int LEDClockPin=5;    //11 d5 ok
static unsigned int LEDDataPin=3;    //5 d3
static unsigned int LEDStrobePin=4;   //6 d4

static unsigned int MinuteButtonPin=6;  //d6 12
static unsigned int HourButtonPin=7;    //d7 13
static unsigned int PWMPin = 11;

char buf[50]; // time output string for debugging

byte decToBcd(byte b)
{  return ( ((b/10) << 4) + (b%10) );}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte b)
{  return ( ((b >> 4)*10) + (b%16) );}

void getTime()
{
  //read from chip and store in hr, mn, scnd
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  I2C_WRITE((uint8_t) 0x00);
  Wire.endTransmission();
 
  Wire.requestFrom(DS1307_I2C_ADDRESS, 3);
  scnd = bcdToDec(I2C_READ());
  mn =  bcdToDec(I2C_READ());
  hr =  bcdToDec(I2C_READ());
}
void setTime()
{
  //to be paranoid, we're going to first stop the clock
  //to ensure we don't have rollovers while we're
  //writing:
  writeRTCreg(0,0x80);
  //now, we'll write everything *except* the second
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  I2C_WRITE((uint8_t) 0x01);
  I2C_WRITE(mn);
  I2C_WRITE(hr);

  Wire.endTransmission();
  //now, we'll write the seconds; we didn't have to keep
  //track of whether the clock was already running, because
  //scnd already knows what we want it to be. This
  //will restart the clock as it writes the new seconds value.
  writeRTCreg(0,scnd);
}
byte readRTCreg(byte adr)
{
   if(adr > 0x3F) { return 0xff; }
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  I2C_WRITE(adr);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 1);
  return I2C_READ();
}
void writeRTCreg(byte adr, byte val)
{
if(adr > 0x3F) { return; }
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   I2C_WRITE(adr);
   I2C_WRITE(val);
   Wire.endTransmission();
}

void print_DS1307time()
{
  /* Format the time and date and insert into the temporary buffer */
  snprintf(buf, sizeof(buf), "RTC time: %02d:%02d:%02d",
  hr, mn, scnd);

  /* Print the formatted string to serial so we can see the time */
  Serial.println(buf);

}

void setup()
{
  // initialise the hardware
  // initialize the appropriate pins as outputs:
  pinMode(LEDClockPin, OUTPUT);
  pinMode(LEDDataPin, OUTPUT);
  pinMode(LEDStrobePin, OUTPUT);
 
 
  //pinMode(BrightnessPin, INPUT);
  pinMode(MinuteButtonPin, INPUT);
  pinMode(HourButtonPin, INPUT);
  digitalWrite(MinuteButtonPin, HIGH);  //set internal pullup
  digitalWrite(HourButtonPin, HIGH); //set internal pullup


  pinMode(PWMPin, OUTPUT);
 
  Serial.begin(9600);
  Wire.begin();
   // test whether the DS1302 is there
  Serial.print("Verifying DS1307 ");
  // start by verifying that the chip has a valid signature
  if (readRTCreg(0x20) == 0x55) {
    // Signature is there - set the present flag and mmove on
    DS1307Present=true;
    Serial.println("Valid Signature");
  }
  else
  {
    // Signature isnt there - may be a new chip -
    //   do a write to see if it will hold the signature
    writeRTCreg(0x20,0x55);
    if (readRTCreg(0x20) == 0x55) {
      // We can store data - assume that it is a new chip that needs initialisation
/*      // Start by clearing the clock halt flag.
          //"Bit 7 of register 0 is the clock halt (CH) bit.
          //When this bit is set to a 1, the oscillator is disabled."
            byte _reg0_sec = decToBcd(scnd);
            _reg0_sec = _reg0_sec & ~0x80;
            writeRTCreg(0,_reg0_sec);
*/
      // Set the time and date on the chip
      scnd = 0;
      mn = 0;
      hr = 12;
      setTime();
      // set the DS1302 present flag
      DS1307Present=true;
      Serial.println("present - new chip initialised.");
    }
    else  Serial.println("absent");
  } 


  msTick=millis();      // Initialise the msTick counter
    selftest();
  selftestmode=false;

  if (DS1307Present) {
    // Get the current time and date from the chip
   getTime();
    }
 
  displaytime();        // display the current time
}



void ledsoff(void) {
Display1=0;
Display2=0;
Display3=0;
}

void WriteLEDs(void) {
// Now we write the actual values to the hardware
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display3);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display2);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display1);
digitalWrite(LEDStrobePin,HIGH);
delay(2);
digitalWrite(LEDStrobePin,LOW);


}

void selftest(void){
  Serial.print("TEST");
  analogWrite(PWMPin, 255);
 
  ledsoff(); MTEN; WriteLEDs(); delay(500);
  ledsoff(); HALF; WriteLEDs(); delay(500);
  ledsoff(); QUARTER; WriteLEDs(); delay(500);
  ledsoff(); TWENTY; WriteLEDs(); delay(500);
  ledsoff(); MFIVE; WriteLEDs(); delay(500);
  ledsoff(); MINUTES; WriteLEDs(); delay(500);
  ledsoff(); PAST; WriteLEDs(); delay(500);
  ledsoff(); TO; WriteLEDs(); delay(500);
  ledsoff(); ONE; WriteLEDs(); delay(500);
  ledsoff(); TWO; WriteLEDs(); delay(500);
  ledsoff(); THREE; WriteLEDs(); delay(500);
  ledsoff(); FOUR; WriteLEDs(); delay(500);
  ledsoff(); HFIVE; WriteLEDs(); delay(500);
  ledsoff(); SIX; WriteLEDs(); delay(500);
  ledsoff(); SEVEN; WriteLEDs(); delay(500);
  ledsoff(); EIGHT; WriteLEDs(); delay(500);
  ledsoff(); NINE; WriteLEDs(); delay(500);
  ledsoff(); HTEN; WriteLEDs(); delay(500);
  ledsoff(); ELEVEN; WriteLEDs(); delay(500);
  ledsoff(); TWELVE; WriteLEDs(); delay(500);
  ledsoff(); OCLOCK; WriteLEDs(); delay(500);
}


void displaytime(void){

  // start by clearing the display to a known state
  ledsoff();
 
  Serial.print("It is ");

  // now we display the appropriate minute counter
  if ((mn>4) && (mn<10)) {
    MFIVE;
    MINUTES;
    Serial.print("Five Minutes ");
  }
  if ((mn>9) && (mn<15)) {
    MTEN;
    MINUTES;
    Serial.print("Ten Minutes ");
  }
  if ((mn>14) && (mn<20)) {
    QUARTER;
      Serial.print("Quarter ");
  }
  if ((mn>19) && (mn<25)) {
    TWENTY;
    MINUTES;
    Serial.print("Twenty Minutes ");
  }
  if ((mn>24) && (mn<30)) {
    TWENTY;
    MFIVE;
    MINUTES;
    Serial.print("Twenty Five Minutes ");
  } 
  if ((mn>29) && (mn<35)) {
    HALF;
    Serial.print("Half ");
  }
  if ((mn>34) && (mn<40)) {
    TWENTY;
    MFIVE;
    MINUTES;
    Serial.print("Twenty Five Minutes ");
  } 
  if ((mn>39) && (mn<45)) {
    TWENTY;
    MINUTES;
    Serial.print("Twenty Minutes ");
  }
  if ((mn>44) && (mn<50)) {
    QUARTER;
    Serial.print("Quarter ");
  }
  if ((mn>49) && (mn<55)) {
    MTEN;
    MINUTES;
    Serial.print("Ten Minutes ");
  }
  if (mn>54) {
    MFIVE;
    MINUTES;
    Serial.print("Five Minutes ");
  }



  if ((mn <5))
  {
    switch (hr) {
    case 1:
      ONE;
      Serial.print("One ");
      break;
    case 2:
      TWO;
      Serial.print("Two ");
      break;
    case 3:
      THREE;
      Serial.print("Three ");
      break;
    case 4:
      FOUR;
      Serial.print("Four ");
      break;
    case 5:
      HFIVE;
      Serial.print("Five ");
      break;
    case 6:
      SIX;
      Serial.print("Six ");
      break;
    case 7:
      SEVEN;
      Serial.print("Seven ");
      break;
    case 8:
      EIGHT;
      Serial.print("Eight ");
      break;
    case 9:
      NINE;
      Serial.print("Nine ");
      break;
    case 10:
      HTEN;
      Serial.print("Ten ");
      break;
    case 11:
      ELEVEN;
      Serial.print("Eleven ");
      break;
    case 12:
      TWELVE;
      Serial.print("Twelve ");
      break;
    }
  OCLOCK;
  Serial.println("O'Clock");
  }
  else
    if ((mn < 35) && (mn >4))
    {
      PAST;
      Serial.print("Past ");
      switch (hr) {
    case 1:
      ONE;
      Serial.println("One ");
      break;
    case 2:
      TWO;
      Serial.println("Two ");
      break;
    case 3:
      THREE;
      Serial.println("Three ");
      break;
    case 4:
      FOUR;
      Serial.println("Four ");
      break;
    case 5:
      HFIVE;
      Serial.println("Five ");
      break;
    case 6:
      SIX;
      Serial.println("Six ");
      break;
    case 7:
      SEVEN;
      Serial.println("Seven ");
      break;
    case 8:
      EIGHT;
      Serial.println("Eight ");
      break;
    case 9:
      NINE;
      Serial.println("Nine ");
      break;
    case 10:
      HTEN;
      Serial.println("Ten ");
      break;
    case 11:
      ELEVEN;
      Serial.println("Eleven ");
      break;
    case 12:
      TWELVE;
      Serial.println("Twelve ");
      break;
      }
    }
    else
    {
      // if we are greater than 34 minutes past the hour then display
      // the next hour, as we will be displaying a 'to' sign
      TO;
      Serial.print("To ");
      switch (hr) {
      case 1:
        TWO;
       Serial.println("Two ");
       break;
      case 2:
        THREE;
      Serial.println("Three ");
        break;
      case 3:
        FOUR;
      Serial.println("Four ");
        break;
      case 4:
        HFIVE;
      Serial.println("Five ");
        break;
      case 5:
        SIX;
      Serial.println("Six ");
        break;
      case 6:
        SEVEN;
      Serial.println("Seven ");
        break;
      case 7:
        EIGHT;
      Serial.println("Eight ");
        break;
      case 8:
        NINE;
      Serial.println("Nine ");
        break;
      case 9:
        HTEN;
      Serial.println("Ten ");
        break;
      case 10:
        ELEVEN;
      Serial.println("Eleven ");
        break;
      case 11:
        TWELVE;
      Serial.println("Twelve ");
        break;
      case 12:
        ONE;
      Serial.println("One ");
        break;
      }
    }



   WriteLEDs();
  
}


void incrementtime(void){
  // increment the time counters keeping care to rollover as required
  scnd=0;
  if (++mn >= 60) {
    mn=0;
    if (++hr == 13) {
      hr=1; 
    }
  } 
  // debug outputs
  Serial.println();
//  if (DS1307Present)
//  print_DS1307time();
//  else{
//  Serial.print("Arduino Time: " );
  Serial.print(hr);
  Serial.print(":");
  Serial.print(mn);
  Serial.print(":");
  Serial.println(scnd);
//  }

}


void loop(void)
{
 
  //selftest();
int aread = sq(analogRead(3)/4)+3;
  //Uncomment the following line and comment the next one in order to
  //  enable dimming via a potentiometer connected to pin 0:
  analogWrite(PWMPin, aread>255 ? 255:aread);
  //analogWrite(PWMPin, 255);
 
    // heart of the timer - keep looking at the millisecond timer on the Arduino
    // and increment the seconds counter every 1000 ms
    if ( millis() - msTick >999) {
        msTick=millis();
        scnd++;
/*        // Flash the onboard Pin13 Led so we know something is hapening!
        digitalWrite(13,HIGH);
        delay(100);
        digitalWrite(13,LOW);   
*/    }
   
   
   
    //test to see if we need to increment the time counters
    if (scnd==60)
    {
      incrementtime();
      displaytime();
    }
if (DS1307Present) {
    // Get the current time and date from the chip
     getTime();
    }
    // test to see if a forward button is being held down
    // for time setting
    if ( (digitalRead(MinuteButtonPin) ==0 ) && scnd!=1)
      // the forward button is down
      // and it has been more than one second since we
      // last looked
    {
      mn=(((mn/5)*5) +5);
      scnd=0;
      incrementtime();
      scnd++;  // Increment the second counter to ensure that the name
      // flash doesnt happen when setting time
      if (DS1307Present) {

      // Set the time on the chip
      setTime();
    }
    delay(100);
      displaytime();
    }

    // test to see if the back button is being held down
    // for time setting
    if ((digitalRead(HourButtonPin)==0 ) && scnd!=1)
    {
      /*
      minute=(((minute/5)*5) -5);
      second=0; // decrement the minute counter
      if (minute<0) {
        minute=55;
        if (--hour <0) hour=12;
      }
      */
     
      mn = (mn/5)*5;  //round minute down to previous 5 min interval
      if (++hr == 13) {
        hr=1; 
      }
      incrementtime();
      scnd++;  // Increment the second counter to ensure that the name
      // flash doesnt happen when setting time 
      if (DS1307Present) {
      // Set the time and date on the chip
      setTime();
    }
    delay(100);
      displaytime();
    }

}

Picture of Problem in arduino code... you'll have to run this one to understand - Word Clock?
sort by: active | newest | oldest
frollard5 years ago
I can't compile it to give real advice;

debugging; you need to find exactly where it goes wrong. Is your time number correct and the word count wrong -- or is the time math wrong?

I'd write a nested for loop that goes through every possible time from 00:00 to 11:59, and outputs that number to serial monitor, and to the screen. perhaps add a delay to make it obvious whats happening. Increment the time with a procedure rather than just 'set time = x loop', so more like time = time++

If the time counting math is proper, and outputs to the serial and display correctly, then its a problem with your 'hour incrementing' procedure.
I have a hunch that:


minute=(((minute/5)*5) -5);
second=0; // decrement the minute counter
if (minute<0) {
minute=55;
if (--hour <0) hour=12;
}
*/

is causing the problem...right at the end -- are you making the minutes step by increments of 5 while setting the time? in which case it might prevent you from stepping above 16 for some ridiculous reason.

I would personally keep the minutes stored as proper minutes and only convert them during the 'output' calculations.
pro2xy (author)  frollard5 years ago
Yes, thats right, it increments five minutes at a time. But that part you just read is commented out, instead there's an increment function. I should probably post my code again after clearing it out a bit.. shall I?
+1
pro2xy (author)  frollard5 years ago
Normal time increment is fine. When it is incrementing itself it runs well and good. Just when setting time using the 'minute' button, it goes wrong. Lately I realised that its not just for 16 but any value above 15...
pro2xy (author) 5 years ago
Latest update! It worked... I flashed the AVR with the same code again and it worked fine :D but strange
thanks all... which one should I mark the best answer?
frollard pro2xy5 years ago
Glad you got it working, and thanks for the BA :)

Keep coding and if it works well -- post your iteration as an ible!
pro2xy (author)  frollard5 years ago
I will... Just waiting for a camera to take the pics.. :)
pro2xy (author) 5 years ago
Forgot to add.. The code is a mix of a couple of codes found on the net. The base being Doug Jackson's word clock. The interaction with the RTC is based on I2C (Wire library)