質問するログイン新規登録

回答編集履歴

3

追記

2021/11/14 12:39

投稿

thkana
thkana

スコア7739

answer CHANGED
@@ -85,4 +85,121 @@
85
85
  で、D3の波形。基本的には1ms毎にパルスが立つんだけど、長い目?で見ると、
86
86
  ![波形](8b125cdb73a11493281779277b6391fd.jpeg)
87
87
  100msの後10msからときとしてもっと長く、書き込みに専念しているようです。~~この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...~~(誤り。オシロのサンプリングが足りなくて細くなったパルスが見えてなかった...)
88
- 512byte溜めて一気に書き込む、というのが対応でしょうね。
88
+ 512byte溜めて一気に書き込む、というのが対応でしょうね。
89
+
90
+ ---
91
+ しつこくいじってみました。以下のプログラム参照。多分動いているんじゃないかと。
92
+ 512byte毎にSDカードに書き込んでいて、大抵は10ms~18msぐらいでwriteが終わるのですが時々100ms~170msかかるときがあります(発生原因は把握していませんがSDカードの都合?)。
93
+ これをカバーしようとするとAD結果のバッファサイズ(BUFSIZE)をそれなりに大きくしなきゃいけない、というあたりが落とし穴か。(100ms以上かかるのが連続しないという保証も実はないのだけれど、UNOではもうメモリに余裕がない)
94
+
95
+ ```Arduino
96
+ #include <MsTimer2.h>
97
+ #include <SD.h>
98
+ #include <SPI.h>
99
+ #include <TimerOne.h>
100
+
101
+ //#define HARDDEBUG
102
+
103
+ const int chipSelect = 10; // Arduino UNOでは10、Arduino MEGAでは53
104
+ File dataFile;
105
+
106
+ const int BUFSIZE = 200;
107
+ int rbuf[BUFSIZE];
108
+ int wp = 0, rp = 0;
109
+ int overrun = 0;
110
+
111
+ //電圧測定及びSDカード保存
112
+ void mesuring(void) {
113
+ #ifdef HARDDEBUG
114
+ digitalWrite(4, HIGH);
115
+ #endif
116
+ wp = (wp + 1) % BUFSIZE;
117
+ rbuf[wp] = analogRead(A0);
118
+ if (wp == rp) {
119
+ overrun = 1;
120
+ }
121
+ #ifdef HARDDEBUG
122
+ digitalWrite(4, LOW);
123
+ #endif
124
+ }
125
+
126
+ void setup(void) {
127
+ pinMode(2, INPUT_PULLUP);
128
+ #ifdef HARDDEBUG
129
+ pinMode(3, OUTPUT);
130
+ pinMode(4, OUTPUT);
131
+ #endif
132
+ /* ----- Setting up serial communication with PC ------ */
133
+ /* ここでUSBを介してPCとシリアル通信を始める。9600はシリアル通信のボーレート
134
+ */
135
+ Serial.begin(115200);
136
+ while (!Serial) {
137
+ ; // wait for serial port to connect. Needed for native USB port only
138
+ //何らかの問題があってシリアルポートに接続できないときは、このループにトラップされる
139
+ }
140
+
141
+ /* ----- Initialisation of SD card ------ */
142
+ Serial.print("Initializing SD card...");
143
+ // see if the card is present and can be initialized:
144
+ if (!SD.begin(chipSelect)) {
145
+ Serial.println("Card failed, or not present");
146
+ // don't do anything more:
147
+ while (1)
148
+ ;
149
+ }
150
+ Serial.println("card initialized.");
151
+ dataFile = SD.open("datalog.csv", FILE_WRITE);
152
+ if (!dataFile) {
153
+ Serial.println("File Open Error.");
154
+ while (1)
155
+ ;
156
+ }
157
+ Serial.println("File Open.");
158
+ Timer1.initialize(1000); //マイクロ秒単位で設定
159
+ Timer1.attachInterrupt(mesuring);
160
+ }
161
+
162
+ void loop(void) {
163
+ /* SDカードに書き込み */
164
+ if (wp != rp) {
165
+ #ifdef HARDDEBUG
166
+ digitalWrite(3, HIGH);
167
+ #endif
168
+ rp = (rp + 1) % BUFSIZE;
169
+ // Serial.println(rbuf[rp]);
170
+ pushBuf(rbuf[rp]);
171
+ #ifdef HARDDEBUG
172
+ digitalWrite(3, LOW);
173
+ #endif
174
+ }
175
+ if (digitalRead(2) == LOW) {
176
+ dataFile.close();
177
+ Serial.println("Stop.");
178
+ while (1)
179
+ ;
180
+ }
181
+ if (overrun) {
182
+ Serial.println("OR");
183
+ overrun = 0;
184
+ dataFile.close();
185
+ Serial.println(".");
186
+ while (1)
187
+ ;
188
+ }
189
+ }
190
+ uint32_t t0, t1, t2;
191
+ void pushBuf(int val) {
192
+ int wdat = val * 500l / 1023; //固定小数点数
193
+ t1 = millis();
194
+ dataFile.print(wdat/100);
195
+ dataFile.print('.');
196
+ dataFile.println(wdat %100);
197
+ t2 = millis();
198
+ if (t2 - t1 > 8) {
199
+ Serial.print(t1 - t0);
200
+ Serial.print("/");
201
+ Serial.println(t2 - t1);
202
+ t0 = t2;
203
+ }
204
+ }
205
+ ```

2

訂正

2021/11/14 12:39

投稿

thkana
thkana

スコア7739

answer CHANGED
@@ -84,4 +84,5 @@
84
84
  ```
85
85
  で、D3の波形。基本的には1ms毎にパルスが立つんだけど、長い目?で見ると、
86
86
  ![波形](8b125cdb73a11493281779277b6391fd.jpeg)
87
- 100msの後10msからときとしてもっと長く、書き込みに専念しているようです。この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...
87
+ 100msの後10msからときとしてもっと長く、書き込みに専念しているようです。~~この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...~~(誤り。オシロのサンプリングが足りなくて細くなったパルスが見えてなかった...)
88
+ 512byte溜めて一気に書き込む、というのが対応でしょうね。

1

実験してみた

2021/11/13 04:41

投稿

thkana
thkana

スコア7739

answer CHANGED
@@ -6,4 +6,82 @@
6
6
  もひとつ、割り込み中はいろいろと機能制限があります。大きくは、割り込み中は(それなりの手を打っていないと)他の割り込みが禁止になっています。SPI通信とかは結構割り込みをつかっているんじゃないかしら? 多分Serial.printも危ないです。
7
7
  そういうこともありますので、「割り込みハンドラ内ではあまり大きな仕事をせず、速やかにメインコンテキストに復帰する」のが原則です。
8
8
 
9
- 'Arduino SDカード 書き込み速度'でぐぐったら[こんなのが](https://teratail.com/questions/187675)トップでヒットしました。ご参考まで。
9
+ 'Arduino SDカード 書き込み速度'でぐぐったら[こんなのが](https://teratail.com/questions/187675)トップでヒットしました。ご参考まで。
10
+
11
+ ---
12
+ ちょっとやってみたので追記。
13
+ プログラムは
14
+ ```Arduino
15
+ #include <MsTimer2.h>
16
+ #include <SD.h>
17
+ #include <SPI.h>
18
+ #include <TimerOne.h>
19
+
20
+ const int chipSelect = 10; // Arduino UNOでは10、Arduino MEGAでは53
21
+ volatile int ainput; //読み取ったbit数:intは整数
22
+ volatile uint8_t rdy;
23
+ File dataFile;
24
+
25
+ //電圧測定及びSDカード保存
26
+ void mesuring(void) {
27
+ if (!rdy) {
28
+ ainput = analogRead(A0);
29
+ }
30
+ rdy = 1;
31
+ }
32
+
33
+ void setup(void) {
34
+ pinMode(2, INPUT_PULLUP);
35
+ pinMode(3, OUTPUT);
36
+ /* ----- Setting up serial communication with PC ------ */
37
+ /* ここでUSBを介してPCとシリアル通信を始める。9600はシリアル通信のボーレート
38
+ */
39
+ Serial.begin(115200);
40
+ while (!Serial) {
41
+ ; // wait for serial port to connect. Needed for native USB port only
42
+ //何らかの問題があってシリアルポートに接続できないときは、このループにトラップされる
43
+ }
44
+
45
+ /* ----- Initialisation of SD card ------ */
46
+ Serial.print("Initializing SD card...");
47
+ // see if the card is present and can be initialized:
48
+ if (!SD.begin(chipSelect)) {
49
+ Serial.println("Card failed, or not present");
50
+ // don't do anything more:
51
+ return;
52
+ }
53
+ Serial.println("card initialized.");
54
+
55
+ int i = 100; //サンプリング間隔[micro sec]
56
+ Timer1.initialize(1000); //マイクロ秒単位で設定
57
+ Timer1.attachInterrupt(mesuring);
58
+ dataFile = SD.open("datalog.csv", FILE_WRITE);
59
+ if (!dataFile) {
60
+ Serial.println("File Open Error.");
61
+ while (1)
62
+ ;
63
+ }
64
+ rdy = 0;
65
+ }
66
+
67
+ void loop(void) {
68
+ /* SDカードに書き込み */
69
+ if (rdy) {
70
+ digitalWrite(3, HIGH);
71
+ dataFile.println(ainput, HEX);
72
+ // dataFile.write(&ainput,2 );
73
+ digitalWrite(3, LOW);
74
+ rdy = 0;
75
+ Serial.println(ainput, HEX);
76
+ }
77
+ if (digitalRead(2) == LOW) {
78
+ dataFile.close();
79
+ Serial.println("Stop.");
80
+ while (1)
81
+ ;
82
+ }
83
+ }
84
+ ```
85
+ で、D3の波形。基本的には1ms毎にパルスが立つんだけど、長い目?で見ると、
86
+ ![波形](8b125cdb73a11493281779277b6391fd.jpeg)
87
+ 100msの後10msからときとしてもっと長く、書き込みに専念しているようです。この期間割り込みも止まっていました。割り込みが動いていればバッファリングで誤魔化す手もあるんだけど...