在Arduino上串行發送float
,double
和int16
的最佳方式是什麼?如何通過串行發送浮動
Serial.print()
只發送值爲ASCII編碼。但我想發送值作爲字節。 Serial.write()
接受字節和字節碼,但將值轉換爲字節的最佳方式是什麼?
我試圖將int16
投射到byte*
,沒有運氣。我也使用了memcpy,但是它使用了很多CPU週期。 Arduino使用簡單的C/C++。這是一款ATmega328微控制器。
在Arduino上串行發送float
,double
和int16
的最佳方式是什麼?如何通過串行發送浮動
Serial.print()
只發送值爲ASCII編碼。但我想發送值作爲字節。 Serial.write()
接受字節和字節碼,但將值轉換爲字節的最佳方式是什麼?
我試圖將int16
投射到byte*
,沒有運氣。我也使用了memcpy,但是它使用了很多CPU週期。 Arduino使用簡單的C/C++。這是一款ATmega328微控制器。
是的,發送這些數字,你必須先將它們轉換爲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終止的左對齊(無前導空白或零)字符串。
您可以隨時隨地進行轉換/無論如何你喜歡;這些功能只是插圖。
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));
}
擊敗我吧.. – hjhill 2010-07-17 09:50:21
如果這些字節是以字節形式發送的 - 二進制定義 - 那麼它可能不起作用:一些字節看起來像控制字符,接收器可能會採取行動。所以這些數字必須被ascii化。此外,chars幾乎總是通過串行線路以7位發送,因此嘗試將它們發送爲8位字節將會丟棄高位。 – 2010-07-17 10:13:21
如果發射器和接收器具有不同的字節順序,這種傳輸數據的方式將不起作用。 – 2014-04-23 11:42:28
大小很重要嗎?如果是,則可以使用ASCII85將每個32位組編碼爲5個ASCII字符,請參閱http://en.wikipedia.org/wiki/Ascii85。
使用Firmata協議。報價:
Firmata是一種通用協議,用於從主機上的軟件與微控制器 進行通信。它旨在與任何主機 計算機軟件包一起工作。現在在 數量的語言中有一個匹配的對象。使用此協議很容易將其他軟件的對象添加到 。基本上,這個固件建立了一個協議,用於從主機軟件與Arduino交談。目的是允許 的人從主機 計算機上的軟件完全控制Arduino。
你需要查找的行話是「序列化」。
這是一個有趣的串行連接問題,它可能會限制哪些字符可以端到端,並且可能無法傳遞每個字符八位。
對某些字符代碼的限制是相當普遍的。下面的幾個即興:
如果軟件流控制在使用,然後按照常規的控制字符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協議是更好的答案。它具有可以被人類理解的優點,並且對串行連接的問題更具抵抗力。除非你發送浮點數據,否則表示的低效率可能會因易於實現而被超過。
只要你接受自由,並保持你的排放。
也許這是最好的方法將浮點數轉換爲字節和字節浮點數,-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;
}
關於。 `
結構和聯合解決了這個問題。使用與結構匹配的字節大小的聯合的打包結構。重疊指向結構和聯合的指針(或在結構中添加聯合)。使用Serial.write發送流。在接收端有一個匹配的結構/聯合。只要字節順序不匹配,否則可以使用「C」hto(s..l)函數進行解壓縮。添加「標題」信息來解碼不同的結構/聯合。
可能重複[如何在二進制輸出一個int?](http://stackoverflow.com/questions/3269767/how-to-output-an-int-in-binary) – 2010-07-17 09:50:58