アプリ版:「スタンプのみでお礼する」機能のリリースについて

シリアル通信で得たデータを二次元配列へ格納するために、
以前では、
if(Serial.available()>120){
for(int k=0;k<8;k++){
for(int l=0;l<15;l++){
//読み込んだ値を配列に代入
matrix[k][l]=Serial.read();
}
}
}
このようなやり方で読み込んだ値を二次元配列に代入していたのですが、
128個以上のデータを扱いたい場合、Serial.availableでは保持できず、困っています。

方法として、
(1)一つずつデータを読み込み、128回ループを繰り返し配列に貯めていく。その後配列を2次元配列に代入する。
(2)一つデータを読みこんだら二次元配列の1行目1列目のドットに格納、もう一つデータを読みこんだら二次元配列の1行目2列目のドットに格納…というように、
読みこんだデータをそのまま二次元配列のそれぞれの場所へ格納していく。

というような二つの方法を思いついたのですが、
(1)の方法では、配列にデータを貯蓄していくコードをこのように↓書いたのですがうまくいかず、
for(int i=0;i<128;i++){
if(Serial.available()>0){
data[128] = Serial.read();
}
}

(2)の方法では、データを二次元配列のそれぞれの場所へ格納していく指定方法が分かりませんでした。

正しい書き方や、良いアイデアをお持ちの方がいましたら、是非御教授お願いします。

A 回答 (3件)

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ループではなく自前の処理として、何番目を読み込んでいるところなのかを管理できるわけです。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
説明不足で申し訳ありません。
データは0~255の値が常にシリアル通信で送られてきていて、その値を8×15のLEDマトリクスの明るさの値として使用しています。
(このページに近いことを行っています。→ http://kousaku-kousaku.blogspot.jp/2008/08/ardui … )
forループを使用しない配列の指定を初めて見るので、申し訳ありませんが詳細を伺ってもよろしいでしょうか。

お礼日時:2012/08/28 18:47

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のデータを読み終わった。だけど、特別な処理は不要
}
}
}
---
となるわけです。
    • good
    • 0
この回答へのお礼

理解できました。非常に分かりやすいご説明ありがとうございます。
早速試してみましたが、どうやら時間がかかりすぎているようで、映像を出力しているようにみえませんでした。現在このようなコードですが↓一ドットずつ順番に次の明るさに変化していくのが目に見えて分かる感じです。

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);
}
}

何か良い方法がないでしょうか…。

お礼日時:2012/08/28 20:52

とりあえず、


データ読み込みの方の
> if (Serial.available() > 0) {
これを、
> while (Serial.available() > 0) {
にすれば改善されるかと思います。

現状のコードでは、「1バイト受け取ってデータ更新」→「1画面表示」の繰り返しになっているので、
1ドットずつ表示が順次切り替わっているように見えてしまうわけです。
それを、「受け取り済みのデータをすべて更新」→「1画面表示」するように変えるわけです。
    • good
    • 0
この回答へのお礼

無事狙い通りに動作しました。何度もお答え頂き、分かりやすく説明して下さり、ありがとうございました!感謝します。

お礼日時:2012/08/29 14:38

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!