Creating critical regions

Started developing home assistant custom stuff some weeks ago and cannot get thread synchronization to work. Hoping for some ideas from other developers out there…
My case is:
I have one common class handling Rx and Tx of 433Mhz traffic via a cheapish Tx /Rx module I have connected to pins 17/27. Pretty basic stuff as seen in many threads. Both Tx and Rx work flawlessly when used independently.
When I activate both Rx (which is supposed to be run “in the background”, just collecting 433MHz traffic such as my temp/hum sensors and Tx (flicking light switches via Nexa outlets), I get poor Nexa outlet switch response. Since it works flawlessly when disabling the Rx module, I have concluded that it is due to my Rx handler. It makes perfect sense, as my transmitting antenna is just some 50cm from my receiver. Of course the Rx module picks up everything that is Transmitted. Each pulse being detected will cause an edge detect callback via GPIO and this will inevitably take some time to handle.
The tx pulses needed are in the range of about 100us up to about 10ms, thus an interrupt of maybe 100us would obviously mess my transmission up. 50us probably would too. Hard to tell.

So, my solution to the problem (coming from the embedded world) would be to just disable interrupts (not so easy on a Raspberry pi I guess) or at least create some kind of critical region where the Rx module cannot pick up any GPIO edges.
So far I have tried the following without success:

  1. Set the GPIO Rx pin as output during the transmission.
  2. Do the whole transmission with RLock():
  3. Use a class static variable which acts as a semaphore, Tx starts when it is released and grabs it so that the rx_callback is not allowed to act on its input pulse.

The code I have is based on the rpi_rf component which some changes to make my sensors detected and my Nexa outlets react correctly.
The rpi_rf component does have logic saying that it is not possible to enable rx if tx is enabled and vice versa, so I guess the problem is not trivial at least.

Any help appreciated.

The problem with embedding something like this directly into HASS (via custom_componet or whatever) is that the RX portion of this application will be SO noisy that it will tie up any async loops considerably.

I feel this is better pushed into a separate process (or even dedicated hardware, i.e. arduino or it’s own raspi) Then that process can report to HASS using any number of available methods (mqtt, HASS REST API, etc) or through a protocol of its own that you then write a HASS custom component to consume.

Regardless of how you decide to continue, in my trials with RF TX/RX, I’ve found the best solution is to turn off the RX antenna/module entirely when transmitting. Yes, you’ll miss any messages sent during that time, but it’s the only way I found to get reliable transmission when using ardunio/raspi.

Good luck!

Excellent response. Thank you.
I agree it tends to be quite noisy as there are numerous edges detected.
I did also consider moving this to my old arduino (this home assistant project is really a way for me to migrate from the arduino, but as you suggest I could keep it as a 433Mz reception unit).
I would however prefer to keep it all in one place if possible.

I am not concerned about the messages lost while transmitting as transmissions are not very frequent.

You suggest I turn of the Rx antenna/module entirely. I guess you mean cut the power to it? Power it from GPIO?
Or do you have another way of turning it off entirely? I tried setting its Rx pin GPIO to OUTwards bound but got some complaint from the GPIO module? Maybe I did it the wrong way?

Again, thanks for your kind response.

You could cut the power entirely, perhaps directly from the Pi, if not, then with a relay.

What I did (in a project long since scrapped) was to just stop listening to the GPIO pin. In other words, I turned it off in code. The mere presence of a RX device shouldn’t affect your ability to transmit. As long as you are certain the PIN is being ignored entirely, then that should be good enough. In Arduino, this is easy, because you control everything the Arduino is doing at any moment. On Pi, it’s a bit trickier because there may be processes and kernel modules handling GPIOs in ways you may not be aware of.

As there might be others interested in the subject, I share my gained wizdom here…
Following the advice of swiftlyfalling, I removed the radio traffic rx part from homeassist.
I did however keep the functionality in the pi. After some googling I found the pigpio library, which together with the paho mqtt library served as a platform on which to rewrite the whole reception handling in C.

So, in short, I now have an external application reading the GPIO through the pigpio library which sends received sensor data to home assistant as mqtt messages. Oh, and I started an mqtt broker on the pi aswell of course.

Result: MUCH more consistent rx sensor traffic.

Also, there doesn’t seem to be any noticable interference between hass and my rx module. I don’t see any difference in the sensors detected with or without running hass. Seems realtime-ish enough, at least for my purposes.

1 Like