2017-01-14 2 views
0

モバイルからudu8アレイを使用して255を超える整数をブルートゥース経由でArduinoに送信したい。uint8の配列で255より大きい整数を送信する

私が使用しているBLEモジュールはUint16Arrayを受け入れないため、Uint8アレイのみを使用するように制限されています。

マイアプリのコード:

var data = new Uint8Array(3); 
data[0]= 1; 
data[1]= 123; 
data[2]= 555; 

ble.writeWithoutResponse(app.connectedPeripheral.id, SERVICE_UUID, WRITE_UUID, data.buffer, success, failure); 

マイデバイス固有コード:

void SimbleeBLE_onReceive(char *data, int len) { 
    Serial.print(data[0]); // prints 1 
    Serial.print(data[1]); // prints 123 
    Serial.print(data[2]); // failed to print 555 
} 

UINT8は唯一私がそれよりも大きい値を送信するにはどうすればよい、255件までの整数を可能にするので?

+3

それを複数のバイトに分割することで、それはメモリのようになります。 –

+0

コードは '555'を印刷するのに失敗していませんが、すでにそれを割り当てていません。 – alk

答えて

0

あなたはそれを分割する必要があります。あなたは既にint16が16ビットであることを知っています(つまり、それを格納するのに2バイト必要です)。

エンディアンについては非常に小さいです。エンディアンでは、格納されるときのバイトの順序を意味します。たとえば、値が0x1234の場合は、0x12 0x34(ビッグエンディアン)または0x34 0x12(リトルエンディアン)として格納できます。

const int datalen = 3; 
uint16_t data[datalen]; 
data[0]= 1; 
data[1]= 123; 
data[2]= 555; 

uint8_t sendingData[] = new uint8_t[datalen * sizeof(uint16_t)]; 
for (int i = 0; i < datalen; i++) 
{ 
    sendingData[i * 2] = (data[i] >> 8) & 0xFF; 
    sendingData[i * 2 + 1] = data[i] & 0xFF; 
} 

functionToSendData(sendingData, datalen * sizeof(uint16_t)); 

これはビッグエンディアン形式で送信します。通常はCで

私はあなたが使用どのような言語を知って、そうしないでください...あなたはこのような何かを行う++。あなたは1リトルエンディアンを好む場合は、

sendingData[i * 2] = data[i] & 0xFF; 
    sendingData[i * 2 + 1] = (data[i] >> 8) & 0xFF; 

を書く簡単なバージョンは、あなたが(送信のエンディアンを知る最初のケースで

const int datalen = 3; 
uint16_t data[datalen]; 
data[0]= 1; 
data[1]= 123; 
data[2]= 555; 

functionToSendData((uint8_t*)data, datalen * sizeof(uint16_t)); 

することができ、それはどのようにあなたのコードに応じほとんど、あるいは大きいです)、2番目はアーキテクチャーやコンパイラーに依存します。

var sendingData = new Uint8Array(data.buffer) 

をしてから、この新しい配列を送信します

JavaScriptでは、あなたはこれを使用することができます。クレジットは、あなたがそれを受信したとき、あなたは何エンディアンを知っている必要がありますので、最後の方法は、ほとんどのエラーが発生しやすいことに

// Data is big endian 
void SimbleeBLE_onReceive(char *receivedData, int len) { 
    uint16_t data[] = new uint16_t[len/2]; 

    for (int i = 0; i < len/2; i++) 
     data = (((uint16_t)receivedData[i * 2]) << 8) + receivedData[i * 2 + 1]; 

    Serial.print(data[0]); 
    Serial.print(data[1]); 
    Serial.print(data[2]); 
} 

// Data is little endian 
void SimbleeBLE_onReceive(char *receivedData, int len) { 
    uint16_t data[] = new uint16_t[len/2]; 

    for (int i = 0; i < len/2; i++) 
     data = receivedData[i * 2] + (((uint16_t)receivedData[i * 2 + 1]) << 8); 

    Serial.print(data[0]); 
    Serial.print(data[1]); 
    Serial.print(data[2]); 
} 

// Trust the compiler 
void SimbleeBLE_onReceive(char *receivedData, int len) { 
    uint16_t *data = receivedData; 

    Serial.print(data[0]); 
    Serial.print(data[1]); 
    Serial.print(data[2]); 
} 

を変換するために、これらの3つのいずれかを行う必要がありますthis answer

に行きますコンパイラを使用し、それはsendongのものと一致する必要があります。

エンディアン不一致の場合は、「ランダム」な数字が表示されます。しかし、それは本当に簡単にデバッグされます。たとえば、値156(16進0x9C)を送信し、39936(16進0x9C00)を受け取ります。見る?バイトは反転されます。別の例:8942(16進0x22EE)を送信し、60962(16進0xEE22)を受信する。

これで問題は起こると思いますが、「ブロック内に」バイトを受け取らないことがあります。たとえば、1 123 555(16進数で、ビッグエンディアンは6バイト、特に00 01 00 7B 02 2B)を送信すると、わずか3バイトまたは4バイトのSimbleeBLE_onReceiveが呼び出されます。その他。したがって、パケットの開始および/または終了を示す一種のプロトコルを定義し、それらをすべて処理する準備ができるまでバッファにバッファを蓄積する必要があります。

+0

このような説明回答をありがとう! – MANnDAaR

0

送信側と受信側のデータを0〜255の範囲で保持するために、何らかのスケーリングを使用します。たとえば、除算と乗算のためにデータが255より下に送信され、受信側でデータが拡大されます。

また、データの高低範囲がわかっている場合は、Arduinoマッピング関数を使用することになります。

y = map(mapped value, actual lo, actual hi, mapped lo, mapped hi) 

あなたは完全な範囲がわからない場合、あなたはconstrain()機能を使用することができます。

関連する問題