mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-11 03:42:12 +02:00
Keep network tasks from preempting Somfy frame transmission
`Transceiver::sendFrame` bit-bangs each symbol with `delayMicroseconds` from the loop task, which runs at FreeRTOS priority 1. On single-core parts like the ESP32-C3, the WiFi and lwIP tasks run at higher priority on the same core, so they preempt the loop task when a packet arrives. That can delay an edge by several hundred microseconds. This firmware's own decoder only accepts a 640us half-symbol within 30%, so the motor probably can't decode the frame either. Because RTS is one-way, the firmware still updates the shade position, and the UI shows the shade moving even though the motor never got a valid frame. I measured this with an instrumented build on a C3, sending commands to a shade that isn't paired to any motor. When commands went out one at a time, 38% of frames had an edge more than 200us late. With other traffic (three commands at once, background HTTP requests, or position updates streaming during a move), 56-71% did, and the worst edge was 2ms late. The shade was set to 2 repeats (three frames per command), and 8 of the 33 commands sent under load had a late edge in every frame. Raise the loop task's priority above the network tasks from the first hardware sync pulse through the last data bit, then restore it so lwIP and WiFi can catch up between frames. With the change, out of 738 test frames, no edge was more than 9us late, and HTTP latency under load was unchanged. My shades seem more responsive now, but the failures were intermittent enough that I'm not confident about it. I've only tested this with 56-bit shades.
This commit is contained in:
parent
eb75868adb
commit
3d7fe0a65f
1 changed files with 5 additions and 0 deletions
|
|
@ -4330,6 +4330,10 @@ void Transceiver::sendFrame(byte *frame, uint8_t sync, uint8_t bitLength) {
|
||||||
//delayMicroseconds(9565);
|
//delayMicroseconds(9565);
|
||||||
//delay(80);
|
//delay(80);
|
||||||
}
|
}
|
||||||
|
// On single-core parts the WiFi and lwIP tasks can preempt us mid-frame and delay an edge
|
||||||
|
// enough to corrupt the frame, so we bump the priority until the last data bit.
|
||||||
|
const UBaseType_t priority = uxTaskPriorityGet(NULL);
|
||||||
|
vTaskPrioritySet(NULL, configMAX_PRIORITIES - 1);
|
||||||
// Depending on the bitness of the protocol we will be sending a different hwsync.
|
// Depending on the bitness of the protocol we will be sending a different hwsync.
|
||||||
// 56-bit 2 pulses for the first frame and 7 for the repeats
|
// 56-bit 2 pulses for the first frame and 7 for the repeats
|
||||||
// 80-bit 24 pulses for the first frame and 14 pulses for the repeats
|
// 80-bit 24 pulses for the first frame and 14 pulses for the repeats
|
||||||
|
|
@ -4364,6 +4368,7 @@ void Transceiver::sendFrame(byte *frame, uint8_t sync, uint8_t bitLength) {
|
||||||
last_bit = 0;
|
last_bit = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vTaskPrioritySet(NULL, priority);
|
||||||
// End with a 0 no matter what. This accommodates the 56-bit protocol by telling the
|
// End with a 0 no matter what. This accommodates the 56-bit protocol by telling the
|
||||||
// motor that there are no more follow on bits.
|
// motor that there are no more follow on bits.
|
||||||
if(last_bit == 0) {
|
if(last_bit == 0) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue