├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── README.md ├── examples ├── Example10_CheckStatus │ └── Example10_CheckStatus.ino ├── Example11_ChangeAddress │ └── Example11_ChangeAddress.ino ├── Example1_WritingLog │ └── Example1_WritingLog.ino ├── Example2_AppendFile │ └── Example2_AppendFile.ino ├── Example3_CreateFile │ └── Example3_CreateFile.ino ├── Example4_ReadFileSize │ └── Example4_ReadFileSize.ino ├── Example5_ReadFile │ └── Example5_ReadFile.ino ├── Example6_MakeDirectory │ └── Example6_MakeDirectory.ino ├── Example7_ReadDirectoryContents │ └── Example7_ReadDirectoryContents.ino ├── Example8_RemoveDirectory │ └── Example8_RemoveDirectory.ino └── Example9_ReadVersion │ └── Example9_ReadVersion.ino ├── keywords.txt ├── library.properties └── src ├── SparkFun_Qwiic_OpenLog_Arduino_Library.cpp └── SparkFun_Qwiic_OpenLog_Arduino_Library.h /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Subject of the issue 2 | Describe your issue here. 3 | 4 | ### Your workbench 5 | * What development board or microcontroller are you using? 6 | * What version of hardware or breakout board are you using? 7 | * How is the breakout board wired to your microcontroller? 8 | * How is everything being powered? 9 | * Are there any additional details that may help us help you? 10 | 11 | ### Steps to reproduce 12 | Tell us how to reproduce this issue. Please post stripped down example code demonstrating your issue. 13 | 14 | ### Expected behavior 15 | Tell us what should happen 16 | 17 | ### Actual behavior 18 | Tell us what happens instead 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | SparkFun License Information 2 | ============================ 3 | 4 | SparkFun uses two different licenses for our files — one for hardware and one for code. 5 | 6 | Hardware 7 | --------- 8 | 9 | **SparkFun hardware is released under [Creative Commons Share-alike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/).** 10 | 11 | Note: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-sa/4.0/legalcode). 12 | 13 | You are free to: 14 | 15 | Share — copy and redistribute the material in any medium or format 16 | Adapt — remix, transform, and build upon the material 17 | for any purpose, even commercially. 18 | The licensor cannot revoke these freedoms as long as you follow the license terms. 19 | Under the following terms: 20 | 21 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 22 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 23 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | Notices: 25 | 26 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 27 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 28 | 29 | 30 | Code 31 | -------- 32 | 33 | **SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).** 34 | 35 | The MIT License (MIT) 36 | 37 | Copyright (c) 2016 SparkFun Electronics 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy 40 | of this software and associated documentation files (the "Software"), to deal 41 | in the Software without restriction, including without limitation the rights 42 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | copies of the Software, and to permit persons to whom the Software is 44 | furnished to do so, subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun Qwiic OpenLog Library 2 | =========================================================== 3 | 4 | [![SparkFun Qwiic OpenLog](https://cdn.sparkfun.com/assets/parts/1/3/5/5/4/15164-SparkFun_Qwiic_OpenLog-01.jpg)](https://www.sparkfun.com/products/15164) 5 | 6 | 7 | [*SparkFun Qwiic OpenLog (DEV-15164)*](https://www.sparkfun.com/products/15164) 8 | 9 | 10 | This library makes using the Qwiic OpenLog easy to use. It creates a Print class so that you can do things like 11 | 12 | mylogger.print("The battery voltage is:"); 13 | mylogger.println(batteryVoltage); 14 | 15 | And your data will be recorded to LOG00001.TXT for later review. Please see the examples to get started. 16 | 17 | Available commands: 18 | 19 | * boolean **begin**(int deviceAddress) - Start comminication with a given OpenLog 20 | * String **getVersion**() - Returns a string that is the current firmware version 21 | * uint8_t **getStatus**() - Returns various status bits 22 | * boolean **setI2CAddress**(uint8_t addr) - Set the I2C address of the OpenLog 23 | * boolean **append**(String fileName) - Open and append to a file 24 | * boolean **create**(String fileName) - Create a file but don't open it for writing 25 | * boolean **makeDirectory**(String directoryName) - Create the given directory 26 | * boolean **changeDirectory**(String directoryName) - Change to the given directory 27 | * int32_t **size**(String fileName) - Given a file name, read the size of the file 28 | * void **read**(uint8_t* userBuffer, uint16_t bufferSize, String fileName) - Read the contents of a file into the provided buffer 29 | * boolean **searchDirectory**(String options) - Search the current directory for a given wildcard 30 | * String **getNextDirectoryItem**() - Return the next file or directory from the search 31 | * uint32_t **remove**(String thingToDelete) - Remove file or directory including the contents of the directory 32 | 33 | The SparkFun Qwiic OpenLog is the smarter and better looking cousin to the extremely popular [OpenLog](https://www.sparkfun.com/products/13712). We've ported the serial based interface to I2C. Now you can daisy chain lots of I2C devices and log them all without taking up your serial port. 34 | 35 | We've written a large number of example sketches to show how to record logs, create new logs, create and navigate directories, remove files and directories, and read the contents of files. 36 | 37 | Qwiic OpenLog supports clock stretching which means it performs even better than the original! Qwiic OpenLog will record data up to 21,000 bytes per second at 400kHz. As the receive buffer fills up QOL will hold the clock line letting the master know that it is busy. Once QOL is finished with a task it releases the clock allowing the data to continue flowing without corruption. 38 | 39 | Need to get freaky and have multiple data loggers on the same bus? You're in luck. Qwiic OpenLog has both a solder jumper to allow for two devices on the same bus as well as a software setting to allow for the setting of any I2C address. Don't get too freaky though; the limit is 111 devices (0x08 to 0x77) on the same bus. Any microSD card up to 32GB will work. 40 | 41 | We will be adding more features to the firmware over time and we've made it very easy to upgrade! If you're comfortable sending a sketch to an Uno then you can upgrade the firmware on Qwiic OpenLog. 42 | 43 | Library written by Nathan Seidle ([SparkFun](http://www.sparkfun.com)). 44 | 45 | Repository Contents 46 | ------------------- 47 | 48 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 49 | * **/src** - Source files for the library (.cpp, .h). 50 | * **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 51 | * **library.properties** - General library properties for the Arduino package manager. 52 | 53 | Documentation 54 | -------------- 55 | 56 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 57 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/qwiic-openlog-hookup-guide)** - Basic information on how to install an Arduino library. 58 | * **[Product Repository](https://github.com/sparkfun/Qwiic_OpenLog)** - Main repository (including hardware files) 59 | 60 | License Information 61 | ------------------- 62 | 63 | This product is _**open source**_! 64 | 65 | Various bits of the code have different licenses applied. Anything SparkFun wrote is beerware; if you see me (or any other SparkFun employee) at the local, and you've found our code helpful, please buy us a round! 66 | 67 | Please use, reuse, and modify these files as you see fit. Please maintain attribution to SparkFun Electronics and release any derivative under the same license. 68 | 69 | Distributed as-is; no warranty is given. 70 | 71 | - Your friends at SparkFun. 72 | -------------------------------------------------------------------------------- /examples/Example10_CheckStatus/Example10_CheckStatus.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to read the status byte of the OpenLog 9 | 10 | Qwiic OpenLog records any incoming byte to the default log file. If quered by the master it will 11 | normally respond with a status byte with the following structure: 12 | 13 | Bit 0: SD/Init Good 14 | Bit 1: Last Command Succeeded 15 | Bit 2: Last Command Known 16 | Bit 3: File Currently Open 17 | Bit 4: In Root Directory 18 | Bit 5: 0 - Future Use 19 | Bit 6: 0 - Future Use 20 | Bit 7: 0 - Future Use 21 | 22 | Instances where the status byte is not sent is when an active command is running such as read file size, 23 | read file contents, etc. If you have been running lots of other examples then please unplug/plug OpenLog so as 24 | to power cycle it and return it to its default logging state. 25 | */ 26 | 27 | #include 28 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 29 | OpenLog myLog; //Create instance 30 | 31 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 32 | 33 | #define STATUS_SD_INIT_GOOD 0 34 | #define STATUS_LAST_COMMAND_SUCCESS 1 35 | #define STATUS_LAST_COMMAND_KNOWN 2 36 | #define STATUS_FILE_OPEN 3 37 | #define STATUS_IN_ROOT_DIRECTORY 4 38 | 39 | void setup() 40 | { 41 | pinMode(ledPin, OUTPUT); 42 | 43 | Wire.begin(); 44 | myLog.begin(); 45 | 46 | Serial.begin(9600); //9600bps is used for debug statements 47 | Serial.println("OpenLog Status Example"); 48 | 49 | byte status = myLog.getStatus(); 50 | 51 | Serial.print("Status byte: 0x"); 52 | if(status < 0x10) Serial.print("0"); 53 | Serial.println(status, HEX); 54 | 55 | if(status == 0xFF) 56 | { 57 | Serial.println("OpenLog failed to respond. Freezing."); 58 | while(1); //Freeze! 59 | } 60 | 61 | if(status & 1< 17 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 18 | OpenLog myLog; //Create instance 19 | 20 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 21 | 22 | byte originalAddress = 42; //Original address of the Qwiic OpenLog 23 | byte newAddress = 30; //Address we want to go to 24 | 25 | #define STATUS_SD_INIT_GOOD 0 26 | #define STATUS_LAST_COMMAND_SUCCESS 1 27 | #define STATUS_LAST_COMMAND_KNOWN 2 28 | #define STATUS_FILE_OPEN 3 29 | #define STATUS_IN_ROOT_DIRECTORY 4 30 | 31 | void setup() 32 | { 33 | pinMode(ledPin, OUTPUT); 34 | 35 | Wire.begin(); 36 | Wire.setClock(400000); //Go super fast 37 | 38 | Serial.begin(9600); //9600bps is used for debug statements 39 | Serial.println("OpenLog Address Change Example"); 40 | 41 | if (myLog.begin(originalAddress) == false) //Talk to OpenLog using this address (spoiler alert: it's going to change) 42 | { 43 | Serial.println("OpenLog failed to respond. Check wiring. Freezing."); 44 | while (1); 45 | } 46 | else 47 | { 48 | Serial.println("OpenLog detected!"); 49 | } 50 | 51 | Serial.println(F("Press a key to begin")); 52 | while (Serial.available()) Serial.read(); //Clear buffer 53 | while (Serial.available() == 0) delay(10); //Wait for user to press a key 54 | 55 | myLog.setI2CAddress(30); //Set the I2C address 56 | 57 | byte status = myLog.getStatus(); //Check the status byte, using new address, to see if command worked (and if we can talk to OpenLog in general) 58 | 59 | Serial.print("Status byte: 0x"); 60 | if (status < 0x10) Serial.print("0"); 61 | Serial.println(status, HEX); 62 | 63 | if (status & 1 << STATUS_LAST_COMMAND_SUCCESS) 64 | { 65 | Serial.println("Last command was successful"); 66 | Serial.print("The OpenLog address was successfully changed to "); 67 | Serial.print(newAddress, DEC); 68 | Serial.println("."); 69 | 70 | //When we changed the address of OpenLog the library also updated the address 71 | //So we can immediately start recording 72 | myLog.println("This is recorded to the last open log file but using the new I2C address"); 73 | //Upon reset our code would need to begin with a myLog.begin(newAddress) to continue communication. 74 | } 75 | else 76 | { 77 | Serial.println("Last command failed."); 78 | Serial.println("Pull the SD card and check the config.txt file for the address OpenLog is configured to."); 79 | } 80 | 81 | Serial.println("Done!"); 82 | } 83 | 84 | void loop() 85 | { 86 | //Blink the Status LED because we're done! 87 | digitalWrite(ledPin, HIGH); 88 | delay(1000); 89 | digitalWrite(ledPin, LOW); 90 | delay(1000); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /examples/Example1_WritingLog/Example1_WritingLog.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to record various text and variables to Qwiic OpenLog 9 | 10 | To Use: 11 | Insert a formatted SD card into Qwiic OpenLog 12 | Attach Qwiic OpenLog to a RedBoard or Uno with a Qwiic cable 13 | Load this sketch onto the RedBoard 14 | Open a terminal window to see the Serial.print statements 15 | Then insert the SD card into a computer view the log file contents 16 | */ 17 | 18 | #include 19 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 20 | OpenLog myLog; //Create instance 21 | 22 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 23 | 24 | void setup() 25 | { 26 | pinMode(ledPin, OUTPUT); 27 | 28 | Wire.begin(); //Initialize I2C 29 | myLog.begin(); //Open connection to OpenLog (no pun intended) 30 | 31 | Serial.begin(9600); //9600bps is used for debug statements 32 | Serial.println("OpenLog Write File Test"); 33 | 34 | //Record something to the default log 35 | myLog.println("This goes to the log file"); 36 | Serial.println("This goes to the terminal"); 37 | 38 | float batteryVoltage = 3.4; 39 | myLog.println("Batt voltage: " + String(batteryVoltage)); 40 | 41 | batteryVoltage = batteryVoltage + 0.71; 42 | 43 | myLog.println("Batt voltage: " + String(batteryVoltage)); 44 | myLog.syncFile(); 45 | 46 | Serial.println(F("Done!")); 47 | } 48 | 49 | void loop() 50 | { 51 | //Blink the Status LED because we're done! 52 | digitalWrite(ledPin, HIGH); 53 | delay(1000); 54 | digitalWrite(ledPin, LOW); 55 | delay(1000); 56 | } 57 | -------------------------------------------------------------------------------- /examples/Example2_AppendFile/Example2_AppendFile.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to create new files and write to them 9 | 10 | To Use: 11 | Insert a formatted SD card into Qwiic OpenLog 12 | Attach Qwiic OpenLog to a RedBoard or Uno with a Qwiic cable 13 | Load this sketch onto the RedBoard 14 | Open a terminal window to see the Serial.print statements 15 | Then insert the SD card into a computer view the log file contents 16 | 17 | Note: We can use the F("") in sketches to move big print statements into program memory to save RAM. 18 | See more at: https://forum.arduino.cc/index.php?topic=428015.0 19 | */ 20 | 21 | #include 22 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 23 | OpenLog myLog; //Create instance 24 | 25 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 26 | 27 | const byte OpenLogAddress = 42; //Default Qwiic OpenLog I2C address 28 | 29 | void setup() 30 | { 31 | pinMode(ledPin, OUTPUT); 32 | 33 | Wire.begin(); 34 | myLog.begin(); //Open connection to OpenLog (no pun intended) 35 | 36 | Serial.begin(9600); //9600bps is used for debug statements 37 | Serial.println("Run OpenLog Append File Test"); 38 | myLog.println("Run OpenLog Append File Test"); 39 | 40 | myLog.println("This is recorded to the default log file"); 41 | myLog.append("appendMe.txt"); 42 | myLog.println("This is recorded to appendMe.txt"); 43 | myLog.println("If this file doesn't exist it is created and"); 44 | myLog.println("anything sent to OpenLog will be recorded to this file"); 45 | 46 | myLog.println(); 47 | myLog.println(F("Note: We can use the F(\"\") in sketches to move big print statements into program memory to save RAM")); 48 | myLog.append("appendMe1.txt"); 49 | myLog.println(F("Note: We can use the F(\"\") in sketches to move big print statements into program memory to save RAM")); 50 | myLog.println(F("Note: We can use the F(\"\") in sketches to move big print statements into program memory to save RAM")); 51 | myLog.syncFile(); 52 | 53 | Serial.println("Done!"); 54 | } 55 | 56 | void loop() 57 | { 58 | //Blink the Status LED because we're done! 59 | digitalWrite(ledPin, HIGH); 60 | delay(1000); 61 | digitalWrite(ledPin, LOW); 62 | delay(1000); 63 | } 64 | -------------------------------------------------------------------------------- /examples/Example3_CreateFile/Example3_CreateFile.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to create new files and write to them 9 | 10 | To Use: 11 | Insert a formatted SD card into Qwiic OpenLog 12 | Attach Qwiic OpenLog to a RedBoard or Uno with a Qwiic cable 13 | Load this sketch onto the RedBoard 14 | Open a terminal window to see the Serial.print statements 15 | Then insert the SD card into a computer view the log file contents 16 | */ 17 | 18 | #include 19 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 20 | OpenLog myLog; //Create instance 21 | 22 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 23 | 24 | void setup() 25 | { 26 | pinMode(ledPin, OUTPUT); 27 | 28 | Wire.begin(); 29 | myLog.begin(); //Open connection to OpenLog (no pun intended) 30 | 31 | Serial.begin(9600); //9600bps is used for debug statements 32 | Serial.println("Run OpenLog New File Test"); //Goes to terminal 33 | myLog.println("Run OpenLog New File Test"); //Goes to the default LOG#.txt file 34 | 35 | myLog.println("This is recorded to the default log file"); 36 | myLog.create("NewFile.txt"); 37 | myLog.println("This is also recorded to the default log file. But a new file has been created"); 38 | myLog.println("If you want to write to a file use appendFile in example 2"); 39 | myLog.syncFile(); 40 | 41 | Serial.println("Done!"); 42 | } 43 | 44 | void loop() 45 | { 46 | //Blink the Status LED because we're done! 47 | digitalWrite(ledPin, HIGH); 48 | delay(1000); 49 | digitalWrite(ledPin, LOW); 50 | delay(1000); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /examples/Example4_ReadFileSize/Example4_ReadFileSize.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to: 9 | Record some strings to a default log 10 | Check the size of a given file name 11 | If the given file doesn't exist, say so 12 | */ 13 | 14 | #include 15 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 16 | OpenLog myLog; //Create instance 17 | 18 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 19 | 20 | void setup() 21 | { 22 | pinMode(ledPin, OUTPUT); 23 | 24 | Wire.begin(); 25 | Wire.setClock(400000); //Go super fast 400kHz I2C 26 | myLog.begin(); //Open connection to OpenLog (no pun intended) 27 | 28 | Serial.begin(9600); //9600bps is used for debug statements 29 | Serial.println(); 30 | Serial.println("OpenLog Read File Size Example"); 31 | 32 | //Record something to the default log 33 | myLog.println("OpenLog Read File Size Example"); 34 | myLog.syncFile(); 35 | 36 | String myFile = "testme.txt"; 37 | 38 | //Get size of file 39 | long sizeOfFile = myLog.size(myFile); 40 | 41 | if (sizeOfFile == -1) 42 | { 43 | Serial.println(F("File not found.")); 44 | } 45 | else 46 | { 47 | Serial.println(F("File found!")); 48 | Serial.print(F("Size of file: ")); 49 | Serial.println(sizeOfFile); 50 | } 51 | 52 | Serial.println(F("Done!")); 53 | } 54 | 55 | void loop() 56 | { 57 | //Blink the Status LED because we're done! 58 | digitalWrite(ledPin, HIGH); 59 | delay(1000); 60 | digitalWrite(ledPin, LOW); 61 | delay(1000); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /examples/Example5_ReadFile/Example5_ReadFile.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to: 9 | Record some strings to a default log 10 | Check the size of a given file name 11 | If that given file doesn't exist, create it with random characters 12 | Read back the contents of the given file (containing random characters) 13 | */ 14 | 15 | #include 16 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 17 | OpenLog myLog; //Create instance 18 | 19 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 20 | 21 | void setup() 22 | { 23 | pinMode(ledPin, OUTPUT); 24 | 25 | Wire.begin(); 26 | Wire.setClock(400000); //Go super fast 27 | myLog.begin(); //Open connection to OpenLog (no pun intended) 28 | 29 | Serial.begin(9600); //9600bps is used for debug statements 30 | Serial.println("OpenLog Read File Test"); 31 | 32 | //Record something to the default log 33 | myLog.println("OpenLog Read File Test"); 34 | 35 | String myFile = "testFile.txt"; 36 | 37 | //Get size of file 38 | long sizeOfFile = myLog.size(myFile); 39 | 40 | if (sizeOfFile == -1) //File does not exist. Create it. 41 | { 42 | Serial.println(F("File not found, creating one...")); 43 | 44 | myLog.append(myFile); //Create file and begin writing to it 45 | 46 | //Write a random number of random characters to this new file 47 | myLog.println("The Beginning"); 48 | randomSeed(analogRead(A0)); 49 | 50 | //Write 300 to 500 random characters to the file 51 | int charsToWrite = random(300, 500); 52 | for (int x = 0 ; x < charsToWrite ; x++) 53 | { 54 | byte myCharacter = random('a', 'z'); //Pick a random letter, a to z 55 | 56 | myLog.write(myCharacter); 57 | } 58 | myLog.println(); 59 | myLog.println("The End"); 60 | myLog.syncFile(); 61 | } 62 | else 63 | { 64 | Serial.println("File found!"); 65 | } 66 | 67 | //Get size of file 68 | sizeOfFile = myLog.size(myFile); 69 | 70 | if (sizeOfFile > -1) 71 | { 72 | Serial.print(F("Size of file: ")); 73 | Serial.println(sizeOfFile); 74 | 75 | //Read the contents of myFile by passing a buffer into .read() 76 | //Then printing the contents of that buffer 77 | byte myBufferSize = 200; 78 | byte myBuffer[myBufferSize]; 79 | //myLog.read(myBuffer, myBufferSize, myFile, 4); //Doesn't yet work 80 | myLog.read(myBuffer, myBufferSize, myFile); //Load myBuffer with contents of myFile 81 | 82 | //Print the contents of the buffer 83 | Serial.println("File contents:"); 84 | for (int x = 0 ; x < myBufferSize ; x++) 85 | { 86 | Serial.write(myBuffer[x]); 87 | } 88 | Serial.println("\nDone with file contents"); 89 | } 90 | else 91 | { 92 | Serial.println(F("Size error: File not found")); 93 | } 94 | 95 | Serial.println(F("Done!")); 96 | } 97 | 98 | void loop() 99 | { 100 | //Blink the Status LED because we're done! 101 | digitalWrite(ledPin, HIGH); 102 | delay(1000); 103 | digitalWrite(ledPin, LOW); 104 | delay(1000); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /examples/Example6_MakeDirectory/Example6_MakeDirectory.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to: 9 | Create a directory 10 | Move into that directory called MONDAY 11 | Create a sub directory within MONDAY called LOGS 12 | Create and write to a file inside MONDAY 13 | */ 14 | 15 | #include 16 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 17 | OpenLog myLog; //Create instance 18 | 19 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 20 | 21 | void setup() 22 | { 23 | pinMode(ledPin, OUTPUT); 24 | 25 | Wire.begin(); 26 | Wire.setClock(400000); //Go super fast 27 | 28 | Serial.begin(9600); //9600bps is used for debug statements 29 | Serial.println("OpenLog Directory Test"); 30 | myLog.begin(); //Open connection to OpenLog (no pun intended) 31 | 32 | //Record something to the default log 33 | myLog.println("Time to make a directory"); 34 | 35 | myLog.changeDirectory(".."); //Make sure we're in the root directory 36 | myLog.makeDirectory("MONDAY"); 37 | myLog.changeDirectory("MONDAY"); //Go into this new directory 38 | myLog.makeDirectory("LOGS"); //Create a sub directory within this new directory 39 | 40 | myLog.println(F("But we are still recording to the original log file in root")); 41 | 42 | myLog.append("TheNewMe.txt"); 43 | myLog.println(F("This is in the new file located in the MONDAY directory!")); 44 | myLog.syncFile(); 45 | 46 | Serial.println(F("Done!")); 47 | } 48 | 49 | void loop() 50 | { 51 | //Blink the Status LED because we're done! 52 | digitalWrite(ledPin, HIGH); 53 | delay(1000); 54 | digitalWrite(ledPin, LOW); 55 | delay(1000); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /examples/Example7_ReadDirectoryContents/Example7_ReadDirectoryContents.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to read the files in a given directory. 9 | You can use wildcards if desired. This is handy for listing a certain type of file such 10 | as *.LOG or LOG01*.TXT 11 | 12 | If you need to check if a file exists, use the readFileSize command (there's an 13 | example sketch showing how). 14 | */ 15 | 16 | #include 17 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 18 | OpenLog myLog; //Create instance 19 | 20 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 21 | 22 | void setup() 23 | { 24 | pinMode(ledPin, OUTPUT); 25 | 26 | Wire.begin(); 27 | Wire.setClock(400000); //Go super fast 28 | myLog.begin(); //Open connection to OpenLog (no pun intended) 29 | 30 | Serial.begin(9600); //9600bps is used for debug statements 31 | Serial.println("OpenLog Read Directory Test"); 32 | 33 | //Record something to the default log 34 | myLog.println(F("Let's read the current directory!")); 35 | 36 | Serial.println("List of things in this directory:"); 37 | 38 | myLog.searchDirectory("*"); //Give me everything 39 | //myLog.searchDirectory("*.txt"); //Give me all the txt files in the directory 40 | //myLog.searchDirectory("*/"); //Get just directories 41 | //myLog.searchDirectory("*.*"); //Get just files 42 | //myLog.searchDirectory("LOG*.TXT"); //Give me a list of just the logs 43 | //myLog.searchDirectory("LOG000*.TXT"); //Get just the logs LOG00000 to LOG00099 if they exist. 44 | 45 | String fileName = myLog.getNextDirectoryItem(); 46 | while (fileName != "") //getNextDirectoryItem() will return "" when we've hit the end of the directory 47 | { 48 | Serial.println(fileName); 49 | fileName = myLog.getNextDirectoryItem(); 50 | } 51 | Serial.println(F("Done!")); 52 | } 53 | 54 | void loop() 55 | { 56 | //Blink the Status LED because we're done! 57 | digitalWrite(ledPin, HIGH); 58 | delay(1000); 59 | digitalWrite(ledPin, LOW); 60 | delay(1000); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /examples/Example8_RemoveDirectory/Example8_RemoveDirectory.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to: 9 | Create a directory 10 | Create some files there 11 | Delete a specific file 12 | Delete *.TXT 13 | Remove the directory we created 14 | */ 15 | 16 | #include 17 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 18 | OpenLog myLog; //Create instance 19 | 20 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 21 | 22 | void setup() 23 | { 24 | pinMode(ledPin, OUTPUT); 25 | 26 | Wire.begin(); 27 | Wire.setClock(400000); //Go super fast 28 | myLog.begin(); //Open connection to OpenLog (no pun intended) 29 | 30 | Serial.begin(9600); //9600bps is used for debug statements 31 | Serial.println("OpenLog Removing a Directory Example"); 32 | 33 | Serial.println(F("Press a key to begin")); 34 | while(Serial.available()) Serial.read(); //Clear buffer 35 | while(Serial.available() == 0) delay(10); //Wait for user to press a key 36 | 37 | Serial.println(F("Making a directory and empty files")); 38 | myLog.println(F("Making a directory and empty files")); //Record something to the default log 39 | myLog.syncFile(); 40 | 41 | //Create some directories and files 42 | myLog.changeDirectory(".."); //Return to root 43 | myLog.makeDirectory("MONDAY"); 44 | myLog.changeDirectory("MONDAY"); //Move into this sub directory 45 | myLog.append("TheNewMe.txt"); 46 | myLog.append("Test1.txt"); 47 | myLog.append("Test2.txt"); 48 | myLog.append("Test3.txt"); 49 | 50 | myLog.println(F("This is recorded to the last appended file in MONDAY")); 51 | myLog.syncFile(); 52 | 53 | if(myLog.removeFile("Test1.txt") == 1) //Delete a specific file 54 | Serial.println(F("We have deleted Test1.txt! You can remove the SD card to see.")); 55 | else 56 | Serial.println(F("Failed to delete Test1.txt")); 57 | 58 | Serial.println(F("Press a key to delete all the files in the MONDAY directory.")); 59 | while(Serial.available()) Serial.read(); //Clear buffer 60 | while(Serial.available() == 0) delay(10); //Wait for user to press a key 61 | 62 | //If user reinserted the SD card it will cause OpenLog to reset so we need to re-navigate out to MONDAY 63 | myLog.changeDirectory(".."); //Return to root 64 | myLog.changeDirectory("MONDAY"); //Move into this sub directory 65 | 66 | long thingsDeleted = myLog.removeFile("*.TXT"); //This is not case sensitive 67 | Serial.print("Files deleted: "); 68 | Serial.println(thingsDeleted); 69 | 70 | Serial.println(F("Press a key to remove the MONDAY directory.")); 71 | while(Serial.available()) Serial.read(); //Clear buffer 72 | while(Serial.available() == 0) delay(10); //Wait for user to press a key 73 | 74 | myLog.changeDirectory(".."); //Return to root 75 | 76 | thingsDeleted = myLog.removeDirectory("MONDAY"); //Remove MONDAY and everything in it 77 | Serial.print("Things deleted: "); 78 | Serial.println(thingsDeleted); 79 | 80 | //Note: We cannot recordToOpenLog() here because we have deleted the log we were appending to 81 | //You must create a new file using appendFile() to continue logging 82 | 83 | Serial.println(F("Done!")); 84 | } 85 | 86 | void loop() 87 | { 88 | //Blink the Status LED because we're done! 89 | digitalWrite(ledPin, HIGH); 90 | delay(1000); 91 | digitalWrite(ledPin, LOW); 92 | delay(1000); 93 | } 94 | 95 | -------------------------------------------------------------------------------- /examples/Example9_ReadVersion/Example9_ReadVersion.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An I2C based datalogger - Like the OpenLog but for I2C 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: February 2nd, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | This example shows how to read the firmware version of Qwiic OpenLog. 9 | 10 | This is helpful when getting support. We will be adding features as we go and having the firmware 11 | version will let us know what features your board supports. 12 | */ 13 | 14 | #include 15 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 16 | OpenLog myLog; //Create instance 17 | 18 | int ledPin = LED_BUILTIN; //Status LED connected to digital pin 13 19 | 20 | void setup() 21 | { 22 | pinMode(ledPin, OUTPUT); 23 | 24 | Wire.begin(); 25 | myLog.begin(); 26 | 27 | Serial.begin(9600); 28 | Serial.print("Qwiic OpenLog Version: "); 29 | Serial.println(myLog.getVersion()); 30 | 31 | Serial.println("Done!"); 32 | } 33 | 34 | void loop() 35 | { 36 | //Blink the Status LED because we're done! 37 | digitalWrite(ledPin, HIGH); 38 | delay(1000); 39 | digitalWrite(ledPin, LOW); 40 | delay(1000); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | OpenLog KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | 17 | write KEYWORD2 18 | begin KEYWORD2 19 | getVersion KEYWORD2 20 | getStatus KEYWORD2 21 | setI2CAddress KEYWORD2 22 | append KEYWORD2 23 | create KEYWORD2 24 | makeDirectory KEYWORD2 25 | changeDirectory KEYWORD2 26 | size KEYWORD2 27 | read KEYWORD2 28 | searchDirectory KEYWORD2 29 | getNextDirectoryItem KEYWORD2 30 | removeFile KEYWORD2 31 | removeDirectory KEYWORD2 32 | remove KEYWORD2 33 | sendCommand KEYWORD2 34 | syncFile KEYWORD2 35 | writeString KEYWORD2 36 | 37 | ####################################### 38 | # Constants (LITERAL1) 39 | ####################################### -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun Qwiic OpenLog 2 | version=3.0.2 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=Library for the SparkFun Qwiic OpenLog 6 | paragraph=An Arduino Library for the SparkFun I2C based datalogger, Qwiic OpenLog. The Qwiic OpenLog is a powerful flexible datalogger that makes it very easy to record any sort of data over I2C which allows for daisychaining and redundant logging. Available at: https://www.sparkfun.com/products/14641 7 | category=Data Storage 8 | url=https://github.com/sparkfun/SparkFun_Qwiic_OpenLog_Arduino_Library 9 | architectures=* -------------------------------------------------------------------------------- /src/SparkFun_Qwiic_OpenLog_Arduino_Library.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library written for the Qwiic OpenLog 3 | SparkFun sells these at its website: www.sparkfun.com 4 | Do you like this library? Help support SparkFun. Buy a board! 5 | https://www.sparkfun.com/products/14641 6 | 7 | Written by Nathan Seidle @ SparkFun Electronics, February 2nd, 2018 8 | 9 | Qwiic OpenLog makes it very easy to record data over I2C to a microSD. 10 | 11 | This library handles the initialization of the Qwiic OpenLog and the calculations 12 | to get the temperatures. 13 | 14 | https://github.com/sparkfun/SparkFun_Qwiic_OpenLog_Arduino_Library 15 | 16 | Development environment specifics: 17 | Arduino IDE 1.8.3 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | */ 27 | 28 | #include "SparkFun_Qwiic_OpenLog_Arduino_Library.h" 29 | 30 | // Attempt communication with the device 31 | // Return true if we got a 'Polo' back from Marco 32 | boolean OpenLog::begin(uint8_t deviceAddress, TwoWire &wirePort) 33 | { 34 | _deviceAddress = deviceAddress; // If provided, store the I2C address from user 35 | _i2cPort = &wirePort; // Grab which port the user wants us to use 36 | 37 | // We require caller to begin their I2C port, with the speed of their choice 38 | // external to the library 39 | //_i2cPort->begin(); 40 | 41 | // Check communication with device 42 | uint8_t status = getStatus(); 43 | if (status & 1 << STATUS_SD_INIT_GOOD) 44 | { 45 | // We are good to go! 46 | return (true); 47 | } 48 | 49 | return (false); // SD did not init. Card not present? 50 | } 51 | 52 | // Simple begin 53 | boolean OpenLog::begin(int deviceAddress) 54 | { 55 | return (begin(deviceAddress, Wire)); 56 | } 57 | 58 | // Get the version number from OpenLog 59 | String OpenLog::getVersion() 60 | { 61 | sendCommand(registerMap.firmwareMajor, ""); 62 | // Upon completion Qwiic OpenLog will have 2 bytes ready to be read 63 | _i2cPort->requestFrom(_deviceAddress, (uint8_t)1); 64 | 65 | uint8_t versionMajor = _i2cPort->read(); 66 | sendCommand(registerMap.firmwareMinor, ""); 67 | // Upon completion Qwiic OpenLog will have 2 bytes ready to be read 68 | _i2cPort->requestFrom(_deviceAddress, (uint8_t)1); 69 | 70 | uint8_t versionMinor = _i2cPort->read(); 71 | 72 | return (String(versionMajor) + "." + String(versionMinor)); 73 | } 74 | 75 | // Get the status byte from OpenLog 76 | // This function assumes we are not in the middle of a read, file size, or other function 77 | // where OpenLog has bytes qued up 78 | // Bit 0: SD/Init Good 79 | // Bit 1: Last Command Succeeded 80 | // Bit 2: Last Command Known 81 | // Bit 3: File Currently Open 82 | // Bit 4: In Root Directory 83 | // Bit 5: 0 - Future Use 84 | // Bit 6: 0 - Future Use 85 | // Bit 7: 0 - Future Use 86 | uint8_t OpenLog::getStatus() 87 | { 88 | sendCommand(registerMap.status, ""); 89 | // Upon completion OpenLog will have a status byte ready to read 90 | 91 | _i2cPort->requestFrom(_deviceAddress, (uint8_t)1); 92 | 93 | return (_i2cPort->read()); 94 | } 95 | 96 | // Change the I2C address of the OpenLog 97 | // This will be recorded to OpenLog's EEPROM and config.txt file. 98 | boolean OpenLog::setI2CAddress(uint8_t addr) 99 | { 100 | String temp; 101 | temp = (String)addr; 102 | boolean result = sendCommand(registerMap.i2cAddress, temp); 103 | 104 | // Upon completion any new communication must be with this new I2C address 105 | 106 | _deviceAddress = addr; // Change the address internally 107 | 108 | return (result); 109 | } 110 | 111 | // Append to a given file. If it doesn't exist it will be created 112 | boolean OpenLog::append(String fileName) 113 | { 114 | return (sendCommand(registerMap.openFile, fileName)); 115 | // Upon completion any new characters sent to OpenLog will be recorded to this file 116 | } 117 | 118 | // Create a given file in the current directory 119 | boolean OpenLog::create(String fileName) 120 | { 121 | return (sendCommand(registerMap.createFile, fileName)); 122 | // Upon completion a new file is created but OpenLog is still recording to original file 123 | } 124 | 125 | // Given a directory name, create it in whatever directory we are currently in 126 | boolean OpenLog::makeDirectory(String directoryName) 127 | { 128 | return (sendCommand(registerMap.mkDir, directoryName)); 129 | // Upon completion Qwiic OpenLog will respond with its status 130 | // Qwiic OpenLog will continue logging whatever it next receives to the current open log 131 | } 132 | 133 | // Given a directory name, change to that directory 134 | boolean OpenLog::changeDirectory(String directoryName) 135 | { 136 | return (sendCommand(registerMap.cd, directoryName)); 137 | // Upon completion Qwiic OpenLog will respond with its status 138 | // Qwiic OpenLog will continue logging whatever it next receives to the current open log 139 | } 140 | 141 | // Return the size of a given file. Returns a 4 byte signed long 142 | int32_t OpenLog::size(String fileName) 143 | { 144 | sendCommand(registerMap.fileSize, fileName); 145 | // Upon completion Qwiic OpenLog will have 4 bytes ready to be read 146 | 147 | _i2cPort->requestFrom(_deviceAddress, (uint8_t)4); 148 | 149 | int32_t fileSize = 0; 150 | while (_i2cPort->available()) 151 | { 152 | uint8_t incoming = _i2cPort->read(); 153 | fileSize <<= 8; 154 | fileSize |= incoming; 155 | } 156 | 157 | return (fileSize); 158 | } 159 | 160 | // Read the contents of a file, up to the size of the buffer, into a given array, from a given spot 161 | void OpenLog::read(uint8_t *userBuffer, uint16_t bufferSize, String fileName) 162 | { 163 | uint16_t spotInBuffer = 0; 164 | uint16_t leftToRead = bufferSize; // Read up to the size of our buffer. We may go past EOF. 165 | sendCommand(registerMap.readFile, fileName); 166 | // Upon completion Qwiic OpenLog will respond with the file contents. Master can request up to 32 bytes at a time. 167 | // Qwiic OpenLog will respond until it reaches the end of file then it will report zeros. 168 | 169 | while (leftToRead > 0) 170 | { 171 | uint8_t toGet = I2C_BUFFER_LENGTH; // Request up to a 32 byte block 172 | if (leftToRead < toGet) 173 | toGet = leftToRead; // Go smaller if that's all we have left 174 | 175 | _i2cPort->requestFrom(_deviceAddress, toGet); 176 | while (_i2cPort->available()) 177 | userBuffer[spotInBuffer++] = _i2cPort->read(); 178 | 179 | leftToRead -= toGet; 180 | } 181 | } 182 | 183 | // Read the contents of a directory. Wildcards allowed 184 | // Returns true if OpenLog ack'd. Use getNextDirectoryItem() to get the first item. 185 | boolean OpenLog::searchDirectory(String options) 186 | { 187 | if (sendCommand(registerMap.list, options) == true) 188 | { 189 | _searchStarted = true; 190 | return (true); 191 | // Upon completion Qwiic OpenLog will have a file name or directory name ready to respond with, terminated with a \0 192 | // It will continue to respond with a file name or directory until it responds with all 0xFFs (end of list) 193 | } 194 | return (false); 195 | } 196 | 197 | // Returns the name of the next file or directory folder in the current directory 198 | // Returns "" if it is the end of the list 199 | String OpenLog::getNextDirectoryItem() 200 | { 201 | if (_searchStarted == false) 202 | return (""); // We haven't done a search yet 203 | 204 | String itemName = ""; 205 | _i2cPort->requestFrom(_deviceAddress, (uint8_t)I2C_BUFFER_LENGTH); 206 | 207 | uint8_t charsReceived = 0; 208 | while (_i2cPort->available()) 209 | { 210 | uint8_t incoming = _i2cPort->read(); 211 | 212 | if (incoming == '\0') 213 | return (itemName); // This is the end of the file name. We don't need to read any more of the 32 bytes 214 | else if (charsReceived == 0 && incoming == 0xFF) 215 | { 216 | _searchStarted = false; 217 | return (""); // End of the directory listing 218 | } 219 | else 220 | itemName += (char)incoming; // Add this byte to the file name 221 | 222 | charsReceived++; 223 | } 224 | 225 | // We shouldn't get this far but if we do 226 | return (itemName); 227 | } 228 | 229 | // Remove a file, wildcards supported 230 | // OpenLog will respond with the number of items removed 231 | uint32_t OpenLog::removeFile(String thingToDelete) 232 | { 233 | return (remove(thingToDelete, false)); 234 | } 235 | 236 | // Remove a directory, wildcards supported 237 | // OpenLog will respond with 1 when removing a directory 238 | uint32_t OpenLog::removeDirectory(String thingToDelete) 239 | { 240 | return (remove(thingToDelete, true)); // Delete all files in the directory as well 241 | } 242 | 243 | // Remove a file or directory (including everything in that directory) 244 | // OpenLog will respond with the number of items removed 245 | // Returns 1 if only a directory is removed (even if directory had files in it) 246 | uint32_t OpenLog::remove(String thingToDelete, boolean removeEverything) 247 | { 248 | if (removeEverything == true) 249 | sendCommand(registerMap.rmrf, thingToDelete); //-rf causes any directory to remove contents as well 250 | else 251 | sendCommand(registerMap.rm, thingToDelete); // Just delete a thing 252 | 253 | // Upon completion Qwiic OpenLog will have 4 bytes ready to read, representing the number of files beleted 254 | 255 | _i2cPort->requestFrom(_deviceAddress, (uint8_t)4); 256 | 257 | int32_t filesDeleted = 0; 258 | while (_i2cPort->available()) 259 | { 260 | uint8_t incoming = _i2cPort->read(); 261 | filesDeleted <<= 8; 262 | filesDeleted |= incoming; 263 | } 264 | 265 | return (filesDeleted); // Return the number of files removed 266 | 267 | // Qwiic OpenLog will continue logging whatever it next receives to the current open log 268 | } 269 | 270 | // Send a command to the unit with options (such as "append myfile.txt" or "read myfile.txt 10") 271 | boolean OpenLog::sendCommand(uint8_t registerNumber, String option1) 272 | { 273 | _i2cPort->beginTransmission(_deviceAddress); 274 | _i2cPort->write(registerNumber); 275 | if (option1.length() > 0) 276 | { 277 | //_i2cPort->print(" "); //Include space 278 | _i2cPort->print(option1); 279 | } 280 | 281 | if (_i2cPort->endTransmission() != 0) 282 | { 283 | #ifndef __SAMD21G18A__ 284 | return (false); 285 | #endif 286 | } 287 | 288 | return (true); 289 | // Upon completion any new characters sent to OpenLog will be recorded to this file 290 | } 291 | 292 | // Write a single character to Qwiic OpenLog 293 | size_t OpenLog::write(uint8_t character) 294 | { 295 | _i2cPort->beginTransmission(_deviceAddress); 296 | _i2cPort->write(registerMap.writeFile); // Send the byte that corresponds to writing a file 297 | _i2cPort->write(character); 298 | if (_i2cPort->endTransmission() != 0) 299 | { 300 | #ifndef __SAMD21G18A__ 301 | return (false); 302 | #endif 303 | } 304 | return (1); 305 | } 306 | 307 | int OpenLog::writeString(String string) 308 | { 309 | _i2cPort->beginTransmission(_deviceAddress); 310 | _i2cPort->write(registerMap.writeFile); 311 | 312 | // remember, the rx buffer on the i2c openlog is 32 bytes 313 | // and the register address takes up 1 byte so we can only 314 | // send 31 data bytes at a time 315 | if (string.length() > 31) 316 | { 317 | return -1; 318 | } 319 | if (string.length() > 0) 320 | { 321 | //_i2cPort->print(" "); //Include space 322 | _i2cPort->print(string); 323 | } 324 | 325 | if (_i2cPort->endTransmission() != 0) 326 | { 327 | #ifndef __SAMD21G18A__ 328 | return (false); 329 | #endif 330 | } 331 | 332 | return (1); 333 | } 334 | 335 | bool OpenLog::syncFile() 336 | { 337 | _i2cPort->beginTransmission(_deviceAddress); 338 | _i2cPort->write(registerMap.syncFile); 339 | 340 | if (_i2cPort->endTransmission() != 0) 341 | { 342 | #ifndef __SAMD21G18A__ 343 | return (false); 344 | #endif 345 | } 346 | 347 | return (1); 348 | } -------------------------------------------------------------------------------- /src/SparkFun_Qwiic_OpenLog_Arduino_Library.h: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library written for the Qwiic OpenLog 3 | SparkFun sells these at its website: www.sparkfun.com 4 | Do you like this library? Help support SparkFun. Buy a board! 5 | https://www.sparkfun.com/products/14641 6 | 7 | Written by Nathan Seidle @ SparkFun Electronics, February 2nd, 2018 8 | 9 | Qwiic OpenLog makes it very easy to record data over I2C to a microSD. 10 | 11 | This library handles the initialization of the Qwiic OpenLog and the calculations 12 | to get the temperatures. 13 | 14 | https://github.com/sparkfun/SparkFun_Qwiic_OpenLog_Arduino_Library 15 | 16 | Development environment specifics: 17 | Arduino IDE 1.8.3 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | */ 27 | 28 | #pragma once 29 | 30 | #if (ARDUINO >= 100) 31 | #include "Arduino.h" 32 | #else 33 | #include "WProgram.h" 34 | #endif 35 | 36 | #include 37 | 38 | //The default I2C address for the Qwiic OpenLog is 0x2A (42). 0x29 is also possible. 39 | #define QOL_DEFAULT_ADDRESS (uint8_t)42 40 | 41 | //Bits found in the getStatus() byte 42 | #define STATUS_SD_INIT_GOOD 0 43 | #define STATUS_LAST_COMMAND_SUCCESS 1 44 | #define STATUS_LAST_COMMAND_KNOWN 2 45 | #define STATUS_FILE_OPEN 3 46 | #define STATUS_IN_ROOT_DIRECTORY 4 47 | 48 | //Platform specific configurations 49 | 50 | //Define the size of the I2C buffer based on the platform the user has 51 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 52 | #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 53 | 54 | //I2C_BUFFER_LENGTH is defined in Wire.H 55 | #define I2C_BUFFER_LENGTH BUFFER_LENGTH 56 | 57 | #elif defined(__SAMD21G18A__) 58 | 59 | //SAMD21 uses RingBuffer.h 60 | #define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE 61 | 62 | #elif __MK20DX256__ 63 | //Teensy 64 | 65 | #elif ARDUINO_ARCH_ESP32 66 | //ESP32 based platforms 67 | 68 | #else 69 | 70 | //The catch-all default is 32 71 | #define I2C_BUFFER_LENGTH 32 72 | 73 | #endif 74 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 75 | 76 | 77 | class OpenLog : public Print { 78 | 79 | public: 80 | 81 | struct memoryMap { 82 | byte id; 83 | byte status; 84 | byte firmwareMajor; 85 | byte firmwareMinor; 86 | byte i2cAddress; 87 | byte logInit; 88 | byte createFile; 89 | byte mkDir; 90 | byte cd; 91 | byte readFile; 92 | byte startPosition; 93 | byte openFile; 94 | byte writeFile; 95 | byte fileSize; 96 | byte list; 97 | byte rm; 98 | byte rmrf; 99 | byte syncFile; 100 | }; 101 | 102 | const memoryMap registerMap = { 103 | .id = 0x00, 104 | .status = 0x01, 105 | .firmwareMajor = 0x02, 106 | .firmwareMinor = 0x03, 107 | .i2cAddress = 0x1E, 108 | .logInit = 0x05, 109 | .createFile = 0x06, 110 | .mkDir = 0x07, 111 | .cd = 0x08, 112 | .readFile = 0x09, 113 | .startPosition = 0x0A, 114 | .openFile = 0x0B, 115 | .writeFile = 0x0C, 116 | .fileSize = 0x0D, 117 | .list = 0x0E, 118 | .rm = 0x0F, 119 | .rmrf = 0x10, 120 | .syncFile = 0x11, 121 | }; 122 | //These functions override the built-in print functions so that when the user does an 123 | //myLogger.println("send this"); it gets chopped up and sent over I2C instead of Serial 124 | virtual size_t write(uint8_t character); 125 | int writeString(String string); 126 | bool syncFile(void); 127 | 128 | //By default use the default I2C addres, and use Wire port 129 | boolean begin(uint8_t deviceAddress = QOL_DEFAULT_ADDRESS, TwoWire &wirePort = Wire); 130 | boolean begin(int deviceAddress); 131 | 132 | String getVersion(); //Returns a string that is the current firmware version 133 | uint8_t getStatus(); //Returns various status bits 134 | 135 | boolean setI2CAddress(uint8_t addr); //Set the I2C address we read and write to 136 | boolean append(String fileName); //Open and append to a file 137 | boolean create(String fileName); //Create a file but don't open it for writing 138 | boolean makeDirectory(String directoryName); //Create the given directory 139 | boolean changeDirectory(String directoryName); //Change to the given directory 140 | int32_t size(String fileName); //Given a file name, read the size of the file 141 | 142 | void read(uint8_t* userBuffer, uint16_t bufferSize, String fileName); //Read the contents of a file into the provided buffer 143 | 144 | boolean searchDirectory(String options); //Search the current directory for a given wildcard 145 | String getNextDirectoryItem(); //Return the next file or directory from the search 146 | 147 | uint32_t removeFile(String thingToDelete); //Remove file 148 | uint32_t removeDirectory(String thingToDelete); //Remove a directory including the contents of the directory 149 | uint32_t remove(String thingToDelete, boolean removeEverthing); //Remove file or directory including the contents of the directory 150 | 151 | //These are the core functions that send a command to OpenLog 152 | boolean sendCommand(uint8_t registerNumber, String option1); 153 | 154 | private: 155 | 156 | //Variables 157 | TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware 158 | uint8_t _deviceAddress; //Keeps track of I2C address. setI2CAddress changes this. 159 | uint8_t _escapeCharacter = 26; //The character that needs to be sent to QOL to get it into command mode 160 | uint8_t _escapeCharacterCount = 3; //Number of escape characters to get QOL into command mode 161 | 162 | boolean _searchStarted = false; //Goes true when user does a search. Goes false when we reach end of directory. 163 | }; --------------------------------------------------------------------------------