Adding DS2417 RTC to existing analog clock code

Hi All

Still having problems with the code for this clock.

#define SP1 7
#define SP2 8
#define SP3 10
#define SP4 11

#define SET_PIN 9


#include <OneWire.h>
#include "myPushSwitch.h"

OneWire ds(A0);  // on pin A0
// Set input has internal pullup; LOW when active; no double-click; no double-click delay; use default debounce time
PushSwitch setSwitch(SET_PIN, INPUT_PULLUP, LOW, false);



const uint32_t ONE_MINUTE = 60 * 1000UL;
const uint32_t MAX_SET_STEP_INTERVAL = 1000UL;
const uint32_t MIN_SET_STEP_INTERVAL = 50UL;
const uint32_t SET_STEP_DELTA = 100UL;



void parkMotor()
{
  // step 0
  digitalWrite(SP1, LOW);
  digitalWrite(SP2, LOW);
  digitalWrite(SP3, LOW);
  digitalWrite(SP4, LOW);
}

void stepMotor(uint16_t tickLength)
{
  // step 0
  digitalWrite(SP1, LOW);
  digitalWrite(SP2, HIGH);
  digitalWrite(SP3, HIGH);
  digitalWrite(SP4, HIGH);
  delayMicroseconds(tickLength);
  // step 1
  digitalWrite(SP1, LOW);
  digitalWrite(SP2, HIGH);
  digitalWrite(SP3, HIGH);
  digitalWrite(SP4, LOW);
  delayMicroseconds(tickLength);
  // step 2
  digitalWrite(SP1, HIGH);
  digitalWrite(SP2, HIGH);
  digitalWrite(SP3, HIGH);
  digitalWrite(SP4, LOW);
  delayMicroseconds(tickLength);
  // step 3
  digitalWrite(SP1, HIGH);
  digitalWrite(SP2, LOW);
  digitalWrite(SP3, LOW);
  digitalWrite(SP4, LOW);
  delayMicroseconds(tickLength);
  // step 4
  digitalWrite(SP1, HIGH);
  digitalWrite(SP2, LOW);
  digitalWrite(SP3, LOW);
  digitalWrite(SP4, HIGH);
  delayMicroseconds(tickLength);
  // step 5
  digitalWrite(SP1, LOW);
  digitalWrite(SP2, LOW);
  digitalWrite(SP3, LOW);
  digitalWrite(SP4, HIGH);
  delayMicroseconds(tickLength);
  // step 6
  digitalWrite(SP1, LOW);
  digitalWrite(SP2, HIGH);
  digitalWrite(SP3, HIGH);
  digitalWrite(SP4, HIGH);
  delayMicroseconds(tickLength);
  // idle
  parkMotor();
}



uint32_t lastStepTime;
uint32_t stepInterval;
uint32_t secondsCount;


void setup()
{
  //Serial.begin(115200);
  //Serial.println("program started");

  pinMode(SP1, OUTPUT);
  pinMode(SP2, OUTPUT);
  pinMode(SP3, OUTPUT);
  pinMode(SP4, OUTPUT);
  parkMotor();
  setSwitch.begin();

  lastStepTime = secondsCount;
  stepInterval = ONE_MINUTE;

}

void loop()
{
  byte i;
  byte present = 0;
  byte data[8];
  byte addr[8];

  if ( !ds.search(addr)) {
     
      ds.reset_search();
     
      return;
  }

 
  for( i = 0; i < 8; i++) {
   
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      
      return;
  }

  if ( addr[0] != 0x27) {
      
      return;
  }


  // write!
  
  present = ds.reset();
  ds.select(addr);
  ds.write(0x99,1);   // write RTC - this is the write code
  ds.write(0x3C); //This is the control byte.  AC in hex = 10101100
                   //read the datasheet and you will see that this is important
                   //to start the internal osc's... Or to make the clock start
                   //counting seconds.  --ril3y
  present = ds.reset();

  // read!
  present = ds.reset();
  ds.select(addr);
  ds.write(0x66,1);   // read RTC

 
  for ( i = 0; i < 5; i++) {
    data[i] = ds.read();
  }
 
  for ( i = 1; i < 5; i++) {
  
   
    }


  
  
 

// convert bytes in data[] array to a more useful form

secondsCount = (((((data[4]*256UL)+data[3])*256UL)+data[2])*256UL)+data[1];




  switchEvent event = setSwitch.update();
  if (event == switchPressed)
  {
    //Serial.print("switch pressed - ");
    stepInterval = MAX_SET_STEP_INTERVAL;
    //Serial.println(stepInterval);
  }
  else if (event == switchReleased)
  {
    lastStepTime = millis();
    stepInterval = ONE_MINUTE;
    //Serial.println("switch released");
  }

  if (millis() - lastStepTime > stepInterval)
  {
    lastStepTime = millis();
    //Serial.println("tick");
    stepMotor(6000);
    switchState state = setSwitch.read();
    if (state == switchWasPressed)
    {
      //Serial.print("switch still pressed - ");
      if (stepInterval > (MIN_SET_STEP_INTERVAL + SET_STEP_DELTA))
      {
        stepInterval -= SET_STEP_DELTA;

      }
      else
      {
        stepInterval = MIN_SET_STEP_INTERVAL;
      }
      //Serial.println(stepInterval);
    }
  }

}

I can't get the time for the RTC to replace the millis() function without upsetting the clock movement and setting the clock with the push button.

I'm beginning to pull my hair out with it now.

Thank you

Observations:

  • I don't understand why you're doing a One-Wire address scan on EVERY pass through the 'loop()' function. I'd think you'd do it once (in 'setup()') and save the results for use in the 'loop()' function. Your RTC hardware isn't changing while the clock is in operation, is it? If not, then the RTC's address isn't going to change.

  • I have my doubts that you should be messing with the device's control byte on EVERY pass through 'loop()'. But, I haven't read the device data sheet cover-to-cover (after all, it's not my project), have you?

  • When you finally get around to reading from the RTC (I presume it's the time you're reading, but I haven't read the datasheet cover-to-cover), you then proceed to do NOTHING with the result.

  • It's not clear to me that you need to even read the time from the RTC on EVERY pass through 'loop()'. Remember, reading from the One-Wire bus is SLOW. I'd think you'd want to just read the RTC periodically (every 10 seconds? every 10 minutes?) and use the results to true-up a 'millis()'-based software timer.

  • Your 'stepMotor()' function is ugly. It would benefit from defining the required states in an array and then stepping through using a 'for' loop.

It occurs to me that you don't even need to know what time it is. What you need to know is that a certain amount of time (say one second) has passed. The DS2417 has a handy-dandy interrupt feature just for that.

So, set up the DS2417's Interrupt output to give you a pulse every second. That's so slow that you don't need to use interrupts on the Arduino, just poll it. Count up 60 of those pulses and you know a minute has passed, then step your clock. Make sure the stepping lasts less than one second so you don't miss the next pulse. Otherwise you'll need to be a little more clever, but it's still doable.

So would you count the pulses in the same manner as if you were counting button presses.

Increment a counter variable every time you detect the falling edge of the DS2417's 1-second ~INT output. When the counter reaches 60, reset it to 0 and step your clock.

I have got the RTC interrupt working and have got the code to count the input from the RTC.

How would be the best way to merge this code into the clock code.

gfvalvo how would you make the stepMotor() function not ugly

#include <OneWire.h>

// DS2417 Real Time Clock
OneWire ds(A0);  // on pin A0

int ledPin = 13;
int pin_irq = 2;
volatile int IRQcount;

void setup() {

 Serial.begin (9600);
 byte i;
  byte present = 0;
  byte data[8];
  byte addr[8];
  
  present = ds.reset();
  ds.select(addr);
  ds.write(0x99,1);   // write RTC - this is the write code
  ds.write(0x8C);  //This is the control byte.  8C in hex = 10001100          
  present = ds.reset();
  
  pinMode(ledPin, OUTPUT);
  pinMode(pin_irq, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pin_irq), counter, FALLING);
}

void counter() {

IRQcount++;
  
}

void loop() {

 //IRQcount = 0;
 delay(1000);
 int result = IRQcount;
 Serial.print(F("Counted = "));
 Serial.println(result);

 if (IRQcount%10 == 0) {
     digitalWrite(ledPin, HIGH);
   } else {
     digitalWrite(ledPin, LOW);
   }

 
}