基于Windows Universal BluetoothLE样本实现RFduino-MPU6050数据自动更新的问询
Hey there! Let's get your MPU6050 angle data updating automatically after a single button click in your UWP app. The key here is to use BLE's notification feature instead of manually calling ReadAsync() every time—this lets your RFduino push new data to the UWP app whenever the angle changes. Here's how to do it step by step:
1. First, make sure your RFduino supports notifications
Before touching the UWP code, confirm your RFduino is set up to send notifications for the angle data characteristic. In your RFduino sketch:
- When defining the characteristic for MPU6050 angles, add the
RFduinoBLE_NOTIFYflag. For example:// Define your angle characteristic (adjust UUID and length to match your setup) RFduinoBLECharacteristic angleCharacteristic("ANGLE", RFduinoBLE_NOTIFY, 8); // 8 bytes for two floats - In the
loop()function, after updating the MPU6050 angle values, callRFduinoBLE.notifyCharacteristicValue()to push the data to connected devices:void loop() { // Read MPU6050 angles and store in variables (e.g., float angleX, angleY) // ... your existing MPU6050 reading code ... // Convert angles to bytes (match your UWP parsing logic) byte data[8]; memcpy(data, &angleX, 4); memcpy(data+4, &angleY, 4); // Push data via BLE notification RFduinoBLE.notifyCharacteristicValue(&angleCharacteristic, data, sizeof(data)); delay(100); // Adjust delay based on how often you want updates }
2. Modify your UWP code to subscribe to notifications
Replace your current "Read" button click logic with code that subscribes to the characteristic's notifications, then listens for incoming data updates.
Step 2.1: Update the button click handler
Instead of reading data once, we'll subscribe to notifications and enable automatic updates:
// Store the characteristic as a class-level variable to access it in the event handler private GattCharacteristic _angleCharacteristic; private async void ReadButton_Click(object sender, RoutedEventArgs e) { // Disable the button to prevent duplicate subscriptions ReadButton.IsEnabled = false; // Get your angle data characteristic (you should already have this from device discovery) _angleCharacteristic = /* Your existing code to retrieve the characteristic */; // Request the RFduino to send notifications var status = await _angleCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync( GattClientCharacteristicConfigurationDescriptorValue.Notify); if (status == GattCommunicationStatus.Success) { // Subscribe to the ValueChanged event to receive new data _angleCharacteristic.ValueChanged += AngleCharacteristic_ValueChanged; ReadButton.Content = "Auto-updating..."; } else { // Handle subscription failure (e.g., show error message) ReadButton.IsEnabled = true; // Add error handling here (e.g., a message dialog) } }
Step 2.2: Add the ValueChanged event handler
This function will trigger every time the RFduino pushes new angle data. We'll parse the data and update the UI:
private void AngleCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) { // Extract the raw byte data from the notification byte[] rawData = new byte[args.CharacteristicValue.Length]; DataReader.FromBuffer(args.CharacteristicValue).ReadBytes(rawData); // Parse the bytes into angle values (match your RFduino's data format) // Example: assuming two 4-byte floats (X and Y angles) in little-endian format float angleX = BitConverter.ToSingle(rawData, 0); float angleY = BitConverter.ToSingle(rawData, 4); // Update the UI—must use Dispatcher since this event runs on a background thread _ = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Update your UI elements (e.g., TextBlocks) with the new angles AngleXDisplay.Text = $"X Angle: {angleX:F2}°"; AngleYDisplay.Text = $"Y Angle: {angleY:F2}°"; }); }
3. Add cleanup logic (optional but recommended)
To avoid memory leaks or unnecessary notifications when the user navigates away or wants to stop updates:
Add a "Stop" button handler
private async void StopButton_Click(object sender, RoutedEventArgs e) { if (_angleCharacteristic != null) { // Cancel the notification subscription await _angleCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync( GattClientCharacteristicConfigurationDescriptorValue.None); // Unsubscribe from the event _angleCharacteristic.ValueChanged -= AngleCharacteristic_ValueChanged; // Reset the button state ReadButton.IsEnabled = true; ReadButton.Content = "Start Auto-Update"; _angleCharacteristic = null; } }
Clean up when navigating away from the page
protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); if (_angleCharacteristic != null) { // Clean up the subscription asynchronously _ = _angleCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync( GattClientCharacteristicConfigurationDescriptorValue.None); _angleCharacteristic.ValueChanged -= AngleCharacteristic_ValueChanged; } }
Key Notes to Remember
- Data Format Consistency: Make sure the way you convert angles to bytes on the RFduino matches how you parse them in UWP (e.g., endianness, data type, byte count). Mismatches will lead to incorrect angle values.
- UI Thread Safety: Always use
Dispatcher.RunAsyncwhen updating UI elements from theValueChangedevent—this event runs on a background thread, and direct UI updates will cause exceptions. - Battery Life: Adjust the
delay()in your RFduino sketch to balance update frequency and battery usage. Too frequent updates will drain the RFduino's battery faster.
内容的提问来源于stack exchange,提问作者Yann Kang

