Skip to content

Proposal for dynamic rate limiting on SCPI communication #903

Open
@chille

Description

@chille

The problem

When writing the driver for the OWON HDS200 I encountered a problem that had no perfect solution.

Some commands, like :DMM:MEAS?, can be sent without any rate limiting. When requesting data with SCPITransport::SendCommandQueuedWithReply() the call will be blocked until the data is returned. It is then safe to immidiately sent another command.

Other commands, like :DMM:RANGE {V, mV} takes a really long time. As the command is write only, there is no waiting for a reply. If a request is sent directly after, then it will either get dropped, or might possible get the wrong data. I currently block for around 800 ms to avoid this.

This problem have a few possible solutions:

  1. Do all the rate limiting with usleep(). This might freeze the GUI for a couple of seconds when doing things that takes longer time.

  2. Use the already built in rate limiting. Then everything will be slow. A :DMM:MEAS? will do something like 1.2 readings per second, instead of 15. Other things like the scope might be even worse.

  3. Extend the SCPITransport to have some kind of dynamic rate limiting. Something where each command could have a "settle time" that will block the next command until it is safe to run. This is the solution I propose.

How do we implement this?

API changes

All SCPITransform::Send*() functions will have an extra argument added:
std::chrono::milliseconds settle_time = chrono::milliseconds(0)
This settle_time is optional and will default to 0 ms.
This will not need any refactoring in other classes.

Storing the required data

SCPITransport::m_txQueue will be changed from:
std::list<std::string> m_txQueue;
to
std::pair<std::string,std::chrono::milliseconds> m_txQueue;

In this way we can store both the command and the associated "settle time".

Nothing in the scopehal-apps repo uses m_txQueue outside of the SCPITransport class. So this should be easy to change.

Sending data

All code that does some kind of timing in SCPITransport should do it like this instead:

If settle_time > 0
	Use settle_time
Else
	Use m_rateLimitingInterval

I have not yet looked into what exact stepts that will be needed for this. It could possibly be as easy as letting RateLimitingWait() be aware of the settle_time.

Notes

  • If settle_time > 0, then this value will always be used, even if it is lower than the global rate limit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiAPI improvementscore

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions