質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
M5Stack

M5Stackは、小型のマイコンモジュールです。拡張モジュールが豊富に用意されており、センサと組み合わせることで測定機能を自由に追加することができます。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

2回答

1467閲覧

M5StackとArduino間を用いて複数データのやり取りがしたい

tau

総合スコア0

M5Stack

M5Stackは、小型のマイコンモジュールです。拡張モジュールが豊富に用意されており、センサと組み合わせることで測定機能を自由に追加することができます。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/11/20 11:54

前提・実現したいこと

はじめまして、趣味の機械工作にM5StackとArduinoを組み合わせようとしたところ、プログラミングで行き詰ってしまい、その道の方にアイデアをもらうために今回質問をさせていただきました。

以前私はArduinoを用いた簡単な玩具を作ったことがあり、今回はその玩具にM5Stackを組み合わせ、画面にArduinoから受信した値を表示すれば面白くなるのではないかと考えました。

やり取りするデータが二種類あるため、混同を防ぐためにもググって出てきた、配列と疑似的なsplit関数を用いた方法を試したのですが、代入がうまくいかないのか、どちらのデータも最初に定義していた0が返ってくる形になりました。

いくつか試してみたところ、ググって持ってきたsplit関数が悪さをしているのではないかとまでは推測できたのですが、如何せん調べて出てきたものほぼそのままを使った状態なので、どう直せばいいのかも検討がつきません。
当方プログラミングの初心者のため覚束無い質問になっているかとは思いますが、どうかお知恵をお貸しください。

発生している問題

Arduinoから送った複数データを場合分けしてM5Stackの画面に表示したいが、場合分けと代入がうまくいかず両データ共に0が返ってくる。

該当のソースコード

POSX=1
POSY=2

//Arduino上の送信に関する部分 void loop(){ 中略  SendData(POSX, posX);  SendData(POSY, posY);  delay(10); } void SendData(int kind, int data){ Serial.write(kind); Serial.write(","); Serial.write(int(data)); Serial.write("\n"); }
//M5Stack上の疑似split関数など int split(String data, char delimiter, int *dst){ int index = 0; int arraySize = (sizeof(data)/sizeof((data)[0])); int datalength = data.length(); for (int i = 0; i < datalength; i++) { char tmp = data.charAt(i); if ( tmp == delimiter ) { index++; if ( index > (arraySize - 1)) return -1; } else dst[index] += float(tmp); } return (index + 1); } void serialEvent(){ String myString = Serial.readStringUntil('\n'); int index = split(myString, ',', cmds); if(Serial.available() >= 2){ switch((cmds[0])){ case POSX: posX = cmds[1]; break; case POSY: posY = cmds[1]; break; } } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ググって持ってきたsplit関数が悪さをしている

いや、悪いですねぇ。でも、ネットにあったのを真似ただけ、ワタシは悪くない、とか言いたいのでしょうか。真似てはいけない間違ったモノは初心者だからといってやっぱり真似ちゃいけません。
なるほど、' Arduino split string 'でググると上位でヒットするこれですか。
これがマトモでないことは、最初の一行で
String cmds[2]={"\0"};
とでも変更してみれば破綻することで簡単にわかります。

Arduino

1String cmds[3] = {"\0"}; // 分割された文字列を格納する配列 2 3int split(String data, char delimiter, String *dst, int arraySize) { 4 int index = 0; 5 int datalength = data.length(); 6 for (int i = 0; i < datalength; i++) { 7 char tmp = data.charAt(i); 8 if ( tmp == delimiter ) { 9 index++; 10 if ( index > (arraySize - 1)) return -1; 11 } 12 else dst[index] += tmp; 13 } 14 return (index + 1); 15} 16 17void setup() { 18 // 文字列 19 String cmd = "on,off,on"; 20 // 分割数 = 分割処理(文字列, 区切り文字, 配列) 21 int index = split(cmd, ',', cmds, sizeof(cmds)/sizeof(cmds[0])); 22 // 結果表示 23 Serial.begin(9600); 24 if(index<0){ 25 Serial.println("ERROR"); 26 }else 27 for (int i = 0; i < index; i++) { 28 Serial.println(cmds[i]); 29 } 30} 31 32void loop() { 33}

とでもすればいいでしょうか。

もちろん、引数をintの配列にして、エラーが出ないように適当に変更してもそれで動くというものではありません。
例えば、

Arduino

1int cmds[3] = {}; // 分割された数値を格納する配列 2 3int split(String data, char delimiter, int *dst, int arraySize) { 4 int index = 0; 5 String val=""; 6 int datalength = data.length(); 7 for (int i = 0; i < datalength; i++) { 8 char tmp = data.charAt(i); 9 if ( tmp == delimiter ) { 10 dst[index++]=val.toInt(); 11 val=""; 12 if ( index > (arraySize - 1)) return -1; 13 } 14 else val += tmp; 15 } 16 dst[index]=val.toInt(); 17 return (index + 1); 18} 19 20void setup() { 21 // 文字列 22 String cmd = "123, 456 , 78 "; 23 // 分割数 = 分割処理(文字列, 区切り文字, 配列) 24 int index = split(cmd, ',', cmds, sizeof(cmds)/sizeof(cmds[0])); 25 // 結果表示 26 Serial.begin(9600); 27 if(index<0){ 28 Serial.println("ERROR"); 29 }else 30 for (int i = 0; i < index; i++) { 31 Serial.println(cmds[i]); 32 } 33} 34 35void loop() { 36 37}

ぐらいやってみて、数値の切り出しができるか確認してから自分のプログラムに取り込むべきでしょう。

で、serialEventの方はあなたのオリジナルでしょうか。
if(Serial.available() >= 2){
は何をしているのか、ちょっと説明してみて下さい。

投稿2020/11/20 14:05

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tau

2020/11/20 14:30

thkana様 まずは回答ありがとうございます。 if(Serial.available()>=2){ のくだりについてなのですが、実はthkana様の提示した件のサイトを元に、私のやろうとしていることに近いことを行おうとしたブログがあり、私が参考にしたのはそちらになります。 そちらで受信用の関数として掲載されたものに含まれていました。 初心者のためあまりよく考えずに入れてしまったのですが、2つ以上のデータが受信した時(今回の場合posXとposYを同時に受信することがあるため)、以下の処理を行え、という意味だと認識しています。 お手数をおかけしますが、もう少しご教授お願いできると幸いです。
thkana

2020/11/21 04:43

たとえ趣味でも機械工作をする方なら、なにも考えずにあっちのものとこっちのものをセロハンテープでくっつけても動くわけがない、という感じ、わかりますよね。それとも、万が一動いちゃうかも知れないことを期待してやってみるクチですか? 機械(コンピュータも同じですけれど)は、こちらが初心者かベテランかなんて関係なく、ちゃんと作れば動きますし、ヘンなことやれば壊れます(コンピュータ壊すのは結構大変ですけれど)。 > 初心者のためあまりよく考えずに入れてしまった 取るべき行動は逆じゃないですか? 初心者なればこそ、よく考えるべきじゃないですか? ベテランなら経験だけでも相当判断できちゃいますけど、初心者なら一つ一つ吟味して組み合わせなきゃ。 if(Serial.available() >= 2){ で何が起こるのか、追ってみて下さい。
guest

0

まず、シリアル受信側では、1行の文字列を受信して処理するようにしましょう
受信文字を、バッファにためていき、\nが来たら、そのバッファの文字列を処理するようにします。

投稿2020/11/20 11:57

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問