10

Arduinoで、、、およびオーバーシリアル floatdouble送信するための最良の方法は何ですか?int16

値をASCIIエンコードSerial.print()として送信するだけです。しかし、私は値をバイトとして送信したいと思います。バイトとバイト配列を受け入れますが、値をバイトに変換する最良の方法は何ですか?Serial.write()

運が悪かっint16たので、にキャストしようとしました。byte*memcpyも使用しましたが、これは多くのCPUサイクルに使用されます。ArduinoはプレーンなC/C++を使用しています。ATmega328マイクロコントローラーです。

4

9 に答える 9

10

うーん。これはどう:

void send_float (float arg)
{
  // get access to the float as a byte-array:
  byte * data = (byte *) &arg; 

  // write the data to the serial
  Serial.write (data, sizeof (arg));
}
于 2010-07-17T09:49:14.427 に答える
9

はい、これらの番号を送信するには、最初にASCII文字列に変換する必要があります。Cを使用している場合sprintf()、IMOは、この変換を行うための最も便利な方法です。

[後で追加:AAAGHH!ints/longsの場合、関数の入力引数が符号なしになりたいことを忘れました。に渡されるフォーマット文字列についても同様ですsprintf()。そこで、以下で変更しました。見つけにくいバグだった私のひどい見落としについて申し訳ありません。また、ulongもう少し一般的にします。]

char *
int2str( unsigned long num ) {
    static char retnum[21];       // Enough for 20 digits plus NUL from a 64-bit uint.
    sprintf( retnum, "%ul", num );
    return retnum;
}

フロートとダブルについても同様です。変換を行うコードは事前にわかっています。変換するエンティティの種類を指定する必要があるため、関数char *float2str( float float_num)と。を使用することになりchar *dbl2str( double dblnum)ます。

変換から、NULで終了する左調整済み(先行ブランクまたはゼロなし)の文字列が取得されます。

どこでも/とにかく好きなように変換を行うことができます。これらの関数は単なる例示です。

于 2010-07-17T10:01:58.200 に答える
3

Firmataプロトコルを使用します。引用:

Firmataは、ホストコンピューター上のソフトウェアからマイクロコントローラーと通信するための汎用プロトコルです。これは、任意のホストコンピュータソフトウェアパッケージで動作することを目的としています。現在、多くの言語で一致するオブジェクトがあります。このプロトコルを使用する他のソフトウェアのオブジェクトを追加するのは簡単です。基本的に、このファームウェアは、ホストソフトウェアからArduinoと通信するためのプロトコルを確立します。目的は、ホストコンピューター上のソフトウェアからArduinoを完全に制御できるようにすることです。

于 2010-09-07T07:30:44.173 に答える
2

調べる必要のある専門用語は「シリアル化」です。

これは、シリアル接続での興味深い問題であり、エンドツーエンドで使用できる文字に制限があり、文字ごとに8ビットを渡すこともできない場合があります。

特定の文字コードの制限はかなり一般的です。これが袖口からのいくつかです:

  • ソフトウェアフロー制御が使用されている場合、従来、制御文字DC1およびDC3(Ctrl-QおよびCtrl-S、XONおよびXOFFとも呼ばれる)は、他の送信者を開始および停止するために送信されるため、データとして送信できません。ケーブルの端。

  • 一部のデバイスでは、NULおよび/またはDEL文字(0x00および0x7F)がレシーバーのFIFOから単に消えることがあります。

  • 受信者がUnixttyであり、termioモードが正しく設定されていない場合、文字Ctrl-D(EOTまたは0x04)により、ttyドライバーがttyを開いているプロセスにファイルの終わりを通知する可能性があります。

シリアル接続は通常、バイト幅とパリティビットを含めるように構成できます。一部の接続では、8ビットバイトではなく、パリティ付きの7ビットバイトを使用する必要があります。(非常に古い)レガシーハードウェアに接続して、5ビットおよび6ビットバイト用に多くのシリアルポートを構成することも可能です。1バイトあたりの使用可能なビット数が8ビット未満の場合、バイナリデータを処理するにはより複雑なプロトコルが必要になります。

ASCII85は、7ビットデータと制御文字の制限の両方を回避するための一般的な手法です。これは、慎重に選択された85個のASCII文字コードのみを使用してバイナリデータを再書き込みするための規則です。

さらに、送信者と受信者の間のバイト順序については確かに心配する必要があります。すべてのシステムがIEEE-754浮動小数点を使用しているわけではないため、浮動小数点形式についても心配する必要があるかもしれません。

肝心なのは、純粋なASCIIプロトコルを選択することがより良い答えであることが多いということです。人間が理解できるという利点があり、シリアル接続の問題に対してはるかに耐性があります。浮動小数点データの塊を送信しない限り、実装の容易さによって表現の非効率性が上回る可能性があります。

受け入れるものは寛大で、放出するものは控えめにしてください。

于 2010-09-07T07:55:44.360 に答える
1

これは単純に機能します。Serial.println()関数を使用 する

void setup() {
  Serial.begin(9600);

}

void loop() {
  float x = 23.45585888;
  Serial.println(x, 10);
  delay(1000);
}

そしてこれは出力です:

ここに画像の説明を入力してください

于 2019-10-12T10:36:46.453 に答える
0

サイズは重要ですか?含まれている場合は、ASCII85を使用して各32ビットグループを5つのASCII文字にエンコードできます。http://en.wikipedia.org/wiki/Ascii85を参照してください。

于 2010-07-17T16:39:12.690 に答える
0

おそらく、それがFloatをByteに、ByteをFloatに変換する最良の方法です-HamidReza。

int breakDown(int index, unsigned char outbox[], float member)
{
  unsigned long d = *(unsigned long *)&member;

  outbox[index] = d & 0x00FF;
  index++;

  outbox[index] = (d & 0xFF00) >> 8;
  index++;

  outbox[index] = (d & 0xFF0000) >> 16;
  index++;

  outbox[index] = (d & 0xFF000000) >> 24;
  index++;
  return index;
}


float buildUp(int index, unsigned char outbox[])
{
  unsigned long d;

  d =  (outbox[index+3] << 24) | (outbox[index+2] << 16)
    | (outbox[index+1] << 8) | (outbox[index]);
  float member = *(float *)&d;
  return member;
}

よろしく。`

于 2014-04-23T11:13:36.513 に答える
0

構造と組合がその問題を解決します。構造体と一致するバイトサイズの共用体を持つパック構造体を使用します。構造体と共用体へのポインターをオーバーラップします(または構造体に共用体を追加します)。Serial.writeを使用してストリームを送信します。受信側に一致する構造/ユニオンがあります。バイトオーダーが問題と一致しない限り、「C」hto(s..l)関数を使用して解凍できます。「ヘッダー」情報を追加して、さまざまな構造体/共用体をデコードします。

于 2017-10-09T13:08:33.333 に答える
0

Arduino IDEの場合:

float buildUp(int index, unsigned char outbox[])
{
  unsigned long d;
 d = (long(outbox[index +3]) << 24)  |   \
     (long(outbox[index +2]) << 16) |   \
     (long(outbox[index +1]) << 8)  |   \
     (long(outbox[index]));
 float member = *(float *)&d;
 return member;
}

それ以外の場合は機能しません。

于 2020-12-03T20:54:04.210 に答える