4.2.2 Simple Custom Trigger Streaming |
The C:\Program Files\RAYLASE\ProcessDataAnalyzer\API\SampleCode\SampleApplications\SimpleCustomTriggerStreaming demonstrates a simplified approach to implementing custom trigger-based trace saving. Unlike the more complex Custom Trigger Streaming example, this sample focuses on a single, specific trigger condition: detecting signal timing anomalies. It provides a clearer, more focused example of how to stream trace data and trigger trace saves programmatically.
This example is particularly useful for:
Understanding the basic streaming and triggering workflow
Detecting signal dropout or timing irregularities
Learning how to process frames efficiently in real-time
Implementing custom trigger logic with the Process Data Analyzer Client API
The SimpleCustomTriggerStreaming example implements a streamlined architecture:
Uses the Process Data Analyzer Client API for streaming and acquisition control
Monitors signal timing between consecutive samples
Triggers trace saves when timing threshold is exceeded
Processes frames asynchronously using channels for efficiency
Supports multiple control cards in parallel
The application uses a JSON configuration file to define trigger parameters:
{
"Cards": [
{
"ConnectionId": "SP310194",
"CardIP": "10.2.0.101",
"deltaTus": 100.0,
"FramesPerTrace": 50,
"FramesAfterTrigger": 3,
"TraceSavePath": "C:\\Traces"
}
]
}Configuration parameters:
ConnectionId: Serial number of the control card
CardIP: IP address of the control card
deltaTus: Maximum allowed time difference (µs) between consecutive signal samples. If exceeded, a trace save is triggered.
FramesPerTrace: Number of frames to capture before the trigger (pre-trigger buffer)
FramesAfterTrigger: Number of frames to skip after triggering to avoid multiple saves for the same event
TraceSavePath: Directory where trace files will be saved
The example implements a simple but effective trigger condition that detects timing anomalies:
// Check X signal timing if (hasX && lastXTimestamp.HasValue) { double timeDifference = currentTimestamp - lastXTimestamp.Value; if (timeDifference > _cardConfiguration.deltaTus) { return true; // Trigger condition met } } // Check Y signal timing if (hasY && lastYTimestamp.HasValue) { double timeDifference = currentTimestamp - lastYTimestamp.Value; if (timeDifference > _cardConfiguration.deltaTus) { return true; // Trigger condition met } }
The condition monitors the BuiltInSignal BisField0RxX and BisField0RxY signals. If the time gap between consecutive samples of either signal exceeds the configured threshold, the trigger fires and a trace save is requested.
The application uses a dual-task architecture for efficient processing:
Streaming Task: Continuously receives frames from the Process Data Analyzer server via gRPC streaming and writes them to a channel
Processing Task: Reads frames from the channel, checks trigger conditions, and calls TriggerTraceSave when conditions are met
This separation allows the streaming task to continuously receive data without blocking on condition checking, ensuring no frames are lost due to processing delays.
// Streaming task - receives frames using (var call = _api.Streaming.GetFrame(new API.GetFrameRequest() { DeviceId = _id, TimestampInTicks = false, })) { _api.Acquisition.Start(new API.AcquisitionStartRequest() { Card = _id }); while (await call.ResponseStream.MoveNext(token)) { var frame = call.ResponseStream.Current; _channelWriter.TryWrite(frame); // Pass to processing task } } // Processing task - checks conditions while (await _channelReader.WaitToReadAsync()) { while (_channelReader.TryRead(out var frame)) { if (CheckConditions(frame)) { _api.Streaming.TriggerTraceSave(new TriggerTraceSaveRequest() { DeviceId = _id }); } } }
The main program follows this workflow:
Load configuration from JSON file (card settings, trigger parameters)
Start the Process Data Analyzer server using the Client API
Load PDA configuration file and set card connection parameters
Create a CardStream instance for each configured card
Start streaming and processing threads for each card in parallel
Wait for user input to stop the application
Stop all streams and print statistics
The application supports monitoring multiple control cards simultaneously. Each card runs in its own thread with independent streaming and processing tasks. This allows for:
Parallel acquisition from multiple scan heads
Independent trigger conditions per card
Separate trace save paths for each card
Isolated error handling per card stream
To run the SimpleCustomTriggerStreaming application:
Create a Configuration.json file with your card settings and trigger parameters
Prepare a PDA configuration file (see PDA Configuration) with the appropriate card and signal settings
Run the application from the command line:
SimpleCustomTriggerStreaming.exe "path\to\Configuration.json" "path\to\PdaConfiguration.json"
Optional: Provide a custom path to ProcessDataAnalyzer.Service.exe as a third argument
Monitor console output for trigger events and statistics
Press any key to stop streaming and view final statistics
This simplified example differs from the full Custom Trigger Streaming sample in several ways:
Aspect | SimpleCustomTriggerStreaming | CustomTriggerStreaming |
|---|---|---|
Trigger Condition | Single: Signal timing anomaly | Multiple: Position, velocity, power, etc. |
Complexity | Simplified, focused example | Full-featured, production-ready |
Code Structure | 3 files, ~300 lines | Multiple files, extensive configuration |
Learning Curve | Easier to understand | More comprehensive but complex |
Use SimpleCustomTriggerStreaming as a starting point to understand the basic concepts, then refer to CustomTriggerStreaming for advanced features and production deployment patterns.
This example can be extended to implement more sophisticated trigger conditions:
Position-based triggering: Trigger when commanded vs. measured position difference exceeds a threshold
Velocity monitoring: Trigger on sudden velocity changes or overshoots
Power monitoring: Trigger when laser power deviates from expected values
Multi-signal correlation: Trigger based on relationships between multiple signals
Statistical analysis: Implement moving average or standard deviation checks
Adaptive thresholds: Adjust trigger parameters based on historical data