Hi All
I'm quite inexperienced at Arduino and C coding generally, but have been playing with GPS 1PPS signals and also the concept of frequency references.
I started by reading about this project:
and am using the basic concept of this code to try and use a 1PPS signal to control the on chip Timer1 on a Nano. I am initially trying to count a 5 MHz external signal.
The code runs OK and without the 5MHz signal attached it counts 0, but with the external signal the counts are almost random - so clearly something is very wrong.
I have a 1PPS GPS signal connected to both D2 for INT0 and also D8 for the ICP1 input. THe 5MHz external signal (conditioned through a 74HC14) is connected to D5.
I would be very grateful for any constructive feedback on the following:
#include <LiquidCrystal_I2C.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <PWM.h>
static const int RXPin = 7, TXPin = 6;
static const uint32_t GPSBaud = 9600;
#define INT0_PIN 2 // D2 NANO pin, INTERRUPT 0
#define ICP1 8 // D8 NANO pin, T1's ICP1 input - 1PPS
#define T1_CLK 5 // D5 NANO pin, T1's clock input - 5MHz
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
//I2C LCD device
LiquidCrystal_I2C lcd(0x27,16,2);
char line0 [17];
char line1 [17];
//Sat count
int satsUsed = 0;
char satBuffer [2];
// signals leading-edge of one_pps_pulse
boolean one_pps_flag;
// Counter variables
unsigned int prev_t1_count = 0;
unsigned int t1_count = 0;
unsigned int t1_delta = 0;
void updateDisplay()
{
lcd.setCursor(0,0);
lcd.print(line0);
lcd.print(line1);
}
void initDisplay()
{
for (int i=0; i<=15; i++)
{
line0[i] = ' ';
line1[i] = ' ';
}
line0[0] = 'S';
line0[1] = 'a';
line0[2] = 't';
line0[3] = 's';
line0[4] = ':';
line0[5] = ' ';
updateDisplay();
}
void onePPS()
{
one_pps_flag = true;
}
void timer1_setup (byte mode, int prescale, byte outmode_A, byte outmode_B, byte capture_mode)
{
// NOTE: This code found at:
// http://sphinx.mythic-beasts.com/~markt/ATmega-timers.html
// enforce field widths for sanity
mode &= 15 ;
outmode_A &= 3 ;
outmode_B &= 3 ;
capture_mode &= 3 ;
byte clock_mode = 0 ; // 0 means no clocking - the counter is frozen.
switch (prescale)
{
case 1: clock_mode = 1 ; break ;
case 8: clock_mode = 2 ; break ;
case 64: clock_mode = 3 ; break ;
case 256: clock_mode = 4 ; break ;
case 1024: clock_mode = 5 ; break ;
default:
if (prescale < 0)
clock_mode = 7 ; // external clock
}
TCCR1A = (outmode_A << 6) | (outmode_B << 4) | (mode & 3) ;
TCCR1B = (capture_mode << 6) | ((mode & 0xC) << 1) | clock_mode ;
}
// This custom version of delay() ensures that the gps object
// is being "fed"
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
void setup()
{
lcd.init();
lcd.clear();
lcd.backlight();
initDisplay();
//initialize all timers except for 0, to save time keeping functions
InitTimersSafe();
Serial.begin(115200);
ss.begin(GPSBaud);
// interrupt on falling edge of one_pps signal.
pinMode(INT0_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(INT0_PIN), onePPS, FALLING);
// Timer 1: external clock. Neg. Edge capture. No noise cancellation.
timer1_setup (0x00, -1, 0x00, 0x00, 0x00);
}
void loop()
{
satsUsed = gps.satellites.value();
sprintf (satBuffer, "%03i", satsUsed);
line0[6] = satBuffer[1];
line0[7] = satBuffer[2];
updateDisplay();
smartDelay(100);
if (millis() > 5000 && gps.charsProcessed() < 10)
Serial.println(F("No GPS data received: check wiring"));
if (one_pps_flag)
{
// this code should only run once each time the 1PPS interrupt has been triggered
one_pps_flag = false;
prev_t1_count = t1_count; //save old count
t1_count = ICR1; // new counter snapshot
// compensate for counter wraparound
if (t1_count < prev_t1_count)
{
t1_delta = 65536 - (prev_t1_count - t1_count);
}
else
{
t1_delta = t1_count - prev_t1_count;
}
Serial.println(t1_delta, HEX); // an ideal 5MHz count would yeild 4B40 HEX
}
}
I would be grateful for any feedback on this code: