/* For SkyPod GPS logger with wind sensor. Operates an Arduino Nano which powers a u-blox NEO 7M GPS board, microSD breakout board, ModernDevice wind sensor Rev P, and BME280 barometric pressure, temperature, and humidity sensor. Sensor data are saved to microSD card about every five seconds. GPS RX is connected D7, TX to D8. BME280 SCL wire is connected to A5, SDA to A4. Wind sensor OUT is connected to A0, TMP to A2. The wind sensor requires at least 8 volts and is powered from VIN. All of the hardware was powered by a 9 volt Lithium battery. C. Fastie 03/2017 */ #include // library for SPI devices (uSD board) #include // library for GPS #include // library for serial comm. (with GPS) #include // library for the uSD board #include // library for comm. with I2C sensors #include // libary for BME280 const byte chipSelect = 10; // the SD card CS pin is wired to pin 10 TinyGPS gps; // make the tinyGPS object SoftwareSerial ss(8, 7); // Assign the SoftwareSerial TX and RX pins for the GPS #define SENSOR_MS 1000 // Sensor reading delay // The following two lines allow code in the BME280 library to compute altitude from pressure. // Before use, change the hgInches variable to the actual current sealevel barometric pressure. // Consult a weather website for the current value. Then save and load the sketch onto the Nano. float hgInches = 30.05; // Enter the current sealevel barometric pressure here (xx.xx inches Hg) #define SEALEVELPRESSURE_HPA (hgInches/0.02952998751) // hPa=(inches Hg)/0.02952998751 Adafruit_BME280 bme; // Use the BME280 sensor as an I2C device const int OutPin = A0; // wind sensor analog pin hooked up to Wind P sensor "OUT" pin const int TempPin = A2; // temp sensor analog pin hooked up to Wind P sensor "TMP" pin float zeroWind_v = 1.3692; float windMPH; float WS_MPH; void setup() { Serial.begin(9600); ss.begin(9600); // the GPS uses this if (!bme.begin(0x76)) // Initialize the BME sensor at this address { Serial.println("no BME"); while(1); // Wait forever since we don't have BME data } pinMode(chipSelect, OUTPUT); // The CS pin on the SD card if (!SD.begin(chipSelect)) // see if the card is present and can be initialized {Serial.println("no SD"); while(1); // Wait forever since we can't write data } File dataFile = SD.open("wind_bme.txt", FILE_WRITE); if (dataFile) { // if the file is available, write a header to it: dataFile.println("SkyPod GPS Wind BME280"); dataFile.println("Date,Time,Lon,Lat,Alt,hPa,bmeTemp,bmeHumid,bmeAlt,WindMPH,Windtemp"); dataFile.close(); } else { // Serial.println("file err 1"); // if the file is not open, display an error: } } // end setup void loop() { bool newData = false; for (unsigned long start = millis(); millis() - start < 1000;) // gather GPS data for 1 second { while (ss.available()) // while the GPS data is coming via software serial { char c = ss.read(); // read the characters into c if (gps.encode(c)) newData = true; // Did a new valid sentence come in? } } if (newData) // if a new valid GPS sentence was read { int windADunits = analogRead(OutPin); // read data from WindSensorRevP float windMPH = pow((((float)windADunits - 264.0) / 85.6814), 3.36814); // Serial.print(windMPH); // Serial.println(" MPH"); int tempRawAD = analogRead(TempPin); float tempC = ((((float)tempRawAD * 5.0) / 1024.0) - 0.400) / .0195; // Serial.print(tempC); // Serial.println(" C"); // Serial.println(); float flat, flon, falt; // the next 7 lines parse the GPS data unsigned long age; int year; byte month, day, hour, minute, second, hundredths; gps.f_get_position(&flat, &flon, &age); // read the latitude and longitude falt = gps.f_altitude(); // read the altitude gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age); // read the time char sz[32]; sprintf(sz, "%02d/%02d/%02d,%02d:%02d:%02d,", month, day, year, hour, minute, second); File dataFile = SD.open("wind_bme.txt", FILE_WRITE); // write to this file dataFile.print(sz); // write date time data to SD card dataFile.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6); // write GPS longitude data to SD card dataFile.print(","); dataFile.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6); // write GPS latitude data to SD card dataFile.print(","); dataFile.print(falt == TinyGPS::GPS_INVALID_ALTITUDE ? 0.0 : falt, 1); // write GPS altitude data to SD card dataFile.print(","); dataFile.print(bme.readPressure() / 100.0F); // write Pressure hPa data to SD card dataFile.print(","); dataFile.print(bme.readTemperature()); // write temperature data from BME280 to SD card dataFile.print(","); dataFile.print(bme.readHumidity()); // write BME280 humidity data dataFile.print(","); dataFile.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); // write altitude data computed from BME280 pressure dataFile.print(","); dataFile.print(windMPH); // write WindSensorRevP data dataFile.print(","); dataFile.println(tempC); // write WindSensorRevP data dataFile.flush(); dataFile.close(); } // endif (newData) delay (5000); // write data to SD card only every few seconds } // end main loop