【问题标题】:Core Bluetooth - Communicate with LED Light核心蓝牙 - 与 LED 灯通信
【发布时间】:2022-01-07 23:53:40
【问题描述】:

我正在研究与 LED 灯通信的核心蓝牙。当外围设备将值写入通信时,需要一些时间才能得到硬件(LED)的响应。当我们使用 UISLider 写入值时,我们面临着硬件延迟。我认为每当我们快速移动滑块时都会出现队列。我该如何解决这个延迟?

    let slider0:UInt8 = UInt8(sliderBrightness.value) // Brightness
    let slider1:UInt8 = UInt8(mode) // Mode
    let slider2:UInt8 = UInt8(sliderDirection.value) // Direction
    let slider3:UInt8 = UInt8(sliderStrength.value) // Strength
    let slider4:UInt8 = UInt8(sliderWhite.value) // Neutral LED Dimming
    let slider5:UInt8 = UInt8(sliderOrange.value) // Warm LED Dimming
    let slider6:UInt8 = UInt8(mode == 3 ? sliderOrbit.value : sliderOnTime.value)  // According to Mode
    let slider7:UInt8 = UInt8(sliderOffTime.value) // According to Mode
    let slider8:UInt8 = UInt8(255)
    let buff: [UInt8] = [slider0,slider1,slider2,slider3,slider4,slider5,slider6,slider7,slider8]
    
    let data = Data(bytes: buff, count: buff.count)
    let sliderVal = Int(sender?.value ?? 0.0)
    guard let char  = ledChar else {return}
    if sender == nil || sliderVal % 1 == 0 {
        print(sliderVal)
        
        if sender != nil, previousValue == sliderVal {
            return
        }
        previousValue = sliderVal
        pendingRequestWorkItem?.cancel()

        let requestWorkItem = DispatchWorkItem { [weak self] in
            self?.writeLEDValueToChar( withCharacteristic: char, withValue: data)
        }

        pendingRequestWorkItem = requestWorkItem
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(12),
                                      execute: requestWorkItem)

【问题讨论】:

  • 你有什么问题?
  • @Larme 当我使用滑块将值写入 ble 硬件时,硬件会延迟以反映输出。
  • 延迟多长时间?
  • @MichaelKotzjan 这取决于我移动滑块的频率。如果我给硬件一个写入输入值,它工作正常,但在滑块的情况下,用户可以非常频繁地移动滑块并且延迟即将到来
  • 这听起来像DispatchQueue 是你的问题。您将每个新值放入此队列,以便将其发送到设备。 BLE 速度不够快,无法处理您的实时数据。

标签: swift bluetooth-lowenergy core-bluetooth cbcentralmanager cbperipheral


【解决方案1】:

您可以尝试的一件事是一起摆脱调度队列并直接写入值。当然,有些值不会被写入,因为手机仍将处理最后一个值传输。您可以简单地忽略此错误。像这样的东西可以解决问题:

if sender == nil || sliderVal % 1 == 0 {
    print(sliderVal)
        
    if sender != nil, previousValue == sliderVal {
        return
    }
    previousValue = sliderVal
    writeLEDValueToChar( withCharacteristic: char, withValue: data)
}

另一种方法是通过设置滑块的step width 来不使用滑块中的所有可能值:

Slider(
    value: $speed,
    in: 0...100,
    step: 5
)

这样您将只获得值 0, 5, 10, 15, ... 而不是 0.0000, 0.0001, 0.0002, ... 这会在移动滑块时减少 DispatchQueue 中的条目数量

【讨论】:

  • 感谢您的宝贵回复。其实我已经实现了这个技巧。现在我使用 didwritevalue 方法在硬件空闲时传递最新值。它也适用于这种逻辑。
  • 很高兴听到您自己管理得很好。由于您现在正在跳过一些值,您是否看到 LED 上的差异?更改值时,您是否会看到不太平滑的过渡?
  • 顺时针和逆时针过渡不平滑当我跳过值时,其余控件工作正常,如亮度、颜色变化。所以我已经实现了上面的评论逻辑。
  • 很有趣,谢谢分享!
猜你喜欢
  • 2014-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
相关资源
最近更新 更多