2

I am working on Core Bluetooth communicate with LED Light. When peripheral write the value to communication, take some time to get response from hardware(LED).As we are using UISLider to write values we are facing delay in hardware. I think a queue occur whenever we are moving slider fast. How can i fix this delay?

    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)
Balkaran
  • 33
  • 7

1 Answers1

1

One thing you could try would be to get rid of the dispatch queue all together and write the value directly. Of course, some values will not be written since the phone will still be handling the last value transmission. You could simply ignore this error. Something like this could do the trick:

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

Another way could be to not use every possible value from the slider by setting the step width of the slider:

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

This way you would get only the values 0, 5, 10, 15, ... instead of 0.0000, 0.0001, 0.0002, ... which would decrease the amount of entries in the DispatchQueue while moving the slider

Michael Kotzjan
  • 2,093
  • 2
  • 14
  • 23
  • 1
    Thanks your valuable response. Actually I already implemented this trick. Now I am using didwritevalue method to pass the latest value when hardware is free. It is working fine with this logic also. – Balkaran Dec 03 '21 at 07:19
  • 1
    Great to hear you managed well on your own. Since you are now skipping some values, do you see the difference on your LED? Do you get visible less smooth transitions when changing the value? – Michael Kotzjan Dec 03 '21 at 07:54
  • Clockwise and Anti-Clockwise transition is not smooth When I skipped values, rest of controls are working fine like brightness, color changing. So I have Implemented above comment logic. – Balkaran Dec 03 '21 at 08:04
  • Very interesting, thanks for sharing! – Michael Kotzjan Dec 03 '21 at 08:19