I am learning Arduino C++ and came across the following function syntax in the code snippet below;
void printInfoTo( Print & output ) // <<-- QUESTION
{
output.print( F("\nTime: ") );
if (fix.valid.time) {
if (fix.dateTime.hours < 10) output.print( '0' );
output.print(fix.dateTime.hours);
output.print( ':' );
...
}
...
}
I spent some time reading several C++ tutorials via google, but can't find
clear education as to this syntax here. It looks a lot like pass argument by
reference, and the sketch, which I post fully below (from an unrelated thread),
calls this in two different ways;
printInfoTo( Serial ); OR printInfoTo( sensorData );
So, in summary, I can clearly see that the purpose is to be able to call the
same print fuction, but have the function either end up doing;
Serial.print("my string"); // which is print to serial debug port
or else do
sensorData.print("my string"); // which is print to a file on SD card
So I figured out the result, but I can't understand the actual syntax "void printInfoTo( Print & output )".
In Googling, the function argument by reference says; void MyFunctionName( Type & Variable) { }
So is "Print" a data type in Arduino core, or is "Print" as a function argument before the "&"
simply causing a relationship to the following function body code output.print("my string");
and therefore substituting either "serial" or "sensordata" for "output" in program code?
The entire sketch that I found this in is below
#include <Wire.h>
#include <RTClib.h>
RTC_DS1307 RTC;
unsigned int lastRTCset; // when the RTC was last set from GPS time
#undef SECONDS_PER_DAY // bad RTClib!
#include <NeoSWSerial.h>
NeoSWSerial gpsPort(3, 2);
#include <NMEAGPS.h>
NMEAGPS gps;
gps_fix fix; // all the parsed pieces from GPS
unsigned int fixCount; // how many GPS updates we have received
//int TEMPERATURE_PIN = 0; <-- I don't think the temperature device is on RX pin 0!
int TEMPERATURE_PIN = A0; // Is this what you mean?
float temp;
#include <SdFat.h>
#include <SPI.h>
const int CS_PIN = 4;
SdFat SD;
File sensorData;
#include <Adafruit_MPL3115A2.h>
Adafruit_MPL3115A2 baro;
float baroPressure, baroAlt, baroTemp;
//-----------------------------
void setup()
{
Serial.begin(115200);
Serial.println( F("NeoGPS+NeoSWSerial test!") );
baro.begin();
pinMode( 10, OUTPUT );
SD.begin( CS_PIN );
sensorData = SD.open("DataFile.txt", FILE_WRITE);
Wire.begin();
gpsPort.begin(9600);
gps.send_P( &gpsPort, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC & GGA
gps.send_P( &gpsPort, F("PMTK220,1000") ); // 1Hz
RTC.begin();
if (RTC.isrunning()) {
// Set the RTC to the date & time this sketch was compiled,
// but *ONLY* if the build time is more recent than the RTC time.
// It will only set the clock forward, not back to a previous time.
DateTime build(__DATE__, __TIME__);
long buildSeconds = build.secondstime();
long nowSeconds = RTC.now().secondstime();
if (buildSeconds > nowSeconds)
RTC.adjust( build );
} else {
Serial.println( F("RTC is NOT running!") );
}
} // setup
//-----------------------------
void loop() {
// Check for GPS characters and parse them
if (gps.available( gpsPort )) {
// Enough characters have been received to create a new fix structure
fix = gps.read();
fixCount++;
checkRTC();
if (fixCount % 2) {
// Now is a good time to take some readings
temp = analogRead( TEMPERATURE_PIN ) * 0.48828125;
baroPressure = baro.getPressure();
baroAlt = baro.getAltitude();
baroTemp = baro.getTemperature();
printInfoTo( Serial );
if (sensorData.isOpen()) {
printInfoTo( sensorData );
sensorData.flush(); // instead of close and re-open
}
}
}
} // loop
//-----------------------------
void checkRTC()
{
if (RTC.isrunning()) {
// Set the RTC from the GPS or vice versa
if (fix.valid.time && fix.valid.date) {
// We have a valid GPS date/time, set the RTC time once per hour
if (fixCount - lastRTCset > 60*60) {
lastRTCset = fixCount; // wait another hour
DateTime now( fix.dateTime.year, fix.dateTime.month, fix.dateTime.date,
fix.dateTime.hours, fix.dateTime.minutes, fix.dateTime.seconds );
RTC.adjust( now );
}
} else {
// We don't have a valid GPS date/time, get it from the RTC
DateTime now = RTC.now();
fix.dateTime.date = now.day();
fix.dateTime.month = now.month();
fix.dateTime.year = now.year();
fix.dateTime.hours = now.hour();
fix.dateTime.minutes = now.minute();
fix.dateTime.seconds = now.second();
fix.valid.date = true;
fix.valid.time = true;
}
}
} // checkRTC
//-----------------------------
void printInfoTo( Print & output )
{
output.print( F("\nTime: ") );
if (fix.valid.time) {
if (fix.dateTime.hours < 10) output.print( '0' );
output.print(fix.dateTime.hours);
output.print( ':' );
if (fix.dateTime.minutes < 10) output.print( '0' );
output.print(fix.dateTime.minutes);
output.print( ':' );
if (fix.dateTime.seconds < 10) output.print( '0' );
output.print(fix.dateTime.seconds);
output.print( '.' );
if (fix.dateTime_cs < 10) output.print( '0' );
output.print(fix.dateTime_cs);
}
output.print( F("\nDate: ") );
if (fix.valid.date) {
output.print(fix.dateTime.month);
output.print( '/' );
output.print(fix.dateTime.date);
output.print( '/' );
output.print(fix.dateTime.full_year());
}
output.print( F("\nFix: ") );
if (fix.valid.status)
output.print( fix.status );
output.print( F("\nLocation: ") );
if (fix.valid.location) {
output.print( fix.latitude(), 6 );
output.print( ',' );
output.print( fix.longitude(), 6 );
}
output.print( F("\nSpeed (knots): ") );
if (fix.valid.speed)
output.print( fix.speed() );
output.print( F("\nAngle: ") );
if (fix.valid.heading)
output.print( fix.heading() );
output.print( F("\nAltitude: ") );
if (fix.valid.altitude)
output.print( fix.altitude() );
output.print( F("\nSatellites: ") );
if (fix.valid.satellites)
output.print( fix.satellites );
output.println();
output.print(temp);
output.println( F("*C External") );
output.print( baroPressure / 3377 );
output.println( F(" Inches (Hg)") );
output.print( baroAlt );
output.println( F(" Meters") );
output.print( baroTemp );
output.println( F("*C Internal") );
} // printInfoTo
Thanks for your help.
Neal