Skip to content

Refactorings #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,46 @@
"unordered_map": "cpp",
"vector": "cpp",
"string_view": "cpp",
"initializer_list": "cpp"
"initializer_list": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp"
}
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The Arduino_UnifiedStorage library provides a unified interface to access differ


## Examples
* [**examples/SimpleStorageWriteRead**](https://github.com/arduino-libraries/Arduino_UnifiedStorage/blob/main/examples/SimpleStorageWriteRead/SimpleStorageWriteRead.ino) - Write/read simple data from SD, USB and internal storage
* [**examples/SimpleStorageWriteRead**](https://github.com/arduino-libraries/Arduino_UnifiedStorage/blob/main/examples/SimpleStorageWriteRead/SimpleStorageWriteRead.ino) - Write/read simple data from &sd, USB and internal storage
* [**examples/AdvancedUSBInternalOperations**](https://github.com/arduino-libraries/Arduino_UnifiedStorage/blob/main/examples/AdvancedUSBInternalOperations/AdvancedUSBInternalOperations.ino) - Navigate file structure and demonstrate file operations between USB and internal storage
* [**examples/BackupInternalPartitions**](https://github.com/arduino-libraries/Arduino_UnifiedStorage/blob/main/examples/BackupInternalPartitions/BackupInternalPartitions.ino) - Back up all partitions on the internal storage to a USB Mass Storage device.

Expand Down Expand Up @@ -40,9 +40,9 @@ The Arduino_UnifiedStorage library provides a unified interface to access differ
## Compatibility
This library has been tested with the following STM32 and Renesas based Arduino boards. The availability of storage mediums depends on the hardware interfaces:
* Portenta Machine Control: USB and Internal QSPI Flash
* Portenta H7 + Portenta Breakout: USB, SD, and QSPI
* Portenta H7 + Portenta Breakout: USB, &sd, and QSPI
* Portenta H7 + Vision Shield: SD and QSPI
* Portenta C33 + Portenta Breakout: USB, SD, and QSPI
* Portenta C33 + Portenta Breakout: USB, &sd, and QSPI
* Portenta C33 + Vision Shield: SD and QSPI
* Opta: Internal QSPI Flash and USB

Expand Down
57 changes: 57 additions & 0 deletions examples/AdvancedInternalStorage/AdvancedInternalStorage.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <Arduino_UnifiedStorage.h>
#include <vector>



void testWriting(Arduino_UnifiedStorage * storage){
Folder root = storage->getRootFolder();
UFile file = root.createFile("file.txt", FileMode::WRITE);
file.write("writing stuff to the file");
file.changeMode(FileMode::READ);
Serial.println("Reading from file: " + file.readAsString());
file.close();
file.remove();
}

const char* createPartitionName(int i) {
char buffer[20]; // Adjust the size accordingly
snprintf(buffer, sizeof(buffer), "Part%d", i);
return buffer;
}

void testAllPartitions(std::vector<Partition> partitions){
for (size_t i = 1; i < partitions.size() + 1; ++i) {
const char * partitionName = createPartitionName(i);

InternalStorage thisPartition = InternalStorage(i, partitionName, partitions[i - 1].fs);
if(thisPartition.begin()){
Serial.println("Succesfully initialised partition: " + String(partitionName));
testWriting(&thisPartition);
}
}
}

void setup(){



Serial.begin(115200);
while(!Serial);

std::vector<Partition> onePartition = {{16384, FS_LITTLEFS}};
InternalStorage::partition(onePartition);
testAllPartitions(onePartition);
delay(5000);


std::vector<Partition> fourPartitions = {{4096, FS_LITTLEFS}, {4096, FS_LITTLEFS}, {4096, FS_LITTLEFS}, {4096, FS_LITTLEFS}};
InternalStorage::partition(fourPartitions);
testAllPartitions(fourPartitions);
delay(5000);

}

void loop(){


}
184 changes: 184 additions & 0 deletions examples/OptaLogger/OptaLogger.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
This example demonstrates the usage of the "Arduino_UnifiedStorage" library for logging and backing up data to USB storage in case a USB Mass Storage device is inserted.

The code defines two main functions: "logData" and "performUpdate".
The "logData" function logs sensor data by reading an analog sensor and writing the data to the log file.

The "performUpdate" function performs the update process by:
* reading the last update size from a file (number of bytes)
* copying the new data from the log file to a backup file
* and updating the last update size.

INSTRUCTIONS
* Make sure the QSPI storage of your board is properly partitioned.
* You can do that by flashing the QSPIFormat example that can be found in the STM32H747_System folder
* Open the serial monitor and select answer with "Y" when this appears "Do you want to use partition scheme 1? Y/[n]"
* Reboot the board
* This sketch will log data, and check if there is any USB MSD Device connected to the USB Port of the Opta.
The USB device is mounted and unmounted after every update operation. The first status LED is on when the USB drive is mounted.
So as long as the status LED is off you can safely remove the drive.
The sketch will log to internal storage in the meantime, and wait for the USB drive to be inserted again.
*/

#include "Arduino_UnifiedStorage.h"
#include <vector>

constexpr auto baudrate { 115200 };


#define USB_MOUNTED_LED LED_D0
#define SUCCESFULLY_COPIED_LED



InternalStorage internalStorage = InternalStorage(true, "userData", FS_FAT);
USBStorage usbStorage = USBStorage();
std::vector<String> sensorDataBuffer;

unsigned long bytesWritten = 0;
unsigned long lastLog = 0;
unsigned long lastMove = 0;
unsigned long lastBackup = 0;


volatile bool usbAvailable = false;
bool backingUP = false;

void connectionCallback(){
usbAvailable = true;
}

void disconnectionCallback(){
usbAvailable = false;
}
// Function to run a given method periodically
void runPeriodically(void (*method)(), unsigned long interval, unsigned long* variable) {
unsigned long currentMillis = millis();

if (currentMillis - *variable >= interval) {
*variable = currentMillis;
method(); // Call the provided method
}
}

// Function to log sensor data
void logDataToRAM() {
int timeStamp = millis();
int sensorReading = analogRead(A0);
String line = String(timeStamp) + "," + String(sensorReading) + "\n";
sensorDataBuffer.push_back(line);
}

void moveDataToQSPI() {
if(!backingUP){
UFile _logFile = internalStorage.getRootFolder().createFile("log.txt", FileMode::APPEND);
for (const auto& line : sensorDataBuffer) {
bytesWritten += _logFile.write(line); // Write the log line to the file
}
_logFile.close();
sensorDataBuffer.clear();
}
}


void performUpdate() {
Folder usbRoot = usbStorage.getRootFolder(); // Get the root folder of the USB storage
UFile logFile = internalStorage.getRootFolder().createFile("log.txt", FileMode::READ);
UFile backupFile = usbRoot.createFile("backup_file.txt", FileMode::APPEND); // Create or open the backup file
UFile lastUpdateFile = usbRoot.createFile("diff.txt", FileMode::READ); // Create or open the last update file

backingUP = true;
unsigned lastUpdateBytes = lastUpdateFile.readAsString().toInt(); // Read the last update size from the file

printToSerialOrRS485("Last update bytes: " + String(lastUpdateBytes) + "\n");

if (lastUpdateBytes >= bytesWritten) {
printToSerialOrRS485("No new data to copy. \n");
backupFile.close();
lastUpdateFile.close();
backingUP = false;
return;
}

logFile.seek(lastUpdateBytes); // Move the file pointer to the last update position
unsigned long totalBytesToMove = bytesWritten - lastUpdateBytes;
printToSerialOrRS485("New update bytes: " + String(totalBytesToMove) + "\n");

uint8_t* buffer = new uint8_t[totalBytesToMove];

size_t bytesRead = logFile.read(buffer, totalBytesToMove);
size_t bytesMoved = backupFile.write(buffer, bytesRead); // Only write the bytes that haven't been backed up yet

printToSerialOrRS485("Successfully copied " + String(bytesMoved) + " new bytes.");

lastUpdateFile.changeMode(FileMode::WRITE); // Open the last update file in write mode
lastUpdateFile.write(String(lastUpdateBytes + bytesMoved)); // Update the last update size

backupFile.close();
logFile.close();
lastUpdateFile.close();


usbStorage.unmount(); // Unmount the USB storage

digitalWrite(USB_MOUNTED_LED, HIGH);
backingUP = false;
delete[] buffer;
}


// Function to backup data to USB storage
void backupToUSB() {
if (usbAvailable) {
printToSerialOrRS485("USB Mass storage is available \n");
delay(100);
if (!usbStorage.isMounted()) {

printToSerialOrRS485("Mounting USB Mass Storage \n");
digitalWrite(USB_MOUNTED_LED, LOW);
if(usbStorage.begin()){
performUpdate();
}

} else if (usbStorage.isMounted()) {
printToSerialOrRS485("USB Mass storage is connected, performing update \n");
performUpdate();

}
} else {
printToSerialOrRS485("USB Mass storage is not available \n");
}

}


void setup() {
beginRS485(baudrate);


usbStorage.onConnect(connectionCallback);
usbStorage.onDisconnect(disconnectionCallback);

pinMode(USB_MOUNTED_LED, OUTPUT);
printToSerialOrRS485("Formatting internal storage... \n");
int formatted = internalStorage.format(FS_LITTLEFS);
printToSerialOrRS485("QSPI Format status: " + String(formatted) + "\n");



if (!internalStorage.begin()) {
printToSerialOrRS485("Failed to initialize internal storage \n");
return;
} else {
printToSerialOrRS485("Initialized storage \n");
}

}

void loop() {


runPeriodically(logDataToRAM, 100, &lastLog);
runPeriodically(moveDataToQSPI, 1000, &lastMove);
runPeriodically(backupToUSB, 10000, &lastBackup);
}
Loading