forked from oyama/pico-vfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
136 lines (119 loc) · 3.81 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Multi-core logger that saves 1kHz sampling data to an SD card
*
* This code is not specifically tuned. The data is substituted with random numbers,
* and the actual application will probably be reading the ADC or communicating with
* the sensor chip. Also, the method of outputting CSV files is slow. The method of
* outputting binary data is faster.
*
* Copyright 2024, Hiroyuki OYAMA. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <math.h>
#include <pico/multicore.h>
#include <pico/stdlib.h>
#include <pico/time.h>
#include <pico/util/queue.h>
#include <stdio.h>
#include <string.h>
#include "filesystem/vfs.h"
#if !defined(SAMPLING_RATE_HZ)
#define SAMPLING_RATE_HZ 1000
#endif
typedef struct {
float accel_x;
float accel_y;
float accel_z;
float gyro_x;
float gyro_y;
float gyro_z;
float mag_x;
float mag_y;
float mag_z;
uint64_t timestamp;
} sensor_data_t;
queue_t sensor_queue;
static char write_buffer[1024 * 8];
static float normal_random(float mean, float stddev) {
static bool has_spare = false;
static float spare;
if (has_spare) {
has_spare = false;
return mean + stddev * spare;
}
has_spare = true;
float u, v, s;
do {
u = (float)rand() / RAND_MAX * 2.0f - 1.0f;
v = (float)rand() / RAND_MAX * 2.0f - 1.0f;
s = u * u + v * v;
} while (s >= 1.0f || s == 0.0f);
s = sqrtf(-2.0f * logf(s) / s);
spare = v * s;
return mean + stddev * u * s;
}
static bool sampling_task(repeating_timer_t *t) {
(void)t;
sensor_data_t entry = {0};
entry.timestamp = (uint64_t)get_absolute_time();
entry.accel_x = normal_random(0, 0.01);
entry.accel_y = normal_random(0, 0.01);
entry.accel_z = normal_random(-1.0, 0.01);
entry.gyro_x = normal_random(0, 0.001);
entry.gyro_y = normal_random(0, 0.001);
entry.gyro_z = normal_random(0, 0.001);
entry.mag_x = normal_random(-0.25, 0.0001);
entry.mag_y = normal_random(0.1, 0.01);
entry.mag_z = normal_random(0.4, 0.01);
queue_try_add(&sensor_queue, &entry);
return true;
}
static void produce_sensor_data_task(void) {
repeating_timer_t timer;
add_repeating_timer_us((int64_t)((1.0 / SAMPLING_RATE_HZ) * -1000000),
&sampling_task, NULL, &timer);
while (true)
__wfi();
}
int main(void) {
stdio_init_all();
if (!fs_init()) {
printf("SD card device not found\n");
return -1;
}
queue_init(&sensor_queue, sizeof(sensor_data_t), 1024);
FILE *fp = fopen("/sd/sensor_data.csv", "w");
if (fp == NULL) {
printf("fopen failed: %s\n", strerror(errno));
}
setvbuf(fp, write_buffer, _IOFBF, sizeof(write_buffer));
fprintf(fp, "Time,AccelX,AccelY,AccelZ,GyroX,GyroY,GyroZ,MagX,MagY,Magz\n");
multicore_reset_core1();
sleep_ms(100);
multicore_launch_core1(produce_sensor_data_task);
sensor_data_t entry = {0};
absolute_time_t last_checkpoint = get_absolute_time();
uint32_t n = 0;
while (1) {
queue_remove_blocking(&sensor_queue, &entry);
fprintf(fp, "%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f\n",
(double)entry.timestamp / 1000 / 1000,
entry.accel_x, entry.accel_y, entry.accel_z,
entry.gyro_x, entry.gyro_y, entry.gyro_x,
entry.mag_x, entry.mag_y, entry.mag_z);
n += 1;
absolute_time_t now = get_absolute_time();
int64_t duration = absolute_time_diff_us(last_checkpoint, now);
if (duration >= 1000000) {
printf("Store %lu samples/sec, Remaining queue %u\n",
n, queue_get_level(&sensor_queue));
n = 0;
last_checkpoint = now;
}
}
fclose(fp);
queue_free(&sensor_queue);
while (1)
tight_loop_contents();
}