[英]How to send float over serial
嗯。 這個怎么樣:
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));
}
是的,要發送這些數字,您必須先將它們轉換為ASCII字符串。 如果您正在使用 C,則sprintf()
是 IMO 進行此轉換的最簡便方法:
[后來補充:啊啊啊! 我忘了對於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 結尾的左調整(沒有前導空格或零)字符串。
您可以在任何地方/以您喜歡的方式進行轉換; 這些功能只是說明。
使用Firmata協議。 引用:
Firmata 是一種通用協議,用於通過主機上的軟件與微控制器進行通信。 它旨在與任何主機計算機軟件包一起使用。 現在有多種語言的匹配對象。 很容易為其他軟件添加對象以使用此協議。 基本上,這個固件建立了一個協議,用於從主機軟件與 Arduino 對話。 目的是讓人們可以通過主機上的軟件完全控制 Arduino。
您需要查找的行話是“序列化”。
這是一個關於串行連接的有趣問題,它可能對哪些字符可以端到端地進行限制,並且也可能無法每個字符傳遞 8 位。
對某些字符代碼的限制相當普遍。 這是袖口上的一些:
如果使用軟件流控制,則通常控制字符 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 協議是更好的答案。 它的優點是可以被人類理解,並且更能抵抗串行連接的問題。 除非您正在發送大量浮點數據,否則表示的低效率可能會被實現的簡易性所抵消。
只是對你接受的東西保持自由,對你發出的東西保持保守。
也許這是將 Float 轉換為 Byte 並將 Byte 轉換為 Float 的最佳方式,-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;
}
問候。 `
大小重要嗎? 如果是這樣,您可以使用 ASCII85 將每個 32 位組編碼為 5 個 ASCII 字符,請參閱http://en.wikipedia.org/wiki/Ascii85 。
結構和工會解決了這個問題。 使用具有與結構匹配的字節大小聯合的打包結構。 將指向結構和聯合的指針重疊(或在結構中添加聯合)。 使用 Serial.write 發送流。 在接收端有一個匹配的結構/聯合。 只要字節順序匹配沒有問題,否則您可以使用“C” hto(s..l) 函數解包。 添加“標題”信息以解碼不同的結構/聯合。
對於 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;
}
否則不工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.