Skip to content

Commit bb0133b

Browse files
authored
Merge pull request #59 from manchoz/main
Add SPIF and Little FS example
2 parents 19d0904 + 4d249e8 commit bb0133b

File tree

1 file changed

+258
-0
lines changed

1 file changed

+258
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
/*
2+
This sketch shows how to use Nicla in standalone mode and how to save data
3+
the on-board 2MB SPI Flash using the LitteFS filesystem.
4+
5+
Please, take care both ot RAM and Flash usage at run-time.
6+
7+
This example shows how to use MbedOS-native Storage APIs
8+
- https://os.mbed.com/docs/mbed-os/v6.15/apis/data-storage.html
9+
10+
C/C++ storage APIs are supporte too
11+
- C-based STDIO: https://en.cppreference.com/w/cpp/header/cstdio
12+
- Stream-based: https://en.cppreference.com/w/cpp/io
13+
*/
14+
15+
#include <BlockDevice.h>
16+
#include <Dir.h>
17+
#include <File.h>
18+
#include <FileSystem.h>
19+
#include <LittleFileSystem.h>
20+
21+
// The name of the root of the filesystem
22+
constexpr auto userRoot { "fs" };
23+
24+
// The SPIF Block Device
25+
mbed::BlockDevice* spif;
26+
// The LittleFS filesystem
27+
mbed::LittleFileSystem fs { userRoot };
28+
29+
#include <Arduino_BHY2.h>
30+
31+
SensorXYZ accel(SENSOR_ID_ACC);
32+
SensorXYZ gyro(SENSOR_ID_GYRO);
33+
Sensor temp(SENSOR_ID_TEMP);
34+
Sensor gas(SENSOR_ID_GAS);
35+
SensorQuaternion rotation(SENSOR_ID_RV);
36+
37+
void setup()
38+
{
39+
Serial.begin(115200);
40+
41+
for (const auto timeout = millis() + 2500; !Serial && millis() < timeout; delay(250))
42+
;
43+
44+
Serial.print("Loading the SPI Flash Storage and LittleFS filesystem...");
45+
46+
// Get core-wide instance of SPIF Block Device
47+
spif = mbed::BlockDevice::get_default_instance();
48+
spif->init();
49+
50+
// Mount the filesystem
51+
int err = fs.mount(spif);
52+
if (err) {
53+
err = fs.reformat(spif);
54+
Serial.print("Error mounting file system: ");
55+
Serial.println(err);
56+
while (true)
57+
;
58+
}
59+
Serial.println(" done.");
60+
61+
Serial.print("Initialising the sensors... ");
62+
BHY2.begin();
63+
64+
accel.begin();
65+
gyro.begin();
66+
temp.begin();
67+
gas.begin();
68+
rotation.begin();
69+
Serial.println(" done.");
70+
}
71+
72+
void loop()
73+
{
74+
static auto printTime = millis();
75+
static auto storeTime = millis();
76+
static auto statsTime = millis();
77+
78+
BHY2.update();
79+
80+
// Store data from sensors to the SPI Flash Memory
81+
if (millis() - storeTime >= 1000) {
82+
storeTime = millis();
83+
storeData();
84+
}
85+
86+
// List files on the Flash Memory and print contents
87+
if (millis() - printTime >= 5000) {
88+
printTime = millis();
89+
listDirsAlt();
90+
}
91+
92+
// Retrieve and print Flash Memory stats
93+
if (millis() - statsTime >= 10000) {
94+
statsTime = millis();
95+
printStats();
96+
}
97+
}
98+
99+
void listDirsAlt()
100+
{
101+
String baseDirName = "/";
102+
baseDirName += userRoot;
103+
104+
Serial.print("Listing file on ");
105+
Serial.print(baseDirName);
106+
Serial.println(" Filesystem");
107+
108+
// Open the root of the filesystem
109+
mbed::Dir dir(&fs, "/");
110+
dirent ent;
111+
112+
// Cycle through all the directory entries
113+
while ((dir.read(&ent)) > 0) {
114+
switch (ent.d_type) {
115+
case DT_DIR: {
116+
Serial.print("Directory ");
117+
Serial.println(ent.d_name);
118+
break;
119+
}
120+
case DT_REG: {
121+
Serial.print("Regular File ");
122+
Serial.print(ent.d_name);
123+
124+
// Declare and open the file in read-only mode
125+
mbed::File file;
126+
auto ret = file.open(&fs, ent.d_name);
127+
if (ret) {
128+
Serial.println("Unable to open file");
129+
continue;
130+
}
131+
Serial.print(" [");
132+
Serial.print(file.size());
133+
Serial.println(" bytes]");
134+
135+
if (file.size() > 0) {
136+
// Print file with an ad-hoc function. YMMV.
137+
printFile(file);
138+
139+
// Empty file after reading all the content. YMMV.
140+
file.close();
141+
ret = file.open(&fs, ent.d_name, O_TRUNC);
142+
if (ret < 0)
143+
Serial.println("Unable to truncate file");
144+
} else {
145+
// Remove file if empty. YMMV.
146+
file.close();
147+
fs.remove(ent.d_name);
148+
}
149+
150+
break;
151+
}
152+
default: {
153+
Serial.print("Other ");
154+
break;
155+
}
156+
}
157+
}
158+
}
159+
160+
void storeData()
161+
{
162+
// Append data to file on LittleFS filesystem
163+
constexpr auto filename { "sensors.csv" };
164+
165+
// Open in file in write mode.
166+
// Create if doesn't exists, otherwise open in append mode.
167+
mbed::File file;
168+
auto err = file.open(&fs, filename, O_WRONLY | O_CREAT | O_APPEND);
169+
if (err) {
170+
Serial.print("Error opening file for writing: ");
171+
Serial.println(err);
172+
return;
173+
}
174+
175+
// Save sensors data as a CSV line
176+
auto csvLine = sensorsToCSVLine();
177+
178+
auto ret = file.write(csvLine.c_str(), csvLine.length());
179+
if (ret != csvLine.length()) {
180+
Serial.print("Error writing data: ");
181+
Serial.println(ret);
182+
}
183+
file.close();
184+
}
185+
186+
void printStats()
187+
{
188+
struct statvfs stats { };
189+
fs.statvfs(userRoot, &stats);
190+
191+
auto blockSize = stats.f_bsize;
192+
193+
Serial.print("Total Space [Bytes]: ");
194+
Serial.println(stats.f_blocks * blockSize);
195+
Serial.print("Free Space [Bytes]: ");
196+
Serial.println(stats.f_bfree * blockSize);
197+
Serial.print("Used Space [Bytes]: ");
198+
Serial.println((stats.f_blocks - stats.f_bfree) * blockSize);
199+
Serial.println();
200+
}
201+
202+
String sensorsToCSVLine()
203+
{
204+
String line;
205+
206+
// Pre-allocate maxLine bytes for line
207+
constexpr size_t maxLine { 128 };
208+
line.reserve(maxLine);
209+
210+
line = "";
211+
line += millis();
212+
line += ",";
213+
line += accel.x();
214+
line += ",";
215+
line += accel.y();
216+
line += ",";
217+
line += accel.z();
218+
line += ",";
219+
line += gyro.x();
220+
line += ",";
221+
line += gyro.y();
222+
line += ",";
223+
line += gyro.z();
224+
line += ",";
225+
line += temp.value();
226+
line += ",";
227+
line += gas.value();
228+
line += ",";
229+
line += rotation.x();
230+
line += ",";
231+
line += rotation.y();
232+
line += ",";
233+
line += rotation.z();
234+
line += ",";
235+
line += rotation.w();
236+
line += "\r\n";
237+
238+
return line;
239+
}
240+
241+
void printFile(mbed::File& file)
242+
{
243+
// Read and print file len-bytes at time
244+
// to preserve RAM
245+
constexpr size_t len { 256 };
246+
247+
size_t totalLen { file.size() };
248+
249+
while (totalLen > 0) {
250+
char buf[len] {};
251+
252+
auto read = file.read(buf, len);
253+
totalLen -= read;
254+
for (const auto& c : buf)
255+
Serial.print(c);
256+
}
257+
Serial.println();
258+
}

0 commit comments

Comments
 (0)