Go Down

Topic: setClock() causes program to freeze (Read 2125 times) previous topic - next topic

bach_tenor

I'm using a DS1307 real-time clock for a project, and I'm attempting to set the clock during an interrupt.
I've verified that the clock can be set during normal/non-interrupt operation without freezing, so it seems to only be a problem during interrupt routines.

I remember having a problem with freezing occurring during interrupt due to calling delay(), and so I looked through the wire and RTC libraries I'm using but did not find any instances of delay() being called.

I'm not sure what is causing this problem, so I am hoping someone else might know what the problem is here.

PaulS

Might help to show your code, so we know what libraries you're using.

I'm wondering, though, why you need to set the clock during an ISR. Could you simply set a flag that says that the clock needs to be set?
The art of getting good answers lies in asking good questions.

bach_tenor

Sorry about that, here's the offending code. This SaveTimes() function is called during the interrupt. I tried setting a flag to set the clock back in the main loop, but depending on where the interrupt occurred, the program may resume after the interrupt and overwrite any changes I've made to the clock variables before it gets a chance to call SetClock().

Quote

void SaveTimes()
{
  setClock();
  
  //Save transition times (hour/minute) to EEPROM                                      
  EEPROM.write(16, DesiredValue[0]);
  EEPROM.write(17, DesiredValue[1]);
  EEPROM.write(18, DesiredValue[2]);
  EEPROM.write(19, DesiredValue[3]);
  
  clearLCD();
  selectLineOne();
  Serial.print("Saving Clock...");
  kp_escstate = HIGH;
  InterruptDelay(2000);
}



Quote

/*
**********************************************************************
 RTC Function Library
 **********************************************************************
 */
void setClock()
{
  //Debugging
  clearLCD();
  selectLineOne();
  Serial.print("debug");
  InterruptDelay(1000);
  
  Wire.beginTransmission(DS1307);
  Wire.send(R_SECS);
  Wire.send(second);
  Wire.send(minute);
  Wire.send(hour);
  Wire.send(wkDay);
  Wire.send(day);
  Wire.send(month);
  Wire.send(year);
  Wire.send(ctrl);
  Wire.endTransmission();
  //Debugging
  clearLCD();
  selectLineOne();
  Serial.print("debug2");
  InterruptDelay(1000);
}


void getClock()
{
  Wire.beginTransmission(DS1307);
  Wire.send(R_SECS);
  Wire.endTransmission();
  Wire.requestFrom(DS1307, 8);
  second = Wire.receive();
  minute = Wire.receive();
  hour   = Wire.receive();
  wkDay  = Wire.receive();
  day    = Wire.receive();
  month  = Wire.receive();
  year   = Wire.receive();
  ctrl   = Wire.receive();
}


byte bcd2Dec(byte bcdVal)
{
  return bcdVal / 16 * 10 + bcdVal % 16;
}

byte dec2Bcd(byte decVal)
{
  return decVal * 16 / 10 - decVal % 16;  
}

void printHex2(byte hexVal)
{
  if (hexVal < 0x10)
    Serial.print("0");
  Serial.print(hexVal, HEX);
}


void printDec2(byte decVal)
{
  if (decVal < 10)
    Serial.print("0");
  Serial.print(decVal, DEC);
}


void printDayName(byte d)
{
  switch (d) {
  case 1:
    Serial.print("SUN");
    break;
  case 2:
    Serial.print("MON");
    break;
  case 3:
    Serial.print("TUE");
    break;
  case 4:
    Serial.print("WED");
    break;
  case 5:
    Serial.print("THU");
    break;
  case 6:
    Serial.print("FRI");
    break;
  case 7:
    Serial.print("SAT");
    break;
  default:
    Serial.print("???");
  }
}


void printMonthName(byte m)
{
  switch (m) {
  case 1:
    Serial.print("JAN");
    break;
  case 2:
    Serial.print("FEB");
    break;
  case 3:
    Serial.print("MAR");
    break;
  case 4:
    Serial.print("APR");
    break;
  case 5:
    Serial.print("MAY");
    break;
  case 6:
    Serial.print("JUN");
    break;
  case 7:
    Serial.print("JUL");
    break;
  case 8:
    Serial.print("AUG");
    break;
  case 9:
    Serial.print("SEP");
    break;
  case 10:
    Serial.print("OCT");
    break;
  case 11:
    Serial.print("NOV");
    break;
  case 12:
    Serial.print("DEC");
    break;
  default:
    Serial.print("???");
  }
}
/*
**********************************************************************
 END RTC Function Library
 **********************************************************************
 */


PaulS

The SaveTimes() function is called during an interrupt. It calls setClock(), EEPROM.write(), clearLCD(), selectLineOne(), and InterruptDelay().

The setClock() function calls clearLCD(), selectLineOne(), and InterruptDelay() twice each, as well as using the Wire functions to communicate with the RTC.

And, you are sure that it is the Wire functions that are causing the program to freeze.

Interrupt handlers are supposed to be fast. The clearLCD() function is not. I don't know what InterruptDelay() does, but it's name suggests that it is not fast, along with the value passed to it. EEPROM.write is not particularly fast, either.

My guess is that you need to re-think what you are doing in the interrupt handler, and only do the things that need to be done to process the interrupt. Clearing the LCD screen and writing to it are not among the things that belong in an interrupt handler.

The interrupt handler should store some values (the time to be set) and set some flags (the RTC needs to be set to the stored time). Then, after the interrupt handler ends, and loop() regains control, it can see that the clock needs to be synced, and do it.
The art of getting good answers lies in asking good questions.

retrolefty

#4
Feb 28, 2010, 06:15 pm Last Edit: Feb 28, 2010, 06:19 pm by retrolefty Reason: 1
The problem may be as simple as all interrupts are disabled once you are inside a ISR routine. Certainly some of the many devices and routines you are trying to run inside your ISR need to have interrupts enabled?

I guess you could just try to re-enable interrupts once you enter your ISR (add a "interrupts();" statement) but that is really not recommended practice for ISR routines. As already suggested, you really should rethink your sketch design and just use the ISR routine to set or reset some global flag variables and let your main loop() routine test those flag variables and call the needed tasks.

Lefty

Go Up