Skip to content

Commit 799c97a

Browse files
authored
Merge pull request #449 from cparata/master
Add MLC examples for LSM6DSOX on Nano RP2040 and Nicla Vision
2 parents acd815d + 2f6d599 commit 799c97a

File tree

8 files changed

+1059
-0
lines changed

8 files changed

+1059
-0
lines changed
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
/*
2+
This example exposes the second MB of Nicla Vision flash as a USB disk.
3+
The user can interact with this disk as a bidirectional communication with the board
4+
For example, the board could save data in a file to be retrieved later with a drag and drop.
5+
If the user does a double tap, the firmware goes to datalogger mode (green led on).
6+
Now the user can do another double tap to start a recording of the IMU data
7+
(green led blinking). With another double tap the recording will be stopped (green led on).
8+
Now the user can start/stop other recordings of the IMU data using again the double tap.
9+
The log files are saved in flash with an increasing number suffix data_0.txt, data_1.txt, etc.
10+
If you want to transfer the log files to the PC, you can reset the board and
11+
wait for 10 seconds (blue led blinking).
12+
*/
13+
14+
#include "PluggableUSBMSD.h"
15+
#include "QSPIFBlockDevice.h"
16+
#include "MBRBlockDevice.h"
17+
#include "FATFileSystem.h"
18+
#include "LSM6DSOXSensor.h"
19+
20+
#define INT_1 LSM6DS_INT
21+
#define SENSOR_ODR 104.0f // In Hertz
22+
#define ACC_FS 2 // In g
23+
#define GYR_FS 2000 // In dps
24+
#define MEASUREMENT_TIME_INTERVAL (1000.0f/SENSOR_ODR) // In ms
25+
#define FIFO_SAMPLE_THRESHOLD 199
26+
#define FLASH_BUFF_LEN 8192
27+
28+
typedef enum {
29+
DATA_STORAGE_STATE,
30+
DATA_LOGGER_IDLE_STATE,
31+
DATA_LOGGER_RUNNING_STATE
32+
} demo_state_e;
33+
34+
volatile demo_state_e demo_state = DATA_STORAGE_STATE;
35+
volatile int mems_event = 0;
36+
uint32_t file_count = 0;
37+
unsigned long timestamp_count = 0;
38+
bool acc_available = false;
39+
bool gyr_available = false;
40+
int32_t acc_value[3];
41+
int32_t gyr_value[3];
42+
char buff[FLASH_BUFF_LEN];
43+
uint32_t pos = 0;
44+
45+
QSPIFBlockDevice root(QSPI_SO0, QSPI_SO1, QSPI_SO2, QSPI_SO3, QSPI_SCK, QSPI_CS, QSPIF_POLARITY_MODE_1, 40000000);
46+
// Partition 1 is allocated to WiFi
47+
mbed::MBRBlockDevice lsm_data(&root, 2);
48+
static mbed::FATFileSystem lsm_fs("lsm");
49+
50+
LSM6DSOXSensor AccGyr(&SPI1, PIN_SPI_SS1);
51+
52+
USBMSD MassStorage(&root);
53+
54+
rtos::Thread acquisition_th;
55+
56+
FILE *f = nullptr;
57+
58+
void INT1Event_cb()
59+
{
60+
mems_event = 1;
61+
}
62+
63+
void USBMSD::begin()
64+
{
65+
int err = lsm_fs.mount(&lsm_data);
66+
if (err) {
67+
Serial.println("mount failed");
68+
err = lsm_fs.reformat(&lsm_data);
69+
if (err) {
70+
Serial.println("Reformat failed");
71+
return;
72+
}
73+
}
74+
}
75+
76+
mbed::FATFileSystem &USBMSD::getFileSystem()
77+
{
78+
static mbed::FATFileSystem fs("lsm");
79+
return fs;
80+
}
81+
82+
void led_green_thd()
83+
{
84+
while (1) {
85+
if (demo_state == DATA_LOGGER_RUNNING_STATE) {
86+
digitalWrite(LEDG, LOW);
87+
delay(100);
88+
digitalWrite(LEDG, HIGH);
89+
delay(100);
90+
}
91+
}
92+
}
93+
94+
void Read_FIFO_Data(uint16_t samples_to_read)
95+
{
96+
uint16_t i;
97+
98+
for (i = 0; i < samples_to_read; i++) {
99+
uint8_t tag;
100+
// Check the FIFO tag
101+
AccGyr.Get_FIFO_Tag(&tag);
102+
switch (tag) {
103+
// If we have a gyro tag, read the gyro data
104+
case LSM6DSOX_GYRO_NC_TAG: {
105+
AccGyr.Get_FIFO_G_Axes(gyr_value);
106+
gyr_available = true;
107+
break;
108+
}
109+
// If we have an acc tag, read the acc data
110+
case LSM6DSOX_XL_NC_TAG: {
111+
AccGyr.Get_FIFO_X_Axes(acc_value);
112+
acc_available = true;
113+
break;
114+
}
115+
// We can discard other tags
116+
default: {
117+
break;
118+
}
119+
}
120+
// If we have the measurements of both acc and gyro, we can store them with timestamp
121+
if (acc_available && gyr_available) {
122+
int num_bytes;
123+
num_bytes = snprintf(&buff[pos], (FLASH_BUFF_LEN - pos), "%lu %d %d %d %d %d %d\n", (unsigned long)((float)timestamp_count * MEASUREMENT_TIME_INTERVAL), (int)acc_value[0], (int)acc_value[1], (int)acc_value[2], (int)gyr_value[0], (int)gyr_value[1], (int)gyr_value[2]);
124+
pos += num_bytes;
125+
timestamp_count++;
126+
acc_available = false;
127+
gyr_available = false;
128+
}
129+
}
130+
// We can add the termination character to the string, so we are ready to save it in flash
131+
buff[pos] = '\0';
132+
pos = 0;
133+
}
134+
135+
void setup()
136+
{
137+
Serial.begin(115200);
138+
MassStorage.begin();
139+
pinMode(LEDB, OUTPUT);
140+
pinMode(LEDG, OUTPUT);
141+
digitalWrite(LEDB, HIGH);
142+
digitalWrite(LEDG, HIGH);
143+
144+
// Initialize SPI1 bus.
145+
SPI1.begin();
146+
147+
//Interrupts.
148+
attachInterrupt(INT_1, INT1Event_cb, RISING);
149+
150+
// Initialize IMU.
151+
AccGyr.begin();
152+
AccGyr.Enable_X();
153+
AccGyr.Enable_G();
154+
// Configure ODR and FS of the acc and gyro
155+
AccGyr.Set_X_ODR(SENSOR_ODR);
156+
AccGyr.Set_X_FS(ACC_FS);
157+
AccGyr.Set_G_ODR(SENSOR_ODR);
158+
AccGyr.Set_G_FS(GYR_FS);
159+
// Enable the Double Tap event
160+
AccGyr.Enable_Double_Tap_Detection(LSM6DSOX_INT1_PIN);
161+
// Configure FIFO BDR for acc and gyro
162+
AccGyr.Set_FIFO_X_BDR(SENSOR_ODR);
163+
AccGyr.Set_FIFO_G_BDR(SENSOR_ODR);
164+
// Start Led blinking thread
165+
acquisition_th.start(led_green_thd);
166+
}
167+
168+
void loop()
169+
{
170+
171+
if (mems_event) {
172+
mems_event = 0;
173+
LSM6DSOX_Event_Status_t status;
174+
AccGyr.Get_X_Event_Status(&status);
175+
if (status.DoubleTapStatus) {
176+
switch (demo_state) {
177+
case DATA_STORAGE_STATE: {
178+
// Go to DATA_LOGGER_IDLE_STATE state
179+
demo_state = DATA_LOGGER_IDLE_STATE;
180+
digitalWrite(LEDG, LOW);
181+
Serial.println("From DATA_STORAGE_STATE To DATA_LOGGER_IDLE_STATE");
182+
break;
183+
}
184+
case DATA_LOGGER_IDLE_STATE: {
185+
char filename[32];
186+
// Go to DATA_LOGGER_RUNNING_STATE state
187+
snprintf(filename, 32, "/lsm/data_%lu.txt", file_count);
188+
Serial.print("Start writing file ");
189+
Serial.println(filename);
190+
// open a file to write some data
191+
// w+ means overwrite, so every time the board is rebooted the file will be overwritten
192+
f = fopen(filename, "w+");
193+
if (f != nullptr) {
194+
// write header
195+
fprintf(f, "Timestamp[ms] A_X [mg] A_Y [mg] A_Z [mg] G_X [mdps] G_Y [mdps] G_Z [mdps]\n");
196+
fflush(f);
197+
Serial.println("From DATA_LOGGER_IDLE_STATE To DATA_LOGGER_RUNNING_STATE");
198+
demo_state = DATA_LOGGER_RUNNING_STATE;
199+
digitalWrite(LEDG, HIGH);
200+
timestamp_count = 0;
201+
pos = 0;
202+
acc_available = false;
203+
gyr_available = false;
204+
// Set FIFO in Continuous mode
205+
AccGyr.Set_FIFO_Mode(LSM6DSOX_STREAM_MODE);
206+
}
207+
break;
208+
}
209+
case DATA_LOGGER_RUNNING_STATE: {
210+
// Empty the FIFO
211+
uint16_t fifo_samples;
212+
AccGyr.Get_FIFO_Num_Samples(&fifo_samples);
213+
Read_FIFO_Data(fifo_samples);
214+
// Store the string in flash
215+
fprintf(f, "%s", buff);
216+
fflush(f);
217+
218+
// Close the log file and increase the counter
219+
fclose(f);
220+
file_count++;
221+
// Set FIFO in Bypass mode
222+
AccGyr.Set_FIFO_Mode(LSM6DSOX_BYPASS_MODE);
223+
// Go to DATA_LOGGER_IDLE_STATE state
224+
demo_state = DATA_LOGGER_IDLE_STATE;
225+
// Wait for the led thread ends the blinking
226+
delay(250);
227+
digitalWrite(LEDG, LOW);
228+
Serial.println("From DATA_LOGGER_RUNNING_STATE To DATA_LOGGER_IDLE_STATE");
229+
break;
230+
}
231+
default:
232+
Serial.println("Error! Invalid state");
233+
}
234+
}
235+
}
236+
237+
if (demo_state == DATA_LOGGER_RUNNING_STATE) {
238+
uint16_t fifo_samples;
239+
240+
// Check the number of samples inside FIFO
241+
AccGyr.Get_FIFO_Num_Samples(&fifo_samples);
242+
243+
// If we reach the threshold we can empty the FIFO
244+
if (fifo_samples > FIFO_SAMPLE_THRESHOLD) {
245+
// Empty the FIFO
246+
Read_FIFO_Data(fifo_samples);
247+
// Store the string in flash
248+
fprintf(f, "%s", buff);
249+
fflush(f);
250+
}
251+
}
252+
253+
if (demo_state == DATA_STORAGE_STATE && millis() > 10000) {
254+
// Disable the sensor and go to Mass Storage mode
255+
AccGyr.Disable_Double_Tap_Detection();
256+
AccGyr.Disable_X();
257+
AccGyr.Disable_G();
258+
while (1) {
259+
digitalWrite(LEDB, LOW);
260+
delay(100);
261+
digitalWrite(LEDB, HIGH);
262+
delay(100);
263+
}
264+
}
265+
}

0 commit comments

Comments
 (0)