forked from amkovkov/GranuSightSoftware2
218 lines
7.3 KiB
C#
218 lines
7.3 KiB
C#
using System.Device.Gpio;
|
|
using System.Device.Pwm;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace GSS2.Core.Hardware;
|
|
|
|
public class IlluminatorService : IDisposable
|
|
{
|
|
public class IlluminatorServiceConfiguration
|
|
{
|
|
public static IlluminatorServiceConfiguration Default => new IlluminatorServiceConfiguration
|
|
{
|
|
WhitePwmPin = 13,
|
|
Uv254PwmPin = 18,
|
|
Uv365PwmPin = 12,
|
|
WhiteRelayPin = 16,
|
|
Uv254RelayPin = 15,
|
|
Uv365RelayPin = 20,
|
|
FanPin = 21,
|
|
|
|
PwmFrequency = 200,
|
|
|
|
MaxWhitePwmDuty = 1.0,
|
|
MaxUv254PwmDuty = 1.0,
|
|
MaxUv365PwmDuty = 1.0
|
|
};
|
|
|
|
public int WhitePwmPin { get; set; }
|
|
public int Uv254PwmPin { get; set; }
|
|
public int Uv365PwmPin { get; set; }
|
|
public int WhiteRelayPin { get; set; }
|
|
public int Uv254RelayPin { get; set; }
|
|
public int Uv365RelayPin { get; set; }
|
|
public int FanPin { get; set; }
|
|
|
|
public int PwmFrequency { get; set; }
|
|
|
|
public double MaxWhitePwmDuty { get; set; }
|
|
public double MaxUv254PwmDuty { get; set; }
|
|
public double MaxUv365PwmDuty { get; set; }
|
|
}
|
|
|
|
private static readonly Dictionary<int, int> PinPwmChips = new()
|
|
{
|
|
{ 12, 0 },
|
|
{ 13, 0 },
|
|
{ 14, 0 },
|
|
{ 15, 0 },
|
|
{ 18, 0 },
|
|
{ 19, 0 },
|
|
};
|
|
private static readonly Dictionary<int, int> PinPwmChannels = new()
|
|
{
|
|
{ 12, 0 },
|
|
{ 13, 1 },
|
|
{ 14, 2 },
|
|
{ 15, 3 },
|
|
{ 18, 2 },
|
|
{ 19, 3 }
|
|
};
|
|
|
|
private bool _disposedValue;
|
|
private readonly ILogger<IlluminatorService> _logger;
|
|
private readonly IlluminatorServiceConfiguration _configuration;
|
|
|
|
private readonly GpioController _gpio;
|
|
private readonly PwmChannel _whitePwm;
|
|
private readonly PwmChannel _uv254Pwm;
|
|
private readonly PwmChannel _uv365Pwm;
|
|
private readonly GpioPin _whiteRelay;
|
|
private readonly GpioPin _uv254Relay;
|
|
private readonly GpioPin _uv365Relay;
|
|
private readonly GpioPin _fanRelay;
|
|
|
|
public IlluminatorService(ILogger<IlluminatorService> logger, IlluminatorServiceConfiguration? configuration = null)
|
|
{
|
|
_logger = logger;
|
|
|
|
_logger.LogInformation("Illuminator initialization");
|
|
|
|
if (configuration is null)
|
|
{
|
|
_logger.LogWarning("Illuminator configuration not set. Using default configuration.");
|
|
_configuration = IlluminatorServiceConfiguration.Default;
|
|
}
|
|
else
|
|
{
|
|
_configuration = configuration;
|
|
}
|
|
|
|
_logger.LogDebug(@$"Illuminator use following configuration:
|
|
WhitePwmPin: {_configuration.WhitePwmPin}
|
|
Uv254PwmPin: {_configuration.Uv254PwmPin}
|
|
Uv365PwmPin: {_configuration.Uv365PwmPin}
|
|
WhiteRelayPin: {_configuration.WhiteRelayPin}
|
|
Uv254RelayPin: {_configuration.Uv254RelayPin}
|
|
Uv365RelayPin: {_configuration.Uv365RelayPin}
|
|
FanPin: {_configuration.FanPin}
|
|
PwmFrequency: {_configuration.PwmFrequency}
|
|
MaxWhitePwmDuty: {_configuration.MaxWhitePwmDuty}
|
|
MaxUv254PwmDuty: {_configuration.MaxUv254PwmDuty}
|
|
MaxUv365PwmDuty: {_configuration.MaxUv365PwmDuty}
|
|
");
|
|
|
|
CheckPwmPin(_configuration.WhitePwmPin);
|
|
CheckPwmPin(_configuration.Uv254PwmPin);
|
|
CheckPwmPin(_configuration.Uv365PwmPin);
|
|
|
|
try
|
|
{
|
|
_gpio = new GpioController();
|
|
_whitePwm = PwmChannel.Create(PinPwmChips[_configuration.WhitePwmPin], PinPwmChannels[_configuration.WhitePwmPin], _configuration.PwmFrequency, CalculateDuty(0, _configuration.MaxWhitePwmDuty));
|
|
_uv254Pwm = PwmChannel.Create(PinPwmChips[_configuration.Uv254PwmPin], PinPwmChannels[_configuration.Uv254PwmPin], _configuration.PwmFrequency, CalculateDuty(0, _configuration.MaxUv254PwmDuty));
|
|
_uv365Pwm = PwmChannel.Create(PinPwmChips[_configuration.Uv365PwmPin], PinPwmChannels[_configuration.Uv365PwmPin], _configuration.PwmFrequency, CalculateDuty(0, _configuration.MaxUv365PwmDuty));
|
|
|
|
_whiteRelay = _gpio.OpenPin(_configuration.WhiteRelayPin, PinMode.Output, PinValue.Low);
|
|
_uv254Relay = _gpio.OpenPin(_configuration.Uv254RelayPin, PinMode.Output, PinValue.Low);
|
|
_uv365Relay = _gpio.OpenPin(_configuration.Uv365RelayPin, PinMode.Output, PinValue.Low);
|
|
_fanRelay = _gpio.OpenPin(_configuration.FanPin, PinMode.Output, PinValue.Low);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.LogCritical(e, "An exception occurred while illuminator initialization");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public void SetIntensity(double? white = null, double? uv365 = null, double? uv254 = null)
|
|
{
|
|
try
|
|
{
|
|
if (white is not null) _whitePwm.DutyCycle = CalculateDuty(white.Value, _configuration.MaxWhitePwmDuty);
|
|
if (uv365 is not null) _uv365Pwm.DutyCycle = CalculateDuty(uv365.Value, _configuration.MaxUv365PwmDuty);
|
|
if (uv254 is not null) _uv254Pwm.DutyCycle = CalculateDuty(uv254.Value, _configuration.MaxUv254PwmDuty);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.LogError(e, "An exception occurred while setting illuminator intensity");
|
|
}
|
|
}
|
|
public void TurnOn()
|
|
{
|
|
try
|
|
{
|
|
_fanRelay.Write(PinValue.High);
|
|
|
|
_whitePwm.Start();
|
|
_uv254Pwm.Start();
|
|
_uv365Pwm.Start();
|
|
|
|
_whiteRelay.Write(PinValue.High);
|
|
_uv254Relay.Write(PinValue.High);
|
|
_uv365Relay.Write(PinValue.High);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.LogError(e, "An exception occurred while turning on illuminator");
|
|
}
|
|
}
|
|
public void TurnOff()
|
|
{
|
|
try
|
|
{
|
|
_whitePwm.Stop();
|
|
_uv254Pwm.Stop();
|
|
_uv365Pwm.Stop();
|
|
|
|
_whiteRelay.Write(PinValue.Low);
|
|
_uv254Relay.Write(PinValue.Low);
|
|
_uv365Relay.Write(PinValue.Low);
|
|
|
|
_fanRelay.Write(PinValue.Low);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.LogError(e, "An exception occurred while turning off illuminator");
|
|
}
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!_disposedValue)
|
|
{
|
|
if (disposing)
|
|
{
|
|
try
|
|
{
|
|
TurnOff();
|
|
}
|
|
catch { }
|
|
|
|
_whiteRelay?.Dispose();
|
|
_uv254Relay?.Dispose();
|
|
_uv365Relay?.Dispose();
|
|
_fanRelay?.Dispose();
|
|
_whitePwm?.Dispose();
|
|
_uv254Pwm?.Dispose();
|
|
_uv365Pwm?.Dispose();
|
|
_gpio?.Dispose();
|
|
}
|
|
|
|
_disposedValue = true;
|
|
}
|
|
}
|
|
void IDisposable.Dispose()
|
|
{
|
|
Dispose(disposing: true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
private static void CheckPwmPin(int pin)
|
|
{
|
|
if (!PinPwmChips.TryGetValue(pin, out var _) || !PinPwmChannels.TryGetValue(pin, out var _))
|
|
throw new ArgumentException($"Unsupported PWM pin {pin}");
|
|
}
|
|
private static double CalculateDuty(double intensity, double maxDuty) => Math.Clamp(intensity, 0.0, 1.0) * Math.Clamp(maxDuty, 0.0, 1.0);
|
|
}
|