🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Arduino

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

Q&A

解決済

2回答

3187閲覧

シリアルモニターからArduino uno に小数の値を送りたい。

Midona

総合スコア5

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Arduino

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

1グッド

0クリップ

投稿2019/12/21 05:46

編集2019/12/22 00:31

前提・実現したいこと

Arduino unoとDAコンバーターを使い、PCからArduinoへシリアルモニターを通して0.0V~5.0Vの値を0.1V単位で送信し、送信された電圧値を出力する回路を作りたいと思っているところです。しかし、シリアルモニターから送信される値はASCIIコードでArduino側へ送られてしまう為、小数を含む数値をどうやって送ればいいのか分からず詰まっています。
シリアルモニターで2.6と送信した時Arduino側でも2.6という数値として受け取る。...という風にするにはどうすればいいのか教えて欲しいです。

試したこと

送る値が1桁の場合には、文字の'0'を引けば数値に変換出来るということは分かったのですが小数の時はどうすればいいのかわからず質問しました。
まだ、始めたての為質問の説明が分かりづらいと思いますがよろしくお願いします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

thkana👍を押しています

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

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

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

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

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

y_waiwai

2019/12/21 05:51

質問文は編集できます 追記修正しましょう
guest

回答2

0

ベストアンサー

少数じゃなくて小数、ね。

シリアル通信の話としては以前の回答を読んでおいて欲しいのですけれど。
要は、1バイトで送れない情報があるなら、送り側と受け側で何らかの規則を決めて、何バイトかをまとめて扱うようにしなきゃいけない、ということです。

で、シリアルモニターとArduinoでやるとしたら、お手軽なのはデータを改行で区切ることでしょう。
送る側は、データ毎にEnterキーを叩けばいいだけ。
受ける側は、 Serial.readStringUtil()関数に'\n'を引数として与えて、得られたStringデータ(例えば"1.2"、正確に言えば"1.2\r"だけど...)に対して.toFloat()メンバ関数を働かせれば小数データに戻せます。

サンプル。ただ数値を送り返してくるだけ。

Arduino

1void setup() { 2 Serial.begin(9600); 3} 4 5void loop() { 6 if (Serial.available()) { 7 String rcvd = Serial.readStringUntil('\n'); 8 float data = rcvd.toFloat(); 9 Serial.println(data); 10 } 11}

文字の'0'を引けば数値に変換出来るということは分かったのですが少数の時はどうすればいいのか

こちらを真面目に追求するならこんな感じで。

Arduino

1float data; 2bool afterDp = false; //小数点以下の処理中trueとする 3float weight = 1; //小数点以下の'重み' 4 5void setup() { 6 Serial.begin(9600); 7} 8 9void loop() { 10 if (Serial.available()) { 11 int rcvd = Serial.read(); 12 if (rcvd == '\n') { 13 //改行だったら一つのデータ終わり 14 Serial.println(data); 15 //次のデータのために初期化 16 data = 0; 17 afterDp = false; 18 weight = 1; 19 } else if (rcvd == '.') { 20 //小数点発見を記録 21 afterDp = true; 22 } else if (isdigit(rcvd)) { 23 //数字だったら 24 if (afterDp) { 25 //小数部の処理 26 weight /= 10; 27 data = data + (rcvd - '0') * weight; 28 } else { 29 //整数部の処理 30 data = data * 10 + rcvd - '0'; 31 } 32 } 33 } 34}

投稿2019/12/21 08:09

編集2019/12/21 08:35
thkana

総合スコア7703

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

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

Midona

2019/12/22 00:12

関数を使ったコードだけでなく、文字'0'を引いてやる方法も丁寧に教えて頂き大変勉強になりました。ありがとうございました。
guest

0

シリアル通信では、文字列の通信として、1行という単位で通信させましょう
送信は文字列や1行単位で送信できるのですが、受信は1バイトづつ受信されるため、受信のデータを貯めていかないとあきません

ということで、
・1バイトづつ受信して、バッファに貯めていく
・改行コードが来たら、1行受信したとして受信文字列をなんかする
という手順を取る必要があります

まずはこの行ごとの通信というのを、ArduinoとPCの間できちんと確実にできるようにしましょう。
それができたら、あとは数値を文字列に、文字列を数値に変換することだけです。
それは、sprintf やsscanfでできるでしょう

投稿2019/12/21 10:02

y_waiwai

総合スコア88038

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

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

Midona

2019/12/22 00:30

1行単位で通信を行うという事をすれば良かったのですね。勉強になりました。丁寧に説明していただき、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問