My problem remains the slight flicker occurring at regular 1 second intervals, something like a heartbeat and only when the gps serial is active.
Yes, as you can see here, other libraries will take about 1.4ms to parse the sentence, and it happens all in one burst. NeoGPS spreads about 0.8ms of processing out across the receipt of ~80 characters, blocking loop()
an average of only 10us. I’m a little skeptical that you could see this difference, though.
Hmm… Here’s your sketch modified to use NeoGPS and NeoSWSerial, plus a few debug prints you may need to remove:
#include <NeoSWSerial.h>
#include <Wire.h>
#include "NMEAGPS.h"
NMEAGPS gps;
uint32_t changes; // debug, shows how many times the multiplexing switches
// GPS Setup
// Set false to display 12 hour format, or true to use 24 hour:
#define TIME_24_HOUR true
// Offset the hours from UTC (universal time) to your local time:
#define HOUR_OFFSET 9
// Use Analog pins A0, A1 connected to GPS pins Tx, Rx respectively
NeoSWSerial gpsSerial( A0, A1 );
// Output Setup
// Cathode Pins SN74141 (1)
const int outPin_c0_a = 2;
const int outPin_c0_b = 3;
const int outPin_c0_c = 4;
const int outPin_c0_d = 5;
// Cathode SN74141 (2)
const int outPin_c1_a = 6;
const int outPin_c1_b = 7;
const int outPin_c1_c = 8;
const int outPin_c1_d = 9;
// anode pins
const int outPin_a_1 = 10;
const int outPin_a_2 = 11;
const int outPin_a_3 = 12;
const int outPin_a_4 = 13;
// Display Setup
byte NumberArray[6]={0,0,0,0,0,0}; // current display
int display_status = 0; // which tube anode to display now
long tube_start = 0; // multiplex start time
const uint16_t tube_delay = 3000; // multiplexing delay in microseconds; adjust for tube type
void setup() { // OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Serial.begin( 9600 );
Serial.println( F("archibald started") );
// initialize ArduiNix pins
pinMode(outPin_c0_a, OUTPUT);
pinMode(outPin_c0_b, OUTPUT);
pinMode(outPin_c0_c, OUTPUT);
pinMode(outPin_c0_d, OUTPUT);
pinMode(outPin_c1_a, OUTPUT);
pinMode(outPin_c1_b, OUTPUT);
pinMode(outPin_c1_c, OUTPUT);
pinMode(outPin_c1_d, OUTPUT);
pinMode(outPin_a_1, OUTPUT);
pinMode(outPin_a_2, OUTPUT);
pinMode(outPin_a_3, OUTPUT);
pinMode(outPin_a_4, OUTPUT);
// Setup the GPS using a 9600 baud connection (the default for most
// GPS modules).
gpsSerial.begin(9600);
// Configure GPS to only output minimum data (location, time, fix).
gps.send_P( &gpsSerial, (str_P) F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") );
// Use a 1 Hz, once a second, update rate.
gps.send_P( &gpsSerial, (str_P) F("PMTK220,1000") );
// Start-up display test (counts up 0 to 9 on all tubes at boot-up)
const uint16_t digit_interval = 250;
uint16_t start = millis()-digit_interval;
uint8_t i=0;
while (i <= 9) {
if ((uint16_t)millis()-start >= digit_interval) {
NumberArray[0] = i; // upperHour
NumberArray[1] = i; // lowerHour
NumberArray[2] = i; // upperMin
NumberArray[3] = i; // lowerMin
NumberArray[4] = i; // upperColon
NumberArray[5] = i; // lowerColon
Serial.println( i );
i++;
start += digit_interval;
}
WriteDisplay( NumberArray );
}
} // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void loop() { // 000000000000000000000000000000000000000000000000
while (gpsSerial.available()) {
if ((gps.decode( gpsSerial.read() ) == NMEAGPS::DECODE_COMPLETED) &&
(gps.nmeaMessage == NMEAGPS::NMEA_RMC) &&
gps.fix().valid.time) {
Serial << gps.fix().dateTime;
Serial.print( ' ' );
Serial.print( changes );
Serial.println();
changes = 0;
// Grab the current hours, minutes, seconds from the GPS.
// This will only be set once the GPS has a fix! Make sure to add
// a coin cell battery so the GPS will save the time between power-up/down.
// Offset to the local time zone
NeoGPS::clock_t localSeconds = gps.fix().dateTime; // UTC to seconds
localSeconds += HOUR_OFFSET * NeoGPS::SECONDS_PER_HOUR;
NeoGPS::time_t localTime( localSeconds );
// Adjust for 12 or 24-hour format
uint8_t hours = localTime.hours;
if (!TIME_24_HOUR && hours > 12)
hours -= 12;
// Get the high and low order values for hours,min,seconds.
NumberArray[0] = hours/10;
NumberArray[1] = hours % 10;
NumberArray[2] = localTime.minutes/10;
NumberArray[3] = localTime.minutes % 10;
NumberArray[4] = localTime.seconds/10;
NumberArray[5] = localTime.seconds % 10;
}
}
WriteDisplay( NumberArray );
} // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// Functions below
// Write Display for each tube
// sets tube display (without using "delay")
void WriteDisplay( byte* array ) {
if (micros()-tube_start >= tube_delay) {
changes++; // <-- debug statement, remove eventually!
switch (display_status) {
case 0: // set anode 1
digitalWrite(outPin_a_3, LOW);
DisplayBin(array[0],array[3]);
digitalWrite(outPin_a_1, HIGH);
tube_start += tube_delay;
display_status++;
break;
case 1: // clear anode 1, set anode 2
digitalWrite(outPin_a_1, LOW);
DisplayBin(array[1],array[2]);
digitalWrite(outPin_a_2, HIGH);
tube_start += tube_delay;
display_status++;
break;
case 2: // clear anode 2, set anode 3
digitalWrite(outPin_a_2, LOW);
DisplayBin(array[4],array[5]);
digitalWrite(outPin_a_3, HIGH);
tube_start += tube_delay;
display_status = 0;
break;
}
}
}
// DisplayBin
// Sets cathodes. Expects data in Bin/BCD format (native format of 74141)
void DisplayBin(byte num1, byte num2) {
// Write to output pins.
digitalWrite(outPin_c0_a, bitRead(num1, 0));
digitalWrite(outPin_c0_b, bitRead(num1, 1));
digitalWrite(outPin_c0_c, bitRead(num1, 2));
digitalWrite(outPin_c0_d, bitRead(num1, 3));
digitalWrite(outPin_c1_a, bitRead(num2, 0));
digitalWrite(outPin_c1_b, bitRead(num2, 1));
digitalWrite(outPin_c1_c, bitRead(num2, 2));
digitalWrite(outPin_c1_d, bitRead(num2, 3));
}
It uses micros
instead, too. With a tube_delay
of 3000, it says the multiplexing happens about 333 times per second, more or less.
Cheers,
/dev