Using the Wifi D1 Mini - Real-time Clock and Logger
by wiredcav in Circuits > Arduino
5126 Views, 3 Favorites, 0 Comments
Using the Wifi D1 Mini - Real-time Clock and Logger
This isn't going to be an exciting Instructable telling you how to make a flying car. This will hopefully just save other people the time I wasted working out how to use this nifty little device I bought on Ebay. I occasionally use these little MicroSD card loggers with my Arduino or ESP32 projects to log data, but the one shortcoming is that I can't include timestamps in my data. Of course I can include the time since power-up, but it would sometimes be nice to have time-of-day, and even calendar dates in my logs. So I picked up a really inexpensive (about $3 shipped) board on Ebay that logs to a MicroSD card and acts as a real-time clock that will maintain the time even when the Arduino is powered down.
It's not hard to use, but as often seems to happen to me, I struggled to find good examples of how to use this thing. In this case it was made worse because the "Wifi D1 Mini" or "Wemos D1 Mini" seems to also be the name of a related device that also has wifi capability and a built-in ESP8266. The one I got from Ebay is a VERY simple device that does not have a processor, and doesn't support wifi (despite the name). And I don't need it to do those things. The image above shows what mine looks like.
For Starters - Some Notes..
As I mentioned, this card is both a real-time clock (RTC) and MicroSD card logger. Interestingly, the two functions are entirely independent. They don't share data lines or protocol. They don't even share the power supply. The only thing in common between the two is the Ground (GND).
Important note... apparently a lot of people have found that the on-board battery drains VERY fast (like hours or days). Obviously this is not what you want in a real-time clock. You kind of want a year or years. And this is what I found on mine. It seems the folks that made this thing added a diode and a resistor to protect against reverse voltage if you insert the battery backward. It's nice that they add this protection, but that's also what's draining the battery way too quickly. The solution is pretty simple. You just remove those two components (see above pic). It would be handy to use a hot air station to remove them, but I was able to do it without too much difficulty using a standard soldering iron moving quickly between the two ends of each component.
There are a number of pins that don't seem to be used, and I don't see any evidence that they're connected to anything. They are: RST, A0, D0, D3, D4, TX, and RX. Perhaps they're used on the board that supports Wifi and has an ESP8266 - dunno.
The logger can write data to files on any FAT16 (for cards up to 2 GB) or FAT32 (for cards from 4 GB to 32 GB) formatted MicroSD card.
The card uses a CR1220 backup battery to maintain the time when it's powered off. The battery is inserted with the (+) side outward or away from the PC board.
When I first started playing with my module, I didn't have a CR1220 lying around. So I hooked it up to an external 3.3V source. The spec sheet I found for the on-board IC indicates a voltage range of 2.0 to 3.5 volts for this backup, but it didn't work when I gave it 3.3V. It did work when I reduced it to 3.0V and it also worked when I used the CR1220 battery as intended.
Wiring
As I mentioned, there are basically two independent modules in one. So I'll treat them that way here. Of course you could talk to both modules from the same Arduino sketch, but not over the same data lines.
For the real-time clock...
D1-Mini Description Arduino
D1 SCL Typically A5
D2 SDA Typically A4
5V Vcc 5V
GND Ground GND
And for the MicroSD card logger...
D1-Mini Description Arduino
D5 CLK or SCK 13 (data clock)
D6 MISO 12 (Master in, Slave out)
D7 MOSI 11 (Master out, Slave In)
D8 CS or SS 10 (chip-select or slave-select) Drive this pin high when talking to the logger.
3.3V Vcc 3.3V
GND Ground GND
Arduino Sketch for Real-time Clock
//========================================================================================================== // Date and time functions using a DS1307 RTC connected via I2C and Wire lib // // Logger Description Arduino // D1 SCL A5 (remember to use 4.7K pullup resistor) // D2 SDA A4 (remember to use 4.7K pullup resistor) // Also required: GND, 5V, and V(bat) // V(bat): 2.0 - 3.5V (this is the CR1220 that goes on the back of the RTC/Logger board; "+" side out) // // This sketch is based on the one found in this thread: https://forum.arduino.cc/index.php?topic=128928.0... // with minor modifications by me. // // NOTES: // - When I tried to replace the backup battery with 3.3V from the arduino it didn't work. // But when I gave it 3V from my external power supply, it did. // - The module I have, "Wifi D1 Mini" or "Wemos D1 Mini", has a diode and resistor added to the // circuit to protect against reverse polarity if the battery is inserted the wrong way. // But that increases the battery drain tremendously. So I removed those components and plan // to be careful when inserting the battery (positive side outward). // The problem and the solution are described here: https://sharedinventions.com/?p=663 // //========================================================================================================== #include "RTClib.h" // Adafruit RTClib version 1.12.5 (and its dependencies). Install this through the library manager in this IDE RTC_DS1307 rtc; char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; void setup () { Serial.begin(57600); Serial.println("Looking for Real Time Clock..."); if (! rtc.begin()) { Serial.println("Could NOT find RTC"); Serial.flush(); abort(); } else { Serial.println("Found RTC"); } if (! rtc.isrunning()) { Serial.println("\nReal Time Clock is NOT running, Setting the time now..."); // When time needs to be set on a new device, or after a power loss, the // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); Serial.println("Time has been set"); // This line sets the RTC with an explicit date & time, for example to set // January 21, 2014 at 3am you would call: // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); } else { Serial.println("\nReal Time Clock is already running - NOT setting the time now."); } } void loop () { Serial.println("Checking time..."); Serial.flush(); DateTime now = rtc.now(); Serial.println("Got the time"); Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(" ("); Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 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(" since midnight 1/1/1970 = "); Serial.print(now.unixtime()); Serial.print("s = "); Serial.print(now.unixtime() / 86400L); Serial.println("d"); // calculate a date which is 7 days, 12 hours, 30 minutes, and 6 seconds into the future DateTime future (now + TimeSpan(7,12,30,6)); Serial.print(" now + 7d + 12h + 30m + 6s: "); Serial.print(future.year(), DEC); Serial.print('/'); Serial.print(future.month(), DEC); Serial.print('/'); Serial.print(future.day(), DEC); Serial.print(' '); Serial.print(future.hour(), DEC); Serial.print(':'); Serial.print(future.minute(), DEC); Serial.print(':'); Serial.print(future.second(), DEC); Serial.println(); Serial.println(); delay(3000); }
Arduino Sketch for MicroSD Card Logger
/*=======================================================================================================
* "Wifi D1 Mini" or "Wemos D1 Mini" MicroSD card logger and real time clock. * NOTE: Despite the name, this card does not support Wifi. It appears there's a card of the * same name that also has an ESP-8266EX, and that one supports Wifi. * * This example sketch demonstrates the logging side using the SD library. * The logging side and the RTC (real-time clock) side appear to be independent of one another, * even using separate voltage inputs and data lines. Only the GND is shared). * * We communicate with the logger shield via SPI bus. * * Logger Description Arduino * D5 CLK or SCK 13 (data clock) * D6 MISO 12 (Master in, Slave out) * D7 MOSI 11 (Master out, Slave In) * D8 CS or SS 10 (chip-select or slave-select) Drive this pin high to tell the * logger you're talking to it. * (Also required: 3.3V and GND) * * The logger can write data to files on any FAT16 (for cards up to 2 GB) or * FAT32 (for cards from 4 GB to 32 GB) formatted MicroSD card. * * Reference: https://www.tutorialspoint.com/arduino/arduino_se... * * This sketch was based on example code that is in the public domain: * https://www.tutorialspoint.com/arduino/arduino_se... * * rhc: Significant modifications to this program by me on 2021-03-24 *=======================================================================================================*/
#include <SPI.h> // Arduino SPI (serial peripheral interface) library (I believe this is native with the Arduino IDE)
#include <SD.h> // Sparkfun SD library version 1.2.4 (enables reading/writing SD cards; install this through the library manager in this IDE)
int loop_counter;
File dataFile;
void setup() { // Open serial communications Serial.begin(9600); pinMode(10, OUTPUT); digitalWrite(10, HIGH); //-3- I may have to set Arduino Pin 10 HIGH here to keep the logger selected (slave-select)
// See if the card is present and can be initialized Serial.print("Initializing SD card..."); while(1) { if (SD.begin()) break; Serial.println("Failed to initialize, or card not present. Trying again..."); delay(2000); } Serial.println("card initialized."); loop_counter = 0;
// Open the file. Note that only one file can be open at a time. // To close this file: dataFile.close(); // FILE_READ: open the file for reading, starting at the BEGINNING of the file. // FILE_WRITE: open the file for reading and writing, starting at the END of the file. // The SD card library uses 8.3 format filenames and is case-insensitive. // So "datalog.txt" is the same as "DATALOG.txt" Serial.println("Opening datalog.txt..."); while(1) { dataFile = SD.open("datalog.txt", FILE_WRITE); if (dataFile) break; Serial.println("Failed to open datalog.txt. Trying again..."); delay(2000); } Serial.println("Opened datalog.txt"); }
void loop() { char my_string[100]; String dataString = ""; // NOTE: dataFile.println() can take char * or String; Strings might be easier to format. sprintf(my_string, "My Test %d", loop_counter); // If the log file is available, write to it: if (dataFile) { dataFile.println(my_string); dataFile.flush(); // NOTE: if you don't flush() or close the file, you'll lose a lot of data you THOUGHT was written to it. // print to the serial port too: Serial.println(my_string); } else { // If the file isn't open, print an error, and try again to open the file. Serial.println(" Error opening datalog.txt"); dataFile = SD.open("datalog.txt", FILE_WRITE); } loop_counter++; delay(1000); }
Conclusion
That's it. You should be able to easily combine elements from both sketches to log timestamped data.
If you use this, please let me know of any shortcomings or errors in this write-up. I'd like to keep it updated to make it as comprehensive and easy to use as possible.
Thanks!