- ベストアンサー
[arduino]数値の大きなデータを二次配列へ
- シリアル通信で得たデータを二次元配列へ格納するための方法について相談です。
- 現在はSerial.available()を使用してデータを読み込んでいますが、128個以上のデータを扱いたい場合に困っています。
- データを貯蓄する方法やデータの格納方法についてのアイデアやお知恵をいただきたいです。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
とりあえず、 データ読み込みの方の > if (Serial.available() > 0) { これを、 > while (Serial.available() > 0) { にすれば改善されるかと思います。 現状のコードでは、「1バイト受け取ってデータ更新」→「1画面表示」の繰り返しになっているので、 1ドットずつ表示が順次切り替わっているように見えてしまうわけです。 それを、「受け取り済みのデータをすべて更新」→「1画面表示」するように変えるわけです。
その他の回答 (2)
- mtaka2
- ベストアンサー率73% (867/1179)
No.1のものです。参考ページを見ました。この場合、LEDの点灯制御を常時行う必要がありますから、 No1の回答の後者の方法じゃないとダメですね。 data[][] へのデータ読み込みは、どういう順番で行けばいいかをまず考えてください。 data[0][0] = Serai.read(); data[0][1] = Serai.read(); … data[0][13] = Serai.read(); data[0][14] = Serai.read(); data[1][0] = Serai.read(); data[1][1] = Serai.read(); … data[1][13] = Serai.read(); data[1][14] = Serai.read(); data[2][0] = Serai.read(); … … data[7][13] = Serai.read(); data[7][14] = Serai.read(); 以上で120個のデータ読み込み完了です。次はまた data[0][0] = Serai.read(); data[0][1] = Serai.read(); と、最初に戻ることになります。 これを、変数kと変数lを使って --- data[k][l] = Serai.read(); --- で読み込んでいるわけです。 ではあるデータを読み込んだあと、次の読み込み保存先はどうなるかを考えると、 ・l は毎回1足す。(k=0,l=0:data[0][0]の次はk=0,l=1:data[0][1]、k=0,l=1:data[0][1]の次はk=0,l=2:data[0][2]、…のように、lは1増える) ただし、l=14の次は、15ではなくl=0。14→0にしたときはkを1足す必要がある。(k=0,l=14:data[0][14]の次はk=1,l=0:data[1][0]、k=1,l=14:data[1][14]の次はk=2,l=0:data[2][0]、…のように、lは0に戻る) ・lを14→0にした時は、k に1を足す。(k=0,l=14:data[0][14]の次はk=1,l=0:data[1][0]、k=1,l=14:data[1][14]の次はk=2,l=0:data[2][0] のように、kは1増える) ただし、k=7の次は、k=8ではなく、最初に戻ってk=0(k=7,l=14:data[7][14]の次は、k=0,l=0:data[0][0])。ここまで来たら120個読み込み完了 ということになります。 これをコードにすると、 --- l++; // lは毎回1足す if (l == 15) {// ただし、l=14の次は、 l = 0; // 15ではなくl=0に戻す k++; // そして、lを14→0にした時は、k に1を足す。 if (k == 8) { // ただし、k=7の次は、 k = 0; // 最初に戻ってk=0 // 120のデータを読み終わった。だけど、特別な処理は不要 } } } --- となるわけです。
お礼
理解できました。非常に分かりやすいご説明ありがとうございます。 早速試してみましたが、どうやら時間がかかりすぎているようで、映像を出力しているようにみえませんでした。現在このようなコードですが↓一ドットずつ順番に次の明るさに変化していくのが目に見えて分かる感じです。 byte matrix[8][16]; void setup(){ for(int i=2;i<=25;i++){ pinMode(i,OUTPUT); digitalWrite(i,LOW); } Serial.begin(9600); } void loop(){ static int k = 0, l = 0; if (Serial.available() > 0) { matrix[k][l] = Serial.read(); l++; if (l == 16) { l = 0; k++; if (k == 8) { k = 0; } } } for(int i=2;i<=9;i++){ digitalWrite(i,HIGH); for(int j=10;j<=25;j++){ digitalWrite(j,LOW); delayMicroseconds(1+ matrix[i-2][j-10]); digitalWrite(j,HIGH); delayMicroseconds(256-matrix[i-2][j-10]); } digitalWrite(i,LOW); } } 何か良い方法がないでしょうか…。
- mtaka2
- ベストアンサー率73% (867/1179)
2通りの方法を挙げておきます。 かならず120個のデータが届くことがわかっており、受取以外になにもする必要がないのであれば、 --- for(int k=0;k<8;k++){ for(int l=0;l<15;l++){ while (Serial.available()== 0) { ;// データがやって来るまで待つ } matrix[k][l]=Serial.read(); } } --- でいいでしょう。forループの中で、必要なデータが届くまで必要に応じて待つわけです。 データの受信を途中で打ち切るとか、状況によっては、別の処理も行いたい場合は、 --- void loop() { static int k = 0, l = 0; if (Serial.available() > 0) { data[k][l] = Serial.read(); l++; if (l == 15) { l = 0; k++; if (k == 8) { k = 0; // 120のデータを読み終わったので、ここで必要な処理を行う。 } } } } --- といった書き方もできます。static 変数にすると、次のloop呼び出しでも変数内容が記憶されたままですので、 forループではなく自前の処理として、何番目を読み込んでいるところなのかを管理できるわけです。
お礼
回答ありがとうございます。 説明不足で申し訳ありません。 データは0~255の値が常にシリアル通信で送られてきていて、その値を8×15のLEDマトリクスの明るさの値として使用しています。 (このページに近いことを行っています。→ http://kousaku-kousaku.blogspot.jp/2008/08/arduinoprocessingledweb.html ) forループを使用しない配列の指定を初めて見るので、申し訳ありませんが詳細を伺ってもよろしいでしょうか。
お礼
無事狙い通りに動作しました。何度もお答え頂き、分かりやすく説明して下さり、ありがとうございました!感謝します。