/* For the Nano logging shield with RTC and SD card. Logs sensor data from two TSL2561 luminosity sensors and displays some of it (every 5 seconds) on a 2x16 LCD. LCD module (http://funduino.de/DL/1602LCD.pdf) has a backpack (http://www.ebay.com/itm/281707994237) to make it an I2C device. C. Fastie, May 2017 */ #include #include #include #include #include #include // https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads more: https://arduino-info.wikispaces.com/LCD-Blue-I2C SdFat SD; //SD will be the SdFat object #define MOSIpin 11 #define MISOpin 12 RTC_DS1307 RTC; //RTC will be the RTC_DS1307 object #define DS1307_I2C_ADDRESS 0x68 char TmeStrng[] = "0000/00/00,00:00:00"; //string template for RTC time stamp //char TmeStr[] = "00:00:00"; //short string template for LCD LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address and stuff int dLCD = 0; int logData = 0; Adafruit_TSL2561_Unified tsl1 = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 0x39); Adafruit_TSL2561_Unified tsl2 = Adafruit_TSL2561_Unified(TSL2561_ADDR_LOW, 0x29); void configureSensor(void) { // You can manually set the gain or enable auto-gain support // tsl1.setGain(TSL2561_GAIN_1X); // No gain ... use in bright light to avoid sensor saturation // tsl2.setGain(TSL2561_GAIN_1X); // tsl1.setGain(TSL2561_GAIN_16X); // 16x gain ... use in low light to boost sensitivity // tsl2.setGain(TSL2561_GAIN_16X); tsl1.enableAutoRange(true); // Auto-gain ... switches automatically between 1x and 16x tsl2.enableAutoRange(true); // Changing the integration time gives you better sensor resolution (402ms = 16-bit data) // tsl1.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); // fast but low resolution // tsl2.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); // tsl1.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); // medium resolution and speed // tsl2.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); tsl1.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); // 16-bit data but slowest conversions tsl2.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); } void setup() { Serial.begin(9600); // Open serial communications Wire.begin(); // start the i2c interface RTC.begin(); // start the RTC // Set the RTC to the computer time when the sketch is loaded. Must comment out for subsequent boots: // RTC.adjust(DateTime((__DATE__), (__TIME__))); lcd.begin(16,2); // initialize the lcd for 16 characters and 2 lines // Serial.print("Find SD: "); if (!SD.begin(10)) { // initialize the SD card // Serial.println("SD fail"); return; } Serial.println("SD OK"); lcd.setCursor(0,0); // Start at character 0 on line 0 lcd.print("SD OK"); // Display on LCD so you know data will be logged delay (3000); // Display for 3 seconds //print a header to the data file with the sealevel pressure: File dataFile = SD.open("datalog.txt", FILE_WRITE); if (dataFile) { // if the file is available, write a header to it: dataFile.println("NDVI autogain"); dataFile.close(); } // else { // Serial.println("file err 1"); // if the file isn’t open, display an error: // } configureSensor(); } // end of setup void loop() { for(int dLCD = 1; dLCD <=3 ; dLCD++) //cycle through 3 displays on the LCD { // logData = logData + 1; // count cycles for eventual write to SD on cycle x // read the sensors: sensors_event_t event1; tsl1.getEvent(&event1); sensors_event_t event2; tsl2.getEvent(&event2); uint16_t broadband1 = 0; float infrared1 = 0; uint16_t infrareda = 0; float NDVI1 = 0; uint16_t broadband2 = 0; uint16_t infraredb = 0; float infrared2 = 0; float NDVI2 = 0; //Populate variables with the latest values: tsl1.getLuminosity (&broadband1, &infrareda); infrared1 = infrareda*1.5; float vis1 = broadband1-infrareda; NDVI1 = (infrared1 - vis1) / (infrared1 + vis1); tsl2.getLuminosity (&broadband2, &infraredb); infrared2 = infraredb*1.5; float vis2 = broadband2-infraredb; NDVI2 = (infrared2 - vis2) / (infrared2 + vis2); DateTime now = RTC.now(); // read the time from the RTC, then construct two data strings: sprintf(TmeStrng, "%04d/%02d/%02d,%02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second()); // [added seconds] // sprintf(TmeStr, "%02d:%02d:%02d", now.hour(), now.minute(), now.second()); if (dLCD == 1) // Display one of 4 messages on the LCD { lcd.clear(); lcd.setCursor(0,0); //Start at character 0 on line 0 lcd.print("NDVI right"); lcd.setCursor(11,0); lcd.print(NDVI1); lcd.setCursor(0,1); lcd.print("NDVI left"); lcd.setCursor(11,1); lcd.print(NDVI2); /* //This is an alternate display for the LCD lcd.clear(); lcd.setCursor(0,0); //Start at character 0 on line 0 lcd.print("Bbnd1"); lcd.setCursor(6,0); lcd.print(broadband1); lcd.setCursor(0,1); lcd.print("LUX1"); lcd.setCursor(5,1); lcd.print(event1.light); */ } if (dLCD == 2) { lcd.clear(); lcd.print("V1"); lcd.setCursor(3,0); lcd.print(vis1); lcd.setCursor(0,1); lcd.print(infrareda); lcd.setCursor(11,1); lcd.print(NDVI1); } if (dLCD == 3) /* { //This is an alternate display for the LCD lcd.clear(); lcd.setCursor(0,0); //Start at character 0 on line 0 lcd.print("Bbnd2"); lcd.setCursor(6,0); lcd.print(broadband2); lcd.setCursor(0,1); lcd.print("LUX2"); lcd.setCursor(5,1); lcd.print(event2.light); } if (dLCD == 4)*/ { lcd.clear(); lcd.print("V2"); lcd.setCursor(3,0); lcd.print(vis2); lcd.setCursor(0,1); lcd.print(infraredb); lcd.setCursor(11,1); lcd.print(NDVI2); } /* //Printing to serial monitor for debugging if (event1.light) { Serial.print(event1.light); Serial.println(" lux1"); Serial.print(broadband1); Serial.println(" 1 (300-1100nm)"); Serial.print(infrared1); Serial.println(" 1 (600-1100nm)"); Serial.print(vis1); Serial.println(" 1 (Visible)"); Serial.print(NDVI1); Serial.println(" 1 (NDVI)"); Serial.println(""); } else { /* If event.light = 0 lux the sensor is probably saturated and no reliable data could be generated! */ /* Serial.println("Sensor1 overload"); } if (event2.light) { Serial.print(event2.light); Serial.println(" 2 lux"); Serial.print(broadband2); Serial.println(" 2 (300-1100nm)"); Serial.print(infrared2); Serial.println(" 2 (600-1100nm)"); Serial.print(vis2); Serial.println(" 2 (Visible)"); Serial.print(NDVI2); Serial.println(" 2 (NDVI)"); Serial.println(""); } else { /* If event.light = 0 lux the sensor is probably saturated and no reliable data could be generated! Serial.println("Sensor2 overload"); }*/ // The commented lines below are handy for troubleshooting but use too much memory for operation /* Serial.print("RTC utc Time: "); Serial.print(now.unixtime()); Serial.println(); Serial.print("RTC time: "); Serial.println(TmeStrng); Serial.print("Temp tote: "); Serial.print(BMEt1); Serial.println(" C"); Serial.print("Humidity tote: "); Serial.print(BMEh1); Serial.println(" %"); Serial.print("Temp room: "); Serial.print(BMEt2); Serial.println(" C"); Serial.print("Humidity room: "); Serial.print(BMEh2); Serial.println(" %"); Serial.print("Pressure: "); Serial.print(BMEp2); Serial.println(" hPa"); Serial.print("Elevation: "); Serial.print(BMEa2); Serial.println(" m"); Serial.println(); Serial.println(logData); Serial.println(); */ if (logData == 0) // write to SD card every cycle { /* Serial.println(); Serial.println("log to SD"); Serial.println(); */ //Construct a big data string to write to µSD card: String dataString = ""; //erase the previous string dataString += TmeStrng; dataString += ","; dataString += String(now.unixtime()); dataString += ","; dataString += String(event1.light); dataString += ","; dataString += String(broadband1); dataString += ","; dataString += String(infrareda); dataString += ","; dataString += String(NDVI1); dataString += ","; dataString += String(event2.light); dataString += ","; dataString += String(broadband2); dataString += ","; dataString += String(infraredb); dataString += ","; dataString += String(NDVI2); // write the data to the SD card: File dataFile = SD.open("datalog.txt", FILE_WRITE); // if the file is available, write to it: if (dataFile) { dataFile.println(dataString); dataFile.close(); } /* else { Serial.println("file err 2"); // if the file isn’t open, display an error: } */ logData = 0; } // end of if (logData) delay(4000); // update LCD every x/1000 seconds } // end of for loop (dispLCD) } // end of the MAIN LOOP