matlab/matlab-agentic-toolkit/matlab-modernize-daq

Claude Code and agent skill by matlab/matlab-agentic-toolkit

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Port MATLAB Data Acquisition Toolbox code from the discouraged (legacy) session-based interface (daq.createSession, addAnalogInputChannel, startBackground, DataAvailable listeners, queueOutputData, wait) to the recommended DataAcquisition interface (daq("ni"), addinput, start, ScansAvailableFcn, write, preload). Use when migrating legacy DAQ scripts, converting session-API calls, working with DataAcquisition objects, writing multi-feature DAQ scripts that combine triggers, callbacks, continuous acquisition, or analog output. Also use when a user says their DAQ script "used to work" or "errors on R20XX", since modernizing legacy session-API code is a frequent fix for those failures. Trigger keywords: daq, DAQ, NI, session interface, addtrigger, addclock, ScansAvailableFcn, ScansRequiredFcn, daq.createSession, addAnalogInputChannel, startBackground, queueOutputData, DataAvailable, evt.Data, evt.TimeStamps, wait(d), preload, discouraged, legacy, modernize, R2020a.

Install

npx vskill@latest install matlab/matlab-agentic-toolkit/matlab-modernize-daq

SKILL.md

Port DAQ Code to the Modern DataAcquisition Interface

Translate legacy session-based Data Acquisition Toolbox code (daq.createSession, addAnalogInputChannel, DataAvailable listeners, startBackground, queueOutputData, wait) to the modern DataAcquisition interface introduced in R2020a (daq("ni"), addinput, ScansAvailableFcn, start, write, preload). Also covers writing new multi-feature DAQ scripts where the modern API patterns are easy to get wrong under cognitive load.

When to Use

  • Porting an existing script that calls daq.createSession, addAnalogInputChannel, addAnalogOutputChannel, addCounterInputChannel, addCounterOutputChannel, or addDigitalChannel.
  • Replacing DataAvailable / DataRequired / ErrorOccurred listeners with ScansAvailableFcn / ScansRequiredFcn / ErrorOccurredFcn.
  • Replacing startBackground / startForeground / s.wait() lifecycle calls.
  • Replacing queueOutputData with preload + write.
  • Writing a new DAQ script that combines two or more of: external triggers, continuous acquisition, callback-driven streaming, analog output with refill, or cross-callback state.
  • Debugging errors like Undefined function 'wait' for input arguments of type 'daq.interfaces.DataAcquisition' or Unrecognized method, property, or field 'Data' for class 'matlabshared.asyncio.buffer.ElementsAvailableInfo'.

When NOT to Use

  • Single-channel foreground acquisition with no trigger and no callbacks (e.g. "acquire 1 s of voltage from ai0 at 10 kHz and plot"). The modern API is straightforward at this scale and this skill would be unnecessary overhead.
  • Picking a DAQ vendor or evaluating non-NI hardware. This skill's evidence base is NI.
  • Signal processing or analysis of already-acquired data (filtering, spectral analysis, etc.). This skill only covers acquiring and generating data through the DataAcquisition interface, not post-processing it.
  • Simulink, App Designer, or real-time-target DAQ workflows.
  • Modernizing matlab.unittest test suites or framework-style test classes (parameterized fixtures, assumeTrue gating, arity-contract tests, helper-class hierarchies). The API substitutions in this skill apply, but the test-harness scaffolding (parent-class stripping, fixture redesign, retiring tests that target removed contracts) is out of scope. Use this skill to translate the API calls inside test bodies, then make the harness-level judgment calls separately.

Workflow

When porting a session-based script or composing a new multi-feature DAQ script, follow this order. Verify after every step — most failure modes in this domain are silent.

  1. Inventory the legacy script (porting only). Identify: device(s), channel types, rate, continuous vs finite, trigger/clock connections, callbacks (DataAvailable/DataRequired/ErrorOccurred), state shared across callbacks, output queueing.
  1. Translate vocabulary. Map every session-API token to its modern counterpart. Consult `references/session-to-modern-mapping.md` — load it whenever a session-API token appears in the legacy script. Common silent-rename traps: NotifyWhenDataAvailableExceeds → ScansAvailableFcnCount, NumberOfScans/NumScans → implicit (no equivalent argument), ExternalTriggerTimeout → DigitalTriggerTimeout, IsContinuous=true → start(d, "Continuous") argument.
  1. Build the DataAcquisition object. d = daq("ni"), set d.Rate, add channels with addinput/addoutput. Apply per-channel properties via the channel handle returned by addinput/addoutput.
  1. Wire triggers and clocks. Use `references/canonical-snippets.md` §1 — load it when the script involves addtrigger or addclock. Argument order is (d, type, role, trigSrc, trigDest) — Source is 4th, Destination is 5th. Verify: the returned trigger object's Source and Destination fields show what you intended.
  1. Wire callbacks. Use canonical snippets §2 — load it when the script needs ScansAvailableFcn or ScansRequiredFcn. Inside the callback, always pull data via read(src, src.ScansAvailableFcnCount, "OutputFormat", "Matrix") — the evt argument is matlabshared.asyncio.buffer.ElementsAvailableInfo and exposes only NumElementsAvailable, no Data, no TimeStamps. Strongly recommend wiring d.ErrorOccurredFcn = @(~,evt) fprintf("DAQ error: %s\n", evt.Error.message) — without it, exceptions inside other callbacks are silently swallowed and the run "succeeds" while every fire throws. For strict ports where the legacy script had no ErrorOccurred listener, surface this trade-off to the user instead of silently adding the handler — let them opt in.
  1. Pick a state-sharing pattern (callbacks only). If a callback needs to maintain state across fires (running counters, phase accumulator, latch flags), see `references/callback-state-patterns.md` — load it any time a callback maintains state. Default: handle-class wrapper or nested function. Avoid src.UserData.X = src.UserData.X + ... field-mutation; it does not persist.
  1. Wire the lifecycle. Use canonical snippets §3 — load it when blocking on completion. There is no wait(d) method on the modern object. For finite acquisitions, prefer start(d, "Duration", seconds(N)) then read or a Running poll. For continuous, set a stop condition inside the callback (if scansRead >= target; stop(src); end) and poll d.Running from the caller.
  1. Run `verifyDataAcquisition` before live execution. Script: `scripts/verifyDataAcquisition.m`. Catches the four highest-frequency silent gaps (missing ErrorOccurredFcn, evt.Data in callback source, wait(d) token, UserData.X = UserData.X + ... field mutation) by inspecting the live object and grepping the source file. Run via mcp__matlab__run_matlab_file if available, or copy into the user's project.
  1. Live verification. Run a short version (e.g. 1–2 s instead of the user's full duration). Check that the script reaches start cleanly, that the callback fires at least once, and that no errors print from ErrorOccurredFcn. Use `mcp__matlab__run_matlab_file` against a saved `.m` file, not mcp__matlab__evaluate_matlab_code — the eval-string buffer runs in script mode and rejects local/nested function definitions, which Pattern 5 and most callback bodies require.

Key Functions

FunctionPurposeToolboxAvailable From
daqCreate a DataAcquisition object (d = daq("ni"))Data Acquisition ToolboxR2020a
addinputAdd input channel (analog, counter, or digital)Data Acquisition ToolboxR2020a
addoutputAdd output channelData Acquisition ToolboxR2020a
addtriggerAdd trigger connection: addtrigger(d, type, role, trigSrc, trigDest)Data Acquisition ToolboxR2020a
addclockAdd clock connection (similar signature)Data Acquisition ToolboxR2020a
readForeground acquire OR pull data inside ScansAvailableFcnData Acquisition ToolboxR2020a
writeWrite output samples (also from inside ScansRequiredFcn)Data Acquisition ToolboxR2020a
preloadLoad initial output buffer before start(d, "Continuous"). Output channels only.Data Acquisition ToolboxR2020a
startBegin background acquisition: start(d), start(d, "Continuous"), start(d, "Duration", seconds(N))Data Acquisition ToolboxR2020a
stopStop a running acquisitionData Acquisition ToolboxR2020a
flushDiscard buffered scans before readingData Acquisition ToolboxR2020a
daqlistEnumerate available devices (replaces daq.getDevices)Data Acquisition ToolboxR2020a
daqresetReset DAQ subsystem (replaces daq.reset)Data Acquisition ToolboxR2020a

Properties on DataAcquisition: Rate, Running, NumScansAcquired, NumScansOutputByHardware, ScansAvailableFcn, ScansAvailableFcnCount, ScansRequiredFcn, ScansRequiredFcnCount, ErrorOccurredFcn, DigitalTriggerTimeout, UserData.

Patterns

The five canonical patterns below appear in full, with verified code, in `references/canonical-snippets.md`. Inline below is the minimal recall snippet for each — enough to anchor the agent's memory under load. Load the reference for the full, runnable forms.

Pattern 1: Add an external start trigger
matlab
trg = addtrigger(d, "Digital", "StartTrigger", "External", "Dev1/PFI0");
trg.Condition = "RisingEdge";
d.DigitalTriggerTimeout = 30;

The 4th argument is the Source ("External" for an external signal). The 5th is the Destination (the device terminal). Reversing them is the most-frequent error in this domain. The trigger condition ("RisingEdge", "FallingEdge") is set on the trigger object returned by `addtrigger` (trg.Condition), not on the DataAcquisition object. There is no d.DigitalTriggerCondition property — inventing one passes static lint but errors at runtime.

Pattern 2: ScansAvailableFcn body — pull data via read, never evt.Data
matlab
d.ScansAvailableFcnCount = round(d.Rate * 0.5);
d.ScansAvailableFcn = @(src, ~) onBlock(src);
d.ErrorOccurredFcn = @(~, evt) fprintf("DAQ error: %s\n", evt.Error.message);
function onBlock(src)
[data, t] = read(src, src.ScansAvailableFcnCount, "OutputFormat", "Matrix");
plot(t, data); drawnow limitrate;
end

The evt argument carries only NumElementsAvailable; it has no Data or TimeStamps. Wiring ErrorOccurredFcn is strongly recommended — without it, callback exceptions are silently swallowed and the run "succeeds" while every fire throws. For strict ports of legacy scripts that did not have an ErrorOccurred listener, ask the user before adding one rather than inserting it silently.

Pattern 3: Block until acquisition completes — there is no wait(d)
matlab
start(d, "Duration", seconds(10));
while d.Running
pause(0.05);
end

wait(d) does not exist on daq.interfaces.DataAcquisition. Poll d.Running, or rely on start(d, "Duration", ...) + a stop condition inside the callback.

Pattern 4: Continuous AO playback with auto-refill
matlab
d = daq("ni");
d.Rate = 1000;
addoutput(d, "Dev1", "ao0", "Voltage");
d.ScansRequiredFcnCount = d.Rate;
d.ScansRequiredFcn = @(src, ~) write(src, generateNextBlock());
preload(d, generateNextBlock());
preload(d, generateNextBlock());
start(d, "Continuous");

preload is output-only — calling it on input-only setups errors. Two preloaded blocks before start give the buffer headroom for the first ScansRequiredFcn to fire.

Pattern 5: Cross-callback state via nested function or handle class
matlab
function runStreamingAcquisition()
d = daq("ni");
addinput(d, "Dev1", "ai0", "Voltage");
d.Rate = 1000;
d.ScansAvailableFcnCount = 200;
scansRead = 0;
target = d.Rate * 5;
d.ScansAvailableFcn = @(src, ~) onBlock(src);
d.ErrorOccurredFcn = @(~, evt) fprintf("DAQ error: %s\n", evt.Error.message);
start(d, "Continuous");
while d.Running
pause(0.05);
end
function onBlock(src)
data = read(src, src.ScansAvailableFcnCount, "OutputFormat", "Matrix");
scansRead = scansRead + size(data, 1);
if scansRead >= target
stop(src);
end
end
end

Nested function captures scansRead by reference, so updates persist across fires. Do not use src.UserData.X = src.UserData.X + ... — that pattern does not persist; counters reset every fire and closed-loop control silently outputs zero forever. Full alternatives (handle class, full UserData rewrite) and their tradeoffs are in `references/callback-state-patterns.md`.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
1,096
Repository forks
134
7-day trend score
35

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 23 Sep 2026, a month ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/matlab/matlab-agentic-toolkit/matlab-modernize-daq/badge)](https://verified-skill.com/skills/matlab/matlab-agentic-toolkit/matlab-modernize-daq)

Something wrong with this skill or its page? Tell us.