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 !

asked Sep 16, 2019 at 9:27
1
  • try disabling the pullup resistor on the input pin Commented Sep 16, 2019 at 15:44

2 Answers 2

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.

answered Sep 16, 2019 at 10:39
3
  • Thank you for your answer, I uploaded your code and I still get only zeros each second on my screen... Commented Sep 16, 2019 at 13:15
  • @JamesONeil Then you should triple check your wiring. Commented Sep 16, 2019 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... Commented Sep 16, 2019 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.

answered Aug 18, 2020 at 15:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.