Recommendations for getting stable PID control loop frequency while using Bluetooth

Hello community!

I’m implementing PID speed controller for a fan connected to Boron and wanted to stream control variables over Bluetooth to Adafruit Bluefruit app. BT code is based on UART peripheral example https://docs.particle.io/tutorials/device-os/bluetooth-le/#uart-peripheral and it works quite well, but the problem is that I am having hard time getting stable control loop while streaming. I’ve tried measuring microseconds since last update, software timers, GPIO interrupts, threading… but each method has failed one way or another.

Before I spend any more time investigating what I’m doing wrong, I just wanted to ask if it is even possible to get bulletproof 100 - 500 ms loop while using Bluetooth and what would be the recommended way to implement it if it is?

I’m almost certain it’s possible, but it will be very difficult to do.

The problem is that interrupts are very drifty on the nRF52, especially when using BLE (and mesh) because the radio runs with high priority interrupts. So even reading the tach pin from an ISR won’t get exact results.

There are a couple ways to solve this, but the method I would use off the top of my head is:

Use the I2S (yes, the sound interface) as a hardware digital sampler. I did this in the DHT22Gen3 library. Because the samples are grabbed in hardware without interrupts, they are not affected by the radio interrupts.

You can get an interrupt when the buffer is full, at which point you calculate the tach frequency from the samples, and use that to adjust your PWM value, which I presume is how you are changing the fan speed. Since you don’t get an interrupt on every tach pulse, the timing of these isn’t as critical.

Thanks for the help! Sounds like this is the point where I should take a step back and try other ideas to solve the problem, which do not require accurate timing. But if I’ll end up implementing the PID, your I2S solution seems to be just what I need.