Arduino Uno + DS1307 + IRLED Photo-gate Interrupt Count

Hello,

I just started using Arduino this Monday and I like it a lot, but I'm stumped. I've done research and really am using this as a last life line. So I'll describe my project thus far:

I have a IR LED powered on and shining directly to a photo-transistor, I also have a DS1307 RTC breakout board that is synced to my computer time connecting into my bread board / Arduino.

Now when the photo-transistor registers high, on I/O 2 of the Arduino board, I have the current date, time, and number of times the pin was set high display on the serial monitor. If the pin remains high it does not continue the count or time-stamp. Only when I block the IR light and then unblock it, (pin going from high to low, back to high) does it increase the count and time-stamp.

I'll post my code below so it's easier to discuss my issue:

 -----------------------------------------------------------

#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <TimeAlarms.h>

// this constant won't change:
const int  photoGate = 2;    // the pin that phototransistor's emmit pin is attached to 
      
// Variables will change:
int IRinteruptCounter = 0;   // counter for the number of interupts in IR light
int gateState = 0;           // current state of the photo gate
int lastGateState = 0;       // previous state of the photo gate


void setup(){
  Serial.begin(9600);
  while (!Serial);
  delay(200); 
  pinMode(photoGate, INPUT); 
  setSyncProvider(RTC.get);           // the function to sync the time from the RTC

}

void loop(){
  tmElements_t tm;   
  gateState = digitalRead(photoGate);  
  if (RTC.read(tm)){
      if (gateState != lastGateState){ 
        if(gateState == HIGH) { 
         time_t timeNow = now();
         time_t timeSec = second(timeNow);   
         if (timeSec == 59){
         IRinteruptCounter = 0;
         }             
          countInterupts();
          showEvent(timeNow); 
         }
       else {
          Serial.println("off"); 
            } 
     lastGateState = gateState;       
    
    }
  }
         else{
          if (RTC.chipPresent()){
            Serial.println("The DS1307 is stopped. Please run the SetTime");
            Serial.println("example to initialize the time and begin running.");
            Serial.println();
          } else {
            Serial.println("DS1307 read error! Please check the circuitry.");
            Serial.println();
          }          
        }  
     }
       
      void countInterupts(){
        IRinteruptCounter++; 
        Serial.println("on");
        Serial.print("number of interupts:  ");
        Serial.print (IRinteruptCounter);
        Serial.println();
     }
     
       void print2digits(int number){
        if (number >= 0 && number <10){
          Serial.write('0');
        }
        Serial.print(number);
      }    
      
      void showEvent(time_t t){       
        Serial.print("Ok, Time = ");
        print2digits(hour(t));
        Serial.write(':');
        print2digits(minute(t));
        Serial.write(':'); 
        print2digits(second(t));
        Serial.print(", DATE (D/M/Y) = "); 
        Serial.print(day(t));
        Serial.write('/'); 
        Serial.print(month(t));
        Serial.write('/');
        Serial.print((year(t)));
        Serial.println();   
      }

So, what I would like to do is count the impulses/minute (ideally per second but I think I'd need a new clock and it would be over kill!)

The issue is that the current way that I have it set up:

if (timeSec == 0){
IRinteruptCounter = 0;
}

It will reset the count, but for the entire ":00" second mark it will keep resetting the count, leaving IRinteruptCounter = 1 . When all I want it to do is that when it reaches ":00 seconds" it resets the count once and then continues, cause I do not want to lose the count at that second. I've considered interrupts but only have managed to understand them working with the Arduino clock and not knowing how to sync it with my RTC.

Any ideas on how to get impulses/minute while synced to an RTC without freezing at the ":00 second" mark? Any insight would help, thank you very much in advance :grinning:

When all I want it to do is that when it reaches ":00 seconds" it resets the count once and then continues, cause I do not want to lose the count at that second.

So, when seconds is 0 but was not last time, you want to do something. Did I get that right?

Thanks for the quick reply PaulS !

seconds is 0 but was not last time

Do you mean:

8:05:00 Do something
8:06:00 Don't do the same thing ?

If so, that's not exactly what I'm asking.

Right now it goes:

8:04:59 count = 22
8:04:59 count = 23
8:04:59 count = 24
8:05:00 count = 1
8:05:00 count = 1
8:05:00 count = 1
8:05:00 count = 1
8:05:01 count = 2
8:05:01 count = 3
etc.

Were I would like it to go:

8:04:59 count = 22
8:04:59 count = 23
8:04:59 count = 24
8:05:00 count = 1
8:05:00 count = 2
8:05:00 count = 3
8:05:00 count = 4
8:05:01 count = 5
8:05:01 count = 6
etc.

Hopefully that clears it up!

You're using lastGateState to ensure that a change in state is only counted once.

Do something similar with the seconds reading, perhaps using a variable called PrevSecond to control when the reset happens.

Thanks for the reply wildbill !

variable called PrevSecond

I did something exactly that, thinking that I could use the same concept from lastGateState.

But the issue I'm having is that when I make PrevSecond a comparable variable to the current second (timeSec), PrevSecond and timeSec just update together, never being different.

This might be that I'm declaring PrevSecond incorrectly, but my initial thought was that it's because timeSec is always updating since it's directly linked to the RTC which is essential, so I'm having trouble "freezing" the current second to be able to make a comparison.

Now if the DS1307 kept track of miliseconds as well this shouldn't be too much of an issue, I would at most lose a milisecond of data, while keeping track of the updated date and time, which isn't a big deal. But I like the simplicity DS1307 including libraries and the breakout board.

So if it's possible currently to solve this issue without involving any change to hardware, I would appreciate any insight! Maybe an interrupt that syncs with the DS1307 ?

But the issue I'm having is that when I make PrevSecond a comparable variable to the current second (timeSec), PrevSecond and timeSec just update together, never being different.

This might be that I'm declaring PrevSecond incorrectly, but my initial thought was that it's because timeSec is always updating since it's directly linked to the RTC which is essential, so I'm having trouble "freezing" the current second to be able to make a comparison.

The issue i"m having is that I can't see your code. So, I'll just have to assume that you wrote it wrong.

My apologies, I posted this in my original post but here it is with my current minute counter, where I have:
if (timeSec == 00)
IRinteruptCounter = 0;

but where I commented out:

time_t prevTime = second(timeNow);
// if I make this the value I don't know how to freeze it here

Sorry if I explained things confusingly.

#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <TimeAlarms.h>

// this constant won't change:
const int  photoGate = 2;    // the pin that phototransistor's emmit pin is attached to 
int Number_of_Impulses= 15;
int Number_of_Timestamps= 15;
int Index=0;
      
// Variables will change:
int IRinteruptCounter = 0;   // counter for the number of interupts in IR light
int gateState = 0;           // current state of the photo gate
int lastGateState = 0;       // previous state of the photo gate

void setup(){
  Serial.begin(9600);
  while (!Serial);
  delay(200); 
  pinMode(photoGate, INPUT); 
  setSyncProvider(RTC.get);           // the function to sync the time from the RTC

 
}

void loop(){
  tmElements_t tm;   
  gateState = digitalRead(photoGate);  
  if (RTC.read(tm)){
    time_t timeNow = now();
    time_t timeSec = second(timeNow);  
   // time_t prevSec = second(timeNow);
     if (timeSec == 00)
         IRinteruptCounter = 0;          
      if (gateState != lastGateState){ 
        if(gateState == HIGH) { 
         time_t timeNow = now();
         time_t timeSec = second(timeNow);    
         countInterupts();
         showEvent(timeNow);          
          }         
       else {
          Serial.println("off"); 
            } 
     lastGateState = gateState;           
    }
  }
         else{
          if (RTC.chipPresent()){
            Serial.println("The DS1307 is stopped. Please run the SetTime");
            Serial.println("example to initialize the time and begin running.");
            Serial.println();
          } else {
            Serial.println("DS1307 read error! Please check the circuitry.");
            Serial.println();
          }          
        }  
     }     
     
      
      void countInterupts(){
        IRinteruptCounter++; 
        Serial.println("on");
        Serial.print("number of interupts:  ");
        Serial.print (IRinteruptCounter);
        Serial.println();
     }
     
       void print2digits(int number){
        if (number >= 0 && number <10){
          Serial.write('0');
        }
        Serial.print(number);
      }    
      
      void showEvent(time_t t){       
        Serial.print("Ok, Time = ");
        print2digits(hour(t));
        Serial.write(':');
        print2digits(minute(t));
        Serial.write(':'); 
        print2digits(second(t));
        Serial.print(", DATE (D/M/Y) = "); 
        Serial.print(day(t));
        Serial.write('/'); 
        Serial.print(month(t));
        Serial.write('/');
        Serial.print((year(t)));
        Serial.println();   
      }

prevTime needs to take its value from timeSec, not by reading the clock again. It also needs to persist between calls to loop so make it static or global.

You need to read timeSec, check whether it's zero and prevTime is fifty nine and if so, zero the count. Then unconditionally set prevTime to timeSec.

wildbill thank you so much that worked marvelously! Really appreciate the reply :slight_smile:

I believe this project is going to evolve with different aspects, if I need to use the forum again should I post on the same thread or make a separate thread?

thanks again!