#include #include void getJPEGPicture_callback(uint16_t pictureSize, uint16_t packageSize, uint16_t packageCount, byte * package); bool getgpsinfo(uint16_t timeout); void blink(int times); int sync_camera(void); #define GPSrxPin 3 #define GPStxPin 4 #define GPSBAUD 4800 #define GPS_BUF_LENGTH 100 // needs to be larger than the max NMEA string size #define ledPin 2 SDCameraC328R camera; void setup() { pinMode(ledPin, OUTPUT); int retval = 0; digitalWrite(ledPin, LOW); // use ordinary idle mode Serial.begin(57600); retval = camera.InitializeSD(); if (retval != 0) blink(retval); retval = sync_camera(); if (retval != 0) blink(retval); } void loop() { for (uint16_t i=0; i<1000; i++) { int retval = 0; // only 2 seconds to update a gps position otherwise we re-sync if (!getgpsinfo(2000)) { retval = sync_camera(); if (retval != 0) blink(retval); continue; } sprintf(camera.filename, "%04d%02d%02d-%02d%02d%02d-%05d.jpg", camera.gpsyear, camera.gpsmonth, camera.gpsday, camera.gpshour, camera.gpsmin, camera.gpssec, i); retval = camera.snapshot(SDCameraC328R::ST_COMPRESSED, 0); if (retval != 0) blink(retval); retval = camera.getJPEGPicture(SDCameraC328R::PT_JPEG, PROCESS_DELAY, &getJPEGPicture_callback); if (retval != 0) blink(retval); delay(500); } } #if FAT_DATETIME_SUPPORT void get_datetime(uint16_t * year, uint8_t * month, uint8_t * day, uint8_t * hour, uint8_t * min, uint8_t * sec) { *year = camera.gpsyear; *month = camera.gpsmonth; *day = camera.gpsday; *hour = camera.gpshour; *min = camera.gpsmin; *sec = camera.gpssec; } #endif // // This callback is called EVERY time a JPEG data packet is received. // (not used) // void getJPEGPicture_callback(uint16_t pictureSize, uint16_t packageSize, uint16_t packageCount, byte * package) { } /* * function that blinks an attached LED N number of times * used here for blinking error codes returned by camera * object methods */ void blink(int err) { if (!err) return; while (1) { for (int i = 0; i < err; i++) { digitalWrite(ledPin, HIGH); delay(200); digitalWrite(ledPin, LOW); delay(200); } delay(1000); } } /* * establishes communication to the attached camera * on the serial port. Will also wait for a gps position * from the attached gps module * * will block forever waiting to get a position from the gps module * * return values: * 0 - success * ERRCODE - camera sync errorcode (see SDCameraC328.h) */ int sync_camera() { int retval = 0; // wait forever to sync the gps, flash the led // every 10 seconds to indicate we are doing // something while (!getgpsinfo(10000)) { digitalWrite(ledPin, HIGH); delay(100); digitalWrite(ledPin, LOW); delay(100); } retval = camera.sync(); if (retval != 0) return (retval); retval = camera.initial(SDCameraC328R::CT_JPEG, SDCameraC328R::PR_80x60, SDCameraC328R::JR_640x480); if (retval != 0) return (retval); retval = camera.setPackageSize(100); if (retval != 0) return (retval); retval = camera.setLightFrequency(SDCameraC328R::FT_50Hz); if (retval != 0) return (retval); // Let camera settle, per manual delay(2000); return retval; } /**** * establishes serial communication to an attached GPS unit. * after receiving either a GPRMC or a GPGGA string calls * the appropriate parse function to update the exif header * returns: * 0 if timeout (ms) is reached * 1 if successful */ bool getgpsinfo(uint16_t timeout) { NewSoftSerial mySerial(GPSrxPin, GPStxPin); mySerial.begin(GPSBAUD); uint8_t gprmc_ret = 0; uint8_t gpgga_ret = 0; while (!(gprmc_ret && gpgga_ret)) { while (mySerial.available() == 0) { delay(1); timeout--; if (!timeout) return 0; } if (mySerial.read() != '$') { continue; // start char } char gps_info[GPS_BUF_LENGTH] = { 0.0 }; for (uint8_t i = 0; i < (GPS_BUF_LENGTH - 1); i++) { while (mySerial.available() == 0) { delay(1); timeout--; if (!timeout) return 0; } char gpsbyte = mySerial.read(); //Serial.print(gpsbyte); if (gpsbyte == 13 || gpsbyte == 10) { // end char // parse and validate the line of gps info if (strcmp(gps_info, "GPRMC") > 0) gprmc_ret = camera.update_exif_GPRMC(gps_info); if (gprmc_ret && strcmp(gps_info, "GPGGA") > 0) gpgga_ret = camera.update_exif_GPGGA(gps_info); break; } else { gps_info[i] = gpsbyte; } } delay(1); timeout--; if (!timeout) return 0; } pinMode(GPSrxPin, OUTPUT); pinMode(GPStxPin, OUTPUT); return 1; }