Home › Forums › Mayfly Data Logger › Recording data from pressure sensors on an SD card
Tagged: datalogger, pressuresensors, SDcard, sensors
- This topic has 12 replies, 5 voices, and was last updated 2017-05-08 at 3:08 PM by MillerG.
-
AuthorPosts
-
-
2017-04-28 at 3:15 PM #2188
Hello,
I have a Mayfly data logger and am looking for some advice on how to log data from 2 pressure sensors onto an SD card. I am a novice in the data logger community so please, bear with me.
I have a Sparkfun MS5803-14BA Breakout aqueous pressure sensor and an Adafruit MPL115A2 I2C Barometric pressure sensor. I am looking to get the data recorded by these sensors onto an SD card, along with the time at which the data was recorded. I have codes for the both sensors as well as the time. The codes are all running very well and are putting out data through the serial monitor in Arduino IDE. Any assistance on how to get this data to record to the SD card would be much appreciated!
-
2017-04-28 at 6:59 PM #2189
MillerG, thanks for posting your question here!
In the meanwhile, have you successfully run the “Simple File Example” sketch? It’s here: https://envirodiy.org/mayfly/software/simple-file/; and also on GitHub here: https://github.com/EnviroDIY/EnviroDIY_Mayfly_Logger/tree/master/examples.
Last, if you are using an SD card that is larger than about 4 GB, you’ll probably need to use a newer Arduino SD library that we are now using: https://github.com/greiman/SdFat. This library can handle SDHC cards with up to 32 GB of capacity. So, if you can’t get our “Simple File Example” to work, then download and put this SdFat folder in your ~/Documents/Arduino/Libraries directory. Then you should be able to replace
Arduino1#include <SD.h>with this code to your “Simple File Example” or any other sketch:
Arduino123#include <SdFat.h>// File system object.SdFat sd; // reassigns all sd functions to SdFat functionsLet us know if you are successful with any of this.
If that works then try to merge the code in the “Simple File Example” with the code that you have working for your sensor.If you still need help. It would be great if you could post your code, using the “Add Code Snippet” button at the top of the forum post editor, or by attaching files to your post via the button at the bottom of the forum post editor.
Last, we’re working on an easy to use ModularSensors library (https://github.com/EnviroDIY/ModularSensors) that will integrate SD logging, radio communication, solar-charing and sleep functions for a set of preselected sensors. Unfortunately your sensor is not on that list at this time, but we could consider adding it in the future (or you could help us)!
-
2017-04-28 at 7:06 PM #2190
If you would like your sensors added to the ModularSensors library, please create an issue for them there!
-
2017-05-01 at 2:56 PM #2192
Anthony,
I have run that Sample Code but do not have success when I try to merge it in with my code.
This is my current code:
Aq_Bar_Pressure.inoArduino123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262#include <Wire.h>#include <SparkFun_MS5803_I2C.h>#include <Wire.h>#include <Adafruit_MPL115A2.h>Adafruit_MPL115A2 mpl115a2;#include <Wire.h>#include "Sodaq_DS3231.h"char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };//year, month, date, hour, min, sec and week-day(starts from 0 and goes to 6)//writing any non-existent time-data may interfere with normal operation of the RTC.//Take care of week-day also.DateTime dt(2017, 04, 24, 15, 04, 0, 1);// Begin class with selected address// available addresses (selected by jumper on board)// default is ADDRESS_HIGH// ADDRESS_HIGH = 0x76// ADDRESS_LOW = 0x77MS5803 sensor(ADDRESS_HIGH);//Create variables to store resultsfloat temperature_c, temperature_f;double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;// Create Variable to store altitude in (m) for calculations;double base_altitude = 1655.0; // Altitude of SparkFun's HQ in Boulder, CO. in (m)/** Simple data logger.*/#include <SPI.h>#include "SdFat.h"// SD chip select pin. Be sure to disable any other SPI devices such as Enet.const uint8_t chipSelect = SS;// Interval between data records in milliseconds.// The interval must be greater than the maximum SD write latency plus the// time to acquire and write data to the SD to avoid overrun errors.// Run the bench example to check the quality of your SD card.const uint32_t SAMPLE_INTERVAL_MS = 1000;// Log file base name. Must be six characters or less.#define FILE_BASE_NAME "Data"//------------------------------------------------------------------------------// File system object.SdFat sd;// Log file.SdFile file;// Time in micros for next data record.uint32_t logTime;//==============================================================================// User functions. Edit writeHeader() and logData() for your requirements.const uint8_t ANALOG_COUNT = 4;//------------------------------------------------------------------------------// Write data header.void writeHeader() {file.print(F("micros"));for (uint8_t i = 0; i < ANALOG_COUNT; i++) {file.print(F(",adc"));file.print(i, DEC);}file.println();}//------------------------------------------------------------------------------// Log a data record.void logData() {uint16_t data[ANALOG_COUNT];// Read all channels to avoid SD write latency between readings.for (uint8_t i = 0; i < ANALOG_COUNT; i++) {data[i] = analogRead(i);}// Write data to file. Start with log time in micros.file.print(logTime);// Write ADC data to CSV record.for (uint8_t i = 0; i < ANALOG_COUNT; i++) {file.write(',');file.print(data[i]);}file.println();}//==============================================================================// Error messages stored in flash.#define error(msg) sd.errorHalt(F(msg))//------------------------------------------------------------------------------void setup(){const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;char fileName[13] = FILE_BASE_NAME "00.csv";Serial.begin(9600);// Wait for USB Serialwhile (!Serial) {SysCall::yield();}delay(1000);Serial.println(F("Type any character to start"));while (!Serial.available()) {SysCall::yield();}// Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with// breadboards. use SPI_FULL_SPEED for better performance.if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {sd.initErrorHalt();}// Find an unused file name.if (BASE_NAME_SIZE > 6) {error("FILE_BASE_NAME too long");}while (sd.exists(fileName)) {if (fileName[BASE_NAME_SIZE + 1] != '9') {fileName[BASE_NAME_SIZE + 1]++;} else if (fileName[BASE_NAME_SIZE] != '9') {fileName[BASE_NAME_SIZE + 1] = '0';fileName[BASE_NAME_SIZE]++;} else {error("Can't create file name");}}if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) {error("file.open");}// Read any Serial data.do {delay(10);} while (Serial.available() && Serial.read() >= 0);Serial.print(F("Logging to: "));Serial.println(fileName);Serial.println(F("Type any character to stop"));// Write data header.writeHeader();// Start on a multiple of the sample interval.logTime = micros()/(1000UL*SAMPLE_INTERVAL_MS) + 1;logTime *= 1000UL*SAMPLE_INTERVAL_MS;Serial.begin(9600);Wire.begin();rtc.begin();rtc.setDateTime(dt); //Adjust date-time as defined 'dt' aboveSerial.begin(9600);//Retrieve calibration constants for conversion math.sensor.reset();sensor.begin();pressure_baseline = sensor.getPressure(ADC_4096);Serial.begin(9600);Serial.println("Hello!");Serial.println("Getting barometric pressure ...");mpl115a2.begin();}void loop() {// Time for next record.logTime += 1000UL*SAMPLE_INTERVAL_MS;// Wait for log time.int32_t diff;do {diff = micros() - logTime;} while (diff < 0);// Check for data rate too high.if (diff > 10) {error("Missed data record");}logData();// Force data to SD and update the directory entry to avoid data loss.if (!file.sync() || file.getWriteError()) {error("write error");}if (Serial.available()) {// Close file and stop.file.close();Serial.println(F("Done"));SysCall::halt();}DateTime now = rtc.now(); //get the current date-timeSerial.print(now.year(), DEC);Serial.print('/');Serial.print(now.month(), DEC);Serial.print('/');Serial.print(now.date(), DEC);Serial.print(' ');Serial.print(now.hour(), DEC);Serial.print(':');Serial.print(now.minute(), DEC);Serial.print(':');Serial.print(now.second(), DEC);Serial.println();Serial.print(weekDay[now.dayOfWeek()]);Serial.println();// To measure to higher degrees of precision use the following sensor settings:// ADC_256// ADC_512// ADC_1024// ADC_2048// ADC_4096// Read temperature from the sensor in deg C. This operation takes abouttemperature_c = sensor.getTemperature(CELSIUS, ADC_512);// Read temperature from the sensor in deg F. Converting// to Fahrenheit is not internal to the sensor.// Additional math is done to convert a Celsius reading.temperature_f = sensor.getTemperature(FAHRENHEIT, ADC_512);// Read pressure from the sensor in mbar.pressure_abs = sensor.getPressure(ADC_4096);// Report values via UARTSerial.print("Temperature C = ");Serial.println(temperature_c);Serial.print("Temperature F = ");Serial.println(temperature_f);Serial.print("Water Pressure abs (mbar)= ");Serial.println(pressure_abs);float pressureKPA = 0, temperatureC = 0;pressureKPA = mpl115a2.getPressure();Serial.print("Atmospheric Pressure (kPa): "); Serial.print(pressureKPA, 4); Serial.println(" kPa");delay(10000);} -
2017-05-01 at 2:59 PM #2193Aq_Bar_Press_NoSD.inoArduino123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116#include <Wire.h>#include <SparkFun_MS5803_I2C.h>#include <Wire.h>#include <Adafruit_MPL115A2.h>Adafruit_MPL115A2 mpl115a2;#include <Wire.h>#include "Sodaq_DS3231.h"char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };//year, month, date, hour, min, sec and week-day(starts from 0 and goes to 6)//writing any non-existent time-data may interfere with normal operation of the RTC.//Take care of week-day also.DateTime dt(2017, 04, 24, 15, 04, 0, 1);// Begin class with selected address// available addresses (selected by jumper on board)// default is ADDRESS_HIGH// ADDRESS_HIGH = 0x76// ADDRESS_LOW = 0x77MS5803 sensor(ADDRESS_HIGH);//Create variables to store resultsfloat temperature_c, temperature_f;double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;// Create Variable to store altitude in (m) for calculations;double base_altitude = 1655.0; // Altitude of SparkFun's HQ in Boulder, CO. in (m)void setup(){Serial.begin(9600);Wire.begin();rtc.begin();rtc.setDateTime(dt); //Adjust date-time as defined 'dt' aboveSerial.begin(9600);//Retrieve calibration constants for conversion math.sensor.reset();sensor.begin();pressure_baseline = sensor.getPressure(ADC_4096);Serial.begin(9600);Serial.println("Hello!");Serial.println("Getting barometric pressure ...");mpl115a2.begin();}void loop() {DateTime now = rtc.now(); //get the current date-timeSerial.print(now.year(), DEC);Serial.print('/');Serial.print(now.month(), DEC);Serial.print('/');Serial.print(now.date(), DEC);Serial.print(' ');Serial.print(now.hour(), DEC);Serial.print(':');Serial.print(now.minute(), DEC);Serial.print(':');Serial.print(now.second(), DEC);Serial.println();Serial.print(weekDay[now.dayOfWeek()]);Serial.println();// To measure to higher degrees of precision use the following sensor settings:// ADC_256// ADC_512// ADC_1024// ADC_2048// ADC_4096// Read temperature from the sensor in deg C. This operation takes abouttemperature_c = sensor.getTemperature(CELSIUS, ADC_512);// Read temperature from the sensor in deg F. Converting// to Fahrenheit is not internal to the sensor.// Additional math is done to convert a Celsius reading.temperature_f = sensor.getTemperature(FAHRENHEIT, ADC_512);// Read pressure from the sensor in mbar.pressure_abs = sensor.getPressure(ADC_4096);// Report values via UARTSerial.print("Temperature C = ");Serial.println(temperature_c);Serial.print("Temperature F = ");Serial.println(temperature_f);Serial.print("Water Pressure abs (mbar)= ");Serial.println(pressure_abs);float pressureKPA = 0, temperatureC = 0;pressureKPA = mpl115a2.getPressure();Serial.print("Atmospheric Pressure (kPa): "); Serial.print(pressureKPA, 4); Serial.println(" kPa");delay(10000);}
-
2017-05-02 at 12:58 PM #2195
The first couple things that stand out are this:
You don’t have to say “Serial.begin(9600)” more than once in your sketch. Just do it once near the beginning of your setup() function and that’s it.
You don’t have to set the date and time of the RTC every time you run the sketch. The way it is written in your examples means that the clock gets programmed with that prewritten date/time every time the board boots up, which is definitely not something you ever want to do. If you’re using a Mayfly (or any real-time-clock) module with a battery backup (the little silver watch-battery), then your RTC will remember the correct date and time for many years, so you only need to set that time once using a standalone sketch like the “Adjust” example sketch with the SODAQ_DS3231 library. Once the clock is set, you can remove all of the lines in your logger sketches that were essentially re-setting it each time. So in the above sketch, remove lines 11, 16, and 41.
I’ll see if I can add the code for SD functionality to the second sketch you posted and attempt to compile it on my computer.
-
2017-05-03 at 12:05 PM #2206
MillerG, can you paste in the error codes you get with your first sketch?
Also, I reformatted your first sketch so that it would render better, but I’m slightly worried that I may have messed something up when I did it. Can you confirm that the first sketch is correctly rendered? Thanks! -
2017-05-03 at 12:14 PM #2210
I don’t get an error code from the sketch. The sketch will upload and show data in the serial monitor. But, it will not log the data onto an SD card, which is my goal.
-
2017-05-03 at 12:18 PM #2211
Anthony,
The first code complied just fine. I will try and upload it to the Mayfly later and let you know how it goes. Thanks!
-
2017-05-03 at 4:08 PM #2212
Something I’m not seeing in your first sketch is where you declare what chipselect pin for the SD card. On the Mayfly it’s 12, so on line 42, change the “SS” to “12”. Then remove all the extra Serial.begin(9600) statements so there’s only one at the beginning of the setup function. And remove the RTC stuff on lines 11, 16, and 41. See if that will write the data to your card.
-
2017-05-05 at 4:04 PM #2220123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108#include <SPI.h>#include <SD.h>#include <Wire.h>#include <Adafruit_MPL115A2.h>Adafruit_MPL115A2 mpl115a2;//Digital pin 12 is the MicroSD slave select pin on the Mayfly#define SD_SS_PIN 12//The data log file#define FILE_NAME "DataLog5.txt"//Data header (these lines get written to the beginning of a file when it's created)#define LOGGERNAME "Mayfly Writing pressure and temp data to microSD card"#define DATA_HEADER "SampleNumber(time?) , Air presure (kPa), Air Temperature(C)"int sampleinterval = 10; //time between samples, in secondsint samplenum = 1; // declare the variable "samplenum" and start with 1//THIS NEEDS CHANGING FOR PRESSURE SENSOR int batteryPin = A6; // on the Mayfly board, pin A6 is connected to a resistor divider on the battery input//Define the values that will be read by pressure sensorfloat airPressureSenseValue;float airTempSenseValue;void setup(){//Initialise the serial connectionSerial.begin(9600);delay(3000);mpl115a2.begin();//Initialise log filesetupLogFile();//Echo the data header to the serial connectionSerial.println(DATA_HEADER);}void loop(){String dataRec = createDataRecord();//Save the data record to the ial connectionSerial.println(dataRec);delay(sampleinterval*1000); //multiply by 1000 to convert from milliseconds to seconds}void setupLogFile(){//Initialise the SD cardif (!SD.begin(SD_SS_PIN)){Serial.println("Error: SD card failed to initialise or is missing.");//Hang// while (true);}//Check if the file already existsbool oldFile = SD.exists(FILE_NAME);//Open the file in write modeFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Add header information if the file did not already existif (!oldFile){logFile.println(LOGGERNAME);logFile.println(DATA_HEADER);}//Close the file to save itlogFile.close();}void logData(String rec){//Re-open the fileFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Write the CSV datalogFile.println(rec);//Close the file to save itlogFile.close();}String createDataRecord(){//Create a String type data record in csv format//SampleNumber, Air pressure, Air temperatureString data = "";data += samplenum; //creates a string called "data", put in the sample numberdata += ","; //adds a comma between valuesairPressureSenseValue = mpl115a2.getPressure(); //assigns pressure to a variableairTempSenseValue = mpl115a2.getTemperature(); //assigns temp to a variable//Write pressure, temp to recorddata += airPressureSenseValue;data += ",";data += airTempSenseValue;samplenum++; //increment the sample numberreturn data;}
This is our current sketch. It will produce the data into the serial monitor. It will also record the header to the SD but not any of the readings from the sensors. Can anybody see any errors in the sketch or know why we can record the header but not the readings?
Thanks
-
2017-05-05 at 4:55 PM #2221
in your main loop function, somewhere in lines 44-47 you need to call:
logData(dataRec);
-
2017-05-08 at 3:08 PM #2222
Thanks Hank! You’re right, that was all we needed.
-
-
AuthorPosts
- You must be logged in to reply to this topic.