diff --git a/Hawkeye.VisionBuilder.UI.Sources.IDS/IDSImageSource.cs b/Hawkeye.VisionBuilder.UI.Sources.IDS/IDSImageSource.cs index 037f417..ec4a1b0 100644 --- a/Hawkeye.VisionBuilder.UI.Sources.IDS/IDSImageSource.cs +++ b/Hawkeye.VisionBuilder.UI.Sources.IDS/IDSImageSource.cs @@ -30,6 +30,7 @@ namespace Inspectron.Camera.UEye _camera = new uEye.Camera(); cameraIdx = _settings.CameraId; System.AppDomain.CurrentDomain.ProcessExit += AppDomain_ProcessExit; + } private void AppDomain_ProcessExit(object sender, EventArgs e) @@ -179,10 +180,10 @@ namespace Inspectron.Camera.UEye throw new Exception("failed to save Parameters"); } } - + public int LastAqTime { get; private set; } private void onFrameEvent(object sender, EventArgs e) { try @@ -191,13 +192,14 @@ namespace Inspectron.Camera.UEye int s32MemId; int active = (int)camera.Memory.GetActive(out s32MemId); int num1 = (int)camera.Memory.Lock(s32MemId); + var sw = System.Diagnostics.Stopwatch.StartNew(); var image = this.MemoryToImage(s32MemId); - int num2 = (int)camera.Memory.Unlock(s32MemId); + sw.Stop(); + LastAqTime = (int)sw.ElapsedMilliseconds; + - if (!_channel.Writer.TryWrite(image)) - { - Log.Warning("Image channel is full, dropping image"); - } + int num2 = (int)camera.Memory.Unlock(s32MemId); + _channel.Writer.TryWrite(image); } catch (TaskCanceledException ex) { @@ -206,9 +208,6 @@ namespace Inspectron.Camera.UEye } } - - - private Channel _channel = Channel.CreateBounded(new BoundedChannelOptions(1) { diff --git a/IDSTest/Program.cs b/IDSTest/Program.cs index 57ad58c..c768ffa 100644 --- a/IDSTest/Program.cs +++ b/IDSTest/Program.cs @@ -1,6 +1,6 @@ using Inspectron.Camera.UEye; -IDSImageSource imageSource = new IDSImageSource(); +IDSImageSource imageSource = new IDSImageSource(new IDSImageSourceSettings("camera"){CameraId = 1}); Console.WriteLine("Opening"); imageSource.InitializeModule(); @@ -8,6 +8,10 @@ imageSource.InitializeModule(); while (true) { Console.WriteLine("Getting image"); + var sw = System.Diagnostics.Stopwatch.StartNew(); var image=imageSource.GetImage(CancellationToken.None).Result; + sw.Stop(); + Console.WriteLine($"Got image in {sw.ElapsedMilliseconds} ms"); + Console.WriteLine("Last acquisition time: " + imageSource.LastAqTime); image.SaveImage("test.png"); } \ No newline at end of file diff --git a/Plugins/Siemens/B24SiemensPlugin/SiemensCameraModule.cs b/Plugins/Siemens/B24SiemensPlugin/SiemensCameraModule.cs index c87ae0d..e2fdef7 100644 --- a/Plugins/Siemens/B24SiemensPlugin/SiemensCameraModule.cs +++ b/Plugins/Siemens/B24SiemensPlugin/SiemensCameraModule.cs @@ -56,7 +56,31 @@ public class SiemensCameraModule: IVisionBuilderModule }, null); _statistics.Metadata = packet.Materialnummer.ToString(); } + Log.Information("Selected recipe {Recipe} for material number {MaterialNumber}", recipe, packet.Materialnummer); + } + //Log.Information("Lifebit: {Lifebit}, KameraStart: {KameraStart}", packet.Lifebit, packet.KameraStart); + //Log.Information("Camera running: {IsRunning}", _singleCameraVm.IsRunning); + //if (recipe != selectedRecipe?.RecipeName) + //{ + // if (packet.KameraStart && !_singleCameraVm.IsRunning) + // { + // Log.Information("Starting camera based on PLC packet."); + // _singleCameraVm.SynchronizationContext!.Post((o) => + // { + // _ = _singleCameraVm.Start(); + // }, null); + // } + // if (!packet.KameraStart && _singleCameraVm.IsRunning) + // { + // Log.Information("Stopping camera based on PLC packet."); + // _singleCameraVm.SynchronizationContext!.Post((o) => + // { + // _ = _singleCameraVm.Stop(); + // }, null); + // } + //} + return packet; diff --git a/VisionBuilder.UI.Common/Processing/BaseRecognitionControl.cs b/VisionBuilder.UI.Common/Processing/BaseRecognitionControl.cs index 0c34ec9..24c2d18 100644 --- a/VisionBuilder.UI.Common/Processing/BaseRecognitionControl.cs +++ b/VisionBuilder.UI.Common/Processing/BaseRecognitionControl.cs @@ -149,7 +149,8 @@ public abstract class BaseRecognitionControl: IRecognitionControl SessionEnded = DateTime.Now }); _loadingService.StopLoading($"Stopping {_settings.CameraName}"); - IsPaused = false; // ensure paused is reset + // note: recipe can be stared paused + //IsPaused = false; // ensure paused is reset } } @@ -157,6 +158,7 @@ public abstract class BaseRecognitionControl: IRecognitionControl { lock (_lock) { + Log.Information("Pausing recognition"); IsPaused = true; } } @@ -165,6 +167,7 @@ public abstract class BaseRecognitionControl: IRecognitionControl { lock (_lock) { + Log.Information("Resuming recognition"); IsPaused = false; } } diff --git a/VisionBuilder.UI.Common/ViewModel/SingleCameraVM.cs b/VisionBuilder.UI.Common/ViewModel/SingleCameraVM.cs index 09e0c05..9157da1 100644 --- a/VisionBuilder.UI.Common/ViewModel/SingleCameraVM.cs +++ b/VisionBuilder.UI.Common/ViewModel/SingleCameraVM.cs @@ -156,14 +156,14 @@ namespace VisionBuilder.UI.Common } - [RelayCommand(CanExecute = nameof(IsResumed))] + [RelayCommand] public void Pause() { _recognitionControl.Pause(); IsPaused = true; } - [RelayCommand(CanExecute = nameof(IsPaused))] + [RelayCommand] public void Resume() { _recognitionControl.Resume(); diff --git a/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs b/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs index 5c9df66..0902f88 100644 --- a/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs +++ b/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs @@ -30,23 +30,42 @@ public class IOCommanderModule:IVisionBuilderModule { _ioCommander = _factory.Create(); _ioCommander.OnPinChanged += OnPinChanged; + BroadcastInitialPinStates(); } catch (Exception e) { Log.Warning("IOCommander did non load: {e}",e); _ioCommander= null; } - + if (_settings.ShowDebugView)_debugViewService.ShowDebugView(); } + private void BroadcastInitialPinStates() + { + if (_ioCommander == null) return; + Task.Run(async () => + { + // Wait for the first poll cycle to populate PinState + for (int attempt = 0; attempt < 10 && _ioCommander?.PinState == null; attempt++) + { + await Task.Delay(200); + } + if (_ioCommander?.PinState == null) return; + for (int i = 0; i < _ioCommander.PinState.Length; i++) + { + OnPinChanged(i + 1, _ioCommander.PinState[i]); + } + }); + } + ConcurrentDictionary _pinStates = new ConcurrentDictionary(); public event Action? OnPinChangedEvent = delegate { }; private void OnPinChanged(int arg1, bool arg2) { - _pinStates.TryAdd(arg1, arg2); + _pinStates[arg1] = arg2; _debugViewService.SetInputPinStatus(arg1, arg2); OnPinChangedEvent?.Invoke(arg1, arg2); } diff --git a/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionControl.cs b/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionControl.cs index 090ebd2..01eeefb 100644 --- a/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionControl.cs +++ b/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionControl.cs @@ -75,6 +75,7 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe protected override (Mat originalImage, Mat analysisImage,TimeSpan processingTime, TimeSpan acquisitionTime, string[] errorNames)? ProcessImage(CancellationToken token) { + var sw = Stopwatch.StartNew(); _workflow.Context.CancellationToken = token; _workflow.ImageSource = _imageSource; @@ -105,7 +106,10 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe } string[] errorNames = _workflow.Operations.Where(x => !x.Result).Select(x => x.Label).ToArray(); - + if (_recognitionConfiguration.AlwaysError) + { + errorNames = errorNames.Concat(new[] { "Forced error" }).ToArray(); + } return (originalImage, analysisImage, sw.Elapsed, cameraTime, errorNames); } diff --git a/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionSettings.cs b/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionSettings.cs index 6ea8fd4..d2b4031 100644 --- a/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionSettings.cs +++ b/VisionBuilder.UI.Recipes.HawkeyeRecipe/HawkeyeRecognitionSettings.cs @@ -6,6 +6,11 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe; public class HawkeyeRecognitionSettings(string cameraName) : BaseRecognitionControlSettings(cameraName) { - - + public bool AlwaysError { get; set; } + + public override void RegisterSettings(InspectronSettings settings) + { + base.RegisterSettings(settings); + settings.RegisterSimple(this, () => AlwaysError, CameraName + "/" + "Recognition", nameof(AlwaysError)); + } } \ No newline at end of file diff --git a/VisionBuilder.UI.Windows.Duo/VisionBuilder.UI.Windows.Duo.csproj b/VisionBuilder.UI.Windows.Duo/VisionBuilder.UI.Windows.Duo.csproj index 0f53df7..9dd1ee4 100644 --- a/VisionBuilder.UI.Windows.Duo/VisionBuilder.UI.Windows.Duo.csproj +++ b/VisionBuilder.UI.Windows.Duo/VisionBuilder.UI.Windows.Duo.csproj @@ -8,7 +8,7 @@ enable Inspectron icon-512.ico false - 2.0.12 + 2.0.14 diff --git a/VisionBuilder.UI.Windows.Test/Program.cs b/VisionBuilder.UI.Windows.Test/Program.cs index 393b118..547ff7b 100644 --- a/VisionBuilder.UI.Windows.Test/Program.cs +++ b/VisionBuilder.UI.Windows.Test/Program.cs @@ -36,13 +36,10 @@ namespace VisionBuilder.UI.Windows.Test //AppDomain.CurrentDomain.FirstChanceException += (sender, e) => //{ - // if (e.Exception.Message.Contains("timed out")) - // { - // File.AppendAllText("timeout_log.txt", - // $"[{DateTime.Now:O}] {e.Exception.GetType().FullName}: {e.Exception.Message}\n" + - // $"{e.Exception.StackTrace}\n" + - // $"--- Inner: {e.Exception.InnerException}\n\n"); - // } + // File.AppendAllText("timeout_log.txt", + // $"[{DateTime.Now:O}] {e.Exception.GetType().FullName}: {e.Exception.Message}\n" + + // $"{e.Exception.StackTrace}\n" + + // $"--- Inner: {e.Exception.InnerException}\n\n"); //}; // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. diff --git a/VisionBuilder.UI.Windows.Test/VisionBuilder.UI.Windows.Uno.csproj b/VisionBuilder.UI.Windows.Test/VisionBuilder.UI.Windows.Uno.csproj index f29022b..b5053e4 100644 --- a/VisionBuilder.UI.Windows.Test/VisionBuilder.UI.Windows.Uno.csproj +++ b/VisionBuilder.UI.Windows.Test/VisionBuilder.UI.Windows.Uno.csproj @@ -8,7 +8,7 @@ enable Inspectron icon-512.ico false - 2.0.13 + 2.0.14