Arduino与Nordic蓝牙芯片融合开发:从入门到实战环境传感器项目
1. 项目背景当Arduino遇上Nordic蓝牙芯片如果你玩过Arduino大概率会为它丰富的生态和简单的上手门槛着迷。但当你试图给Arduino项目加上蓝牙功能尤其是低功耗蓝牙时体验可能就没那么美好了。传统的做法是外挂一个HC-05或HM-10这样的串口透传模块虽然能用但功耗、尺寸、功能灵活性都大打折扣更别提复杂的协议栈开发和射频性能优化了。而另一边Nordic Semiconductor的nRF52系列芯片几乎是低功耗蓝牙领域的“隐形冠军”从消费电子到医疗设备随处可见它的身影性能强大、功耗极低。但它的开发通常意味着要直面复杂的SDK、Keil或Segger Embedded Studio这样的专业IDE以及一整套相对“硬核”的嵌入式开发流程这让很多创客和快速原型开发者望而却步。所以当Nordic宣布为基于Arduino的项目推出蓝牙智能软件开发工具时这就像在两个原本平行的世界之间架起了一座桥。它本质上是一个“适配层”或“硬件抽象层”让你能用熟悉的Arduino IDE和其海量的库去驱动和编程Nordic的高性能蓝牙芯片。这不是简单的串口控制而是将Nordic的nRF5 SDK和SoftDevice蓝牙协议栈封装成了Arduino风格的API。对于开发者而言这意味着你可以继续享受Arduino生态的便捷——一键烧录、丰富的传感器库、图形化编程如通过PlatformIO——同时又能释放Nordic芯片在蓝牙连接、功耗管理和计算性能上的全部潜力。这个动作背后的逻辑很清晰降低高性能蓝牙芯片的开发门槛扩大其用户基数。Nordic看中了Arduino背后庞大的教育、创客和快速原型市场而Arduino开发者则获得了一个通往工业级无线应用的捷径。无论是想做一款超长待机的蓝牙温湿度计还是一个需要复杂多连接的手柄现在都有了更优雅的解决方案。我最初接触这个工具时想法很简单能不能用我桌面上吃灰的Arduino Nano 33 BLE Sense它核心就是Nordic的nRF52840做点更“正经”的蓝牙应用而不是仅限于板载传感器实验这个工具链正好提供了答案。2. 工具链全景解析不只是多了一个板型支持很多人可能会误解认为这只是在Arduino IDE的“板型管理器”里多了一个“Nordic nRF5 Boards”选项。实际上它是一套完整的工具链集成其深度远超添加一个开发板那么简单。我们可以把它拆解为几个核心层来理解。2.1 核心组件nRF5 Arduino Core这是整个体系的基石一个针对Nordic nRF5系列芯片如nRF52832 nRF52840的Arduino核心Core。当你通过Arduino IDE的板型管理器安装它时例如搜索并安装“Arduino nRF5 by Arduino”或“nRF5 by Sandeep Mistry”你实际上是在下载一套针对特定芯片的编译工具链、系统库以及引脚定义映射。这个核心做了几件关键事编译器与链接器它通常基于GCC ARM工具链但经过了特定配置能正确识别nRF5芯片的ARM Cortex-M4/M0内核并链接必要的启动文件和芯片支持文件。系统初始化替换了标准的Arduinoinit()函数。在标准的AVR Arduino上init()主要设置时钟和基本外设。在这里它要复杂得多需要初始化Nordic芯片的时钟系统可能涉及高频晶振、电源管理、以及最关键的一步——初始化并启动SoftDevice。SoftDevice集成这是与普通Arduino开发最本质的区别。SoftDevice是Nordic提供的预编译二进制蓝牙协议栈它作为一段只读代码在芯片上电后首先运行接管了射频、协议时序等最复杂的底层任务。Arduino Core负责将你的应用程序代码sketch链接到SoftDevice预留的存储空间和API入口点。你的setup()和loop()实际上是在SoftDevice营造的安全沙箱中运行的。外设抽象层将Nordic芯片的GPIO、ADC、UART、I2C、SPI、PWM等外设映射成Arduino标准的digitalWrite、analogRead、Serial、Wire、SPI等对象和函数。这让你几乎不用关心芯片数据手册中复杂的寄存器配置。2.2 蓝牙功能库从BLEPeripheral到ArduinoBLE早期版本如Sandeep Mistry维护的版本提供了一个叫BLEPeripheral的库它封装了Nordic SoftDevice的API提供了创建外围设备Peripheral的基本功能如定义服务Service、特征值Characteristic、广播数据等。而现在更主流和强大的选择是ArduinoBLE库。这个库由Arduino官方团队维护提供了更高层、更统一的API。它抽象了蓝牙低功耗的中心Central和外围Peripheral角色使得代码编写更接近“声明式”。例如创建一个带有可读、可写、可通知特征值的服务代码结构非常清晰。ArduinoBLE库底层会调用nRF5 Core提供的专用接口最终与SoftDevice通信。这里有一个关键点ArduinoBLE库的API是跨平台的。它不仅支持Nordic nRF5还支持其他内置BLE的Arduino板如某些基于ESP32的板子。这意味着当你使用这个库时你的蓝牙应用代码在理想情况下具备一定的可移植性。当然底层性能和特定高级功能如蓝牙5.0长距离、高吞吐量仍依赖于Nordic芯片的实现。2.3 开发环境与工作流安装好核心和库之后你的开发流程和经典Arduino项目几乎无异选择板型在“工具”-“开发板”菜单下选择对应的Nordic芯片板型例如“Arduino Nano 33 BLE”。选择SoftDevice版本这是一个Nordic特有的选项。不同版本的SoftDevice支持不同的蓝牙特性如蓝牙4.2 vs 5.0。通常板型定义会指定一个默认的、经过测试的版本。除非你有特殊需求否则不要随意更改。编写代码像平常一样写setup()和loop()使用ArduinoBLE库来构建你的蓝牙应用。编译与上传点击上传按钮。背后发生的事情是编译器将你的代码、ArduinoBLE库、nRF5核心系统库一起编译并链接到指定的SoftDevice上。最终生成的二进制文件通过板载的调试器如J-Link OB 在Nano 33 BLE上由板载的ATSAMD11芯片实现烧录到nRF5芯片的Flash中。这个工作流的巨大优势在于调试信息的可访问性。虽然Arduino IDE的串口监视器依然可用但对于复杂的蓝牙交互调试你可能会需要更强大的工具。这时可以搭配使用nRF Connect for Desktop这款桌面应用特别是其中的“蓝牙低功耗”插件。它可以作为一个功能强大的中心设备扫描、连接你的Arduino设备实时查看和修改服务与特征值监听通知是开发和调试过程中不可或缺的“瑞士军刀”。3. 从零构建一个蓝牙环境传感器实战理论说得再多不如动手做一遍。我们以一个具体的项目为例将一个Arduino Nano 33 BLE Sense搭载nRF52840变成一个蓝牙环境传感器通过手机App实时读取温度、湿度和气压数据。3.1 硬件准备与环境搭建首先确保你手头有Arduino Nano 33 BLE Sense。这块板子集成了HTS221温湿度和LPS22HB气压传感器以及一个Nordic nRF52840芯片完美契合我们的需求。第一步安装硬件支持包。打开Arduino IDE进入“文件”-“首选项”在“附加开发板管理器网址”中确保包含了Arduino官方的板型管理器地址。然后打开“工具”-“开发板”-“开发板管理器”搜索“Arduino Mbed OS Nano Boards”。找到并安装它。这个包包含了Nano 33 BLE系列的支持其底层基于Mbed OS而Mbed OS又封装了Nordic的底层驱动和蓝牙栈。这是目前Arduino官方维护的、对Nordic芯片支持最“正统”的途径。注意这里存在一个历史路径。早期有第三方如Sandeep Mistry提供的“nRF5 by Sandeep Mistry”核心但现在对于Arduino官方推出的基于Nordic芯片的板子优先使用Arduino官方提供的Mbed OS核心。它集成度更高与Arduino生态的兼容性更好。第二步安装必要的库。我们需要两个库ArduinoBLE用于蓝牙功能。Arduino_HTS221和Arduino_LPS22HB用于驱动板载传感器。 打开“工具”-“管理库...”分别搜索并安装这三个库。3.2 服务与特征值设计在蓝牙低功耗中数据是以“服务-特征值”的树状结构组织的。我们需要设计一个自定义服务。服务UUID我们创建一个自定义的128位UUID例如19B10000-E8F2-537E-4F6C-D104768A1214。自定义UUID可以避免与标准服务冲突。特征值我们在该服务下创建三个特征值分别用于传输温度、湿度和气压数据。温度特征(UUID:19B10001-E8F2-537E-4F6C-D104768A1214): 属性为BLERead和BLENotify。可读并且当数据变化时可以主动通知连接的手机避免手机频繁轮询省电。湿度特征(UUID:19B10002-E8F2-537E-4F6C-D104768A1214): 属性同上。气压特征(UUID:19B10003-E8F2-537E-4F6C-D104768A1214): 属性同上。每个特征值的数据格式我们定义为float类型4字节方便在Arduino端直接读取传感器浮点数并发送。3.3 代码实现详解以下是完整的Arduino Sketch代码我将逐段解释关键部分。#include ArduinoBLE.h #include Arduino_HTS221.h #include Arduino_LPS22HB.h // 定义自定义服务UUID和特征值UUID #define ENV_SERVICE_UUID 19b10000-e8f2-537e-4f6c-d104768a1214 #define TEMP_CHAR_UUID 19b10001-e8f2-537e-4f6c-d104768a1214 #define HUMID_CHAR_UUID 19b10002-e8f2-537e-4f6c-d104768a1214 #define PRESSURE_CHAR_UUID 19b10003-e8f2-537e-4f6c-d104768a1214 // 创建BLE服务对象 BLEService environmentService(ENV_SERVICE_UUID); // 创建三个特征值对象并指定其属性可读、可通知 BLEFloatCharacteristic tempCharacteristic(TEMP_CHAR_UUID, BLERead | BLENotify); BLEFloatCharacteristic humidCharacteristic(HUMID_CHAR_UUID, BLERead | BLENotify); BLEFloatCharacteristic pressureCharacteristic(PRESSURE_CHAR_UUID, BLERead | BLENotify); // 更新数据的间隔毫秒 const long updateInterval 2000; unsigned long previousMillis 0; void setup() { Serial.begin(9600); // 等待串口连接仅用于调试 // while (!Serial); // 初始化传感器 if (!HTS.begin()) { Serial.println(Failed to initialize HTS221 humidity and temperature sensor!); while (1); } if (!BARO.begin()) { Serial.println(Failed to initialize LPS22HB pressure sensor!); while (1); } // 初始化BLE if (!BLE.begin()) { Serial.println(Starting BLE failed!); while (1); } // 设置蓝牙设备的本地名称和广播的服务UUID BLE.setLocalName(Nano33BLE-EnvSensor); BLE.setAdvertisedService(environmentService); // 将特征值添加到服务中 environmentService.addCharacteristic(tempCharacteristic); environmentService.addCharacteristic(humidCharacteristic); environmentService.addCharacteristic(pressureCharacteristic); // 将服务添加到BLE设备中 BLE.addService(environmentService); // 为特征值写入初始值可选但推荐 tempCharacteristic.writeValue(0.0); humidCharacteristic.writeValue(0.0); pressureCharacteristic.writeValue(0.0); // 开始广播 BLE.advertise(); Serial.println(BLE Environmental Sensor is now advertising...); Serial.print(Device address: ); Serial.println(BLE.address()); } void loop() { // 等待蓝牙连接事件 BLEDevice central BLE.central(); // 如果有一个中心设备如手机连接上来 if (central) { Serial.print(Connected to central: ); Serial.println(central.address()); // 当连接保持时定期读取传感器并更新特征值 while (central.connected()) { unsigned long currentMillis millis(); // 检查是否到达更新间隔 if (currentMillis - previousMillis updateInterval) { previousMillis currentMillis; updateSensorData(); } // 短暂延迟避免过度占用CPU delay(10); } // 当连接断开 Serial.print(Disconnected from central: ); Serial.println(central.address()); // 连接断开后恢复广播等待下一次连接 BLE.advertise(); } } void updateSensorData() { // 读取传感器数据 float temperature HTS.readTemperature(); // 摄氏度 float humidity HTS.readHumidity(); // 百分比 float pressure BARO.readPressure(); // 千帕 // 打印到串口用于调试 Serial.print(Temp: ); Serial.print(temperature); Serial.print( °C, ); Serial.print(Humidity: ); Serial.print(humidity); Serial.print( %, ); Serial.print(Pressure: ); Serial.print(pressure); Serial.println( kPa); // 更新BLE特征值 // writeValue函数会自动触发通知如果客户端使能了通知 tempCharacteristic.writeValue(temperature); humidCharacteristic.writeValue(humidity); pressureCharacteristic.writeValue(pressure); Serial.println(Updated BLE characteristics.); }代码关键点解析对象化APIArduinoBLE库采用了面向对象的设计。BLEService和BLECharacteristic对象清晰地定义了数据结构。BLEFloatCharacteristic是一个模板类/派生类的例子它专门用于处理float类型数据省去了我们手动将浮点数转换为字节数组的麻烦。广播与连接管理在setup()中我们完成所有初始化并调用BLE.advertise()开始广播。在loop()中BLE.central()是一个非阻塞调用用于检查是否有中心设备连接。一旦连接建立我们就进入一个while (central.connected())的内部循环持续处理数据直到连接断开。这种事件驱动模型非常高效。数据更新策略我们使用millis()进行非阻塞定时每2秒读取一次传感器数据。更新特征值时直接调用writeValue()。这里有一个重要细节writeValue()方法在写入数据后会自动检查该特征值是否开启了“通知”Notify属性并且是否有客户端使能了通知。如果条件满足它会自动通过BLE连接向客户端手机发送一个通知手机App就能实时收到新数据。这是实现低功耗、实时数据传输的关键机制避免了客户端不断轮询Read造成的电量浪费。错误处理对BLE.begin()、HTS.begin()等的返回值进行了检查这是产品级代码的基本素养能快速定位硬件或初始化问题。3.4 手机端验证与数据可视化代码上传到开发板后打开手机上的蓝牙调试App如nRF Connect、LightBlue等。扫描设备你应该能看到名为“Nano33BLE-EnvSensor”的设备。连接后展开服务列表找到我们自定义的UUID服务里面应该有三个特征值。点击每个特征值旁边的“通知”图标通常是一个铃铛或箭头符号使能通知。回到Arduino IDE打开串口监视器。你会看到传感器数据每2秒打印一次同时在手机App上这三个特征值的数据也会同步刷新。恭喜一个完整的蓝牙低功耗传感器节点已经跑通了你可以进一步开发一个简单的手机App使用Android的BluetoothGATT API或iOS的CoreBluetooth框架来连接这个设备订阅通知并将数据以图表等形式展示出来。ArduinoBLE库提供的稳定数据接口使得移动端开发变得非常直接。4. 深入底层功耗优化与高级功能探索用起来简单但要做得专业就必须了解背后的机制尤其是功耗。Nordic芯片以低功耗著称但如果不经优化你的Arduino项目可能依然很耗电。4.1 理解nRF52840的电源模式nRF52840有多种电源模式从高性能的“系统开启”System ON模式到超低功耗的“系统关闭”System OFF模式。在Arduino环境下默认的delay()和millis()等函数会阻止CPU进入深度睡眠因为系统滴答定时器SysTick需要持续运行。优化策略一使用BLE库的延迟函数ArduinoBLE库提供了一个BLE.poll()或delay()的替代方案。在连接状态下为了维持连接和处理事件芯片需要保持一定活跃度。但在广播状态下未连接时我们可以让芯片大部分时间处于深度睡眠。库内部可能会在广播间隔期间调用低功耗函数但依赖于你的主循环设计。最保险的做法是在未连接时使用BLE.poll()来处理BLE栈事件并配合delay()让CPU休眠。但注意简单的delay()在nRF5核心上可能并未优化为低功耗等待。优化策略二手动控制广播间隔与功耗更精细的控制需要直接操作Nordic的底层参数但这部分在标准的Arduino BLE API中可能被隐藏了。你可以尝试修改广播参数// 在setup()中开始广播前设置 BLE.setAdvertisingInterval(160); // 单位0.625ms, 160*0.625100ms BLE.advertise();更长的广播间隔如320对应200ms1024对应640ms可以显著降低平均功耗但代价是手机可能需要更长时间才能扫描到设备。优化策略三在loop中实现深度睡眠对于数据上报不频繁的应用如每10分钟上报一次最佳策略是在采集并发送数据后直接让芯片进入深度睡眠System OFF通过实时时钟RTC定时唤醒。这需要跳出标准的loop()模型。你可以使用arduino-lowpower库如果支持你的板型或者直接操作Nordic的寄存器。这属于进阶操作需要查阅nRF5 SDK文档并了解如何通过Arduino Core访问底层外设。一个折中的方案是使用delay()并配置芯片进入“低功耗运行”模式。对于nRF52在delay()期间如果无事可做CPU会自动进入IDLE或更低的功耗状态。确保你关闭了所有不必要的模块如未用的ADC、I2C、串口等。4.2 利用Nordic芯片的硬件特性nRF52840不仅仅是一个蓝牙芯片它还是一个功能强大的微控制器。高速SPI与QSPI如果你需要连接高速显示屏或存储器nRF52840的SPI速率可以轻松达到32MHz远超传统AVR Arduino的极限。USB CDCNano 33 BLE Sense通过nRF52840的原生USB接口实现了USB串口通信。这意味着你可以通过SerialUSB对象进行高速数据传输甚至实现USB HID设备键盘、鼠标或MIDI设备而这一切都可以在Arduino环境下通过相应的库如HID-Project,MIDIUSB来实现。PDM麦克风接口板载的MP34DT05麦克风就是通过PDM接口连接的。你可以使用PDM库直接进行音频采样实现简单的语音触发或音频分析。蓝牙5.0特性nRF52840支持蓝牙5.0。通过ArduinoBLE库你可以尝试配置2M PHY高速率或Coded PHY长距离。这可能需要使用库中更高级的API或直接配置底层参数。例如增加广播数据量或尝试更快的连接间隔可以提升数据传输速率。4.3 调试与问题排查实战经验在实际项目中你肯定会遇到各种问题。以下是我踩过的一些坑和解决方案问题一编译错误“undefined reference to_write或类似链接错误。这通常是工具链或核心库版本不匹配导致的。首先确保你使用的是正确的板型支持包如Arduino Mbed OS Nano Boards。其次尝试清理编译缓存在Arduino IDE中点击“项目”-“显示项目文件夹”删除项目文件夹下的.build或build目录。最后重启Arduino IDE。如果问题依旧考虑卸载并重新安装板型支持包。问题二程序上传成功但板子无反应蓝牙搜不到。检查电源确保供电充足。USB口供电不稳可能导致芯片复位异常。检查SoftDevice有些第三方核心需要手动烧录SoftDevice。对于官方Mbed核心通常已集成。你可以尝试通过“工具”-“烧录引导程序”来刷新整个芯片注意这会擦除你的程序。检查串口输出在setup()开头加上Serial.begin(9600);和while(!Serial);仅用于调试查看是否有初始化错误信息输出。复位按钮Nano 33 BLE Sense在运行时快速双击复位按钮会进入引导加载程序模式此时板载LED会呈现呼吸灯效果。再次单击复位可退出。有时芯片会卡住需要这样复位。问题三手机能连接但收不到通知Notify数据。这是最常见的问题之一。客户端未使能通知确保手机App如nRF Connect已经点击了特征值旁边的“通知”图标。特征值属性未包含BLENotify检查代码中定义特征值时属性是否包含了BLENotify例如BLERead | BLENotify。数据未改变writeValue只有在值改变时才会触发通知吗不在ArduinoBLE的实现中每次writeValue都会尝试发送通知如果客户端已订阅。但有些客户端App只会在数据变化时才更新UI。确保你的传感器数据确实在变化。连接参数问题连接间隔太短可能导致栈处理不过来而丢包太长则会导致数据延迟。可以在手机App上查看连接参数或者在Arduino端尝试使用BLE.setConnectionInterval()进行调整需要在连接事件中或之前设置。问题四功耗依然很高。串口调试Serial.print()在运行时非常耗电。在产品代码中务必移除所有调试输出。未使用的传感器在setup()中只初始化你用到的传感器。对于未使用的Wire、SPI对象确保其引脚处于高阻态或正确状态。测量方法使用万用表串联在电池供电回路中测量平均电流。区分广播状态电流、连接空闲电流、数据发送峰值电流。Nordic芯片在广播时电流峰值可能达到几个mA但平均电流可以做到几十微安级别。如果平均电流在毫安级说明有地方在持续消耗电流。5. 超越基础构建复杂应用与生态整合掌握了基础传感器数据透传后我们可以尝试更复杂的应用场景并思考如何融入更大的物联网生态。5.1 实现双向通信与设备控制我们的环境传感器目前只是单向发送数据。让我们给它增加一个控制功能通过手机App发送一个指令来改变板载LED的亮度模拟一个开关或调光器。我们需要在之前的自定义服务中新增一个可写Write的特征值。// 新增LED控制特征值UUID #define LED_CONTROL_CHAR_UUID 19b10004-e8f2-537e-4f6c-d104768a1214 // 创建一个可写的字节型特征值 BLEByteCharacteristic ledControlCharacteristic(LED_CONTROL_CHAR_UUID, BLEWrite); // 在setup()中将它添加到服务 environmentService.addCharacteristic(ledControlCharacteristic); // 在loop()的连接处理循环中添加对写入事件的检查 while (central.connected()) { // ... 原有的传感器更新逻辑 ... // 检查LED控制特征值是否被写入 if (ledControlCharacteristic.written()) { byte ledValue ledControlCharacteristic.value(); // 假设我们控制板载的LED引脚LED_BUILTIN analogWrite(LED_BUILTIN, ledValue); // 如果LED支持PWM // 或者 digitalWrite(LED_BUILTIN, ledValue 0 ? HIGH : LOW); Serial.print(LED control value written: ); Serial.println(ledValue); } delay(10); }在手机App上找到这个新增的特征值你可以直接向它写入一个字节比如0-255。设备收到后就会改变LED的亮度。这个模式可以扩展为控制继电器、电机、或者配置设备的参数如传感器采样率。5.2 与物联网平台对接以MQTT为例单纯的蓝牙连接距离有限通常100米。要想数据上云需要一个网关。一个非常经典的架构是Arduino Nano 33 BLE Sense传感器节点 - 手机App/Raspberry Pi蓝牙网关 - MQTT Broker - 云平台/可视化界面。你可以在树莓派上运行一个Python脚本使用bluepy或pybluez库扫描并连接你的Arduino设备订阅传感器特征值的通知。一旦收到新数据脚本就将其封装成JSON格式通过paho-mqtt库发布到本地的Mosquitto MQTT代理服务器。最后Node-RED可以订阅这个MQTT主题将数据存入数据库如InfluxDB并展示在Grafana仪表盘上。这个流程将低功耗的蓝牙边缘设备无缝接入了功能强大的物联网后端系统。Nordic芯片的稳定性和Arduino的快速开发能力在这个链路的前端发挥了关键作用。5.3 对比与选型何时选择NordicArduino方案市面上有很多带蓝牙的微控制器方案比如ESP32。该如何选择选择Nordic (nRF5/nRF52) Arduino方案的情况极致低功耗是首要需求你的设备由电池供电需要续航数周、数月甚至数年。nRF52系列在低功耗优化上非常成熟有完善的电源管理模型和调试工具。需要复杂的蓝牙多角色或高吞吐量项目需要同时作为外围设备和中心设备例如一个既接收手机指令又去连接其他传感器的中继器或者需要利用蓝牙5.0的高速率模式传输大量数据。项目稳定性与可靠性要求高Nordic的SoftDevice是经过认证的协议栈在复杂射频环境下的稳定性和抗干扰能力通常有保障适合商用或工业原型。熟悉Arduino生态但需要更强性能你热爱Arduino的简单但项目需要更多内存、更快的主频或更丰富的外设如USB、高精度ADC。考虑ESP32等其他方案的情况需要Wi-Fi功能这是ESP32的绝对优势。如果你的设备必须连接Wi-FiESP32是更集成、更经济的选择。成本极度敏感在消费级市场中ESP32往往有更大的成本优势。社区资源与特定库如果你的项目严重依赖某个仅针对ESP32优化的库如某些摄像头或语音识别库那可能别无选择。对功耗要求不是极端苛刻ESP32在深度睡眠下功耗也可以很低但在活跃连接和数据处理时的功耗通常高于nRF52。总而言之Nordic为Arduino项目推出的这套开发工具真正意义在于提供了“向下兼容”的灵活性。你可以从最简单的Arduino Sketch开始快速验证想法。随着项目深入当你遇到性能瓶颈或需要深度优化时你有了一条清晰的路径可以逐步深入nRF5 SDK的底层甚至最终完全脱离Arduino环境使用专业的Segger Embedded Studio进行开发。这份“可进可退”的自由度对于从创客原型走向产品化的项目来说价值非凡。它让高性能蓝牙开发不再是一座必须从一开始就全力攀登的险峰而是一条可以从缓坡轻松起步逐渐挑战更高难度的路径。