2010-07-17 66 views
7

在Arduino上串行發送float,doubleint16的最佳方式是什麼?如何通過串行發送浮動

Serial.print()只發送值爲ASCII編碼。但我想發送值作爲字節。 Serial.write()接受字節和字節碼,但將值轉換爲字節的最佳方式是什麼?

我試圖將int16投射到byte*,沒有運氣。我也使用了memcpy,但是它使用了很多CPU週期。 Arduino使用簡單的C/C++。這是一款ATmega328微控制器。

+0

可能重複[如何在二進制輸出一個int?](http://stackoverflow.com/questions/3269767/how-to-output-an-int-in-binary) – 2010-07-17 09:50:58

回答

9

是的,發送這些數字,你必須先將它們轉換爲ASCII字符串。如果您正在使用C工作,sprintf()是,國際海事組織,做這種轉換最方便的方式:

[後來補充: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終止的左對齊(無前導空白或零)字符串。

您可以隨時隨地進行轉換/無論如何你喜歡;這些功能只是插圖。

10

hm。這個怎麼樣:

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)); 
} 
+0

擊敗我吧.. – hjhill 2010-07-17 09:50:21

+2

如果這些字節是以字節形式發送的 - 二進制定義 - 那麼它可能不起作用:一些字節看起來像控制字符,接收器可能會採取行動。所以這些數字必須被ascii化。此外,chars幾乎總是通過串行線路以7位發送,因此嘗試將它們發送爲8位字節將會丟棄高位。 – 2010-07-17 10:13:21

+1

如果發射器和接收器具有不同的字節順序,這種傳輸數據的方式將不起作用。 – 2014-04-23 11:42:28

3

使用Firmata協議。報價:

Firmata是一種通用協議,用於從主機上的軟件與微控制器 進行通信。它旨在與任何主機 計算機軟件包一起工作。現在在 數量的語言中有一個匹配的對象。使用此協議很容易將其他軟件的對象添加到 。基本上,這個固件建立了一個協議,用於從主機軟件與Arduino交談。目的是允許 的人從主機 計算機上的軟件完全控制Arduino。

2

你需要查找的行話是「序列化」。

這是一個有趣的串行連接問題,它可能會限制哪些字符可以端到端,並且可能無法傳遞每個字符八位。

對某些字符代碼的限制是相當普遍的。下面的幾個即興:

  • 如果軟件流控制在使用,然後按照常規的控制字符DC1和DC3(按Ctrl-Q和Ctrl-S,有時也被稱爲XON和XOFF)不能被傳輸爲數據,因爲它們被髮送來啓動和停止電纜另一端的發送者。

  • 在某些設備上,NUL和/或DEL字符(0x00和0x7F)可能會簡單地從接收器的FIFO中消失。

  • 如果接收方是Unix tty,並且termio模式設置不正確,那麼字符Ctrl-D(EOT或0x04)可能會導致tty驅動程序發信號通知文件結束tty開放。

串行連接通常可配置爲字節寬度並可能包含奇偶校驗位。某些連接將要求使用具有奇偶校驗的7位字節,而不是8位字節。甚至可以連接(嚴重舊的)傳統硬件爲5位和6位字節配置許多串行端口。如果每個字節少於8位,則需要更復雜的協議來處理二進制數據。

ASCII85是一種用於處理7位數據和限制控制字符的流行技術。這是一個使用85個仔細選擇的ASCII字符代碼重寫二進制數據的約定。

另外,你一定要擔心發送者和接收者之間的字節順序。您可能還需要擔心浮點格式,因爲並非每個系統都使用IEEE-754浮點。

底線是,經常選擇一個純粹的ASCII協議是更好的答案。它具有可以被人類理解的優點,並且對串行連接的問題更具抵抗力。除非你發送浮點數據,否則表示的低效率可能會因易於實現而被超過。

只要你接受自由,並保持你的排放。

0

也許這是最好的方法將浮點數轉換爲字節和字節浮點數,-Hamid Reza。

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; 
} 

關於。 `

0

結構和聯合解決了這個問題。使用與結構匹配的字節大小的聯合的打包結構。重疊指向結構和聯合的指針(或在結構中添加聯合)。使用Serial.write發送流。在接收端有一個匹配的結構/聯合。只要字節順序不匹配,否則可以使用「C」hto(s..l)函數進行解壓縮。添加「標題」信息來解碼不同的結構/聯合。