1

I am using a DS3231 rtc and I would like to get millisecond accuracy from it so I decided to use the 32kHz generated clock from it. I wrote a code that would count the rising edges or falling edges using an interrupt with (RISING or FALLING parameters) but I get only zeros on my Serial board for the count.

Here is the code I am using :

#include <DS3231.h>
#include <RTClib.h>
#include <Wire.h>
#include "rtc.h"
#define InterruptPin 3

volatile long lcnt = 0;

RTC_DS3231 rtc;

void setup() {
  Wire.begin();
  Serial.begin(74880); // init serial port
  pinMode(InterruptPin, INPUT_PULLUP);
  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__),F(__TIME__)));
  attachInterrupt(digitalPinToInterrupt(InterruptPin), fcnt, FALLING);
}
void loop() {
  unsigned long a=millis();
  if (a<1000){
  Serial.println(lcnt);
  }
}

void fcnt(){
  lcnt+=1;
}

I just want to check how many rising edges I have in 1s. What is strange is that this code used to work and now it doesn't ^^'... I don't know if I changed something by mistake or deleted something useful.

Can somebody help me to resolve this little problem ?

Thanks a lot for your time !

  • try disabling the pullup resistor on the input pin – jsotola Sep 16 '19 at 15:44
1

I'm not sure why you're getting 0 as such, but your interrupt and variable methodology leaves a lot to be desired (probably the cause of the "tutorials" you followed).

My primary concern is that you are using a 32-bit "long" variable in an interrupt, and referencing that directly outside the interrupt. The Arduino is an 8-bit system, which means that all accesses to that variable take many instructions to arrange (splitting it down into 4 8-bit values, manipulating it, recombining it, etc). Because of this no operations on that variable are "atomic".

You need to make them atomic. If you don't then it's perfectly possible for the interrupt to trigger and modify the value in the middle of you doing something with that value.

The simplest way of making it atomic is to disable interrupts, then copy the value to another variable and/or modify it, and enable interrupts again.

Here's an example that I would consider stable:

#include <DS3231.h>
#include <RTClib.h>
#include <Wire.h>
#include "rtc.h"
#define InterruptPin 3

volatile uint32_t lcnt = 0;

RTC_DS3231 rtc;

void setup() {
  Wire.begin();
  Serial.begin(74880); // init serial port
  pinMode(InterruptPin, INPUT_PULLUP);
  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__),F(__TIME__)));
  attachInterrupt(digitalPinToInterrupt(InterruptPin), fcnt, FALLING);
}

void loop() {
  static uint32_t ts = millis();
  uint32_t a = millis();
  if (a - ts >= 1000) {
    ts = a;
    noInterrupts();
    uint32_t currentCount = icnt;
    icnt = 0;
    interrupts();
    Serial.println(currentCount);
  }
}

void fcnt(){
  lcnt+=1;
}

That should print the number of pulses over successive 1 second periods.

| improve this answer | |
  • Thank you for your answer, I uploaded your code and I still get only zeros each second on my screen... – JamesONeil Sep 16 '19 at 13:15
  • @JamesONeil Then you should triple check your wiring. – Majenko Sep 16 '19 at 13:16
  • I already use one interrupt from the ds3231 for the alarm on the pin SQW to wake up my arduino and it works fine so the problem can come only from the pin of the 32kHz clock. I double checked my wiring and nothing wrong there... – JamesONeil Sep 16 '19 at 13:32
0

I used the same code as yours and simply changed the datatype from uint32_t to unsigned long and it started working. May be you can try the same.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.