What GPS module and what Arduino are you using?
how can I do this without a RTC clock?
Most GPS modules have an internal RTC. They will usually report the time, even if it does not have a GPS fix on the satellites. You can use that time if it is sent to the Arduino.
However, you will have to use a different GPS library. My NeoGPS library reports the time if the GPS sends it, even if the GPS device is not locked on to satellites. NeoGPS is smaller and faster than other libraries.
Also, SoftwareSerial
blocks interrupts for long periods of time, so I would suggest switching to another library I maintain, NeoSWSerial. If you can move the GPS to pins 8 & 9, that would be even better. Then you could use AltSoftSerial, which is even more efficient and reliable.
Your sketch looks like a stopwatch. Is that right? Should it display the time when the photocell beam is broken, and hold that time until the beam is not broken? An LCD does not update very quickly, so it would not make sense to have a running clock with with blurry hundredths.
If that's true, here's a version of your sketch that uses NeoGPS and NeoSWSerial:
#include <NeoSWSerial.h>
#include "NMEAGPS.h"
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x3F // <<----- Add your address here. Find it from I2C Scanner
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
int n = 1;
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
NMEAGPS gps;//Declaramos el objeto gps
NeoSWSerial serialgps(4,3);//Declaramos el pin 4 Tx y 3 Rx
const int PIRPin= 2;
//Declaramos la variables para la obtención de datos
gps_fix fix; // The most recent GPS fields
uint32_t lastValidTime; // The last millis() when GPS sent a TIME field
bool GPStimeIncremented = false;
int lastValue = LOW; // The previous state of the photocell pin
void setup()
{
lcd.begin(20,4);//Iniciamos el puerto serie
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.home (); // go home
pinMode(PIRPin, INPUT);
serialgps.begin(9600);//Iniciamos el puerto serie del gps
//Imprimimos:
lcd.setCursor(0,0);
lcd.print( F("Buscando GPS") );
}
void loop()
{
// Always read the GPS information. This will keep
// the fix.dateTime always correct.
while (gps.available( serialgps )) {
fix = gps.read();
if (fix.valid.time) {
// TIME field had current time
lastValidTime = millis();
} else {
// TIME field was empty, just add to the old time.
uint32_t currentMS = millis();
uint32_t dt = currentMS - lastValidTime;
if (dt >= 999) {
lastValidTime += 1000;
if (!GPStimeIncremented) {
// Add one second to the old time
fix.dateTime += (NeoGPS::clock_t) 1;
fix.dateTime_cs = 0;
}
} else if (dt >= 333) {
// Add one-third of a second to the old time (3Hz)
lastValidTime += 333;
fix.dateTime_cs += 33;
}
}
GPStimeIncremented = false;
}
// See if the beam was broken
int value= digitalRead(PIRPin);
// Did it *change* from LOW to HIGH?
if ((lastValue == LOW) && (value == HIGH)) {
// Round the current millis() delta to the nearest hundredth
uint32_t dt = millis() - lastValidTime;
uint8_t hundredths = (dt + 5) / 10 + fix.dateTime_cs;
// Just in case the hundredths gets too big, increment the seconds.
// There is probably a new GPS time about to come in
while (hundredths >= 100) {
hundredths -= 100;
fix.dateTime += (NeoGPS::clock_t) 1;
GPStimeIncremented = true;
}
lcd.setCursor(0,0);
lcd.print( F(" Hora: ") );
if (fix.dateTime.hours <= 9)
lcd.print('0');
lcd.print(fix.dateTime.hours, DEC);
lcd.print(':');
if (fix.dateTime.minutes <=9)
lcd.print('0');
lcd.print(fix.dateTime.minutes, DEC);
lcd.print(':');
if (fix.dateTime.seconds <= 9)
lcd.print('0');
lcd.print(fix.dateTime.seconds, DEC);
lcd.print(';');
if (hundredths <= 9)
lcd.print('0');
lcd.print(hundredths, DEC);
// The displayed time will not change until the pin goes LOW and
// then goes HIGH again.
}
// Remember the pin state for next time, so we know when it *changes*.
lastValue = value;
}
Notes:
1) If the GPS does not report a time, it will just increment the previous time by your GPS update interval (333ms period is 3Hz frequency). Are you sure your update frequency is 3.33Hz? The numbers in the code would have to change if you really have an update period of 300ms.
2) The displayed time is calculated as an offset from the previous GPS time, in hundredths. When the GPS device does not have a fix and the time is not reported (no RTC in the GPS device), the flag GPStimeIncremented
makes sure that an old GPS time does not get incremented more than once per second. If you never have a good GPS time, it will start from 00:00:00.00.
3) The displayed time will not change until the beam is cleared (not broken) and then broken again.
4) NeoGPS has its own time functions, so you don't need the extra Time library.
Cheers,
/dev