10-17-2025 02:05 AM
Hi,
I am developing a software where we will use a function generator and an oscilloscope to generate arbitrary signals and acquire the response using an oscilloscope.
I have done a few simpler projects using the QMH template and was thinking about doing so this time as well.
So there is one MHL for the UI and one for logging the data to file after each test has been performed.
My question is if I should go for a separate MHL for each of the two instruments and have a master MHL that controls the flow of the measurement, or run them both in one "HW engine" MHL which does all that itself.
We do not develop a lot of software so the reusability for an instrument MHL is quite low.
If I have separate MHLs I wil need to pass information back to the HW Engine MHL after each message to the instrument, to know the state. For example if I tell the oscilloscope is set to arm, I would like for the HW engine MHL to know that it is properly armed before triggering my function generator, or when the oscilloscope has acquired a signal, the Scope MHL must tell the HW engine MHL it had done so before I send a request to fetch the data.
How do you solve that in an easy way with so much "status return"s going back and forth?
I could have the instrument MHLs sending return messages to the HW Engine MHL, but the HW Engine MHL must then always handle each return and jump between different cases. If it was all handled by one MHL, i could simply have a loop waiting for the correct return from the instrument.
Here I am missing the simple C way where one could call a function and just check the respon
Please share your thoughts!
10-17-2025 03:16 AM
My tendency would go towards making it separate handler engines. But that is also influenced by the fact that I often have recipe operation where the system is controlled by a user editable recipe in sequential steps with time and other conditions.
A lot of work I recently did involves lab automation where users want to control a test setup that needs to be controlled automatically in more or less complex ways but for repeatability of test results it needs to be rather controlled and it's also extremely boring and error prone for an operator to sit with a stop watch besides the setup to push a button every now and then or change a value. Sometimes the experiments also need to repeatably execute the recipe for days or even months.
So for a one off application that likely won't see many future updates (but watch out once you have a nicely working application, the requests for just this "tiny little" modification or addition will surely pour in 🙂 ) it could be overkill. On the other hand I do see benefits in separating functionality whenever it is possible. The principle of having multiple modules that each control one thing well rather than one module that controls multiple things badly is definitely a strong point to keep in mind. Mixing multiple things in one module also tends to easily end up in a logic spaghetti flow that causes weird and hard to debug errors that require serious refactoring to get fixed. Once you've done the refactoring you discover that half of the logic you created in the course of development and fixing errors and then fixing errors caused by the earlier fixes and so on is simply crap and has actually completely gone. So separating functionality in their own module may seem like quite a lot of work upfront (although if you use a framework like DQMH a lot of that is automated for you and you don't have to edit a new message handler class from scratch for each handler) but it almost always pays off in the long run as it makes development of the modules easier, and even more important, debugging and testing of it.