Simple Logging

This shows the simplest use of a "logger" object. That is, creating an array of variable objects and then creating a logger object that utilizes those variables to update all of the variable results together and save the data to a SD card. The processor then goes to sleep between readings.

This is the example you should use to deploy a logger somewhere where you don't want or have access to a way of streaming live data and you won't want to upload data to the Monitor My Watershed data portal.


Unique Features of the Simple Logging Example

  • Only logs data to an SD card.

To Use this Example

Prepare and set up PlatformIO

  • Create a new PlatformIO project
  • Replace the contents of the platformio.ini for your new project with the platformio.ini file in the examples/simple_logging folder on GitHub.
    • It is important that your PlatformIO configuration has the lib_ldf_mode and build flags set as they are in the example.
    • Without this, the program won't compile.
  • Open simple_logging.ino and save it to your computer. Put it into the src directory of your project.
    • Delete main.cpp in that folder.

Set the logger ID

  • Change the "XXXX" in this section of code to the loggerID assigned by Stroud:
1// Logger ID, also becomes the prefix for the name of the data file on SD card
2const char *LoggerID = "XXXX";

Upload!

  • Test everything at home before deploying out in the wild!

PlatformIO Configuration

1; PlatformIO Project Configuration File
2;
3; Build options: build flags, source filter
4; Upload options: custom upload port, speed and extra flags
5; Library options: dependencies, extra library storages
6; Advanced options: extra scripting
7;
8; Please visit documentation for the other options and examples
9; http://docs.platformio.org/page/projectconf.html
10
11[platformio]
12description = ModularSensors example logging data to an SD card
13
14[env:mayfly]
15monitor_speed = 115200
16board = mayfly
17platform = atmelavr
18framework = arduino
19lib_ldf_mode = deep+
20lib_ignore =
21 RTCZero
22 Adafruit NeoPixel
23 Adafruit GFX Library
24 Adafruit SSD1306
25 Adafruit ADXL343
26 Adafruit STMPE610
27 Adafruit TouchScreen
28 Adafruit ILI9341
29build_flags =
30 -DSDI12_EXTERNAL_PCINT
31 -DNEOSWSERIAL_EXTERNAL_PCINT
32 -DMQTT_MAX_PACKET_SIZE=240
33 -DTINY_GSM_RX_BUFFER=64
34 -DTINY_GSM_YIELD_MS=2
35lib_deps =
36 envirodiy/EnviroDIY_ModularSensors
37; ^^ Use this when working from an official release of the library
38; https://github.com/EnviroDIY/ModularSensors.git#develop
39; ^^ Use this when if you want to pull from the develop branch
40 https://github.com/PaulStoffregen/AltSoftSerial.git
41 https://github.com/SRGDamia1/NeoSWSerial.git
42 https://github.com/EnviroDIY/SoftwareSerial_ExternalInts.git
43; ^^ These are software serial port emulator libraries, you may not need them

The Complete Code

1/** =========================================================================
2 * @example{lineno} simple_logging.ino
3 * @copyright Stroud Water Research Center
4 * @license This example is published under the BSD-3 license.
5 * @author Sara Geleskie Damiano <sdamiano@stroudcenter.org>
6 *
7 * @brief A simple data logging example.
8 *
9 * See [the walkthrough page](@ref example_simple_logging) for detailed
10 * instructions.
11 *
12 * @m_examplenavigation{example_simple_logging,}
13 * ======================================================================= */
14
15// ==========================================================================
16// Include the libraries required for any data logger
17// ==========================================================================
18/** Start [includes] */
19// The Arduino library is needed for every Arduino program.
20#include <Arduino.h>
21
22// Include the main header for ModularSensors
23#include <ModularSensors.h>
24/** End [includes] */
25
26
27// ==========================================================================
28// Data Logging Options
29// ==========================================================================
30/** Start [logging_options] */
31// The name of this program file
32const char* sketchName = "simple_logging.ino";
33// Logger ID, also becomes the prefix for the name of the data file on SD card
34const char* LoggerID = "XXXXX";
35// How frequently (in minutes) to log data
36const uint8_t loggingInterval = 15;
37// Your logger's timezone.
38const int8_t timeZone = -5; // Eastern Standard Time
39// NOTE: Daylight savings time will not be applied! Please use standard time!
40
41// Set the input and output pins for the logger
42// NOTE: Use -1 for pins that do not apply
43const int32_t serialBaud = 115200; // Baud rate for debugging
44const int8_t greenLED = 8; // Pin for the green LED
45const int8_t redLED = 9; // Pin for the red LED
46const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin)
47const int8_t wakePin = 31; // MCU interrupt/alarm pin to wake from sleep
48// Mayfly 0.x D31 = A7
49// Set the wake pin to -1 if you do not want the main processor to sleep.
50// In a SAMD system where you are using the built-in rtc, set wakePin to 1
51const int8_t sdCardPwrPin = -1; // MCU SD card power pin
52const int8_t sdCardSSPin = 12; // SD card chip select/slave select pin
53const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power
54/** End [logging_options] */
55
56
57// ==========================================================================
58// Using the Processor as a Sensor
59// ==========================================================================
60/** Start [processor_sensor] */
61#include <sensors/ProcessorStats.h>
62
63// Create the main processor chip "sensor" - for general metadata
64const char* mcuBoardVersion = "v1.1";
65ProcessorStats mcuBoard(mcuBoardVersion);
66/** End [processor_sensor] */
67
68
69// ==========================================================================
70// Maxim DS3231 RTC (Real Time Clock)
71// ==========================================================================
72/** Start [ds3231] */
73#include <sensors/MaximDS3231.h> // Includes wrapper functions for Maxim DS3231 RTC
74
75// Create a DS3231 sensor object, using this constructor function:
76MaximDS3231 ds3231(1);
77/** End [ds3231] */
78
79
80// ==========================================================================
81// Settings for Additional Sensors
82// ==========================================================================
83// Additional sensors can setup here, similar to the RTC, but only if
84// they have been supported with ModularSensors wrapper functions. See:
85// https://github.com/EnviroDIY/ModularSensors/wiki#just-getting-started
86// Syntax for the include statement and constructor function for each sensor is
87// at
88// https://github.com/EnviroDIY/ModularSensors/wiki#these-sensors-are-currently-supported
89// or can be copied from the `menu_a_la_carte.ino` example
90
91
92// ==========================================================================
93// Creating the Variable Array[s] and Filling with Variable Objects
94// ==========================================================================
95/** Start [variable_arrays] */
96Variable* variableList[] = {
97 new ProcessorStats_SampleNumber(&mcuBoard),
98 new ProcessorStats_FreeRam(&mcuBoard),
99 new ProcessorStats_Battery(&mcuBoard), new MaximDS3231_Temp(&ds3231)
100 // Additional sensor variables can be added here, by copying the syntax
101 // for creating the variable pointer (FORM1) from the
102 // `menu_a_la_carte.ino` example
103 // The example code snippets in the wiki are primarily FORM2.
104};
105// Count up the number of pointers in the array
106int variableCount = sizeof(variableList) / sizeof(variableList[0]);
107
108// Create the VariableArray object
109VariableArray varArray;
110/** End [variable_arrays] */
111
112
113// ==========================================================================
114// The Logger Object[s]
115// ==========================================================================
116/** Start [loggers] */
117// Create a logger instance
118Logger dataLogger;
119/** End [loggers] */
120
121
122// ==========================================================================
123// Working Functions
124// ==========================================================================
125/** Start [working_functions] */
126// Flashes the LED's on the primary board
127void greenredflash(uint8_t numFlash = 4, uint8_t rate = 75) {
128 for (uint8_t i = 0; i < numFlash; i++) {
129 digitalWrite(greenLED, HIGH);
130 digitalWrite(redLED, LOW);
131 delay(rate);
132 digitalWrite(greenLED, LOW);
133 digitalWrite(redLED, HIGH);
134 delay(rate);
135 }
136 digitalWrite(redLED, LOW);
137}
138/** End [working_functions] */
139
140
141// ==========================================================================
142// Arduino Setup Function
143// ==========================================================================
144/** Start [setup] */
145void setup() {
146 // Start the primary serial connection
147 Serial.begin(serialBaud);
148
149 // Print a start-up note to the first serial port
150 Serial.print(F("Now running "));
151 Serial.print(sketchName);
152 Serial.print(F(" on Logger "));
153 Serial.println(LoggerID);
154 Serial.println();
155
156 Serial.print(F("Using ModularSensors Library version "));
157 Serial.println(MODULAR_SENSORS_VERSION);
158
159 // Set up pins for the LED's
160 pinMode(greenLED, OUTPUT);
161 digitalWrite(greenLED, LOW);
162 pinMode(redLED, OUTPUT);
163 digitalWrite(redLED, LOW);
164 // Blink the LEDs to show the board is on and starting up
165 greenredflash();
166
167 // Set the timezones for the logger/data and the RTC
168 // Logging in the given time zone
169 Logger::setLoggerTimeZone(timeZone);
170 // It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0)
171 Logger::setRTCTimeZone(0);
172
173 // Set information pins
174 dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin,
175 greenLED);
176
177 // Begin the variable array[s], logger[s], and publisher[s]
178 varArray.begin(variableCount, variableList);
179 dataLogger.begin(LoggerID, loggingInterval, &varArray);
180
181 // Set up the sensors
182 Serial.println(F("Setting up sensors..."));
183 varArray.setupSensors();
184
185 // Create the log file, adding the default header to it
186 // Do this last so we have the best chance of getting the time correct and
187 // all sensor names correct
188 dataLogger.createLogFile(true); // true = write a new header
189
190 // Call the processor sleep
191 dataLogger.systemSleep();
192}
193/** End [setup] */
194
195
196// ==========================================================================
197// Arduino Loop Function
198// ==========================================================================
199/** Start [loop] */
200void loop() {
201 dataLogger.logData();
202}
203/** End [loop] */