Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DC sources #3

Open
MatthieuDartiailh opened this issue Apr 19, 2015 · 50 comments
Open

DC sources #3

MatthieuDartiailh opened this issue Apr 19, 2015 · 50 comments

Comments

@MatthieuDartiailh
Copy link
Contributor

I think it is time to start writing some drivers to find any remaining issues in the core (the subsystems instantiation might need some rework for examples). I will start with DC current/voltages sources. I have three at my disposition to try to define a kind of standard (Yokogawa 7651, Yokogawa GS200, and Bilt rack with high stability DC voltage source card), if anybody has some it would be interesting to share the manual. As I will be clearer what we can and can't do I will write real driver to serve as a base for the discussion.
We could also target Lock-in and RF sources in the near future I think.

Edited
The following diagram summarize the state of the discussion and the proposed standard hierarchy so far.

  • driver :
    • output : channel
      • mode : Issue self-changing for some, settable for others, could be kept outside of the standard.
      • voltage : Float
      • current : Float
      • voltage_range : Unicode
      • current_range : Unicode
      • voltage_limit_behavior : Unicode, {'Trip', 'Regulate'}
      • current_limit_behavior : Unicode, {'Trip', 'Regulate'}
      • enabled : Bool, Issue self-changing is case of tripping
      • is_output_tripped : Action
      • measure : Action, optional
      • ovp/ovc (over voltage/current protection) : subsystem, optional
        • enabled : Bool
        • behavior : Unicode
        • level : Float
        • reset : Action
        • read_status : Action
      • trigger : optional, (to be discussed)
        • mode : Unicode
        • source : Unicode
        • delay : Float
        • arm: Action
@crazyfermions
Copy link

I have a fair amount of experience with DC sources, since our lab has about 8 different kind of source including high precision single sources like the Yokogawa 7651, custom built multi channel sources from Delft University as well as simple DAC cards.

I personally think we should start with the IviDCPwr specifications, since I found them very useful when programming my drivers.

@MatthieuDartiailh
Copy link
Contributor Author

You can look at my associated PR. I basically followed ivi but took a bit of distance from it as not all instrument can be either voltage and current source and as the protection specification was not exactly fitting my instrument (I was not very motivated to implement stuff for hardcoded behaviour of the instruments but this is mainly laziness and being short on time). Please comment your input would be very valuable to me.

@crazyfermions
Copy link

First of all, I think you did a good job by implementing almost all the functions of the instruments which gives us a good starting point of the discussion. Let's focus for now on the Yokogawa drivers since the trigger feature of the BE* is a more advanced one which can be discussed later.

1) So far, no separation between the instrument itself and the output channel
Every device usually has instrument-wide settings and settings per channel (which is okay for the Yokogawa, but there exist many voltage sources with more than one channel). I think lantz supports sth. like a list of features, inst.voltagelevel[i] = xx, where i is the channel number. This leads to

2) Everything is now accessed as a method/attribute of the instrument
Here is the point where we should decide whether we want a flat API (everything inst.feat) or more like a tree with several levels, like inst.foo.feat, inst.bar.feat, ...
IVI divides the namespaces into logical groups, in this case inst.outputs[i].voltagelevel = xx. In IVI terms, this is called a "repeated capability", which makes intuitively sense because most instruments are in fact built like that (but I don't know if lantz supports sth. like that).
If I remember correctly, someone wrote that IVI tends be "over divisive" which might be true, but on the other hand I think it is not a good idea to have all functionality on one level, because it easily gets very messy and more difficult to work with the driver.

3) Access to lantz functionality
You should also have a look at inherent capabilities, if you haven't; it defines the API for generic instrument functions (mainly 3 different types of functionality groups, DriverOperation, Identity (also see *4 below) and Utility). While not everything makes sense to directly copy to lantz, the general idea is still valid, namely: DriverOperation handles driver options like caching (for lantz there could be the aspect of units for example), of course there can be no final decision before the featureset of lantz is fixed -- but I think this would be an important thing to put into an "official" API.

4) Access to *IDN?
IVI defines a standardized access to the *IDN? query, the idea of which I found useful.

I have some additional minor points, but I am out of time for now, maybe you can comment especially on 1) and 2), because these are the main issues here.

@MatthieuDartiailh
Copy link
Contributor Author

I will try to answer all of your point :

  1. Lantz does not support that kind of list of feature (python-ivi does) because it chooses a more object oriented approach where each channel is represented by a an object and then setting a feature on that object dispatch to the correct channel. This is what is done in the Bilt driver : the rack itself (BN100) is not a voltage source and does not follow the standard but the its channel BE2100 is a voltage source and follow the standard for voltage source.
bn100 = BN100('resource')
bn100.be2100[1].voltage = 1

Hence the yokogawa doe snot bother with channels as it has none, while we can easily add them to the Bilt.

  1. I was the one who said IVI was over-divided to my taste. Meaning that if I have a voltage source I expect to directly access its voltage as it is its main setting. Lantz support hierarchical subsystems but I was thinking to reserve them for more advanced/clearly separated features, such as the features of a lock-in oscillator, the pulses management of a RF source (as suggested by IVI), and such. In IVI it seems there is nothing at the root of an instrument which I find weird.

  2. I will give a look at the inherent capabilities and see how they can fit into the standards. Thanks for pointing this out.

  3. I will see what IVI says about IDN. But note that access to IDN is already provided through the Identify mixin class found in standards.ieee4888. But there is probably room for improvement.

Thanks for your feedback and feel free to give more.

@alexforencich
Copy link
Member

What if the card has more than one channel? I just took a look at the Bilt site, they will be releasing the BE2141 soon, which has 4 channels in one card. So you will need to support bn100.bn2141[m].channel[n].voltage . Might as well implement that now so you don't need to do that later, and so you can present a unified interface.

@MatthieuDartiailh
Copy link
Contributor Author

We can easily do that using Lantz. We will be able to add that later, I would prefer to focus on stabilizing Lantz API and tests those drivers using pyvisa-sim for now.

@MatthieuDartiailh
Copy link
Contributor Author

Furthermore I don't have access to the be2141 manual so I don't even know how the internal channel is selected.

@alexforencich
Copy link
Member

The point is not to support switching channels, it's to create a uniform API that is self-consistent. Have a power supply? Change the voltage with [whatever].channels[n].voltage. Keep the channels[n] even if it only has one channel so that it will be consistent with devices that have more than one channel.

@MatthieuDartiailh
Copy link
Contributor Author

I disagree such a system would not scale well. For the yokogawa you would end up with two level of nesting for an instrument which does not have even have channels ! From my point of view it makes more sense to require a certain type of interface for a function (DCvoltage source) and let the user code pass whatever is the appropriate object (full driver, subsystem or channel). Otherwise the day we discover an instrument composed of even more modules we would have to rewrite everything to add a false level of nesting.

@alexforencich
Copy link
Member

I say it needs a channels[] layer for consistency. If you don't add that, then you end up with a very different API between single channel and multichannel power supplies, which is not very clean. And why would you need to rewrite everything to add a layer of nesting? Isn't the architecture set up in such a way that things can be nested easily? Besides, most instruments are not card-cage based, and even so, I would say one level for card cage and one level for channel is not so bad. And you would only implement the card-cage level for specific instruments that are built that way.

@MatthieuDartiailh
Copy link
Contributor Author

I am still not convinced as this seems very artificial to me. I mean as we cannot hope to cover every corner case and stuff I would really prefer to have consistent subsystem and channels as I described above (meaning that if you only access the standard spec you can pass anything respecting the standard whether it be a full driver, a subsystem or a channel) rather than adding artificial layers. I would really like the others point of view on that. @hgrecco, @arsenovic Could you please comment on this ? @crazyfermions your opinion is of course welcome.

@alexforencich
Copy link
Member

Take the Agilent E3633A and E3631A power supplies, for example. One has 3 outputs. One has a single output. As per the IVI spec, both power supplies present the same interface, psu.channels[0].voltage_level, etc. even when only one channel is present. So, you are recommending that we implement two non-interchangeable APIs within the same line of power supplies from the same manufacturer, just because some of the power supplies only have 1 channel and hence do not need a channels[] layer? And the same goes for your mainframe, as it appears that they have power supply cards with multiple channels. Is it really a good idea to completely reorganize the API for devices with more than 1 channel, just to remove one layer for devices that have only 1 channel?

@MatthieuDartiailh
Copy link
Contributor Author

I see your point. What kind of bothers me is that we will end up having that everywhere : for any instrument we will have to assume that one vendor created a multiple channels version even if we don't know about one yet (I got a two channel RF signal generator two weeks ago, while all my previous where single channel ones). I really need to think about that...

@alexforencich
Copy link
Member

That's a good point. I think it might make the most sense to implement the 'extra' layer when a device is commonly available as a multichannel device for consistency - things like power supplies and arbitrary waveform generators - and then implementing devices that are commonly single-channel as multichannel devices only when necessary for the particular series.

@MatthieuDartiailh
Copy link
Contributor Author

We could do a kind of hack by using getattr (which is called only if an attribute is nowhere to be found). What we would do would be to match the name against something like 'any character'[0]' and if we have a match we return self. This way we write flat instrument and if somebody needs to use in an indifferentiate fashion instruments with and without channel he can. WDYT ?

@alexforencich
Copy link
Member

I think that's a really bad idea, especially because it could mask typos that work on single channel units with the wildcard match but then fail on multichannel units that require a exact match. Also, weren't you opposed to overriding getattr earlier?

@MatthieuDartiailh
Copy link
Contributor Author

We could make the regex less permissive. I was opposed to use getattr for everything which is what you do in python-ivi as querying anything is slowed down . My idea is that people doing simple stuff at the command line or similar can bypass the abstract layer, if people want to stick to something closer to ivi they can use the abstract layer. And I can use the approach I was suggesting by first accessing the right object according to the driver and then use it in general purposes functions. @hgrecco could you comment on this issue I would really appreciate to have your opinion based on Lantz use.

@crazyfermions
Copy link

Even though I have an opinion about this implementation question I rather want to come back to the API design:

@MatthieuDartiailh Did I understand you correctly that you are okay to support multi-channel devices in the form of inst.channel[i].feature but also want a fallback shortcut which maps inst.feat to inst.channel[0].feat (or vice versa, but that is again implementation)?

To me, this sounds more like a feature to support legacy code after an API change while we now can actually decide on a new API. I could be okay with this, but I would actually never use it in a real program (because I do not want to artificially restrict myself to a single channel when its really just one layer of nesting) and I think it is too much effort just for a convenience function because you could just do
channel1 = inst1.channel[0]
channel2 = inst2.channel[0]
channel3 = inst3.channel[1]
...
and have no nesting clutter when working with the command line.

However, the advantage could be that we just make this an official behaviour and then we do not have to add this explicitly as a legacy function when we realize that there are multi-channel devices for an instrument class which we defined as single-channel and then indeed do have to change the API...

@MatthieuDartiailh
Copy link
Contributor Author

I will try to clarify my point of view, which might proves unpopular :

  • I see no strong need to have the same API for single and multichannel devices as for multichannel devices you need the channel id which is useless for instrument without channel. This is backed by the fact that we cannot hope to cover every single corner case (see BN100/BE2100/BE2300 discussion above), and explain why I prefer to implement the standard at a lower level than the instrument.
  • I think it is important to provide the users with a uniform API for systems providing the same functionalities and hence if an instr is a DC source and if a channel of another instrument is a DC source then both the first instrument and the channel of the second should present the same API with respect to the generation of DC voltage/current.
  • my previous proposal using getattr was a way to artificially add a notion of channel to an instrument that does not need one from my point of view but to be closer to IVI specs. Actually we could have a custom descriptor to avoid using getattr at all. I don't like the idea of systematic channel since as I pointed above about RF sources (and @alexforencich agreed on that) it could lead to fairly unnatural situations.

@crazyfermions
Copy link

As alex I certainly do see your point, I am just saying it is not the only point to consider.

  • It's inherently obvious that we can't cover every corner case, but that is actually not what we're discussing here; we are discussing a very widespread instrument feature and I think the BN100/... discussion is actually a very bad example because in my opinion it could be realized within the IVI specs without many quirks. It's more about the fact that if we decide to go down that road we have to be -- as you pointed out -- greedy about the presence of channels, and that could be indeed annoying (however the guys who did the IVI specs have already done quite a good job to cover most cases). Your idea how to solve this is interesting, but it also has disadvantages: If you forget about the physical device and just use a new driver instance for each channel: how do you want to treat instrument-wide commands, such as *RST? You would have either to sync between the different instances or not provide this functionality at all then. From the API point of view I would find it quite annoying that a method of one object affects an unknown number of other objects which are not visibly related to the object itself. (This could be okay as a last resort if you have a strange exotic device, but to make it the default behaviour for a widespread functionality...I don't know about this.) And keep in mind this could actually affect all the low level functionality of lantz too.
  • Totally agreed, but that is independent of whether we use channels or not.
  • Just to make things clear: I like the IVI specs, but I am totally fine with doing things differently. :-) Having two APIs with contradicting design ideas coexisting just to fulfill the wish of everyone involved in the discussion (thank god we are only three ;)) is the worst thing which can happen. We should definitely agree on one and only one way to go.

Maybe @alexforencich can comment on that too, because I am actually confused on what he agreed.

@MatthieuDartiailh
Copy link
Contributor Author

Actually in what I propose global commands would be available at the driver level and not the channel level, as they fulfill quite different purposes. @alexforencich agreed that requiring channels for RFSource would prove unnatural as it is very rare to have such a situation, but as it exists (I have one case) we should cover it. In general I think IVI standards match well simple instruments developed by main vendors but that a number of smaller vendors does not care at all.

I will try to underline my main use case as it influence strongly my point of view. I use instrument drivers as part of a large GUI application (https://github.com/MatthieuDartiailh/HQCMeas that I am reworking at https://github.com/Ecpy/ecpy). In that application, a user builds graphically a sequence of task to execute. If they select a multichannel instrument I need to update the GUI and ask them to select the channel they want to use. Hence it seems very natural to me to specialize code depending on whether or not there are multiple channels. On the other hand for complex operation I want to re-use as much code as possible so passing an object with a well determined interface is important too, but I don't care whether it is the root driver or not.

I really don't like the idea of greedy channels, but if everybody turns against me I will follow the tide.

@alexforencich
Copy link
Member

I like your idea for devices that are rarely multichannel (that oddball RF signal generator) where you add a 'channels' or 'outputs' layer when required. However, multichannel power supplies are not exactly a corner case; they are very common. So I think it makes sense to put it in by default, especially when you consider something like the E3600 series of power supplies from HP/Agilent/Keysight/??? that contains single output, dual output, and triple output power supplies, as well as things like mainframe power supplies that could contain one or more power supply modules.

@hgrecco
Copy link

hgrecco commented Jun 1, 2015

In general, I am with @crazyfermions on this. But I do agree with @MatthieuDartiailh (and supported by @alexforencich) that we should not provide a multichannel API for everything. I think that practicality beats purity here and while any feature might be multichannel a lot of them will not be. In general I think we need to aim to solve common situations, not every situation.

I did not quite get the suggestion about the hack by using __getattr__. But if I guess the idea is to make the too options live together. An option that I have seen is using a user selectable "default_channel" and a single access attribute. For example:

inst.voltage = 10 mV 

is equivalent to

inst.channel[inst.default_channel] = 10 mV

(And of course you can set default_channel)

From the user side, the API is simple but scales well.

@MatthieuDartiailh
Copy link
Contributor Author

I will refactor my drivers during the week to use always use channels. What should we name the channel ? I like outputs better than channel in that it is more explicit I think (the output feature would then be enabled).
What others think about the default channel idea ? @crazyfermions , @alexforencich
We could easily add a default attribute to the channel and an Alias descriptor to the main driver class in charge of using it (this addition would be automatic in the metaclass). The potential drawbacks I see are that it might crowd the main instrument namespace and kind of defeat the purpose of enforcing a kind of standard.

I think I am finally convinced by the practical approach... We will have to make things quite clear in the doccs.

@alexforencich
Copy link
Member

I think sticking to what IVI does makes a lot of sense - output[] for power supplies and function generators, channel[] for scopes, power meters, and frequency counters. This also nicely allows the scope and function generator classes to coexist in one driver (namely for the Agilent scopes with built-in generators).

@alexforencich
Copy link
Member

I'm not sure how useful the default channel idea is. It seems like you can just make a reference ref = instr.channel[index] and then use that instead of inserting another layer of indirection. Also, it could cause difficult to debug issues if some piece of code changes the setting unexpectedly. The SCPI commands for most power supplies work this way, and you either have to remember what you set the channel to or just make sure to always send the channel set command along with whatever setting you're changing to make sure the change always hits the right channel. I presume it was done this way to graft multichannel support onto a single-channel protocol while maintaining backwards compatibility.

@MatthieuDartiailh
Copy link
Contributor Author

I agree with you @alexforencich about the default channel. Anyway we could always insert that later if we find a real need for it. I will go with output it makes sense. For single output instr, any preferences about 0 or 1 as index ?
Thanks for the quick feedback.

@crazyfermions
Copy link

In my opinion, it should be 0. Pythonic and everything.

@MatthieuDartiailh
Copy link
Contributor Author

I am wondering because multichannels instrs are unlikely to index from 0 (is that true ?)

@hgrecco
Copy link

hgrecco commented Jun 1, 2015

The function of the default channel was not done to add multichannel support in a backwards compatible way but rather to avoid a more verbose API in the large variety of instruments in which is not needed.

@MatthieuDartiailh
Copy link
Contributor Author

Coming back to this after a long break. Trying again to find a common interface looking at the already mentioned instruments (yokogawa7651, yokogawags200, Bilt2100) and a new one previously mentioned by @alexforencich keysight E3631A (which we happen to have in the lab but that we do not really need to interface), I encountered a number of new issues that I would like to discuss. Following is the possible architecture for a DC source (still incomplete as some issues are still open) :

  • driver :
    • output : channel
      • voltage : Float
      • current : Float
      • voltage_range : Unicode
      • current_range : Unicode
      • over_voltage_behavior : Unicode
      • over_current_behavior : Unicode
      • enabled : Bool
      • measure : Action, optional

The issues addressed are the following :

  • all instruments have a range, it can be constant and I will add functionality to the core to declare a feature constant.
  • all instruments have a defined behavior if they cannot provide the expected output. I dropped the notion of OVP found in IVI as it matched no of the studied cases
  • this is very close to the IVI specs.

The open issues or points that need further discussions :

  • the meaning of voltage and current change for the yokogawa according to the selected mode. This makes the yokogawa behaves more like what IVI expects. It also means that a number of features will have to be tweaked to work, but it should be feasible.
    This is acceptable from my point of view as we cannot hope to reach any kind of standard without making some compromises. However it means we will have to document in details the working of the drivers.
  • the trigger issue, which is a big one. The yokogawa does not support triggering, the keysight and bilt does. The keysight use a dedicated command, the Bilt does not. My issue is the following :
    • IVI suggests a different name for the value to reach after the trigger, but using that means in combination with the cache that the value in the voltage feature does not reflect the reality and not even the actual setpoint after a trigger.
    • Using the same name, is possible (requires some manual tweaking of the features), then each channel needs a trigger subsystem (with mode, source, delay, initiate (on the keysight the trigger needs to be armed on the channel for the channel to handle the trig) for example). The mode corresponds to the Bilt notion that is to say whether to wait on a trigger or not and what to do when receiving one. To me the big advantage is that we store the requested set point in a single place and we can suggest to people to use measure when working with trig system to assert that everything is alright.

On top of that they are some minor things linked to some capabilities of the keysight (channel tracking, trigger channel locking) but that we can address with some manual tweaking I think.

Waiting for your comments @alexforencich , @crazyfermions , @hgrecco

@alexforencich
Copy link
Member

I need to support E3633A as well which supports OVP and OCP. I also have an E3649A which supports OVP, but not OCP. The E3631A does not support either OVP nor OCP. On the E3633A, for example, you can specify both a 'limit' and a 'protection trip' level for both the voltage and the current - 4 values in total - as well as enable/disable the voltage and current trip independently. In python-ivi, I added an OCP class that mirrored the IVI OVP class to properly support this. I think it will be necessary to do the same here.

@MatthieuDartiailh
Copy link
Contributor Author

Thanks for providing with a real example of OVP. I think that you are right and that having a voltage_protection subsystem and a current_protection subsystem for instrument supporting it makes sense.
Remains the issue of triggering .....

I will copy and update the previous hierarchy summary in the first post so that it is easier to track the state of the discussion.

@alexforencich
Copy link
Member

Yeah, triggering is a different animal. Actually, I have not used the triggering feature personally, and it is not implemented in python-ivi. To me, it rather seems unnecessary if you can just set a new output level directly over the remote interface, though I suppose there are some instances where triggering a new level is useful.

@alexforencich
Copy link
Member

Also, OVP and OCP don't have to be subsystems necessarily; mixins are sufficient. I'm not sure it really qualifies as being a subsystem. Although I suppose there isn't a whole lot of difference between output[].ovp_level and output[].ovp.level .

@MatthieuDartiailh
Copy link
Contributor Author

Look at my edited first post. I think it makes more sense to be subsystem as actually there is not only the level to consider. I am fine to use ovp, and ocp I will update my proposal.

@MatthieuDartiailh
Copy link
Contributor Author

Triggering can be interesting if you need synchronized updates or to control your experiment with pulses, but I agree that software trigger is not that useful.
Actually I think we should tackle this problem from a general point of view as it can appear in a number of instruments.

@alexforencich
Copy link
Member

Ah yeah, good point on the parameters. What would be the values for state for ovp/ocp? Would it make more sense to make it a boolean and call it tripped? The E3633A manual lists level, state (enable/disable), tripped (read only), and clear.

Also, it would be nice to have a 'mode' or 'status' parameter of some sort to see if the power supply is in voltage mode or current mode.

@MatthieuDartiailh
Copy link
Contributor Author

I referred to tripped actually, but I prefer status as I am worried of instrument doing something else than tripping.
I happy with mode which would be read-only on Keysight and settable on yokogawa.

@MatthieuDartiailh
Copy link
Contributor Author

I actually changed status -> read_status as this is similar to a measure for which we agreed we should use Action instead of Feature (because of the cache).

@MatthieuDartiailh
Copy link
Contributor Author

Actually mode will bite us because of the cache .... For Keysight it can change by itself and hence cannot be cached. On the yokogawa, it is a true setting and it would be weird to have a setter Action. As people were not happy with the idea of specifying whether a Feature should be cached or not we are trapped.

@MatthieuDartiailh
Copy link
Contributor Author

If the mode is not settable, simply measuring the output allows to determine the mode. It is perhaps not worth to implement for instrument in which it is not settable.

@MatthieuDartiailh
Copy link
Contributor Author

I added the keysight instruments you mentioned to the wiki page under your name.

@alexforencich
Copy link
Member

I still think implementing an output[].read_status action or similar would be a good idea. All of the supplies that I have used provide status bits that indicate if the output is in voltage mode, current mode, or unregulated. It would be nice to expose this.

@MatthieuDartiailh
Copy link
Contributor Author

Should it be part of the standard ? I am fine with implementing it for keysight but I would find this weird to have the same in a yokogawa.
Any opinion about the trigger discussion ?

This was referenced Oct 8, 2015
@MatthieuDartiailh
Copy link
Contributor Author

I am considering adding a is_output_tripped Action to the base class, as tripping is not the same as turning off (keysight E3633A goes back to its previous when reseting after a trip).
Does that make sense to you ?

@alexforencich
Copy link
Member

This will be different from output[].ovp/ocp.read_status somehow?

@alexforencich
Copy link
Member

The only thing that 'trips' on the E3600 series are the overvoltage/overcurrent protection - the standard current limit does not cause a 'trip' per se, it just limits the current to the programmed current limit. It would be a good idea to have a read_output_mode action, or similar, to report whether the output is currently in voltage or current mode.

@MatthieuDartiailh
Copy link
Contributor Author

I am actually concerned by tripping caused by connecting another source (ie a battery is the standard example found in the docs), that could go unnoticed because output is cached. So yes it would be different.
Doing some experiments with the Yokogawa (manuals are never as good as manual testing it seems), actually the 'protection' is closer to a simple regulation and hence does not requires a ovp/ocp subsystem (actually messes things up). I will go back again and change that.
I will implement a read_output_status to handle current type of regulation and potential accidental tripping. To the users to check that it makes sense (ie a yoko in voltage mode doing constant current is not what one would expect).
I will keep you posted but this is exhausting.

@MatthieuDartiailh
Copy link
Contributor Author

I made some progress on the yokogawas and the E3631A (not yet on E3633A but that should be quite quick). For the time being, I do not use the scpi commons much because I am not sure what can really be generalized. The blank files will be filled later. Feel free to comment (actually there are some questions as comments in the file on which I would appreciate an external opinion).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants