如何将浮点数分离成十六进制数组元素
How to separate floating point into hex array elements
在下面的 BLE 示例中:我想将一个浮点数分成可以分配给 CUSTOM_UUID 的元素。
例如:取 12345.67 并以某种方式将其分配到 CUSTOM_UUID[] 中作为
const uint8_t CUSTOM_UUID[] =
{
0X00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x67
};
BLEUuid uuid = BLEUuid(CUSTOM_UUID);
当前格式在 BLE 广告中显示为:
00000000-0000-0000-0000-000000000000
所以我想做一些类似的事情:
00000000-0000-0000-0000-000001234567 作为第一步。
下一步将处理小数。
/*********************************************************************
This is an example for our nRF52 based Bluefruit LE modules
Pick one up today in the adafruit shop!
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in
any redistribution
Author: KTOWN (Kevin Townsend)
Copyright (C) Adafruit Industries 2017
*********************************************************************/
/* This example constantly advertises a custom 128-bit UUID, and is
* intended to be used in combination with a Central sketch that scans
* for this UUID, and then displays an alert message, sorting matching
* devices by their RSSI level which is an approximate indication of
* distance (although highly subject to environmental obstacles).
*
* By including a custom UUID in the advertising packet, we can easily
* filter the scan results on the Central device, rather than manually
* parsing the advertising packet(s) of every device in range.
*
* This example is intended to be run with the *_central.ino version
* of this application.
*/
#include <bluefruit.h>
#include <ble_gap.h>
//int test_hex = 0x55;
// Software Timer for blinking RED LED
SoftwareTimer blinkTimer;
// Custom UUID used to differentiate this device.
// Use any online UUID generator to generate a valid UUID.
// Note that the byte order is reversed ... CUSTOM_UUID
// below corresponds to the follow value:
// df67ff1a-718f-11e7-8cf7-a6006ad3dba0
const uint8_t CUSTOM_UUID[] =
{
0X00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
BLEUuid uuid = BLEUuid(CUSTOM_UUID);
void setup()
{
Serial.begin(115200);
while ( !Serial ) delay(10); // for nrf52840 with native usb
Serial.println("Bluefruit52 Peripheral Proximity Example");
Serial.println("----------------------------------------\n");
// Initialize blinkTimer for 1000 ms and start it
blinkTimer.begin(1000, blink_timer_callback);
blinkTimer.start();
err_t err = Bluefruit.begin();
if (err)
{
Serial.print("Unable to init Bluefruit (ERROR CODE: ");
Serial.print(err);
Serial.println(")");
while(1)
{
digitalToggle(LED_RED);
delay(100);
}
}
else
{
Serial.println("Bluefruit initialized (peripheral mode)");
}
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(4);
Bluefruit.setName("Bluefruit52");
// Set up and start advertising
startAdv();
Serial.println("Advertising started");
}
void startAdv(void)
{
// Note: The entire advertising packet is limited to 31 bytes!
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Preferred Solution: Add a custom UUID to the advertising payload, which
// we will look for on the Central side via Bluefruit.Scanner.filterUuid(uuid);
// A valid 128-bit UUID can be generated online with almost no chance of conflict
// with another device or etup
Bluefruit.Advertising.addUuid(uuid);
// Alternative Solution: Manufacturer Specific Data (MSD)
// You could also send a custom MSD payload and filter for the 'Company ID'
// via 'Bluefruit.Scanner.filterMSD(CID);', although this does require a
// valid CID, which is why the UUID method above is more appropriate in
// most situations. For a complete list of valid company IDs see:
// https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
// For test purposes, 0xFFFF CAN be used, but according to the Bluetooth SIG:
// > "This value may be used in the internal and interoperability tests before a
// > Company ID has been assigned. This value shall not be used in shipping end
// > products."
uint8_t msd_payload[4]; // Two bytes are required for the CID, so we have 2 bytes user data, expand as needed
uint16_t msd_cid = 0xFFFF;
memset(msd_payload, 0, sizeof(msd_payload));
memcpy(msd_payload, (uint8_t*)&msd_cid, sizeof(msd_cid));
msd_payload[2] = 0x11;
msd_payload[3] = 0x22;
Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, msd_payload, sizeof(msd_payload));
// Not enough room in the advertising packet for name
// so store it in the Scan Response instead
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in units of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start();
}
void loop()
{
}
/**
* Software Timer callback is invoked via a built-in FreeRTOS thread with
* minimal stack size. Therefore it should be as simple as possible. If
* a periodically heavy task is needed, please use Scheduler.startLoop() to
* create a dedicated task for it.
*
* More information http://www.freertos.org/RTOS-software-timer.html
*/
void blink_timer_callback(TimerHandle_t xTimerID)
{
(void) xTimerID;
digitalToggle(LED_RED);
}
我使用这个标准例程将 2 个字节合并为 1 个字节。
float 中的点变成 'E',如果你不想那样,你可以把 float 变成 long。
uint8_t CUSTOM_UUID[16];
void setup() {
Serial.begin(115200);
}
void loop() {
/* example with standard UUID: */
stringToByte("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0");
for (int i = 0; i < 16; i++) {
Serial.println(CUSTOM_UUID[i], HEX);
}
Serial.println();
/* example with float: */
float number = 12345.67;
char floatToString[32];
dtostrf(number, 32, 2, floatToString);
stringToByte(floatToString);
for (int i = 0; i < 16; i++) {
Serial.println(CUSTOM_UUID[i], HEX);
}
while(1);
}
void stringToByte(char * data)
{
// Create two pointers that point to the start of the data
char *leader = data;
char *follower = leader;
int counter = 0;
// Iterate till at the end of the string
while (*leader) {
// Check to see if the current character is a -
if (*leader != '-') {
// Grab the next two characters and move leader forwards
char high = *leader;
leader++;
char low = *leader;
// Convert ASCII 0-9A-F to a value 0-15
if (high > 0x39) high -= 7;
high &= 0x0f;
// Same again for the low byte:
if (low > 0x39) low -= 7;
low &= 0x0f;
// Combine the two into a single byte and store in follower:
*follower = (high << 4) | low;
CUSTOM_UUID[counter] = *follower;
} else {
counter--;
}
// Move both pointers to the next character:
leader++;
follower++;
// increase counter:
counter++;
}
}
这是一种从广告数据包中获得更多带宽的有趣方法,但它违背了 UUID 的预期用途,UUID 用于识别外围设备的服务配置文件和可用特征。 (我假设您打算根据某些浮点传感器值动态生成 UUID。)
当您尝试使用中央(主)设备的 BLE 通信堆栈连接到您的设备时,更改 UUID 会导致很多麻烦,例如Android 或 IOS phone。 BLE Central 设备希望从给定的外围设备收集特征 UUID 的静态层次结构,然后使用这些 UUID 来识别相应的特征值。例如,IOS BLE 堆栈有常量来识别这些众所周知的广告 UUID,在连接之前都可用:CBAdvertisementDataLocalNameKey、CBAdvertisementDataManufacturerDataKey、CBAdvertisementDataServiceUUIDsKey、CBAdvertisementDataSolicitedServiceUUIDsKey。
相反,请注意通用属性配置文件包括数据类型,允许您直接设置和恢复 float 和 double float IEEE-754 浮点特征值,以及可能更好地满足您的目的的定点特征类型。
在您的主机 BLE 堆栈上的文档中搜索 "Characteristic Presentation Format Descriptor" 以查找用于识别类型的常量。
我建议您花一些时间研究 BLE 通信的 iOS 或 Android 代码示例,以及描述 BLE 设备层次结构的各种 Bluetooth/GATT 教程配置文件。在此处找到符合 GATT 配置文件之一的廉价 BLE 设备:https://www.bluetooth.com/specifications/gatt(您可能需要创建一个免费帐户。)并尝试从您的 phone 或 PC 联系它。
或者,看看您是否可以找到使设备符合众所周知的 GATT 配置文件的示例 Arduino 代码,并将其用作您的外围设备。
正如其他人所说,在 运行 时更改 UUID 并不是真正的预期行为,尤其是当中央设备(如智能手机)可以将外围设备的配置文件保存在缓存中时。因此,动态更改它会导致一些麻烦。
通过 BLE 广告数据包发送自定义数据的预期方式是使用制造商特定数据字段。它以 2 个字节的公司 ID 开头,然后可以跟自定义数据。只要你控制中央和外围应用程序,你可以随心所欲地存储你的花车。
此外,请注意在广告数据包中发送自定义 UUID 和制造商特定数据可能需要一些时间 space,而且广告数据包是有限的。如果您需要发送更多数据(例如几个浮点数),请查看扫描响应
在下面的 BLE 示例中:我想将一个浮点数分成可以分配给 CUSTOM_UUID 的元素。
例如:取 12345.67 并以某种方式将其分配到 CUSTOM_UUID[] 中作为
const uint8_t CUSTOM_UUID[] =
{
0X00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x67
};
BLEUuid uuid = BLEUuid(CUSTOM_UUID);
当前格式在 BLE 广告中显示为: 00000000-0000-0000-0000-000000000000 所以我想做一些类似的事情: 00000000-0000-0000-0000-000001234567 作为第一步。 下一步将处理小数。
/*********************************************************************
This is an example for our nRF52 based Bluefruit LE modules
Pick one up today in the adafruit shop!
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in
any redistribution
Author: KTOWN (Kevin Townsend)
Copyright (C) Adafruit Industries 2017
*********************************************************************/
/* This example constantly advertises a custom 128-bit UUID, and is
* intended to be used in combination with a Central sketch that scans
* for this UUID, and then displays an alert message, sorting matching
* devices by their RSSI level which is an approximate indication of
* distance (although highly subject to environmental obstacles).
*
* By including a custom UUID in the advertising packet, we can easily
* filter the scan results on the Central device, rather than manually
* parsing the advertising packet(s) of every device in range.
*
* This example is intended to be run with the *_central.ino version
* of this application.
*/
#include <bluefruit.h>
#include <ble_gap.h>
//int test_hex = 0x55;
// Software Timer for blinking RED LED
SoftwareTimer blinkTimer;
// Custom UUID used to differentiate this device.
// Use any online UUID generator to generate a valid UUID.
// Note that the byte order is reversed ... CUSTOM_UUID
// below corresponds to the follow value:
// df67ff1a-718f-11e7-8cf7-a6006ad3dba0
const uint8_t CUSTOM_UUID[] =
{
0X00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
BLEUuid uuid = BLEUuid(CUSTOM_UUID);
void setup()
{
Serial.begin(115200);
while ( !Serial ) delay(10); // for nrf52840 with native usb
Serial.println("Bluefruit52 Peripheral Proximity Example");
Serial.println("----------------------------------------\n");
// Initialize blinkTimer for 1000 ms and start it
blinkTimer.begin(1000, blink_timer_callback);
blinkTimer.start();
err_t err = Bluefruit.begin();
if (err)
{
Serial.print("Unable to init Bluefruit (ERROR CODE: ");
Serial.print(err);
Serial.println(")");
while(1)
{
digitalToggle(LED_RED);
delay(100);
}
}
else
{
Serial.println("Bluefruit initialized (peripheral mode)");
}
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(4);
Bluefruit.setName("Bluefruit52");
// Set up and start advertising
startAdv();
Serial.println("Advertising started");
}
void startAdv(void)
{
// Note: The entire advertising packet is limited to 31 bytes!
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Preferred Solution: Add a custom UUID to the advertising payload, which
// we will look for on the Central side via Bluefruit.Scanner.filterUuid(uuid);
// A valid 128-bit UUID can be generated online with almost no chance of conflict
// with another device or etup
Bluefruit.Advertising.addUuid(uuid);
// Alternative Solution: Manufacturer Specific Data (MSD)
// You could also send a custom MSD payload and filter for the 'Company ID'
// via 'Bluefruit.Scanner.filterMSD(CID);', although this does require a
// valid CID, which is why the UUID method above is more appropriate in
// most situations. For a complete list of valid company IDs see:
// https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
// For test purposes, 0xFFFF CAN be used, but according to the Bluetooth SIG:
// > "This value may be used in the internal and interoperability tests before a
// > Company ID has been assigned. This value shall not be used in shipping end
// > products."
uint8_t msd_payload[4]; // Two bytes are required for the CID, so we have 2 bytes user data, expand as needed
uint16_t msd_cid = 0xFFFF;
memset(msd_payload, 0, sizeof(msd_payload));
memcpy(msd_payload, (uint8_t*)&msd_cid, sizeof(msd_cid));
msd_payload[2] = 0x11;
msd_payload[3] = 0x22;
Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, msd_payload, sizeof(msd_payload));
// Not enough room in the advertising packet for name
// so store it in the Scan Response instead
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in units of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start();
}
void loop()
{
}
/**
* Software Timer callback is invoked via a built-in FreeRTOS thread with
* minimal stack size. Therefore it should be as simple as possible. If
* a periodically heavy task is needed, please use Scheduler.startLoop() to
* create a dedicated task for it.
*
* More information http://www.freertos.org/RTOS-software-timer.html
*/
void blink_timer_callback(TimerHandle_t xTimerID)
{
(void) xTimerID;
digitalToggle(LED_RED);
}
我使用这个标准例程将 2 个字节合并为 1 个字节。 float 中的点变成 'E',如果你不想那样,你可以把 float 变成 long。
uint8_t CUSTOM_UUID[16];
void setup() {
Serial.begin(115200);
}
void loop() {
/* example with standard UUID: */
stringToByte("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0");
for (int i = 0; i < 16; i++) {
Serial.println(CUSTOM_UUID[i], HEX);
}
Serial.println();
/* example with float: */
float number = 12345.67;
char floatToString[32];
dtostrf(number, 32, 2, floatToString);
stringToByte(floatToString);
for (int i = 0; i < 16; i++) {
Serial.println(CUSTOM_UUID[i], HEX);
}
while(1);
}
void stringToByte(char * data)
{
// Create two pointers that point to the start of the data
char *leader = data;
char *follower = leader;
int counter = 0;
// Iterate till at the end of the string
while (*leader) {
// Check to see if the current character is a -
if (*leader != '-') {
// Grab the next two characters and move leader forwards
char high = *leader;
leader++;
char low = *leader;
// Convert ASCII 0-9A-F to a value 0-15
if (high > 0x39) high -= 7;
high &= 0x0f;
// Same again for the low byte:
if (low > 0x39) low -= 7;
low &= 0x0f;
// Combine the two into a single byte and store in follower:
*follower = (high << 4) | low;
CUSTOM_UUID[counter] = *follower;
} else {
counter--;
}
// Move both pointers to the next character:
leader++;
follower++;
// increase counter:
counter++;
}
}
这是一种从广告数据包中获得更多带宽的有趣方法,但它违背了 UUID 的预期用途,UUID 用于识别外围设备的服务配置文件和可用特征。 (我假设您打算根据某些浮点传感器值动态生成 UUID。)
当您尝试使用中央(主)设备的 BLE 通信堆栈连接到您的设备时,更改 UUID 会导致很多麻烦,例如Android 或 IOS phone。 BLE Central 设备希望从给定的外围设备收集特征 UUID 的静态层次结构,然后使用这些 UUID 来识别相应的特征值。例如,IOS BLE 堆栈有常量来识别这些众所周知的广告 UUID,在连接之前都可用:CBAdvertisementDataLocalNameKey、CBAdvertisementDataManufacturerDataKey、CBAdvertisementDataServiceUUIDsKey、CBAdvertisementDataSolicitedServiceUUIDsKey。
相反,请注意通用属性配置文件包括数据类型,允许您直接设置和恢复 float 和 double float IEEE-754 浮点特征值,以及可能更好地满足您的目的的定点特征类型。
在您的主机 BLE 堆栈上的文档中搜索 "Characteristic Presentation Format Descriptor" 以查找用于识别类型的常量。
我建议您花一些时间研究 BLE 通信的 iOS 或 Android 代码示例,以及描述 BLE 设备层次结构的各种 Bluetooth/GATT 教程配置文件。在此处找到符合 GATT 配置文件之一的廉价 BLE 设备:https://www.bluetooth.com/specifications/gatt(您可能需要创建一个免费帐户。)并尝试从您的 phone 或 PC 联系它。 或者,看看您是否可以找到使设备符合众所周知的 GATT 配置文件的示例 Arduino 代码,并将其用作您的外围设备。
正如其他人所说,在 运行 时更改 UUID 并不是真正的预期行为,尤其是当中央设备(如智能手机)可以将外围设备的配置文件保存在缓存中时。因此,动态更改它会导致一些麻烦。
通过 BLE 广告数据包发送自定义数据的预期方式是使用制造商特定数据字段。它以 2 个字节的公司 ID 开头,然后可以跟自定义数据。只要你控制中央和外围应用程序,你可以随心所欲地存储你的花车。
此外,请注意在广告数据包中发送自定义 UUID 和制造商特定数据可能需要一些时间 space,而且广告数据包是有限的。如果您需要发送更多数据(例如几个浮点数),请查看扫描响应