回答編集履歴

3

追記

2021/11/14 12:39

投稿

thkana
thkana

スコア7703

test CHANGED
@@ -173,3 +173,237 @@
173
173
  100msの後10msからときとしてもっと長く、書き込みに専念しているようです。~~この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...~~(誤り。オシロのサンプリングが足りなくて細くなったパルスが見えてなかった...)
174
174
 
175
175
  512byte溜めて一気に書き込む、というのが対応でしょうね。
176
+
177
+
178
+
179
+ ---
180
+
181
+ しつこくいじってみました。以下のプログラム参照。多分動いているんじゃないかと。
182
+
183
+ 512byte毎にSDカードに書き込んでいて、大抵は10ms~18msぐらいでwriteが終わるのですが時々100ms~170msかかるときがあります(発生原因は把握していませんがSDカードの都合?)。
184
+
185
+ これをカバーしようとするとAD結果のバッファサイズ(BUFSIZE)をそれなりに大きくしなきゃいけない、というあたりが落とし穴か。(100ms以上かかるのが連続しないという保証も実はないのだけれど、UNOではもうメモリに余裕がない)
186
+
187
+
188
+
189
+ ```Arduino
190
+
191
+ #include <MsTimer2.h>
192
+
193
+ #include <SD.h>
194
+
195
+ #include <SPI.h>
196
+
197
+ #include <TimerOne.h>
198
+
199
+
200
+
201
+ //#define HARDDEBUG
202
+
203
+
204
+
205
+ const int chipSelect = 10; // Arduino UNOでは10、Arduino MEGAでは53
206
+
207
+ File dataFile;
208
+
209
+
210
+
211
+ const int BUFSIZE = 200;
212
+
213
+ int rbuf[BUFSIZE];
214
+
215
+ int wp = 0, rp = 0;
216
+
217
+ int overrun = 0;
218
+
219
+
220
+
221
+ //電圧測定及びSDカード保存
222
+
223
+ void mesuring(void) {
224
+
225
+ #ifdef HARDDEBUG
226
+
227
+ digitalWrite(4, HIGH);
228
+
229
+ #endif
230
+
231
+ wp = (wp + 1) % BUFSIZE;
232
+
233
+ rbuf[wp] = analogRead(A0);
234
+
235
+ if (wp == rp) {
236
+
237
+ overrun = 1;
238
+
239
+ }
240
+
241
+ #ifdef HARDDEBUG
242
+
243
+ digitalWrite(4, LOW);
244
+
245
+ #endif
246
+
247
+ }
248
+
249
+
250
+
251
+ void setup(void) {
252
+
253
+ pinMode(2, INPUT_PULLUP);
254
+
255
+ #ifdef HARDDEBUG
256
+
257
+ pinMode(3, OUTPUT);
258
+
259
+ pinMode(4, OUTPUT);
260
+
261
+ #endif
262
+
263
+ /* ----- Setting up serial communication with PC ------ */
264
+
265
+ /* ここでUSBを介してPCとシリアル通信を始める。9600はシリアル通信のボーレート
266
+
267
+ */
268
+
269
+ Serial.begin(115200);
270
+
271
+ while (!Serial) {
272
+
273
+ ; // wait for serial port to connect. Needed for native USB port only
274
+
275
+ //何らかの問題があってシリアルポートに接続できないときは、このループにトラップされる
276
+
277
+ }
278
+
279
+
280
+
281
+ /* ----- Initialisation of SD card ------ */
282
+
283
+ Serial.print("Initializing SD card...");
284
+
285
+ // see if the card is present and can be initialized:
286
+
287
+ if (!SD.begin(chipSelect)) {
288
+
289
+ Serial.println("Card failed, or not present");
290
+
291
+ // don't do anything more:
292
+
293
+ while (1)
294
+
295
+ ;
296
+
297
+ }
298
+
299
+ Serial.println("card initialized.");
300
+
301
+ dataFile = SD.open("datalog.csv", FILE_WRITE);
302
+
303
+ if (!dataFile) {
304
+
305
+ Serial.println("File Open Error.");
306
+
307
+ while (1)
308
+
309
+ ;
310
+
311
+ }
312
+
313
+ Serial.println("File Open.");
314
+
315
+ Timer1.initialize(1000); //マイクロ秒単位で設定
316
+
317
+ Timer1.attachInterrupt(mesuring);
318
+
319
+ }
320
+
321
+
322
+
323
+ void loop(void) {
324
+
325
+ /* SDカードに書き込み */
326
+
327
+ if (wp != rp) {
328
+
329
+ #ifdef HARDDEBUG
330
+
331
+ digitalWrite(3, HIGH);
332
+
333
+ #endif
334
+
335
+ rp = (rp + 1) % BUFSIZE;
336
+
337
+ // Serial.println(rbuf[rp]);
338
+
339
+ pushBuf(rbuf[rp]);
340
+
341
+ #ifdef HARDDEBUG
342
+
343
+ digitalWrite(3, LOW);
344
+
345
+ #endif
346
+
347
+ }
348
+
349
+ if (digitalRead(2) == LOW) {
350
+
351
+ dataFile.close();
352
+
353
+ Serial.println("Stop.");
354
+
355
+ while (1)
356
+
357
+ ;
358
+
359
+ }
360
+
361
+ if (overrun) {
362
+
363
+ Serial.println("OR");
364
+
365
+ overrun = 0;
366
+
367
+ dataFile.close();
368
+
369
+ Serial.println(".");
370
+
371
+ while (1)
372
+
373
+ ;
374
+
375
+ }
376
+
377
+ }
378
+
379
+ uint32_t t0, t1, t2;
380
+
381
+ void pushBuf(int val) {
382
+
383
+ int wdat = val * 500l / 1023; //固定小数点数
384
+
385
+ t1 = millis();
386
+
387
+ dataFile.print(wdat/100);
388
+
389
+ dataFile.print('.');
390
+
391
+ dataFile.println(wdat %100);
392
+
393
+ t2 = millis();
394
+
395
+ if (t2 - t1 > 8) {
396
+
397
+ Serial.print(t1 - t0);
398
+
399
+ Serial.print("/");
400
+
401
+ Serial.println(t2 - t1);
402
+
403
+ t0 = t2;
404
+
405
+ }
406
+
407
+ }
408
+
409
+ ```

2

訂正

2021/11/14 12:39

投稿

thkana
thkana

スコア7703

test CHANGED
@@ -170,4 +170,6 @@
170
170
 
171
171
  ![波形](8b125cdb73a11493281779277b6391fd.jpeg)
172
172
 
173
- 100msの後10msからときとしてもっと長く、書き込みに専念しているようです。この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...
173
+ 100msの後10msからときとしてもっと長く、書き込みに専念しているようです。~~この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...~~(誤り。オシロのサンプリングが足りなくて細くなったパルスが見えてなかった...)
174
+
175
+ 512byte溜めて一気に書き込む、というのが対応でしょうね。

1

実験してみた

2021/11/13 04:41

投稿

thkana
thkana

スコア7703

test CHANGED
@@ -15,3 +15,159 @@
15
15
 
16
16
 
17
17
  'Arduino SDカード 書き込み速度'でぐぐったら[こんなのが](https://teratail.com/questions/187675)トップでヒットしました。ご参考まで。
18
+
19
+
20
+
21
+ ---
22
+
23
+ ちょっとやってみたので追記。
24
+
25
+ プログラムは
26
+
27
+ ```Arduino
28
+
29
+ #include <MsTimer2.h>
30
+
31
+ #include <SD.h>
32
+
33
+ #include <SPI.h>
34
+
35
+ #include <TimerOne.h>
36
+
37
+
38
+
39
+ const int chipSelect = 10; // Arduino UNOでは10、Arduino MEGAでは53
40
+
41
+ volatile int ainput; //読み取ったbit数:intは整数
42
+
43
+ volatile uint8_t rdy;
44
+
45
+ File dataFile;
46
+
47
+
48
+
49
+ //電圧測定及びSDカード保存
50
+
51
+ void mesuring(void) {
52
+
53
+ if (!rdy) {
54
+
55
+ ainput = analogRead(A0);
56
+
57
+ }
58
+
59
+ rdy = 1;
60
+
61
+ }
62
+
63
+
64
+
65
+ void setup(void) {
66
+
67
+ pinMode(2, INPUT_PULLUP);
68
+
69
+ pinMode(3, OUTPUT);
70
+
71
+ /* ----- Setting up serial communication with PC ------ */
72
+
73
+ /* ここでUSBを介してPCとシリアル通信を始める。9600はシリアル通信のボーレート
74
+
75
+ */
76
+
77
+ Serial.begin(115200);
78
+
79
+ while (!Serial) {
80
+
81
+ ; // wait for serial port to connect. Needed for native USB port only
82
+
83
+ //何らかの問題があってシリアルポートに接続できないときは、このループにトラップされる
84
+
85
+ }
86
+
87
+
88
+
89
+ /* ----- Initialisation of SD card ------ */
90
+
91
+ Serial.print("Initializing SD card...");
92
+
93
+ // see if the card is present and can be initialized:
94
+
95
+ if (!SD.begin(chipSelect)) {
96
+
97
+ Serial.println("Card failed, or not present");
98
+
99
+ // don't do anything more:
100
+
101
+ return;
102
+
103
+ }
104
+
105
+ Serial.println("card initialized.");
106
+
107
+
108
+
109
+ int i = 100; //サンプリング間隔[micro sec]
110
+
111
+ Timer1.initialize(1000); //マイクロ秒単位で設定
112
+
113
+ Timer1.attachInterrupt(mesuring);
114
+
115
+ dataFile = SD.open("datalog.csv", FILE_WRITE);
116
+
117
+ if (!dataFile) {
118
+
119
+ Serial.println("File Open Error.");
120
+
121
+ while (1)
122
+
123
+ ;
124
+
125
+ }
126
+
127
+ rdy = 0;
128
+
129
+ }
130
+
131
+
132
+
133
+ void loop(void) {
134
+
135
+ /* SDカードに書き込み */
136
+
137
+ if (rdy) {
138
+
139
+ digitalWrite(3, HIGH);
140
+
141
+ dataFile.println(ainput, HEX);
142
+
143
+ // dataFile.write(&ainput,2 );
144
+
145
+ digitalWrite(3, LOW);
146
+
147
+ rdy = 0;
148
+
149
+ Serial.println(ainput, HEX);
150
+
151
+ }
152
+
153
+ if (digitalRead(2) == LOW) {
154
+
155
+ dataFile.close();
156
+
157
+ Serial.println("Stop.");
158
+
159
+ while (1)
160
+
161
+ ;
162
+
163
+ }
164
+
165
+ }
166
+
167
+ ```
168
+
169
+ で、D3の波形。基本的には1ms毎にパルスが立つんだけど、長い目?で見ると、
170
+
171
+ ![波形](8b125cdb73a11493281779277b6391fd.jpeg)
172
+
173
+ 100msの後10msからときとしてもっと長く、書き込みに専念しているようです。この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...