Compare commits

...
5 Commits
17 changed files with 457 additions and 89 deletions
+1
View File
@@ -1,3 +1,4 @@
charger-gui/.vs/ charger-gui/.vs/
charger-gui/bin/ charger-gui/bin/
charger-gui/obj/ charger-gui/obj/
charger-gui/publish/
+29 -15
View File
@@ -36,31 +36,45 @@
<RowDefinition Height="30"/> <RowDefinition Height="30"/>
<RowDefinition Height="30"/> <RowDefinition Height="30"/>
<RowDefinition Height="30"/> <RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" FontSize="20" Text="I_acc"/> <TextBlock Grid.Row="0" Grid.Column="0" FontSize="20" Text="I_acc"/>
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="20" Text="{Binding Path=IAcc,Mode=OneWay,StringFormat=F4}" /> <TextBlock Grid.Row="0" Grid.Column="1" FontSize="20" Text="{Binding Path=IReal,Mode=OneWay,StringFormat=F4}" />
<TextBlock Grid.Row="1" Grid.Column="0" FontSize="20" Text="U1_acc"/> <TextBlock Grid.Row="1" Grid.Column="0" FontSize="20" Text="U_acc"/>
<TextBlock Grid.Row="1" Grid.Column="1" FontSize="20" Text="{Binding Path=U1Acc,Mode=OneWay,StringFormat=F4}" /> <TextBlock Grid.Row="1" Grid.Column="1" FontSize="20" Text="{Binding Path=UAcc,Mode=OneWay,StringFormat=F4}" />
<TextBlock Grid.Row="2" Grid.Column="0" FontSize="20" Text="U2_acc"/> <TextBlock Grid.Row="2" Grid.Column="0" FontSize="20" Text="I_raw"/>
<TextBlock Grid.Row="2" Grid.Column="1" FontSize="20" Text="{Binding Path=U2Acc,Mode=OneWay,StringFormat=F4}" /> <TextBlock Grid.Row="2" Grid.Column="1" FontSize="20" Text="{Binding Path=IRaw,Mode=OneWay,StringFormat=F4}" />
<TextBlock Grid.Row="3" Grid.Column="0" FontSize="20" Text="I_lamp"/> <TextBlock Grid.Row="3" Grid.Column="0" FontSize="20" Text="U2"/>
<TextBlock Grid.Row="3" Grid.Column="1" FontSize="20" Text="{Binding Path=ILamp,Mode=OneWay,StringFormat=F4}" /> <TextBlock Grid.Row="3" Grid.Column="1" FontSize="20" Text="{Binding Path=U2,Mode=OneWay,StringFormat=F4}" />
<TextBlock Grid.Row="4" Grid.Column="0" FontSize="20" Text="U1_lamp"/> <TextBlock Grid.Row="4" Grid.Column="0" FontSize="20" Text="U3"/>
<TextBlock Grid.Row="4" Grid.Column="1" FontSize="20" Text="{Binding Path=U1Lamp,Mode=OneWay,StringFormat=F4}" /> <TextBlock Grid.Row="4" Grid.Column="1" FontSize="20" Text="{Binding Path=U3,Mode=OneWay,StringFormat=F4}" />
<TextBlock Grid.Row="5" Grid.Column="0" FontSize="20" Text="U2_lamp"/> <TextBlock Grid.Row="5" Grid.Column="0" FontSize="20" Text="U4"/>
<TextBlock Grid.Row="5" Grid.Column="1" FontSize="20" Text="{Binding Path=U2Lamp,Mode=OneWay,StringFormat=F4}" /> <TextBlock Grid.Row="5" Grid.Column="1" FontSize="20" Text="{Binding Path=U4,Mode=OneWay,StringFormat=F4}" />
<TextBlock Grid.Row="6" Grid.Column="0" FontSize="20" Text="CHARGE"/> <TextBlock Grid.Row="6" Grid.Column="0" FontSize="20" Text="U5"/>
<Ellipse Grid.Row="6" Grid.Column="1" Width="20" Height="20" Fill="{Binding Path=ChargeStatus,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" /> <TextBlock Grid.Row="6" Grid.Column="1" FontSize="20" Text="{Binding Path=U5,Mode=OneWay,StringFormat=F4}" />
<TextBlock Grid.Row="7" Grid.Column="0" FontSize="20" Text="LAMP"/> <TextBlock Grid.Row="7" Grid.Column="0" FontSize="20" Text="CHARGE"/>
<Ellipse Grid.Row="7" Grid.Column="1" Width="20" Height="20" Fill="{Binding Path=LampStatus,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" /> <Ellipse Grid.Row="7" Grid.Column="1" Width="20" Height="20" Fill="{Binding Path=ChargeStatus,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="8" Grid.Column="0" FontSize="20" Text="LAMP"/>
<Ellipse Grid.Row="8" Grid.Column="1" Width="20" Height="20" Fill="{Binding Path=LampStatus,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />
</Grid> </Grid>
<StackPanel Grid.Row="1" Grid.Column="1"> <StackPanel Grid.Row="1" Grid.Column="1">
<TextBlock FontSize="24" Text="MANUAL"/>
<Button Content="Flip Lamp" Height="40" Click="LampButton_Click"/> <Button Content="Flip Lamp" Height="40" Click="LampButton_Click"/>
<Button Content="Flip Charge" Height="40" Click="FlipChargeButton_Click"/> <Button Content="Flip Charge" Height="40" Click="FlipChargeButton_Click"/>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="1" Grid.Column="2"> <StackPanel Grid.Row="1" Grid.Column="2">
<TextBlock FontSize="24" Text="AUTO"/>
<Button Content="Discharge" Height="40" Click="DischargeButton_Click"/> <Button Content="Discharge" Height="40" Click="DischargeButton_Click"/>
<Button Content="Сharge" Height="40" Click="ChargeButton_Click"/> <Button Content="Сharge" Height="40" Click="ChargeButton_Click"/>
<Button Content="Calibrate I" Height="40" Click="CalibrateButton_Click"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="3">
<TextBlock FontSize="24" Text="TRAIN"/>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="20" Text="Duration (s)" Height="40"/>
<TextBox Text="{Binding Path=TrainDuration}" FontSize="20" MinWidth="60"/>
</StackPanel>
<Button Content="GO" Height="40" Click="TrainButton_Click"/>
</StackPanel> </StackPanel>
<TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" Text="{Binding Path=OperationStatus,Mode=OneWay}" /> <TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" Text="{Binding Path=OperationStatus,Mode=OneWay}" />
</Grid> </Grid>
+25
View File
@@ -60,6 +60,16 @@ namespace charger_gui
model.IsCharging = !model.IsCharging; model.IsCharging = !model.IsCharging;
} }
private void CalibrateButton_Click(object sender, RoutedEventArgs e)
{
if (model.CurrentOperation != null)
{
model.CurrentOperation.Cancel();
}
model.CurrentOperation = new CalibrateOperation(log, model);
model.CurrentOperation.Start();
}
private void DischargeButton_Click(object sender, RoutedEventArgs e) private void DischargeButton_Click(object sender, RoutedEventArgs e)
{ {
if (model.CurrentOperation != null) if (model.CurrentOperation != null)
@@ -79,5 +89,20 @@ namespace charger_gui
model.CurrentOperation = new ChargeOperation(log, model); model.CurrentOperation = new ChargeOperation(log, model);
model.CurrentOperation.Start(); model.CurrentOperation.Start();
} }
private void TrainButton_Click(object sender, RoutedEventArgs e)
{
if (model.CurrentOperation != null)
{
model.CurrentOperation.Cancel();
}
model.CurrentOperation = new TrainOperation(log, model, model.TrainDuration);
model.CurrentOperation.Start();
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Environment.Exit(0);
}
} }
} }
+45 -37
View File
@@ -1,10 +1,7 @@
using charger_gui.operations; using charger_gui.operations;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.IO.Ports; using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Media; using System.Windows.Media;
namespace charger_gui namespace charger_gui
@@ -24,87 +21,93 @@ namespace charger_gui
} }
} }
private float iAcc; private float iRaw;
public float IAcc public float IRaw
{ {
get get
{ {
return iAcc; return iRaw;
} }
set set
{ {
iAcc = value; iRaw = value;
OnPropertyChanged("IAcc"); OnPropertyChanged("IRaw");
OnPropertyChanged("IReal");
}
}
public float IZero { get; internal set; }
public float IReal
{
get
{
return IRaw - IZero;
} }
} }
private float u1Acc; private float u2;
public float U1Acc public float U2
{ {
get get
{ {
return u1Acc; return u2;
} }
set set
{ {
u1Acc = value; u2 = value;
OnPropertyChanged("U1Acc"); OnPropertyChanged("U2");
} }
} }
private float u2Acc; private float u3;
public float U2Acc public float U3
{ {
get get
{ {
return u2Acc; return u3;
} }
set set
{ {
u2Acc = value; u3 = value;
OnPropertyChanged("U2Acc"); OnPropertyChanged("U3");
OnPropertyChanged("UAcc");
} }
} }
private float iLamp; private float u4;
public float ILamp public float U4
{ {
get get
{ {
return iLamp; return u4;
} }
set set
{ {
iLamp = value; u4 = value;
OnPropertyChanged("ILamp"); OnPropertyChanged("U4");
} }
} }
private float u1Lamp; private float u5;
public float U1Lamp public float U5
{ {
get get
{ {
return u1Lamp; return u5;
} }
set set
{ {
u1Lamp = value; u5 = value;
OnPropertyChanged("U1Lamp"); OnPropertyChanged("U5");
OnPropertyChanged("UAcc");
} }
} }
private float u2Lamp; public float UAcc
public float U2Lamp
{ {
get get
{ {
return u2Lamp; return U3 - U5;
}
set
{
u2Lamp = value;
OnPropertyChanged("U2Lamp");
} }
} }
@@ -190,7 +193,10 @@ namespace charger_gui
currentOperation.StatusChanged -= OnCurrentOperationStatusChanged; currentOperation.StatusChanged -= OnCurrentOperationStatusChanged;
} }
currentOperation = value; currentOperation = value;
currentOperation.StatusChanged += OnCurrentOperationStatusChanged; if (currentOperation != null)
{
currentOperation.StatusChanged += OnCurrentOperationStatusChanged;
}
OnPropertyChanged("OperationStatus"); OnPropertyChanged("OperationStatus");
} }
} }
@@ -209,6 +215,8 @@ namespace charger_gui
} }
} }
public int TrainDuration { get; set; }
private void FillPorts() private void FillPorts()
{ {
ports = new List<string>(SerialPort.GetPortNames()); ports = new List<string>(SerialPort.GetPortNames());
+73
View File
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- Параметры манифеста UAC
Если вы хотите изменить уровень контроля учетных записей Windows, замените узел
requestedExecutionLevel на один из следующих.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
При указании элемента requestedExecutionLevel будет отключена виртуализация файлов и реестра.
Удалите этот элемент, если виртуализация требуется приложению для обратной
совместимости.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
<applicationRequestMinimum>
<defaultAssemblyRequest permissionSetReference="Custom" />
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
</applicationRequestMinimum>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Список версий Windows, на которых это приложение было протестировано
и будет работать. Раскомментируйте соответствующие элементы, чтобы ОС Windows
автоматически выбрала наиболее совместимое окружение. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- Указывает, что приложение поддерживает определение DPI и не будет автоматически масштабироваться Windows при более высоких
значениях DPI. Приложения Windows Presentation Foundation (WPF) по умолчанию поддерживают определение DPI, им не нужно
специально включать параметр для этого. Для приложений Windows Forms на платформе .NET Framework 4.6, для которых задан этот параметр, необходимо
также задать для "EnableWindowsFormsHighDpiAutoResizing" значение "true" в файле app.config.
При этом приложение начинает учитывать длинные пути. Дополнительные сведения см. на странице https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation.-->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
-->
<!-- Включите темы для общих элементов управления и диалоговых окон Windows (Windows XP и более поздние версии) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>
+6 -7
View File
@@ -67,14 +67,13 @@ namespace charger_gui
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort); IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
while (!shouldRestart) while (!shouldRestart)
{ {
var r1 = master.ReadHoldingRegisters(SLAVE_ADDRESS, 0, 4); var r1 = master.ReadHoldingRegisters(SLAVE_ADDRESS, 0, 2);
model.IAcc = ToFloat(r1[0], r1[1]); model.IRaw = ToFloat(r1[0], r1[1]);
model.ILamp = ToFloat(r1[2], r1[3]);
var r2 = master.ReadHoldingRegisters(SLAVE_ADDRESS, 6, 8); var r2 = master.ReadHoldingRegisters(SLAVE_ADDRESS, 6, 8);
model.U1Acc = ToFloat(r2[0], r2[1]); model.U2 = ToFloat(r2[0], r2[1]);
model.U2Acc = ToFloat(r2[2], r2[3]); model.U3 = ToFloat(r2[2], r2[3]);
model.U1Lamp = ToFloat(r2[4], r2[5]); model.U4 = ToFloat(r2[4], r2[5]);
model.U2Lamp = ToFloat(r2[6], r2[7]); model.U5 = ToFloat(r2[6], r2[7]);
master.WriteSingleRegister(SLAVE_ADDRESS, CHARGE_REGISTER, (ushort)(model.IsCharging ? 1 : 0)); master.WriteSingleRegister(SLAVE_ADDRESS, CHARGE_REGISTER, (ushort)(model.IsCharging ? 1 : 0));
master.WriteSingleRegister(SLAVE_ADDRESS, LAMP_REGISTER, (ushort)(model.IsLampOn ? 1 : 0)); master.WriteSingleRegister(SLAVE_ADDRESS, LAMP_REGISTER, (ushort)(model.IsLampOn ? 1 : 0));
// ничего не упало, коннект есть значит // ничего не упало, коннект есть значит
+45
View File
@@ -13,6 +13,22 @@
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>W:\temp\charger-gui\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>4</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>false</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@@ -33,6 +49,24 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>BEEA544097F13D7DCC301EAB82DAD11595FA2626</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup>
<ManifestKeyFile>charger-gui_TemporaryKey.pfx</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<SignManifests>false</SignManifests>
</PropertyGroup>
<PropertyGroup>
<TargetZone>LocalIntranet</TargetZone>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="NModbus4, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="NModbus4, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\NModbus4.2.1.0\lib\net40\NModbus4.dll</HintPath> <HintPath>packages\NModbus4.2.1.0\lib\net40\NModbus4.dll</HintPath>
@@ -58,6 +92,8 @@
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="Logger.cs" /> <Compile Include="Logger.cs" />
<Compile Include="operations\AutomaticOperation.cs" /> <Compile Include="operations\AutomaticOperation.cs" />
<Compile Include="operations\CalibrateOperation.cs" />
<Compile Include="operations\TrainOperation.cs" />
<Compile Include="operations\ChargeOperation.cs" /> <Compile Include="operations\ChargeOperation.cs" />
<Compile Include="operations\DischargeOperation.cs" /> <Compile Include="operations\DischargeOperation.cs" />
<Compile Include="UpdateWorker.cs" /> <Compile Include="UpdateWorker.cs" />
@@ -93,11 +129,20 @@
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="charger-gui_TemporaryKey.pfx" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="Properties\app.manifest" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishUrlHistory>W:\temp\charger-gui\|C:\Work\charger\charger-gui\publish\</PublishUrlHistory>
<InstallUrlHistory />
<SupportUrlHistory />
<UpdateUrlHistory />
<BootstrapperUrlHistory />
<ErrorReportUrlHistory />
<FallbackCulture>ru-RU</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
</PropertyGroup>
<PropertyGroup>
<EnableSecurityDebugging>false</EnableSecurityDebugging>
</PropertyGroup>
</Project>
Binary file not shown.
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace charger_gui.operations
{
class CalibrateOperation : AutomaticOperation
{
const float SECONDS_TO_PASS = 10f;
private int passed;
private bool isComplete = false;
public override string Status
{
get
{
if (isComplete) return "Calibrating complete in " + passed + " seconds";
else return "Calibrating, passed " + passed + " seconds";
}
}
public CalibrateOperation(Logger log, MainWindowViewModel model) : base(log, model)
{
}
protected override void Work()
{
log.Log("Calibrating started");
var start = DateTime.Now;
model.IsCharging = false;
model.IsLampOn = false;
Thread.Sleep(500);
float sum = 0;
int cnt = 0;
while (passed < SECONDS_TO_PASS)
{
Thread.Sleep(20);
sum += model.IRaw;
cnt++;
passed = (int)((DateTime.Now - start).TotalSeconds);
OnStatusChanged();
}
model.IZero = sum / cnt;
log.Log("Calibrating complete in " + passed + " seconds");
model.IsLampOn = false;
isComplete = true;
OnStatusChanged();
}
}
}
+5 -4
View File
@@ -32,18 +32,19 @@ namespace charger_gui.operations
model.IsCharging = true; model.IsCharging = true;
model.IsLampOn = false; model.IsLampOn = false;
Thread.Sleep(500); Thread.Sleep(500);
while (model.U2Acc < MAX_VOLTAGE) while (model.UAcc < MAX_VOLTAGE)
{ {
Thread.Sleep(1000); Thread.Sleep(1000);
passed = (int)((DateTime.Now - start).TotalSeconds); passed = (int)((DateTime.Now - start).TotalSeconds);
OnStatusChanged(); OnStatusChanged();
log.Log("Charging " + passed + "s " + model.U2Acc.ToString("F4")); log.Log("Charging " + passed + "s " + model.UAcc.ToString("F4"));
if (model.U1Acc < 10f) if (model.U2 < 10f)
{ {
log.Log("Charging error: NO POWER. " + model.U1Acc.ToString("F4")); log.Log("Charging error: NO POWER. " + model.U2.ToString("F4"));
} }
} }
log.Log("Charging complete in " + passed + " seconds"); log.Log("Charging complete in " + passed + " seconds");
model.IsCharging = false;
isComplete = true; isComplete = true;
OnStatusChanged(); OnStatusChanged();
} }
+3 -2
View File
@@ -32,14 +32,15 @@ namespace charger_gui.operations
model.IsCharging = false; model.IsCharging = false;
model.IsLampOn = true; model.IsLampOn = true;
Thread.Sleep(500); Thread.Sleep(500);
while (model.U2Acc > MIN_VOLTAGE) while (model.UAcc > MIN_VOLTAGE)
{ {
Thread.Sleep(1000); Thread.Sleep(1000);
passed = (int)((DateTime.Now - start).TotalSeconds); passed = (int)((DateTime.Now - start).TotalSeconds);
OnStatusChanged(); OnStatusChanged();
log.Log("Discharging " + passed + "s " + model.U2Acc.ToString("F4")); log.Log("Discharging " + passed + "s " + model.U3.ToString("F4"));
} }
log.Log("Discharging complete in " + passed + " seconds"); log.Log("Discharging complete in " + passed + " seconds");
model.IsLampOn = false;
isComplete = true; isComplete = true;
OnStatusChanged(); OnStatusChanged();
} }
+63
View File
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace charger_gui.operations
{
class TrainOperation : AutomaticOperation
{
const float MAX_VOLTAGE = 14.5f;
private int passed;
private bool isComplete = false;
private int duration;
public override string Status
{
get
{
if (isComplete) return "Training complete in " + passed + " seconds";
else return "Training, passed " + passed + " seconds (of " + duration + ")";
}
}
public TrainOperation(Logger log, MainWindowViewModel model, int duration) : base(log, model)
{
this.duration = duration;
}
protected override void Work()
{
log.Log("Training started");
var start = DateTime.Now;
while (passed < duration)
{
model.IsCharging = true;
model.IsLampOn = false;
Thread.Sleep(1000);
model.IsCharging = false;
model.IsLampOn = false;
Thread.Sleep(50);
model.IsCharging = false;
model.IsLampOn = true;
Thread.Sleep(1000);
model.IsCharging = false;
model.IsLampOn = false;
Thread.Sleep(50);
passed = (int)((DateTime.Now - start).TotalSeconds);
OnStatusChanged();
log.Log("Training" + passed + "s " + model.UAcc.ToString("F4"));
if (model.U2 < 10f)
{
log.Log("Training error: NO POWER. " + model.U2.ToString("F4"));
}
}
log.Log("Training complete in " + passed + " seconds");
model.IsCharging = false;
model.IsLampOn = false;
isComplete = true;
OnStatusChanged();
}
}
}
BIN
View File
Binary file not shown.
+94 -24
View File
@@ -1,13 +1,69 @@
#include <ModbusRTU.h> #include <ModbusRTU.h>
class Reader
{
const static int AMOUNT = 20;
const static int FILTER_SIZE = 5;
int pin;
int reads[AMOUNT];
int current_read;
public:
Reader(int pin)
{
this->pin = pin;
current_read = 0;
for (int i = 0; i < AMOUNT; i++) reads[i] = 0;
}
void Read()
{
reads[current_read] = analogRead(pin);
current_read++;
if (current_read >= AMOUNT) current_read -= AMOUNT;
}
int sorted_reads[AMOUNT];
int Get()
{
for (int i = 0; i < AMOUNT; i++)
{
sorted_reads[i] = reads[i];
}
bool f = true;
while (f)
{
f = false;
for (int i = 0; i < AMOUNT - 1; i++)
{
if (sorted_reads[i] > sorted_reads[i + 1])
{
int t = sorted_reads[i];
sorted_reads[i] = sorted_reads[i + 1];
sorted_reads[i + 1] = t;
f = true;
}
}
}/*
float sum = 0;
int cnt = 0;
for (int i = FILTER_SIZE; i < AMOUNT - FILTER_SIZE; i++)
{
sum += reads[i];
cnt++;
}
return (int)(sum / cnt + 0.5);*/
return sorted_reads[AMOUNT / 2];
}
};
ModbusRTU mb; ModbusRTU mb;
#define MODBUS_ADDRESS 1 #define MODBUS_ADDRESS 1
#define I_ACC_LOW_REGISTER 0 #define I_ACC_LOW_REGISTER 0
#define I_ACC_HIGH_REGISTER 1 #define I_ACC_HIGH_REGISTER 1
#define I_LAMP_LOW_REGISTER 2
#define I_LAMP_HIGH_REGISTER 3
#define ACC_STATE_REGISTER 4 #define ACC_STATE_REGISTER 4
#define LAMP_STATE_REGISTER 5 #define LAMP_STATE_REGISTER 5
#define U_ACC_LOW_REGISTER 6 #define U_ACC_LOW_REGISTER 6
@@ -28,6 +84,7 @@ float R_lamp;
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
pinMode(A7, INPUT);
pinMode(A4, INPUT); pinMode(A4, INPUT);
pinMode(A5, INPUT); pinMode(A5, INPUT);
pinMode(A2, INPUT); pinMode(A2, INPUT);
@@ -39,8 +96,6 @@ void setup()
mb.slave(MODBUS_ADDRESS); mb.slave(MODBUS_ADDRESS);
mb.addHreg(I_ACC_LOW_REGISTER); mb.addHreg(I_ACC_LOW_REGISTER);
mb.addHreg(I_ACC_HIGH_REGISTER); mb.addHreg(I_ACC_HIGH_REGISTER);
mb.addHreg(I_LAMP_LOW_REGISTER);
mb.addHreg(I_LAMP_HIGH_REGISTER);
mb.addHreg(ACC_STATE_REGISTER); mb.addHreg(ACC_STATE_REGISTER);
mb.addHreg(LAMP_STATE_REGISTER); mb.addHreg(LAMP_STATE_REGISTER);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@@ -50,33 +105,43 @@ void setup()
} }
} }
float I_lamp; Reader R2(A2);
Reader R3(A3);
Reader R4(A4);
Reader R5(A5);
Reader R7(A7);
float I_acc; float I_acc;
float U1_lamp; float U4;
float U2_lamp; float U5;
float U1_acc; float U2;
float U2_acc; float U3;
void ReadLamp() void ReadLamp()
{ {
int a4 = analogRead(A4); int a4 = R4.Get();
int a5 = analogRead(A5); int a5 = R5.Get();
// multiply by 5 as reference current, // multiply by 5 as reference current,
// multiply by 3 because of the divider // multiply by 3 because of the divider
U1_lamp = a4 / 1023.0 * 5 * 3; U4 = a4 / 1023.0 * 5 * 3;
U2_lamp = a5 / 1023.0 * 5 * 3; U5 = a5 / 1023.0 * 5 * 3;
I_lamp = (U1_lamp - U2_lamp) / R_lamp;
} }
void ReadAcc() void ReadAcc()
{ {
int a2 = analogRead(A2); int a2 = R2.Get();
int a3 = analogRead(A3); int a3 = R3.Get();
// multiply by 5 as reference current, // multiply by 5 as reference current,
// multiply by 3 because of the divider // multiply by 3 because of the divider
U1_acc = a2 / 1023.0 * 5 * 3; U2 = a2 / 1023.0 * 5 * 3;
U2_acc = a3 / 1023.0 * 5 * 3; U3 = a3 / 1023.0 * 5 * 3;
I_acc = (U1_acc - U2_acc) / R_LIMITER; }
const float CURRENT_SENSOR_MAX = 5;
void ReadI()
{
I_acc = ((R7.Get() + 0.0) / 1023.0 - 0.5) * CURRENT_SENSOR_MAX;
} }
void WriteFloatReg(int start, float val) void WriteFloatReg(int start, float val)
@@ -91,14 +156,19 @@ uint16_t lamp_state = 0;
void loop() void loop()
{ {
R2.Read();
R3.Read();
R4.Read();
R5.Read();
R7.Read();
ReadLamp(); ReadLamp();
ReadAcc(); ReadAcc();
ReadI();
WriteFloatReg(I_ACC_LOW_REGISTER, I_acc); WriteFloatReg(I_ACC_LOW_REGISTER, I_acc);
WriteFloatReg(U_ACC_LOW_REGISTER, U1_acc); WriteFloatReg(U_ACC_LOW_REGISTER, U2);
WriteFloatReg(U_ACC_LOW_REGISTER + 2, U2_acc); WriteFloatReg(U_ACC_LOW_REGISTER + 2, U3);
WriteFloatReg(I_LAMP_LOW_REGISTER, I_lamp); WriteFloatReg(U_LAMP_LOW_REGISTER, U4);
WriteFloatReg(U_LAMP_LOW_REGISTER, U1_lamp); WriteFloatReg(U_LAMP_LOW_REGISTER + 2, U5);
WriteFloatReg(U_LAMP_LOW_REGISTER + 2, U2_lamp);
mb.task(); mb.task();
lamp_state = mb.Hreg(LAMP_STATE_REGISTER); lamp_state = mb.Hreg(LAMP_STATE_REGISTER);
acc_state = mb.Hreg(ACC_STATE_REGISTER); acc_state = mb.Hreg(ACC_STATE_REGISTER);
Binary file not shown.
Binary file not shown.