-
Notifications
You must be signed in to change notification settings - Fork 4
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
Comments
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. |
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. |
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 2) Everything is now accessed as a method/attribute of the instrument 3) Access to lantz functionality 4) Access to *IDN? 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. |
I will try to answer all of your point :
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.
Thanks for your feedback and feel free to give more. |
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. |
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. |
Furthermore I don't have access to the be2141 manual so I don't even know how the internal channel is selected. |
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. |
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. |
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. |
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. |
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? |
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... |
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. |
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 ? |
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? |
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. |
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 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... |
I will try to clarify my point of view, which might proves unpopular :
|
As alex I certainly do see your point, I am just saying it is not the only point to consider.
Maybe @alexforencich can comment on that too, because I am actually confused on what he agreed. |
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. |
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. |
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
is equivalent to
(And of course you can set From the user side, the API is simple but scales well. |
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). I think I am finally convinced by the practical approach... We will have to make things quite clear in the doccs. |
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). |
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. |
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 ? |
In my opinion, it should be 0. Pythonic and everything. |
I am wondering because multichannels instrs are unlikely to index from 0 (is that true ?) |
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. |
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) :
The issues addressed are the following :
The open issues or points that need further discussions :
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 |
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. |
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. 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. |
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. |
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 . |
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. |
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. |
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. |
I referred to tripped actually, but I prefer status as I am worried of instrument doing something else than tripping. |
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). |
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. |
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. |
I added the keysight instruments you mentioned to the wiki page under your name. |
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. |
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. |
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). |
This will be different from output[].ovp/ocp.read_status somehow? |
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. |
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. |
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). |
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.
The text was updated successfully, but these errors were encountered: