I'm building a rain gauge using a tipping bucket sensor which is just a NO switch. I'm using an UNO and DS3231 rtc. The end result will show rain for hour, day and week. This code, cut down to relevant parts, works up to the point of starting the relevant count again after it has been set to 0.
#include "RTClib.h"
#include <TimeLib.h>
RTC_DS3231 rtc;
#define BucketSize 0.016115
volatile unsigned long tipCount = 0;
volatile unsigned long tipCountMinute = 0;
volatile unsigned long tipCountHour = 0;
volatile unsigned long tipCountDay = 0;
volatile unsigned long tipCountWeek = 0;
volatile unsigned long contactTime = 0;
volatile unsigned long previousTime = 0;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup () {
Serial.begin(9600);
rtc.begin(); // start the RTC
DateTime now = rtc.now();
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), isr_rg, FALLING);
//+++++ NAME OF SKETCH +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Serial.println(" sketch is -- rain_gauge_10_minimum");
Serial.println("");
//++ use to set time clock +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
void loop() {
// times are too short for testing only
if (second() >= 20) {
tipCountMinute = 0;
}
if (minute() >= 1) {
tipCountHour = 0;
}
DateTime now = rtc.now();
char time_format1[] = "hh:mm:ss";
//+++++++++++++++++++++++++++++++++++++++++++++++
if (millis() - 500 >= previousTime) {
Serial.println(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.println(now.toString(time_format1));
Serial.println(tipCount);
Serial.print("Minute ");
Serial.print(tipCountMinute * BucketSize);
Serial.println(" inches");
Serial.print("Hour ");
Serial.print(tipCountHour * BucketSize);
Serial.println(" inches");
Serial.print("Day ");
Serial.print(tipCountDay * BucketSize);
Serial.println(" inches");
Serial.print("Week ");
Serial.print(tipCountDay * BucketSize);
Serial.println(" inches");
previousTime = millis();
//////////////////////////////////////
delay(5000);
}
}
void isr_rg() {
if ((millis() - contactTime) > 500) {
tipCount++;
tipCountMinute++;
tipCountHour++;
tipCountDay++;
tipCountWeek++;
contactTime = millis();
}
}
This bit does the reset, I'm stuck on what to add to get it to start again.
// times are too short for testing only
if (second() >= 20) {
tipCountMinute = 0;
}
if (minute() >= 1) {
tipCountHour = 0;
}
End result should be something like this on the serial monitor.
I'm sure there are more elegant ways of doing this, this is logical to me but probably not to a coder.
From the beginning, they all do the same thing. After I set "Minute 0.01 inches" to 0, by using this
if (second() >= 20) {
tipCountMinute = 0;
}
hour, day, and week keep adding to their totals until the next one is stopped by this
if (minute() >= 1) {
tipCountHour = 0;
}
At that point minute and hour read 0.00 and stay that way.
How do I get them to start counting again until it is again set to 0?
I don't know how I could possibly show that.
I start the sketch and tip the bucket a couple of times. All four show 0.03. That's correct.
After 20 seconds Minute shows 0.00. That's correct.
Tip the bucket twice minute still shows 0.00, hour, day and week show 0.06. Hour, day and week are correct but, minute should now show 0.03.
When one minute has elapsed minute and hour now both show 0.00. They never show any tips again.
They may still be counting but, it isn't showing on the serial monitor.
Put in Serial.print() statements to reveal values of different variables, as you tip the bucket. Post the results.
As @anon57585045 mentioned above, you need to protect variables shared with an interrupt routine from being corrupted during access.
Do that as follows (example):
noInterrupts();
unsigned long tipCount_copy = tipCount; //make a copy in main loop
interrupts();
Serial.print("Tip count" );
Serial.println(tipCount_copy);
You're checking for second to be >= 20, but second then continues counting to 59 and wraps around; for that 40 seconds, you're blind because you're jamming 0 into the value. Same goes for minutes, you can only see tips in the first minute of the hour, the way I read it.
I'd move the counting to loop(), and only reset the counters when the particular time value rolls over, for example, when secondsnow<secondslast, reset the minute counter, ditto for the other times.
But YMMV.
C
@somewhereinusa Since there's an expectation that your bucket will only tip 2x per second (those millis() checks), this really isn't an application for an interrupt anyway, though it's good brain food to work on it.
C