maz Posted October 28, 2010 Report Share Posted October 28, 2010 Hi everybody - Long time listener, first time caller. I'm in the initial stages of planning an object framework for control of RF test equipment. Most of the decisions are pretty simple, but there's one that I'm having a hard time figuring out how to code. I have a number of RF power sensors. You can't (well, you can, but we don't) communicate with them directly; they plug into another device (generally a power meter, but increasingly other devices support them). The power meters (let's generalize for now) have a variable number of ports for sensors. One or two is typical, but they go up to four. The tricky part is that in my code I'd like to reference the "input power sensor", but that sensor could be attached to any port on any meter. Approach one - power meter object and no power sensor object My sensors have to be statically assigned because I only have a handle to the meter. I always have to put "input power sensor" on "power meter 1:port 1". Or is there something I've missed? Approach two - no power meter object but power sensor objects Now "input power sensor" is dynamically assignable, but if a meter has multiple sensors, I now have multiple indirect handles to the meter, which creates a whole new set of problems: initialization? reset? meter specific commands that have nothing to do with sensors now look strange in the sensor class I could also create a meter class to handle the third problem, but I'm still not so crazy about this idea. The sensor should just point to a meter and a port. Approach three - power meter object and separate, not-inherited-from-the-same-base-class power sensor object Now I have a meter object that makes sense and a sensor object that I can refer to by name that points to that meter object. But how do I store this reference? I thought it would be easy to include a reference to the meter object in the sensor class, but I can't figure out how to do that. I'm sure I'm missing something trivial, so if someone could point me in the right direction, I'd be most appreciative. Thanks! Pete Quote Link to comment
MikaelH Posted October 28, 2010 Report Share Posted October 28, 2010 Hi Pete This is a common problem and I’ve seen many people going down the road of having one Power Meter object and then calling it like PowerMeter.GetPowerFromSnesor(1..n). I don’t like this approach because if you only start with only needing 4 sensor (assume that the Power Meter only have support for max 4 sensors), then your top application only needs to create One PowerMeter object. Then you suddenly needs another PowerSensor, then you have to create another PowerMeter Object and know which sensor ID and which PowerMeter every sensor is linked to. Instead I would go for the PowerSensor objects. Remember that the objects should reflect the reality, and it’s Power Sensors you are dealing with. If you need to have the knowledge of the PowerMeter I suggest that every time you create a PowerSensor object, just also creates a PowerMeter Object if needed and adds a reference to it. When I say needed, I would use named objects of the PowerMeter and if the PowerMeter this sensor is using has not been created yet they create it, and if it is already created then refer to the same object. Of cause this requires object by reference. This is how would have done it. PowerSensors.zip (LV 8.6, using GOOP3 object from GDS) Now I like someone to give me the solution to do this with ByValue objects. ( my reference objects ) Cheers, Mikael Quote Link to comment
Black Pearl Posted October 28, 2010 Report Share Posted October 28, 2010 (edited) You can make this by-val as well. What you need is a bi-directional association. So you need a container of Sensor and Power Meter in each class (somewhere you propably nee to use the parent clas + type cast). When you transform PowerMeter to Sensor, you just place the PowerMeter Obj in the Sensors property and then returen the Sensor, and the other way round. Edit: Search for 'Beagle State Machine' for this birlliant design. Felix Edited October 28, 2010 by Black Pearl Quote Link to comment
ShaunR Posted October 28, 2010 Report Share Posted October 28, 2010 Hi Pete This is a common problem and I’ve seen many people going down the road of having one Power Meter object and then calling it like PowerMeter.GetPowerFromSnesor(1..n). I don’t like this approach because if you only start with only needing 4 sensor (assume that the Power Meter only have support for max 4 sensors), then your top application only needs to create One PowerMeter object. Then you suddenly needs another PowerSensor, then you have to create another PowerMeter Object and know which sensor ID and which PowerMeter every sensor is linked to. Instead I would go for the PowerSensor objects. Remember that the objects should reflect the reality, and it’s Power Sensors you are dealing with. If you need to have the knowledge of the PowerMeter I suggest that every time you create a PowerSensor object, just also creates a PowerMeter Object if needed and adds a reference to it. When I say needed, I would use named objects of the PowerMeter and if the PowerMeter this sensor is using has not been created yet they create it, and if it is already created then refer to the same object. Of cause this requires object by reference. This is how would have done it. PowerSensors.zip (LV 8.6, using GOOP3 object from GDS) Now I like someone to give me the solution to do this with ByValue objects. ( my reference objects ) Cheers, Mikael Why go for one OR the other. Surely a "PowerMeter" contains a collection of "PowerSensors". (amongst other things ) So my "PowerMeter.GetPowerFromSensor(1..n)" would actually be "PowerMeter.GetPowerFromSensor(PowerSensor)". I would also say you would need a lot of knowledge about the power meter since you probably won't be able to talk to any sensors and it will be the device that contains range, scaling, math functions and probably calibration data (unless the cal is on-board the sensor). So you will need things like PowerMeter.SetRange, PowerMeter.SetSamples, PowerMeter.Calibrate etc, etc. So from my viewpoint, the sensor is just a value. The PowerMeter makes that value meaningful. And PowerMeter, Ammeter, Voltmeter are semantics. Quote Link to comment
Daklu Posted October 29, 2010 Report Share Posted October 29, 2010 Good question. Short answer: If you can't directly drop a PowerMeter object in the PowerSensor class, you probably already have a PowerSensor object in the PowerMeter class. LV can't allow circular dependencies like that. To solve your immediate problem drop a LVObject into the PowerSensor class and name it PowerMeter. In your getter downcast it to a PowerMeter object before returning it. Long answer: There are lots of ways to skin this cat. Since you're a little uncertain of which direction to go, I'd favor option 3. Keeping the two classes independent makes them more flexible and easier to maintain. I'm making a lot of assumptions about how the power meter and power sensor work, but I don't know anything about them. In particular, I'm assuming the power meter is a chassis that accepts plug in modules somewhat like a CRIO or CDAQ. First step is to write your PowerMeter and PowerSensor classes thinking about that device only. What can the power meter do regardless of what module is plugged into it? What can the power sensor do regardless of what device it is plugged in to? Don't write any methods in one class that references or uses methods from the other class. That removes your ability to reuse them independently in other apps. For example, at a minimum the power meter would include things like an address/handle for reading and writing to it. It might also contain an array of LVObjects for keeping track of module objects that are plugged into it as well as methods for storing and retrieving those objects. (If all modules that can be plugged into the device have a number of common functions you can create an abstract PowerMeterModule class with overridable methods, but it's not needed at the moment.) The PowerSensor class could have methods like Get PowerReading, Set Scale, etc. It shouldn't have a PortNumber field since the module doesn't know or care what port it is plugged into in the host device. BUT, it does need a host device if you want to communicate with it. So create an abstract Host class that will store the information needed to communicate with host device. It's hard to say what public overridable methods the Host class should have without knowing more about the specific host devices. The most flexible way to go about it is probably to have a SendCommand or similar method. Require child classes to override SendCommand. Use the SendCommand as a generic way to issue commands in your PowerSensor methods. To keep your code tidy, drop PowerMeter.lvclass (and PowerMeterModule.lvclass if you've created one) into PowerMeter.lvlib and drop PowerSensor.lvclass and Host.lvclass into PowerSensor.lvlib. These become part of your reuse library. Once you have two independent classes, the question is how do you get them to work together in your application? Well, do you want your application-level code to talk to the power meter or the power sensor? Either way will work. It depends on your goals. You indicated you want your app to refer to the power sensors, not the power meters, so with that in mind... In your application, create a subclass from PowerSensor:Host. I'll call it HostPowerMeter. Drop a PowerMeter object in HostPowerMeter's private data and create accessors for it. Override the SendCommand method. On the bd use the PowerMeter object's methods to communicate with the power meter. One important thing to note is that you need to set up a PowerMeter object in your application before adding it to the HostPowerMeter object. There are more details than what I've described, but this is the route I'd take. What you need is a bi-directional association. Not necessarily. The PowerSensor object doesn't need to know the details of what it's connected to. It just needs to be able to communicate with the actual power sensor device. I think it would be possible to abstract a Connection object instead of a Host object. The above design uses inheritance and the Host class to avoid direct bi-directional associations, though you could argue they are still present. (Since PowerSensor contains a HostPowerMeter object, which in turn contains a PowerMeter object.) Why go for one OR the other. Surely a "PowerMeter" contains a collection of "PowerSensors". (amongst other things ) Ahhh.... I need to release my LapDog Collections... So my "PowerMeter.GetPowerFromSensor(1..n)" would actually be "PowerMeter.GetPowerFromSensor(PowerSensor)". Except then the PowerMeter class is dependent on the PowerSensor class. You have to drag the PowerSensor code around every time you want to use the PowerMeter class. (Maybe a power meter without a power sensor is meaningless, in which case that would be okay. Otherwise I try to break up dependencies in potential reuse code.) And BTW, I thought you didn't like OOP... Quote Link to comment
ShaunR Posted October 29, 2010 Report Share Posted October 29, 2010 Except then the PowerMeter class is dependent on the PowerSensor class. You have to drag the PowerSensor code around every time you want to use the PowerMeter class. (Maybe a power meter without a power sensor is meaningless, in which case that would be okay. Otherwise I try to break up dependencies in potential reuse code.) Not really. The PowerMeter class has no dependencies its just a container used to manipulate the object you pass in to give the results context and meaning. PowerSensor Could Just as easily be an RTDSensor. You put it more eloquently than I in your previous paragraphs but basically we are thinking along the same lines. And BTW, I thought you didn't like OOP... LVOOP! My other language is DelphiHorses for courses. Quote Link to comment
maz Posted October 29, 2010 Author Report Share Posted October 29, 2010 Thanks for all the quick and detailed responses. After examining Mikael's code and watching the GOOP demo videos, I have now figured out how to do what I wanted. I knew there had to be a way to store a reference to an object, but because I've been using 8.5, I wasn't familiar with DVR. I was looking for a good enough reason to upgrade from 8.5, and I wasn't sure that cluster icons was enough, but DVR is... A better question is - did I have to worry about it? If I have a meter object created, and then wire it to the private data of several power sensor objects, do I still have only one meter object shared among all the sensors? I was under the impression that I would now have a bunch of copies of the original meter object each with its own private data. I've already generalized my Power Meter class to handle different models (and they don't accept anything but sensors), so I'm not sure I need to add an interface layer between the meter and the sensors. I'm also a little worried about making it too complicated for other people to work with. This should work, yes? I don't have to wire the output terminal of the IPE? And I'll still have only a single meter object instantiated? Thanks again for the help! Pete Quote Link to comment
Daklu Posted October 30, 2010 Report Share Posted October 30, 2010 I was looking for a good enough reason to upgrade from 8.5, and I wasn't sure that cluster icons was enough, but DVR is... The DVR is convenient, but the same thing can be accomplished with a SEQ. If you're LVOOPing then that's enough reason to upgrade from 8.5. Later versions seem to be more stable when classes are used. (Though in general 2010 seems to take a small step backwards.) A better question is - did I have to worry about it? If I have a meter object created, and then wire it to the private data of several power sensor objects, do I still have only one meter object shared among all the sensors? I was under the impression that I would now have a bunch of copies of the original meter object each with its own private data. Yes, if you branch the meter class wire it will create copies of the meter object at runtime. That may or may not matter--it depends on how you've built and how you're using your class. If your meter class doesn't contain any mutable state information (stuff that will change after it has been set initially) then it's no problem. All the copies contain the same information and will talk to the same device. I've already generalized my Power Meter class to handle different models (and they don't accept anything but sensors), so I'm not sure I need to add an interface layer between the meter and the sensors. I'm also a little worried about making it too complicated for other people to work with. Are you trying to create reusable code or is this all application-specific code? If it's app code, don't bother with the abstraction layer until you need it. If you're expecting to reuse this code later, take a step back and figure out what each object should be responsible for. For example (and these comments apply only if you want PowerSensor and PowerMeter to be reusable and extendable,) I see your PowerSensor class has a PortNumber field. From what I can tell ports are a property of the meter, not the sensor. The PowerSensor class is a convenient place to put the port number considering your current needs, but it's unwanted baggage in a reuse module. What if you use a different device that doesn't have port numbers? Maybe it uses strings or references to refer to each port. Port number has no meaning to a power sensor. Don't burden your reuse classes with things they don't care about. I also see you've hardcoded the PowerMeter class into the PowerSensor class. If reusability and extendability is your goal, then yes, I'd definitely put an abstraction layer in there. What happens if your manager decides he wants to communicate with a PowerSensor directly instead of through another device. Or maybe you get a new kind of device that accepts a PowerSensor. Are you going to add a new class to the PowerSensor private data for every device that the sensor can be plugged in to? And how are you going to decide which of those classes is the one you need to call in the ReadPower method you're showing? The power sensor isn't dependent on the power meter to function; don't make the PowerSensor class dependent on the PowerMeter class to function. This should work, yes? I don't have to wire the output terminal of the IPE? And I'll still have only a single meter object instantiated? As long as you haven't branched the PowerMeter class wire anywhere, you'll have only one PowerMeter object. (I have to admit that using a DVR seems largely unnecessary. I don't see what using a PowerMeter reference is gaining you here.) Quote Link to comment
MikaelH Posted October 30, 2010 Report Share Posted October 30, 2010 So you will need things like PowerMeter.SetRange, PowerMeter.SetSamples, PowerMeter.Calibrate etc, etc. So from my viewpoint, the sensor is just a value. The PowerMeter makes that value meaningful. And PowerMeter, Ammeter, Voltmeter are semantics. Sure the PowerMeter might be the brain in the system, but I would like to hide that from the user insdie the PowerSensor class. I don't want the user to have to know that the Range of the PowerMeter has to be change to make a PowerSensor reading. So when I call PowerSensor.GetPower(ThisRange), this object would know which PowerMeter it's connected to and what the current Range is, and change it if needed. Also If one PowerSensor dies, and we replace it with another PowerSensor, that might be a standalone sensor without a PowerMeter, or connected to another PowerMeter, I don't want the user to need to handle this. That's just how I would have solved it. Cheers, Mikael Quote Link to comment
maz Posted November 1, 2010 Author Report Share Posted November 1, 2010 Perhaps I should have presented my original question in a different way. Stepping back a little now... There exists a power meter class that includes all the commands required to operate meters and read sensors. It queries the equipment on initialization and then sends the appropriate commands for whichever piece is found. It is true that sensors are not always connected to meters. They can be connected to other equipment or directly to the PC via USB. We don't currently use these approaches, but it is not impossible in the future. I figured if I had to, I could create commands for those other types of devices in my power meter class, but that is seeming a bit clunky now. The meat of the application will be a sequence of commands that executes. I would like to use something like inputSensor.read and let the sensor and instrument classes take care of where said sensor is connected and how to read it. So I wanted a way to store both a meter and a port in a single structure that would reference the correct location of that sensor. Mikael has it exactly right, I want the user to not worry at all about how the sensor is connected. He just asks for the power at the input sensor and it is returned to him. There will be a configuration file that maps logical sensor names to physical locations, but the user won't need to know about it. It does appear that I need a more robust structure that will, at the very least, handle the different interfaces that a sensor might be connected to. A couple of questions, then: For academic purposes, let's say I want to create the structure I used in my previous post. I have a power meter object that I can access independently from the sensors, and I have multiple sensor objects that reference a single meter object. Daklu, you said that you thought that DVR was unnecessary. How do I do it without DVR? I couldn't figure out how to create a pointer (not a real pointer, I know) to that meter object in the sensor object.. SEQ? That's creating an unnamed queue and storing it's reference? I was originally envisioning this: Power meter class with functions to read power, set offsets, open windows, etc Power sensor class that simply held a reference to a meter object and the port that the sensor was connected to. Wrapper functions that call methods of the power meter class. Perhaps my structure should look something like this:Power meter class that handles meter related tasks - windows on the display, calibration... but not anything sensor related A sensor interface class that is roughly analogous to my original meter class without meter-specific functions. It will include an device address (or ref to an instrument object) and port. Since the commands will be interface dependent, they have to go here, right? In an earlier post, you talked about creating subclasses of this class for each type of interface. So for a sensor connected to a power meter, you'd have a power meter subclass with power meter object in its private data. Each subclass would have the specific commands necessary to communicate with that device. A power sensor class that has includes its own unique sensor interface object. Although it has functions to read power, set offsets, filtering, etc. they are simply wrappers for the appropriate interface class functions. A related question - I was going to code this so that there was a single "Power Meter" class with a number of methods. Each method would read the instrument type from private data and then send the appropriate command. How much do I gain from making the power meter class virtual each instrument it's own subclass? The host approach above requires it, but it seems like it might be better regardless... Thanks so much for all of your help. I'm sure your replies take as long as mine, and that's no small amount of time. Pete Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.