Best architecture choice for Simulink interface to LabJack DAQ?

11 ビュー (過去 30 日間)
Julian
Julian 2023 年 11 月 20 日
回答済み: Julian 2023 年 12 月 4 日
Hey folks,
I'm writing today with a sort of abstract, architecture-level question that I'm hoping to get your thoughts on. I am creating a Simulink interface "package" for a LabJack T-series DAQ (example) - awesome DAQs that I've used extensively over the years, and which have decent MATLAB support but no corresponding Simulink blockset. I have a number of colleagues who would like to use (or are already using) this DAQ in their work, and would like to do this through a Simulink interface - but don't have the ability to create the underlying infrastructure to do this. I'm relatively new to creating custom blocksets in Simulink, so before I dive in too deeply, I wanted to poll the community about what my best option for doing this is.
Objective: I'd like to make a blockset that can be quickly and easily used to bring data from sensors connected to a LabJack into Simulink. Ideally, the end user's experience is as simple as, "drag a block into a Simulink model, connect to a scope, hit run, see data".
Constraints:
  • I don't care about real-time operation, or even particularly fast operation - our systems are slow enough that 1 Hz data collection is fine for our purposes.
  • I am a relatively junior Simulink developer (...even though I'm the one taking on this project :-D). I've built custom MATLAB functions before in Simulink (and run them in Desktop Real-Time - I was never quite sure how I got that to work?), but I've never developed custom S-functions, and my C is pretty limited.
  • Very generically, the LabJack goes through the following operating "phases". My Simulink interface needs to perform all of these. The attached file thermistorTest.m shows these generic steps.
  • Startup: Connect to the LabJack (create a LabJack object); initialize the channels you want to work with.
  • Run: Request data from/send data to the channels you're working with
  • Shutdown: Close the LabJack object
Current State: I've created a very simple Simulink model that successfully reads a thermistor by doing the following.
  • Create a masked subsystem called Subsystem (I will fix this)
  • Within the mask for this subsystem, add initialization code that connects to the LabJack and configures the AIN0 channel to read a thermistor, using the MATLAB function I've already written called ljThermistorConfigure
  • Within Subsystem --> MATLAB Function1, call the external MATLAB function slx_eReadName to actually run the LabJack eReadName command. This is done to avoid having to declare a whole bunch of functions as extrinsic - I got the idea for this from this answer.
I've proven what I want to do is possible, and works (at least for now) at the rate I want. Now I need to make it generalizable!
Architecture Ideas: I currently have two ideas for how to architect this system
Idea 1: Custom, non-editable LabJack T7 block
  • The user creates some sort of file (CSV, JSON, .mat, whatever) that describes how their LabJack should be configured. This would include information like which channels are in use; how they should be configured; special register values for those channels (e.g. Steinhart-Hart coefficients for thermistors), etc.
  • Via a callback (not sure which one yet), the Simulink LabJack T7 block reads this configuration file, and uses the information in it to programatically define its outputs. For example, if your configuration file specified two analog inputs and one PWM output on channels AIN0, AIN1 and FIO0 respectively, after update the block would have 3 ports.
Idea 2: Editable LabJack T7 "supersystem" block with subsystem blocks for individual functions
  • To set up an experiment, the user first drags a LabJack T7 block into their model. This block takes care of the very basic setup steps for a LabJack - initializing the device object, defining the device handle, etc.
  • The user then goes under that block and adds blocks from a custom block library to define their specific experiment. So, for the example above, they'd drag in two AnalogInput blocks and one PWMOutput block. Each of these blocks takes care of the required configuration steps for that particular operation in its own initialization callback.
And that's where I am! I'd appreciate any and all suggestions, thoughts, critiques on this - I can see this is going to be a pretty extensive project, and I'd like to avoid rework as much as possible (although I know there's going to be a fair amount no matter what I do...) Thanks, all!

採用された回答

Julian
Julian 2023 年 12 月 4 日
First pass at the library is posted! Available on GitHub at:
For now, both the core code and the MLTBX are available in the repository. I'm going to post the MLTBX to File Exchange once I have a proper "release" ready - there are a few more things I'd like to add first. I'll update more here once that's done.

その他の回答 (1 件)

Julian
Julian 2023 年 12 月 1 日
Update on this question: I've decided to go with Idea 2, and - after some struggles with figuring out how to pass block parameters between different levels of nested masks, which I'll share more about here in the future - I've actually got it working pretty well! I can perform analog reads, digital reads, and digital writes; and I can connect to multiple LabJacks simultaneously! I'm going to make a first pass at a library and then post it to my Github - will share more soon.

カテゴリ

Help Center および File ExchangeMulticore Processor Targets についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by