From a68555ec544b9ac43f10c9b76045d6160cc9aece Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:21:13 +0000 Subject: [PATCH 1/6] Initial plan From 5c613efd15ae0a01bee9ac83842eaae5749db594 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:23:11 +0000 Subject: [PATCH 2/6] Document MotorHat disposal/ownership model in README --- src/devices/MotorHat/README.md | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/devices/MotorHat/README.md b/src/devices/MotorHat/README.md index 6392d0de86..ee00273ea0 100644 --- a/src/devices/MotorHat/README.md +++ b/src/devices/MotorHat/README.md @@ -41,6 +41,55 @@ using (var motorHat = new MotorHat()) Check the [ServoMotor documentation](../ServoMotor/README.md) for examples on how to use the ServoMotor class +## Resource management (disposing) + +The `MotorHat` owns all the resources it creates. When you call `CreateDCMotor`, `CreateServoMotor` or `CreatePwmChannel`, the returned object uses PWM channels that belong to the `MotorHat`'s underlying PCA9685 controller. + +Because of this ownership model: + +- **Disposing the `MotorHat` is enough.** `MotorHat.Dispose()` stops every channel it handed out and then disposes the underlying PCA9685 (and its I2C device). You do not need to dispose the motors, servos or PWM channels separately. +- **Disposing a motor as well is safe.** Disposing a `DCMotor` created by `CreateDCMotor` only stops its PWM channels; it does not dispose them. Combined with the point above, disposing both the motor and the `MotorHat` will not throw or leave the board in a random state. +- **Order does not matter.** You can dispose the motors before or after the `MotorHat`; the result is the same. + +The recommended pattern is to keep the objects you need alive for as long as the `MotorHat` and let a single `using` (or `Dispose`) on the `MotorHat` clean everything up: + +```csharp +using (var motorHat = new MotorHat()) +{ + var motor = motorHat.CreateDCMotor(1); + + motor.Speed = 1; + + // ... use the motor ... + + // No need to dispose 'motor' explicitly; disposing 'motorHat' releases it. +} +``` + +If you wrap the `MotorHat` in your own class, forward disposal to the `MotorHat`. Disposing the individual motors as well is harmless but not required: + +```csharp +public class PumpController : IDisposable +{ + private MotorHat _motorHat = new MotorHat(); + private List _motors = new List(); + + public void Initialise() + { + _motors.Add(_motorHat.CreateDCMotor(1)); + } + + // ... use the motors ... + + public void Dispose() + { + // Disposing the MotorHat stops and releases every motor/channel it created. + // Order is not important and disposing the motors as well would be safe. + _motorHat.Dispose(); + } +} +``` + ## Support - Up to 4 DC Motors From 8af576da2d6d4f9393bb481852f330cc5ecf1534 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:23:40 +0000 Subject: [PATCH 3/6] Use American spelling 'Initialize' in README sample --- src/devices/MotorHat/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/MotorHat/README.md b/src/devices/MotorHat/README.md index ee00273ea0..1528e92ea7 100644 --- a/src/devices/MotorHat/README.md +++ b/src/devices/MotorHat/README.md @@ -74,7 +74,7 @@ public class PumpController : IDisposable private MotorHat _motorHat = new MotorHat(); private List _motors = new List(); - public void Initialise() + public void Initialize() { _motors.Add(_motorHat.CreateDCMotor(1)); } From 9bc2313fe7d700189a481e7f9162172d1c4b37fb Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Thu, 30 Jul 2026 17:38:10 +0200 Subject: [PATCH 4/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/devices/MotorHat/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/devices/MotorHat/README.md b/src/devices/MotorHat/README.md index 1528e92ea7..679f43a93d 100644 --- a/src/devices/MotorHat/README.md +++ b/src/devices/MotorHat/README.md @@ -48,8 +48,8 @@ The `MotorHat` owns all the resources it creates. When you call `CreateDCMotor`, Because of this ownership model: - **Disposing the `MotorHat` is enough.** `MotorHat.Dispose()` stops every channel it handed out and then disposes the underlying PCA9685 (and its I2C device). You do not need to dispose the motors, servos or PWM channels separately. -- **Disposing a motor as well is safe.** Disposing a `DCMotor` created by `CreateDCMotor` only stops its PWM channels; it does not dispose them. Combined with the point above, disposing both the motor and the `MotorHat` will not throw or leave the board in a random state. -- **Order does not matter.** You can dispose the motors before or after the `MotorHat`; the result is the same. +- **If you dispose motors explicitly, do it before disposing the `MotorHat`.** A `DCMotor` created by `CreateDCMotor` stops its PWM channels in `Dispose()`, and stopping a channel after the PCA9685 has been disposed can throw. +- **Dispose order matters when disposing both.** Prefer nested `using` (motor inside the `MotorHat` scope) so the motor is disposed first. The recommended pattern is to keep the objects you need alive for as long as the `MotorHat` and let a single `using` (or `Dispose`) on the `MotorHat` clean everything up: From dbdd54a2e7abb1030f49bf9408e60804035a8f1c Mon Sep 17 00:00:00 2001 From: Krzysztof Wicher Date: Thu, 30 Jul 2026 17:38:26 +0200 Subject: [PATCH 5/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/devices/MotorHat/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/devices/MotorHat/README.md b/src/devices/MotorHat/README.md index 679f43a93d..d64bcf75a3 100644 --- a/src/devices/MotorHat/README.md +++ b/src/devices/MotorHat/README.md @@ -84,8 +84,7 @@ public class PumpController : IDisposable public void Dispose() { // Disposing the MotorHat stops and releases every motor/channel it created. - // Order is not important and disposing the motors as well would be safe. - _motorHat.Dispose(); + // If you dispose motors explicitly, dispose them before disposing the MotorHat. } } ``` From 62716ec5050f4b91064a6734eb3423372f80e4f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:44:18 +0000 Subject: [PATCH 6/6] Update Dispose example to show motors-first disposal order --- src/devices/MotorHat/README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/devices/MotorHat/README.md b/src/devices/MotorHat/README.md index d64bcf75a3..34aae2fca8 100644 --- a/src/devices/MotorHat/README.md +++ b/src/devices/MotorHat/README.md @@ -83,8 +83,14 @@ public class PumpController : IDisposable public void Dispose() { - // Disposing the MotorHat stops and releases every motor/channel it created. - // If you dispose motors explicitly, dispose them before disposing the MotorHat. + // Dispose motors first (their Dispose stops the PWM channels), + // then dispose the MotorHat which releases the underlying PCA9685 + I2C device. + foreach (var motor in _motors) + { + motor.Dispose(); + } + + _motorHat.Dispose(); } } ```