// Code developed by Dr Kris Chan & Dr Bruce Main, King's College London 10.11.2018 // ////////////////////////////////////////////////////////////////////////////////////// /* LIBRARIES */ #include // SPI communication library (for clock & SD card) #include "ds3234.h" // clock library #include // SD library #include // sleep library #include // power library (for sleep) #include // Additional library for BME680 #include "Adafruit_BME680.h" // BME680 library #include // Other general functions library #include // I2C communication library (for BME680) /* Constants */ const int CS = 10; //sd card SPI chip select int ss = 9; //clock SPI chip select int AlarmPin = 2; //pin which alarm communicates with unsigned int wADC; //Arduino internal temperature call //BME680 housekeeping Adafruit_BME680 bme; // BME680 setup float bmetemp, bmegas, bmepres, bmehum; // create float (x.xx) variables to store BME values temporarily //SD HOUSEKEEPING SdFat sd; SdFile file; char newfile[] = "BMElog1min.csv"; //name of file //ALARM HOUSEKEEPING unsigned char wakeup_min; struct ts t; uint8_t sleep_period = 1; //sleep period volatile boolean extInterrupt1 = false; //SET ALARM SUBROUTINE void set_alarm(void) { wakeup_min = (t.min / sleep_period + 1) * sleep_period; if (wakeup_min > 59) { wakeup_min -= 60; } uint8_t flags[4] = { 0, 1, 1, 1}; DS3234_set_a2(ss, wakeup_min, 0, 0, flags); //set Alarm1 DS3234_set_creg(ss, DS3234_INTCN | DS3234_A2IE); //activate Alarm1 } //END ALARM SUBROUTINE void(* resetFunc) (void) = 0;//declare reset function at address 0 //START SETUP void setup() { Serial.begin(9600); while (!Serial); Serial.println(F("BME680 test")); if (!bme.begin()) { Serial.println("Could not find a valid BME680 sensor, check wiring!"); delay(30); resetFunc(); //call reset while (1); } // Set up oversampling and filter initialization bme.setTemperatureOversampling(BME680_OS_8X); bme.setHumidityOversampling(BME680_OS_2X); bme.setPressureOversampling(BME680_OS_4X); bme.setIIRFilterSize(BME680_FILTER_SIZE_3); bme.setGasHeater(320, 150); // 320*C for 150 ms // Serial.println("setupstart"); SPI.beginTransaction(SPISettings(6000000, MSBFIRST, SPI_MODE3)); DS3234_init(ss, DS3234_INTCN); delay(10); DS3234_get(ss, &t); delay(10); set_alarm(); DS3234_clear_a2f(ss); delay(10); pinMode (AlarmPin, INPUT); attachInterrupt(0, alarm, FALLING); // setting the alarm interrupt delay(100); while (!sd.begin(CS, SPI_HALF_SPEED)) {} // open the file for write at end like the Native SD library file.open(newfile, O_WRITE | O_CREAT | O_APPEND); file.close(); Serial.println("setupend"); //would print to the Arduino screen if connected delay(100); } //END SETUP //START LOOP void loop() { if (! bme.performReading()) { Serial.println("Failed to perform reading. Resetting"); delay(30); resetFunc(); //call reset return; } Serial.println("loop"); //would print to the Arduino screen if connected delay(50); gotoSleep(); //Arduino put to sleep detachInterrupt(0); //Arduino wakes up & turns off alarm if (extInterrupt1) extInterrupt1 = false; //get BME680 readings bmetemp = bme.temperature; bmepres = bme.pressure /100.0; bmehum = bme.humidity; bmegas = bme.gas_resistance / 1000.0; //run GetTemp subroutine (returns internal uncalibrated Arduino temperature) GetTemp(); //get clock temperature and reset alarm SPI.beginTransaction(SPISettings(6000000, MSBFIRST, SPI_MODE3)); delay(20); DS3234_get(ss, &t); set_alarm(); DS3234_clear_a2f(ss); float dstemp = (DS3234_get_treg(ss)); //prepare data to be written to SD String dataString = ""; dataString += t.year; dataString += ","; dataString += t.mon; dataString += ","; dataString += t.mday; dataString += ","; dataString += t.hour; dataString += ","; dataString += t.min; dataString += ","; dataString += wADC; dataString += ","; dataString += bmetemp; dataString += ","; dataString += bmehum; dataString += ","; dataString += bmepres; dataString += ","; dataString += bmegas; dataString += ","; dataString += dstemp; //print the data to be written to SD Serial.println(dataString); Serial.println(""); delay(50); //write the data to the file while (!sd.begin(CS,SPI_HALF_SPEED)) { } file.open(newfile, O_WRITE | O_APPEND); //Opens the file delay(5); file.println(dataString); //prints data string to the file delay(5); file.close(); //closes the file delay(20); attachInterrupt(0, alarm, FALLING); //turns back on alarm } //END LOOP //START ARDUINO SLEEP SETTING SUBROUTINE void gotoSleep(void) { byte adcsra = ADCSRA; //save the ADC Control and Status Register A ADCSRA = 0; //disable the ADC sleep_enable(); power_spi_disable(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); sleep_bod_disable(); sei(); sleep_cpu(); /* wake up here */ sleep_disable(); power_spi_enable(); ADCSRA = adcsra; //restore ADCSRA } //START ALARM SUBROUTINE void alarm() { extInterrupt1 = true; } //START ARDUINO INTERNAL TEMPERATURE SUBROUTINE double GetTemp(void) { ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3)); ADCSRA |= _BV(ADEN); delay(20); ADCSRA |= _BV(ADSC); while (bit_is_set(ADCSRA,ADSC)); wADC = ADCW; }