@mdingena I don’t have time to give you a full reply right now (busy day; sorry!) but I will attempt to give you a quick response. The simple answer to your question is that you are trying to use a time resolution that FBOS will probably never be able to support. You would be better served with simpler solutions, like a pressure regulator, an anti-siphon valve (to create water flow resistance) or, if you really absolutely must have it, a custom circuit that can trigger a more reliable, higher-resolution hardware timer connected to a GPIO (probably too much work to shave a few hundred ms off).
You also need to remember that the magnetic field in a coil does not instantly drain. This is why some electronics will stay on for a few seconds after being unplugged. You need to take this into account also (not sure how many MS it takes for the coil in the solenoid valve to discharge).
The statement above is not correct. A more correct statement would be “processes in FBOS run in parallel”. Sequences run sequentially in one process, and they do not have control over CPU scheduling- that is the job of the OS and the BEAM VM.
This explanation is further complicated by the fact that the application is written in Elixir, a highly parallelized language. Causing the program to completely pause all operations is not practical in our use case.
This is probably because there is “overhead” that can’t be controlled for in a non-realtime system. Once you use longer WAIT blocks, the effect of this overhead is diminished or becomes less noticeable. That’s my guess but ultimately we did not design the WAIT block to be used for precision or hard real-time constraints. We understood this constraint when we designed the system and did not intend to offer hard-realtime guarantees for the WAIT block. This is not unheard of (see link)
You are oversimplifying the problem. The computer is doing thousands of things even at idle. Things we shouldn’t need to know about (syncing the system clock, allocating file resources, dealing with network devices, etc…). It is the job of the OS and the BEAM virtual machine to make these scheduling decisions; not the programmer. This is generally a good thing- non-realtime OSes are much easier to work with, albeit at the expense of not being able to have fine control of timer events.
If you take a slow computer and write an asynchronous python script that has
sleep() calls and measures the time elapsed between calls to sleep, you will find variation and it will never sleep for the exact amount of time requested, especially if you trigger other system processes or have many programs running. On a low end device like an RPi the effect is amplified.