Planet Earth Wobbles As It Spins, and Now Scientists Know Why
Planet Earth Wobbles As It Spins, and Now Scientists Know Why
"Humans are responsible for some of the wobble in Earth's spin."
Why ads? π€ / Privacy Policy π³
"Humans are responsible for some of the wobble in Earth's spin."
Below is theΒ current version of the code I use for my GPS logger,Β which is powered by a Neo 6M GPS unit, an Arduino SD Card Reader with an 8 GB MicroSD Card, and an Arduino Nano. It logs a wide variety of information about my current location, speed of travel, and other information so I can easily look back at my trip.
/* GPS Logger SD card attached to SPI bus as follows: * ** CS - pin 10 ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 */ #include <TinyGPS++.h> char p_buffer[100]; #define P(str) (strcpy_P(p_buffer, PSTR(str)), p_buffer) #define HOMELAT 42.614277 #define HOMELNG -73.851662 #include <SoftwareSerial.h> // The serial connection to the GPS module SoftwareSerial ss(4, 3); // The TinyGPS++ object TinyGPSPlus gps; // Line Buffer to Save to File char lnBuffer[115]; // Decimal to Number Char String Buffer char numStr[30]; // delay uint8_t prevSecond; // data logger #include <SPI.h> #include <SD.h> const uint8_t chipSelect = 10; // location of previous location, used // to calculate distance traveled float prevLat = 0; float prevLng = 0; float prevAlt = 0; // stored in meters float prevSpeed = 0; // stored in meters per second float prevTime = 0; // keep a running total of miles since last boot float milesSinceBoot = 0; // filename char fileName[13]; // don't do anything if card is bad bool cardWorks = false; void setup() { Serial.begin(115200); ss.begin(9600); for (uint8_t i = 6; i < 9; i++) { pinMode(i, OUTPUT); digitalWrite(i, LOW); } // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println(F("Card failed, or not present")); digitalWrite(8, HIGH); //red cardWorks = false; // don't do anything more: return; } cardWorks = true; Serial.println(F("card initialized.")); digitalWrite(6, HIGH); // green fileName[0] = '\0'; } void loop() { if (!cardWorks) { return; } while (ss.available() > 0) { gps.encode(ss.read()); } // if no GPS blink red LED if (millis() > 5000 && gps.charsProcessed() < 10 && millis() % 1000 == 0) { digitalWrite(8, HIGH); //red } else if (millis() > 5000 && gps.charsProcessed() < 10 && millis() % 500 == 0) { digitalWrite(8, LOW); // red } // check if we have a valid location and blink yellow if invalid if (gps.location.isValid()) { digitalWrite(7, LOW); // yellow } // next two lines will blink yellow (eye catching!) else if (!gps.location.isValid() && millis() % 1000 == 0) { digitalWrite(7, HIGH); // yellow } else if (!gps.location.isValid() && millis() % 500 == 0) { digitalWrite(7, LOW); // yellow } if (gps.location.isValid() && gps.time.second() != prevSecond) { // before we forget, log previous second prevSecond = gps.time.second(); // if no file name, create if (fileName[0] == '\0') { // create filename // Example Filename = 03140201 (year=17, month=03, date=14, hour=02, tripnumber = 0 uint8_t trip = 1; sprintf(fileName, P("%02d%02d%02d%02d.CSV"), gps.date.year() - 2000, gps.date.month(), gps.date.day(), trip); // well, if we have made 99 trips today (usually due to bad power connection) only write final trip while (SD.exists(fileName) && trip < 99) { trip++; sprintf(fileName, P("%02d%02d%02d%02d.CSV"), gps.date.year() - 2000, gps.date.month(), gps.date.day(), trip); } // print to serial where this data is being saved Serial.print(P("Writing to ... ")); Serial.print(fileName); Serial.print(P("\n")); // write header to file File dataFileHead = SD.open(fileName, FILE_WRITE); // if not able to write, then turn LED red if (!dataFileHead) { digitalWrite(6, LOW); // green digitalWrite(8, HIGH); //red } if (dataFileHead && trip != 99) { dataFileHead.println(P("year,month,day,hour,minute,second,sat,latitude,longitude,elev,mph,dir,cdir,grade,accel,trip,mihm,dirhm")); Serial.println( P("year,month,day,hour,minute,second,sat,latitude,longitude,elev,mph,dir,cdir,grade,accel,trip,mihm,dirhm")); lnBuffer[0] = '\0'; dataFileHead.close(); digitalWrite(6, HIGH); // green digitalWrite(8, LOW); //red } } // dont log if no satellites found if (!gps.satellites.value()) return; sprintf(numStr, P("%04d,%02d,%02d,%02d,%02d,%02d, "), gps.date.year(), gps.date.month(), gps.date.day(), gps.time.hour(), gps.time.minute(), gps.time.second()); strcat(lnBuffer, numStr); dtostrf(gps.satellites.value(), 3, 0, numStr); if (gps.satellites.isValid()) strcat(lnBuffer, numStr); strcat(lnBuffer, P(", ")); dtostrf(gps.location.lat(), 10, 6, numStr); if (gps.location.isValid()) strcat(lnBuffer, numStr); strcat(lnBuffer, P(", ")); dtostrf(gps.location.lng(), 10, 6, numStr); if (gps.location.isValid()) strcat(lnBuffer, numStr); strcat(lnBuffer, P(", ")); if (gps.altitude.isValid()) dtostrf(gps.altitude.feet(), 5, 0, numStr); strcat(lnBuffer, numStr); // we only add the additional info if we have enough buffer space // as occassionally before I was accidentially causing the buffer to // overflow. In an idea world, I'd use a bigger buffer but RAM is limited // e.g. if (strlen(lnBuffer) < 100) if (strlen(lnBuffer) < 100) strcat(lnBuffer, P(", ")); dtostrf(gps.speed.mph(), 0, 1, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, P(", ")); dtostrf(gps.course.deg(), 0, 1, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, P(", ")); if (strlen(lnBuffer) < 100) strcat(lnBuffer, TinyGPSPlus::cardinal(gps.course.deg())); if (strlen(lnBuffer) < 100) strcat(lnBuffer, P(", ")); // calculate current grade -- if we have a change in altitude // and we've traveled some kind of distance if (gps.altitude.isValid() && (gps.altitude.meters() - prevAlt) != 0 && TinyGPSPlus::distanceBetween( gps.location.lat(), gps.location.lng(), prevLat, prevLng) != 0) { dtostrf( (gps.altitude.meters() - prevAlt) / TinyGPSPlus::distanceBetween( gps.location.lat(), gps.location.lng(), prevLat, prevLng) , 5, 2, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, numStr); } else { if (strlen(lnBuffer) < 100) strcat(lnBuffer, P("0.00")); } // acceleration if (strlen(lnBuffer) < 100) strcat(lnBuffer, P(", ")); dtostrf((gps.speed.mps() - prevSpeed) / (millis() - prevTime), 7, 4, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, P(", ")); // total milage of trip at this part of logging // only increment when moving to minimize // "idle" gps hop if (prevLat && gps.speed.mph() > 1) { milesSinceBoot += TinyGPSPlus::distanceBetween( gps.location.lat(), gps.location.lng(), prevLat, prevLng) * 0.00062137112; // meters to miles } dtostrf( milesSinceBoot, 5, 2, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, numStr); if (strlen(lnBuffer) < 100) strcat(lnBuffer, P(", ")); // miles from home dtostrf( TinyGPSPlus::distanceBetween( gps.location.lat(), gps.location.lng(), HOMELAT, HOMELNG) * 0.00062137112, 5, 2, numStr); if (strlen(lnBuffer) < 105) strcat(lnBuffer, numStr); // direction from home (for shits and giggles) if (strlen(lnBuffer) < 105) strcat(lnBuffer, P(", ")); if (strlen(lnBuffer) < 110) strcat(lnBuffer, TinyGPSPlus::cardinal(TinyGPSPlus::courseTo( HOMELAT, HOMELNG, gps.location.lat(), gps.location.lng() ))); // save previous lat/lng/alt prevLat = gps.location.lat(); prevLng = gps.location.lng(); prevAlt = gps.altitude.meters(); prevSpeed = gps.speed.mps(); prevTime = millis(); File dataFile = SD.open(fileName, FILE_WRITE); if (dataFile) { dataFile.println(lnBuffer); dataFile.close(); // print to the serial port too: Serial.println(lnBuffer); digitalWrite(6, HIGH); // green digitalWrite(8, LOW); //red } // if the file isn't open, pop up an error: else { Serial.print(F("error opening ")); Serial.print(fileName); Serial.print("\n"); digitalWrite(6, LOW); // green digitalWrite(8, HIGH); //red } // clear buffer lnBuffer[0] = '\0'; } }
This is the code current version of the code I use for my GPS logger,Β which is powered by a Neo 6M GPS unit, an Arduino SD Card Reader with an 8 GB MicroSD Card, and an Arduino Nano. It logs a wide variety of information about my current location, speed of travel, and other information so I can easily look back at my trip.
Metes and bounds is a system or method of describing land, real property (in contrast to personal property) or real estate. Newer systems include rectangular (government survey), lot and block (recorded plat) and Torrens (used in Hawaii, Colorado, Australia, New Zealand and Canada).
Metes. The term "metes" refers to a boundary defined by the measurement of each straight run, specified by a distance between the terminal points, and an orientation or direction. A direction may be a simple compass bearing, or a precise orientation determined by accurate survey methods.
Bounds. The term "bounds" refers to a more general boundary description, such as along a certain watercourse, a stone wall, an adjoining public road way, or an existing building. The system is often used to define larger pieces of property (e.g. farms), and political subdivisions (e.g. town boundaries) where precise definition is not required or would be far too expensive, or previously designated boundaries can be incorporated into the description.
Quantum GIS 3.0 is a really awesome piece of software. QGIS in recent years has been nipping at the heals of ArcGIS but with the latest version its taken another step closer.
QGIS biggest former weakness – the inflexible labeling engine that used to be a pain to edit labels has taken a Quatum leap forward. Also it’s much faster at many operations due to much more threading and caching. It’s great software that is open source, free for anybody to use for any purpose.
You can Download QGIS 3.0 here.
Quantum GIS has steadily become more powerful software since I started using it a decade ago. I'm looking forward to upgrading to 3.0 this weekend after installing Bionic Beaver.