I need to internally power down my Arduino nano every to consume hardly any power so the lipo battery lasts longer. This means I need all the sensors to have power cut to them as well. My project is a datalogger so the switch method is a no-go. It has to be fully integrated via the code to work in my situation. I have some coding experience but had help making the main code from a friend that has no clue how to accomplish this step.
//This code was written to be easy to understand.
//Modify this code as you see fit.
//This code will output data to the Arduino serial monitor.
//Type commands into the Arduino serial monitor to control the D.O. circuit.
//This code was written in the Arduino 1.8.9 IDE
//An Arduino UNO was used to test this code.
//This code was last tested 6/2019
/////////////////////////////////////////////////// RTC //////////////////////////////////////
#include <Wire.h>
#include "Sodaq_DS3231.h"
char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
/////////////////////////////////////////
#include <SoftwareSerial.h> //we have to include the SoftwareSerial library, or else we can't use it
#define Drx 1 //define what pin rx is going to be
#define Dtx 0 //define what pin tx is going to be
SoftwareSerial Dmyserial(Drx, Dtx); //define how the soft serial port is going to work
#define Erx 5 //define what pin rx is going to be
#define Etx 6 //define what pin tx is going to be
SoftwareSerial Emyserial(Erx, Etx); //define how the soft serial port is going to work
String Einputstring = ""; //a string to hold incoming data from the PC
String Esensorstring = ""; //a string to hold the data from the Atlas Scientific product
boolean Einput_string_complete = false; //have we received all the data from the PC
boolean Esensor_string_complete = false; //have we received all the data from the Atlas Scientific product
char *EC; //char pointer used in string parsing
float f_ec; //used to hold a floating point number that is the EC
String Dinputstring = ""; //a string to hold incoming data from the PC
String Dsensorstring = ""; //a string to hold the data from the Atlas Scientific product
String DOVALUE="";
boolean Dinput_string_complete = false; //have we received all the data from the PC
boolean Dsensor_string_complete = false; //have we received all the data from the Atlas Scientific product
float DO; //used to hold a floating point number that is the DO
#include <Wire.h>
#include "Adafruit_MCP9808.h"
// Create the MCP9808 temperature sensor object
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
float TEMPVALUE=0;
//////////////////////////////////////////////////// SD CARDS THINGS /////////////////////////////////////
#include <SPI.h>
#include <SD.h>
File fd;
const uint8_t BUFFER_SIZE = 20;
char fileEC[] = "EC.csv"; // SD library only supports up to 8.3 names
char fileDO[] = "DO.csv";
char fileTEMP[] = "TEMP.csv";
char buff[BUFFER_SIZE+2] = ""; // Added two to allow a 2 char peek for EOF state
uint8_t index = 0;
const uint8_t chipSelect = 8;
const uint8_t cardDetect = 9;
enum states: uint8_t { NORMAL, E, EO };
uint8_t state = NORMAL;
bool alreadyBegan = false; // SD.begin() misbehaves if not first call
/////////////////////////////////////////////////////////////////
void setup() {
//
// pinMode(A1, OUTPUT); /// FOR 5V ////
// pinMode(A2, OUTPUT); ///// FOR 5V ///
//
// pinMode(3, OUTPUT); ///// FOR GRND ///
// pinMode(4, OUTPUT); ///// FOR GRND ////
//
// digitalWrite( 3, HIGH); //// MAKING PIN HIGH OR 5V ////
// digitalWrite( A2, HIGH); //// MAKING PIN HIGH OR 5V ////
//
// digitalWrite( 4, LOW); //// MAKING PIN LOW OR 5V ////
// digitalWrite( 7, LOW); //// MAKING PIN LOW OR 5V ////
//set up the hardware
Serial.begin(9600); //set baud rate for the hardware serial port_0 to 9600
Wire.begin();
rtc.begin();
Dmyserial.begin(9600); //set baud rate for the software serial port to 9600
Dinputstring.reserve(10); //set aside some bytes for receiving data from the PC
Dsensorstring.reserve(30); //set aside some bytes for receiving data from Atlas Scientific product
Emyserial.begin(9600); //set baud rate for the software serial port to 9600
Einputstring.reserve(10); //set aside some bytes for receiving data from the PC
Esensorstring.reserve(30); //set aside some bytes for receiving data from Atlas Scientific product
if (!tempsensor.begin(0x18)) {
Serial.println(F("Couldn't find MCP9808! Check your connections and verify the address is correct."));
while (1);
}
Serial.println(F("Found MCP9808!"));
tempsensor.setResolution(3); // sets the resolution mode of reading, the modes are defined in the table bellow:
pinMode(cardDetect, INPUT);
initializeCard();
}
void EserialEvent() { //if the hardware serial port_0 receives a char
Einputstring = Serial.readStringUntil(13); //read the string until we see a <CR>
Einput_string_complete = true; //set the flag used to tell if we have received a completed string from the PC
}
void DserialEvent() { //if the hardware serial port_0 receives a char
Dinputstring = Serial.readStringUntil(13); //read the string until we see a <CR>
Dinput_string_complete = true; //set the flag used to tell if we have received a completed string from the PC
}
int b=0;
void loop() {
tim();
Serial.println(F(" Let's DO it"));
sleep(900000)
//here we go...
Serial.println(F(""));
Serial.println(F( " DO SENSOR VALUE"));
Serial.println(F(""));
Dmyserial.begin(9600); //set baud rate for the software serial port to 9600
while( DOS()==0);
delay(100);
if (!digitalRead(cardDetect))
{
initializeCard();
}
fd = SD.open(fileDO, FILE_WRITE);
if (fd) {
Serial.print(F("Writing to DO.txt..."))
; fd.print( DO)
;fd.print(",");
;tim();
; fd.close();
Serial.println(F("done."));
} else {
Serial.println(F("error opening DO.txt"));
}
/////////////////////////////////////////////////////////////// EC SENSOR //////////////////////////////////
Serial.println(F(""));
Serial.println(F( " CONDUCTIVIY SENSOR VALUE"));
Serial.println(F(","));
Emyserial.begin(9600); //set baud rate for the software serial port to 9600
while ( ECOND()==0);
delay(100);
if (!digitalRead(cardDetect))
{
initializeCard();
}
fd = SD.open(fileEC, FILE_WRITE);
if (fd) {
Serial.print(F("Writing to EC.txt..."));
;fd.print( f_ec);
;fd.print(",");
;tim();
fd.close();
Serial.println(F("done."));
} else {
Serial.println(F("error opening EC.txt"));
}
////////////////////////////////////////////////////////// TEMP ///////////////////////////////////////
Serial.println(F(""));
Serial.println(F( " TEMPERATURE SENSOR VALUE"));
Serial.println(F(","));
MCP();
if (!digitalRead(cardDetect))
{
initializeCard();
}
fd = SD.open(fileTEMP, FILE_WRITE);
if (fd) {
Serial.print(F("Writing to TEMP.txt..."));
;fd.print( TEMPVALUE);
;fd.print(",");
;tim();
fd.close();
Serial.println(F("done."));
} else {
Serial.println(F("error opening TEMP.txt"));
}
}
///////////////////////////////// DO /////////////////////////////
bool DOS()
{
bool a=0;
if (Dinput_string_complete == true) { //if a string from the PC has been received in its entirety
Dmyserial.print(Dinputstring); //send that string to the Atlas Scientific product
Dmyserial.print('\r'); //add a <CR> to the end of the string
Dinputstring = ""; //clear the string
Dinput_string_complete = false; //reset the flag used to tell if we have received a completed string from the PC
}
if (Dmyserial.available() > 0) { //if we see that the Atlas Scientific product has sent a character
char Dinchar = (char)Dmyserial.read(); //get the char we just received
Dsensorstring += Dinchar; //add the char to the var called sensorstring
if (Dinchar == '\r') { //if the incoming character is a <CR>
Dsensor_string_complete = true; //set the flag
}
}
if (Dsensor_string_complete == true) { //if a string from the Atlas Scientific product has been received in its entirety
Serial.print(F("DO = "));
Serial.println(Dsensorstring);
DOVALUE = Dsensorstring;
//uncomment this section to see how to convert the DO reading from a string to a float
if (isdigit(Dsensorstring[0])) { //if the first character in the string is a digit
DO = Dsensorstring.toFloat(); //convert the string to a floating point number so it can be evaluated by the Arduino
}
a= Dsensor_string_complete;
Dsensorstring = ""; //clear the string
Dsensor_string_complete = false; //reset the flag used to tell if we have received a completed string from the Atlas Scientific product
}
// Serial.println(a);
return a;
}
//
int ECOND()
{
int a=0;
if (Einput_string_complete == true) { //if a string from the PC has been received in its entirety
Emyserial.print(Einputstring); //send that string to the Atlas Scientific product
Emyserial.print('\r'); //add a <CR> to the end of the string
Einputstring = ""; //clear the string
Einput_string_complete = false; //reset the flag used to tell if we have received a completed string from the PC
}
if (Emyserial.available() > 0) { //if we see that the Atlas Scientific product has sent a character
char Einchar = (char)Emyserial.read(); //get the char we just received
Esensorstring += Einchar; //add the char to the var called sensorstring
if (Einchar == '\r') { //if the incoming character is a <CR>
Esensor_string_complete = true; //set the flag
}
}
if (Esensor_string_complete == true) { //if a string from the Atlas Scientific product has been received in its entirety
if (isdigit(Esensorstring[0]) == false) { //if the first character in the string is a digit
Serial.println(Esensorstring); //send that string to the PC's serial monitor
}
else //if the first character in the string is NOT a digit
{
Eprint_EC_data(); //then call this function
}
a=Esensor_string_complete;
Esensorstring = ""; //clear the string
Esensor_string_complete = false; //reset the flag used to tell if we have received a completed string from the Atlas Scientific product
}
return a;
}
void Eprint_EC_data(void) { //this function will pars the string
char Esensorstring_array[30]; //we make a char array
char *TDS; //char pointer used in string parsing
char *SAL; //char pointer used in string parsing
char *GRAV; //char pointer used in string parsing
Esensorstring.toCharArray(Esensorstring_array, 30); //convert the string to a char array
EC = strtok(Esensorstring_array, ","); //let's pars the array at each comma
TDS = strtok(NULL, ","); //let's pars the array at each comma
SAL = strtok(NULL, ","); //let's pars the array at each comma
GRAV = strtok(NULL, ","); //let's pars the array at each comma
Serial.print(F("EC:")); //we now print each value we parsed separately
Serial.println(EC); //this is the EC value
Serial.print(F("TDS:")); //we now print each value we parsed separately
Serial.println(TDS); //this is the TDS value
Serial.print(F("SAL:")); //we now print each value we parsed separately
Serial.println(SAL); //this is the salinity value
Serial.print(F("GRAV:")); //we now print each value we parsed separately
Serial.println(GRAV); //this is the specific gravity
//Serial.println(); //this just makes the output easier to read
f_ec= atof(EC); //uncomment this line to convert the char to a float
}
void MCP()
{
// Serial.println("wake up MCP9808.... "); // wake up MCP9808 - power consumption ~200 mikro Ampere
// tempsensor.wake(); // wake up, ready to read!
// Read and print out the temperature, also shows the resolution mode used for reading.
// Serial.print("Resolution in mode: ");
// Serial.println (tempsensor.getResolution());
float c = tempsensor.readTempC();
float f = tempsensor.readTempF();
Serial.print("Temp: ");
Serial.print(c, 4); Serial.print(F("*C\t and "));
Serial.print(f, 4); Serial.println(F("*F."));
TEMPVALUE =tempsensor.readTempF();
// delay(2000);
// Serial.println("Shutdown MCP9808.... ");
// tempsensor.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling
Serial.println("");
delay(100);
}
//////////////////////////////////////////// CARD /////////////////////
void initializeCard(void)
{
Serial.print(F("Initializing SD card..."));
// Is there even a card?
if (!digitalRead(cardDetect))
{
Serial.println(F("No card detected. Waiting for card."));
while (!digitalRead(cardDetect));
delay(250); // 'Debounce insertion'
}
// Card seems to exist. begin() returns failure
// even if it worked if it's not the first call.
if (!SD.begin(chipSelect) && !alreadyBegan) // begin uses half-speed...
{
Serial.println(F("Initialization failed!"));
initializeCard(); // Possible infinite retry loop is as valid as anything
}
else
{
alreadyBegan = true;
}
Serial.println(F("Initialization done."));
Serial.print(fileEC);
if (SD.exists(fileEC))
{
Serial.println(F(" exists."));
}
else
{
Serial.println(F(" doesn't exist."));
}
Serial.print(fileDO);
if (SD.exists(fileDO))
{
Serial.println(F(" exists."));
}
else
{
Serial.println(F(" doesn't exist. "));
}
Serial.print(fileTEMP);
if (SD.exists(fileTEMP))
{
Serial.println(F(" exists."));
}
else
{
Serial.println(F(" doesn't exist."));
}
Serial.println(F(" CARD INITIALIZATION DONE "));
}
void tim()
{
DateTime now = rtc.now(); //get the current date-time
uint32_t ts = now.getEpoch();
// if (old_ts == 0 || old_ts != ts) {
// old_ts = ts;
Serial.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.print(' ');
Serial.println();
fd.print(now.year(), DEC);
fd.print('/');
fd.print(now.month(), DEC);
fd.print('/');
fd.print(now.date(), DEC);
fd.print(' ');
fd.print(now.hour(), DEC);
fd.print(':');
fd.print(now.minute(), DEC);
fd.print(':');
fd.print(now.second(), DEC);
fd.print(' ');
;fd.println();
}