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

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

ただいまの
回答率

87.35%

ArduinoとRaspberry Pi 3B+間でのUSBシリアル通信

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,557

score 6

Arduinoで一定回数測定した複数の電圧データをリアルタイムでまとめてRaspberry Pi に送り,送り終えたらまた一定回数測定し送る...というのを実現したいと思っていますがやり方がわかりません。教えてください。
電圧測定のコードは下のようになっています。下のコードでいうとs[1000],V0[1000],V1[1000],V2[1000]を送りたいと考えています。転送後ただの数字の並びとしてではなく送る前と同様に配列として扱いたいです。

void setup() {
  // シリアルポート初期化
  Serial.begin(9600);
}

int sampling_num = 1000;
float sampling_rate = 0.001;//1microsに何回サンプリングするか
int sampling_interval = 1/sampling_rate;//[micros]

float s[1000];
float V0[1000];
float V1[1000];
float V2[1000];

void loop() {

  int moji;
  // シリアルポートより、文字を1字読み込む
  moji = Serial.read();

  // 文字入力があった場合のみif関数を実行
  if(moji != -1){

   int i=0;
   int k=0;
   // 開始時間を記録
   unsigned long StartTime = micros();
   unsigned long NextTime = StartTime;

   while(k<sampling_num){i=0;

   while(i<sampling_num){
      s[i]=micros()-StartTime;
      NextTime=NextTime+sampling_interval;
      int result0;
      int result1;
      int result2;  

      result0 = analogRead(0);  
      result1 = analogRead(1);  
      result2 = analogRead(2);   

      V0[i]= result0 * 5.0 / 1023.0;
      V1[i]= result1 * 5.0 / 1023.0; 
      V2[i]= result2 * 5.0 / 1023.0;   

      while (micros() < NextTime){
      }i++;   
    } k++;

    }

}

  

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • thkana

    2019/12/21 10:01

    Arduinoと言っているのがUNOであるなら、RAMが2KBしかないという大問題が...
    ESP32をArduinoとして使っている、とかならいけますけれど。

    キャンセル

  • masotail

    2019/12/21 10:59

    Dueを使う予定です。その場合は可能でしょうか?他の種類のArduinoが適しているならば教えていただきたいです。

    キャンセル

  • thkana

    2019/12/21 13:02

    ARMだとfloatひとつが4byteで、それを4000個確保しようというのだから、その分のメモリ容量はわかりますね?

    キャンセル

回答 2

checkベストアンサー

0

手順は、
(1)arduino側で測定した時間と、3つの電圧の測定を1000回繰り返して

float s[1000];
float V0[1000];
float V1[1000];
float V2[1000];


という4つの配列にデータを入れる。

(2)これらの配列の内容を文字列に変換して、arduinoからraspberryにシリアル通信を使って送る。

(3)raspberry側は送られてきた文字列を4つの配列に戻す。

というような感じです。

arduinoとraspberry間で厳密なデータ交換手順(プロトコル)を定めてから始めると、面倒だと思いますから、データを送るのにはCSV形式の文字列を使うのが良いと思います。

シリアル通信は、バイト(8bit)データの列しか送れません(配列のような構造を持つデータをそのまま送るのは無理です)。

なので、
・Arduino側で配列から文字列に変えて、raspberryに送る。
・raspberry側で文字列を受け取って、それを配列に戻す。
という作業が必要なのです。

=補足:配列のデータを文字列に変えるコード=

回答でcsv形式の文字列と書いたのは、コンマ(",")でデータを区切った文字列で一群のデータ(1つの配列の内容)を表し、改行文字列("\r\n")でデータ群を区切るものを想定しています。
例えば、

float anArray[5] = {1.23, 2.38, -1.25, 4.12, 6.33}; 


という配列は、
"1.23,2.38,-1.25,4.12,6.33\r\n"という文字列にします。

配列から文字列を作るコードは、下記のような感じです。

  string stringData = "";  //結果の文字列を入れる変数
 for (i=0; i<5, i++) {
     if(i<4){ //最初の4つは、データの数字とカンマを追加する
     stringData = stringData + _Floating_to_string("%f",anArray[i])+","; }
     else{  //最後は、データの数字と改行文字列を追加する
     stringData = stringData + _Floating_to_string("%f",anArray[i])+"\r\n";}
  }

raspberry側でこのような文字列を受信したら、改行文字の手前までを切り出して、それをカンマを区切り文字にしたsplit関数で配列にできます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/21 00:57

    ご返答ありがとうございます。
    シリアル通信をする上での方法はわかりましたが調べても具体的な方法はよくわかりませんでした。初歩的な質問で申し訳ありませんが、配列をcsv形式の文字列に変換する方法と文字列を配列に戻す方法について具体的に教えていただきたいです。

    キャンセル

  • 2019/12/21 21:32

    配列を文字列にする方法に関するご丁寧な解説ありがとうございました。
    split関数使用後、文字配列になりますが数値配列として扱いたいと考えています。例えば '1.5' ではなく1.5という数値として配列に格納したいです。その方法を教えていただきです。また改行文字列/r/nを使うことによって複数のデータ群を一つの文字列で表すことができることは分かりましたが、最後に書かれてある改行文字/r/nの手前で切り出すことによって一つの文字列を複数の配列群(ここではs,V0,V1,V2の4つ)に戻す具体的な方法について教えていただきたいです。

    キャンセル

  • 2019/12/22 11:37

    「C++ 文字を数値に変換」でWeb検索すれば判るのではないですか?
    少しは自助努力したほうが良いです。
    何でも人任せでは、いつまで経っても自分でプログラムが書けるようにならないですよ。
    そもそも、C++の参考書とか持ってますか? ちゃんと最初から最後まで読んでいますか?

    キャンセル

0

どんなに頑張ってもシリアル通信はバイトデータの連なりをやりとりすることしか出来ませんから、シリアル通信を通す段階で「ただの数字の並び」にするしかありません。あとは、それをPythonのプログラムで(受け側がPythonというのはあっちにしか書いてなかったか) 再構成してやることになります。

いきなり複雑なことをやらないで、ひとつの数値を送り、受けるところを確実にして下さい。質問の雰囲気からそれが出来ていないだろうと思っているのですが、それが出来なきゃ話になりませんから。
次にそれをふたつの数値にします。
そうしたら、あとは(極論ですが)それを4000回繰り返すだけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る