Browse Source

扫频100Hz以上有bug,低频已可以正常扫频
数据更新过快时会出现界面卡死的情况

l2736 3 months ago
parent
commit
c68ec00519

+ 11 - 9
Avalonia/ShakerApp/ViewModels/MainPage/SineMainPageViewModel.cs

@@ -20,7 +20,7 @@ namespace ShakerApp.ViewModels
         List<LineStyle> lineStyles = new List<LineStyle>() {LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.LongDashDotDot, LineStyle.LongDashDotDot };
         List<string> properties = new List<string>() {nameof(SweepData.Acceleration), nameof(SweepData.TargetAcceleration), nameof(SweepData.UpStopAcceleration), nameof(SweepData.DownStopAcceleration), nameof(SweepData.UpWarnAcceleration), nameof(SweepData.DownWarnAcceleration) };
         List<SweepData> datas = new List<SweepData>();
-
+        DateTime dateTime = DateTime.Now;
         OxyPlot.Annotations.ArrowAnnotation arrowAnnotation = new OxyPlot.Annotations.ArrowAnnotation();
         public AvaloniaList<LineSeries> LineSeries { get; } = new AvaloniaList<LineSeries>();
         private SineMainPageViewModel()
@@ -90,6 +90,8 @@ namespace ShakerApp.ViewModels
             {
                 CommunicationViewModel.Intance.LocalCommunication?.GetEvent<SineDataModel>().Subscrip((_, args) =>
                 {
+                    if ((DateTime.Now - dateTime).TotalMilliseconds <= 100) return;
+                    dateTime = DateTime.Now;
                     UpdateData(args.Data);
                 });
             });
@@ -129,20 +131,20 @@ namespace ShakerApp.ViewModels
                     SetRefSpectrum(SweepConfigViewModel.Instance.RefSpectrum);
                 }
                 UpDateModel(sine);
-                uint targetacc = (uint)sine.CurrentAcceleration * 1000_1000;
-
+                double targetacc = Shaker.Models.Tools.Tools.VoltageToQuantities(sine.CurrentAcceleration, ShakerConfigViewModel.Instance.AccelerationSensitivity) ;
+                uint currentfreq = (uint)(sine.CurrentFrequency * 1000_000);
                 int index = -1;
                 for (int i = 0; i < datas.Count; i++)
                 {
-                    uint tempacc = (uint)(datas[i].Acceleration * 1000_000);
-                    if (tempacc == targetacc)
+                    uint tempfreq = (uint)(datas[i].Frequency * 1000_000);
+                    if (tempfreq == currentfreq)
                     {
                         index = i;
-                        datas[i].Acceleration = sine.CurrentAcceleration;
+                        datas[i].Acceleration =targetacc;
                         UpPlot();
                         return;
                     }
-                    else if (tempacc > targetacc)
+                    else if (tempfreq > currentfreq)
                     {
                         if (i > 0)
                         {
@@ -157,7 +159,7 @@ namespace ShakerApp.ViewModels
                 SweepConfigViewModel.Instance.Model.CalcAmpt(sine.CurrentFrequency, ref value, ref upstop, ref upwarn, ref downstop, ref downwarn);
                 datas.Insert(index + 1, new SweepData()
                 {
-                    Acceleration = sine.CurrentAcceleration,
+                    Acceleration = targetacc,
                     Frequency = sine.CurrentFrequency,
                     TargetAcceleration = value,
                     UpStopAcceleration = upstop,
@@ -193,7 +195,7 @@ namespace ShakerApp.ViewModels
         [PropertyAssociation(nameof(SineDataModel.CurrentFrequency))]
         public double CurrentFrequency { get => Model.CurrentFrequency; set => SetProperty(ref Model.CurrentFrequency, value); }
         [PropertyAssociation(nameof(SineDataModel.CurrentAcceleration))]
-        public double CurrentAcceleration { get => Model.CurrentAcceleration; set => SetProperty(ref Model.CurrentAcceleration, value); }
+        public double CurrentAcceleration { get => Shaker.Models.Tools.Tools.VoltageToQuantities(Model.CurrentAcceleration, ShakerConfigViewModel.Instance.AccelerationSensitivity); set => SetProperty(ref Model.CurrentAcceleration, value); }
         [PropertyAssociation(nameof(SineDataModel.SweepDirection))]
         public SweepDirection SweepDirection { get => Model.SweepDirection; set => SetProperty(ref Model.SweepDirection, value); }
         [PropertyAssociation(nameof(SineDataModel.SweepStep))]

+ 1 - 0
Avalonia/ShakerApp/ViewModels/ShakerConfig/ShakerConfigViewModel.cs

@@ -66,6 +66,7 @@ namespace ShakerApp.ViewModels
         public AvaloniaList<IndexValueItemViewModel<AccelerationConfigViewModel>> Accelerations { get; } = new AvaloniaList<IndexValueItemViewModel<AccelerationConfigViewModel>>();
         [PropertyAssociation(nameof(ShakerConfigModel.DisplacementSensitivity))]
         public double DisplacementSensitivity { get => Model.DisplacementSensitivity; set => SetProperty(ref Model.DisplacementSensitivity, value); }
+        public double AccelerationSensitivity => Accelerations.First().Value.Model.Sensitivity;
         private ShakerConfigViewModel()
         {
             

+ 81 - 18
Calc/SIMDFxpConvert/SIMDFxpConverter.cs

@@ -2,7 +2,9 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Numerics;
 using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -19,14 +21,32 @@ namespace SIMDFxpConvert
             uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
             uint c = count / onecount;
             ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref value);
-            ulong* fxpptr = (ulong*)Unsafe.AsPointer(ref fxp);
+            Vector512<double> max = Vector512<double>.One * dxpinfo.Max;
+            Vector512<double> min = Vector512<double>.One * dxpinfo.Min;
+             ulong* fxpptr = (ulong*)Unsafe.AsPointer(ref fxp);
             for (int i = 0; i < c; i++)
             {
-                var temp = Unsafe.Add(ref source, i) * pow;
-                for (int j = 0; j < onecount; j++)
+                var temp = Unsafe.Add(ref source, i);
+                temp = Vector512.Max(min, temp);
+                temp = Vector512.Min(max, temp);
+                temp *= pow;
+
+                if (dxpinfo.isSigned)
+                {
+                    for (int j = 0; j < onecount; j++)
+                    {
+                        fxpptr[i * onecount + j] = dxpinfo.wordLength > 32 ? (((ulong)(long)temp[j]) << (64 - dxpinfo.wordLength)) : ((ulong)(long)temp[j]);
+                    }
+
+                }
+                else
                 {
-                    fxpptr[i * onecount + j] = (ulong)temp[j];
+                    for (int j = 0; j < onecount; j++)
+                    {
+                        fxpptr[i * onecount + j] = dxpinfo.wordLength > 32 ? (((ulong)temp[j]) << (64 - dxpinfo.wordLength)) : ((ulong)temp[j]);
+                    }
                 }
+
             }
             uint c1 = count % onecount;
             if (c1 != 0)
@@ -34,10 +54,19 @@ namespace SIMDFxpConvert
                 uint start = c * onecount;
                 for (uint i = 0; i < c1; i++)
                 {
-                    ref double temp = ref Unsafe.Add(ref value, start + i);
+                    double temp = Math.Clamp(Unsafe.Add(ref value, start + i),dxpinfo.Min,dxpinfo.Max);
+
+                    if (dxpinfo.isSigned)
+                    {
+                        ref long templ = ref Unsafe.As<ulong, long>(ref Unsafe.Add(ref fxp, start + i));
+                        templ = dxpinfo.wordLength > 32 ? (((long)(temp * pow)) << (64 - dxpinfo.wordLength)) : ((long)(temp * pow));
 
-                    ref ulong tempu = ref Unsafe.Add(ref fxp, start + i);
-                    tempu = (ulong)(temp * pow);
+                    }
+                    else
+                    {
+                        ref ulong tempu = ref Unsafe.Add(ref fxp, start + i);
+                        tempu = dxpinfo.wordLength > 32 ? (((ulong)(temp * pow)) << (64 - dxpinfo.wordLength)) : ((ulong)(temp * pow));
+                    }
                 }
             }
         }
@@ -49,13 +78,29 @@ namespace SIMDFxpConvert
             uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
             uint c = count / onecount;
             ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref value);
-            ulong* fxpptr = (ulong*)Unsafe.AsPointer(ref fxp);
+            ulong* fxpptr = (ulong*)Unsafe.AsPointer(ref fxp); 
+            Vector512<float> max = Vector512<float>.One * (float)dxpinfo.Max;
+            Vector512<float> min = Vector512<float>.One * (float)dxpinfo.Min;
             for (int i = 0; i < c; i++)
             {
-                var temp = Unsafe.Add(ref source, i) * pow;
-                for (int j = 0; j < onecount; j++)
+                var temp = Unsafe.Add(ref source, i);
+                temp = Vector512.Max(min, temp);
+                temp = Vector512.Min(max, temp);
+                temp *= pow;
+                if (dxpinfo.isSigned)
                 {
-                    fxpptr[i * onecount + j] = (ulong)temp[j];
+                    for (int j = 0; j < onecount; j++)
+                    {
+                        fxpptr[i * onecount + j] = dxpinfo.wordLength>32?(((ulong)(long)temp[j])<<(64-dxpinfo.wordLength)):  ((ulong)(long)temp[j]) ;
+                    }
+
+                }
+                else
+                {
+                    for (int j = 0; j < onecount; j++)
+                    {
+                        fxpptr[i * onecount + j] =dxpinfo.wordLength>32?(((ulong)temp[j])<<(64-dxpinfo.wordLength)) : ((ulong)temp[j]) ;
+                    }
                 }
             }
             uint c1 = count % onecount;
@@ -64,10 +109,18 @@ namespace SIMDFxpConvert
                 uint start = c * onecount;
                 for (uint i = 0; i < c1; i++)
                 {
-                    ref float temp = ref Unsafe.Add(ref value, start + i);
+                    float temp =Math.Clamp(Unsafe.Add(ref value, start + i),(float)dxpinfo.Min,(float)dxpinfo.Max);
+                    if (dxpinfo.isSigned)
+                    {
+                        ref long templ = ref Unsafe.As<ulong, long>(ref Unsafe.Add(ref fxp, start + i));
+                        templ = dxpinfo.wordLength>32?(((long)(temp * pow))<<(64-dxpinfo.wordLength)) : ((long)(temp * pow)) ;
 
-                    ref ulong tempu = ref Unsafe.Add(ref fxp, start + i);
-                    tempu = (ulong)(temp * pow);
+                    }
+                    else
+                    {
+                        ref ulong tempu = ref Unsafe.Add(ref fxp, start + i);
+                        tempu = dxpinfo.wordLength > 32 ? (((ulong)(temp * pow)) << (64 - dxpinfo.wordLength)) : ((ulong)(temp * pow)) ;
+                    }
                 }
             }
         }
@@ -84,7 +137,12 @@ namespace SIMDFxpConvert
                 {
                     ref double resultref = ref Unsafe.Add(ref value, i);
                     ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
-                    ulong tempdata = tempfxpref & mask;
+                    ulong tempdata = 0;
+                    if (dxpinfo.wordLength > 32)
+                    {
+                        tempdata = (tempfxpref >> (64 - dxpinfo.wordLength)) & mask;
+                    }
+                    else tempdata = tempfxpref & mask;
                     if ((tempdata & signedmask) != 0)
                     {
                         long signeddata = (long)(tempdata ^ mask);
@@ -100,7 +158,7 @@ namespace SIMDFxpConvert
                 {
                     ref double resultref = ref Unsafe.Add(ref value, i);
                     ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
-                    ulong tempdata = tempfxpref & mask;
+                    ulong tempdata = (dxpinfo.wordLength > 32 ? (tempfxpref >> (64 - dxpinfo.wordLength)) : tempfxpref) & mask;
                     resultref = delta * tempdata;
                 }
             }
@@ -118,7 +176,12 @@ namespace SIMDFxpConvert
                 {
                     ref float resultref = ref Unsafe.Add(ref value, i);
                     ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
-                    ulong tempdata = tempfxpref & mask;
+                    ulong tempdata = 0;
+                    if (dxpinfo.wordLength>32)
+                    {
+                        tempdata = (tempfxpref>>(64-dxpinfo.wordLength)) & mask;
+                    }
+                    else  tempdata = tempfxpref & mask;
                     if ((tempdata & signedmask) != 0)
                     {
                         long signeddata = (long)(tempdata ^ mask);
@@ -134,7 +197,7 @@ namespace SIMDFxpConvert
                 {
                     ref float resultref = ref Unsafe.Add(ref value, i);
                     ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
-                    ulong tempdata = tempfxpref & mask;
+                    ulong tempdata = (dxpinfo.wordLength>32?(tempfxpref>>(64-dxpinfo.wordLength)): tempfxpref) & mask;
                     resultref = delta * tempdata;
                 }
             }

+ 15 - 0
Communication/NetMQ/Core/IMsgSink.cs

@@ -0,0 +1,15 @@
+namespace NetMQ.Core
+{
+    /// <summary>
+    /// Interface IMsgSink mandates a PushMsg( Msg ) method.
+    /// </summary>
+    internal interface IMsgSink
+    {
+        /// <summary>
+        /// Deliver a message. Return true if successful; false otherwise.
+        /// This function takes ownership of the passed message.
+        /// </summary>
+        /// <param name="msg">the message (of type Msg) to deliver</param>
+        bool PushMsg(ref Msg msg);
+    }
+}

+ 17 - 0
Communication/NetMQ/Core/IMsgSource.cs

@@ -0,0 +1,17 @@
+namespace NetMQ.Core
+{
+    /// <summary>
+    /// Classes that implement IMsgSource are able to fetch a message, with the method: PullMsg.
+    /// </summary>
+    internal interface IMsgSource
+    {
+        /// <summary>
+        /// Fetch a message.
+        /// If successful - returns true and writes the message instance to the msg argument.
+        /// If not successful - return false and write null to the msg argument.
+        /// </summary>
+        /// <param name="msg">the Msg to write the fetched message into</param>
+        /// <returns>true if successful - and writes the message to the msg argument</returns>
+        bool PullMsg(ref Msg msg);
+    }
+}

+ 195 - 0
Communication/NetMQ/Core/Utils/Selector.cs

@@ -0,0 +1,195 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Net.Sockets;
+
+
+namespace NetMQ.Core.Utils
+{
+    /// <summary>
+    /// A SelectItem is a pairing of a (Socket or SocketBase) and a PollEvents value.
+    /// </summary>
+    internal sealed class SelectItem
+    {
+        public SelectItem(SocketBase socket, PollEvents @event)
+        {
+            Socket = socket;
+            Event = @event;
+        }
+
+        public SelectItem(Socket fileDescriptor, PollEvents @event)
+        {
+            FileDescriptor = fileDescriptor;
+            Event = @event;
+        }
+
+        public Socket FileDescriptor { get; private set; }
+
+        public SocketBase Socket { get; private set; }
+
+        public PollEvents Event { get; private set; }
+
+        public PollEvents ResultEvent { get; set; }
+    }
+
+    /// <summary>
+    /// A Selector holds three lists of Sockets - for read, write, and error,
+    /// and provides a Select method.
+    /// </summary>
+    internal sealed class Selector
+    {
+        private readonly List<Socket> m_checkRead = new List<Socket>();
+        private readonly List<Socket> m_checkWrite = new List<Socket>();
+        private readonly List<Socket> m_checkError = new List<Socket>();
+
+        /// <summary>
+        /// </summary>
+        /// <param name="items">  (must not be null)</param>
+        /// <param name="itemsCount"></param>
+        /// <param name="timeout">a time-out period, in milliseconds</param>
+        /// <returns></returns>
+        /// <exception cref="FaultException">The internal select operation failed.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="items"/> is <c>null</c>.</exception>
+        /// <exception cref="TerminatingException">The socket has been stopped.</exception>
+        public bool Select( SelectItem[] items, int itemsCount, long timeout)
+        {
+            if (items == null)
+                throw new ArgumentNullException("items");
+
+            if (itemsCount == 0)
+            {
+                return false;
+            }
+
+            bool firstPass = true;
+            int numberOfEvents = 0;
+
+            Stopwatch stopwatch = null;
+
+            while (true)
+            {
+                long currentTimeoutMicroSeconds;
+
+                if (firstPass)
+                {
+                    currentTimeoutMicroSeconds = 0;
+                }
+                else if (timeout < 0)
+                {
+                    // Consider everything below 0 to be infinite
+                    currentTimeoutMicroSeconds = -1;
+                }
+                else
+                {
+                    currentTimeoutMicroSeconds = (timeout - stopwatch.ElapsedMilliseconds) * 1000;
+
+                    if (currentTimeoutMicroSeconds < 0)
+                    {
+                        currentTimeoutMicroSeconds = 0;
+                    }
+                    else if (currentTimeoutMicroSeconds > int.MaxValue)
+                    {
+                        currentTimeoutMicroSeconds = int.MaxValue;
+                    }
+                }
+
+                m_checkRead.Clear();
+                m_checkWrite.Clear();
+                m_checkError.Clear();
+
+                for (int i = 0; i < itemsCount; i++)
+                {
+                    var pollItem = items[i];
+
+                    if (pollItem.Socket != null)
+                    {
+                        if (pollItem.Event != PollEvents.None && pollItem.Socket.Handle.Connected)
+                            m_checkRead.Add(pollItem.Socket.Handle);
+                    }
+                    else
+                    {
+                        if (pollItem.Event.HasIn())
+                            m_checkRead.Add(pollItem.FileDescriptor);
+
+                        if (pollItem.Event.HasOut())
+                            m_checkWrite.Add(pollItem.FileDescriptor);
+                    }
+                }
+
+                try
+                {
+                    SocketUtility.Select(m_checkRead, m_checkWrite, m_checkError, (int)currentTimeoutMicroSeconds);
+                }
+                catch (SocketException x)
+                {
+#if DEBUG
+                    string textOfListRead = StringLib.AsString(m_checkRead);
+                    string textOfListWrite = StringLib.AsString(m_checkWrite);
+                    string textOfListError = StringLib.AsString(m_checkError);
+                    string xMsg = string.Format("In Selector.Select, Socket.Select({0}, {1}, {2}, {3}) threw a SocketException: {4}", textOfListRead, textOfListWrite, textOfListError, currentTimeoutMicroSeconds, x.Message);
+                    Debug.WriteLine(xMsg);
+                    throw new FaultException(innerException: x, message: xMsg);
+#else
+                    throw new FaultException(innerException: x, message: "Within SocketUtility.Select");
+#endif
+                }
+
+                for (int i = 0; i < itemsCount; i++)
+                {
+                    var selectItem = items[i];
+
+                    selectItem.ResultEvent = PollEvents.None;
+
+                    if (selectItem.Socket != null)
+                    {
+                        var events = (PollEvents)selectItem.Socket.GetSocketOption(ZmqSocketOption.Events);
+
+                        if (selectItem.Event.HasIn() && events.HasIn())
+                            selectItem.ResultEvent |= PollEvents.PollIn;
+
+                        if (selectItem.Event.HasOut() && events.HasOut())
+                            selectItem.ResultEvent |= PollEvents.PollOut;
+                    }
+                    else
+                    {
+                        if (m_checkRead.Contains(selectItem.FileDescriptor))
+                            selectItem.ResultEvent |= PollEvents.PollIn;
+
+                        if (m_checkWrite.Contains(selectItem.FileDescriptor))
+                            selectItem.ResultEvent |= PollEvents.PollOut;
+                    }
+
+                    if (selectItem.ResultEvent != PollEvents.None)
+                        numberOfEvents++;
+                }
+
+                if (timeout == 0)
+                    break;
+
+                if (numberOfEvents > 0)
+                    break;
+
+                if (timeout < 0)
+                {
+                    if (firstPass)
+                        firstPass = false;
+
+                    continue;
+                }
+
+                if (firstPass)
+                {
+                    stopwatch = Stopwatch.StartNew();
+                    firstPass = false;
+                    continue;
+                }
+
+                // Check also equality as it might frequently occur on 1000Hz clock
+                if (stopwatch.ElapsedMilliseconds >= timeout)
+                    break;
+            }
+
+            return numberOfEvents > 0;
+        }
+    }
+}

+ 3 - 0
Shaker/Program.cs

@@ -1,5 +1,6 @@
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
 
 namespace ShakerService
 {
@@ -7,6 +8,8 @@ namespace ShakerService
     {
         static  void Main(string[] args)
         {
+            Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
+
 //#if DEBUG
 //            while (!Debugger.IsAttached)
 //            {

+ 1 - 0
Shaker/Service.RTInit.cs

@@ -16,6 +16,7 @@ namespace ShakerService
             ShakerFpga.Instance.ChangeZero.Value = false;
             ServiceShakerConfigViewModel.Instance.SetFpga();
             ServiceShakerControlViewModel.Instance.SetFpga();
+            ShakerFpga.Instance.AdjustmentCoefficient.Value = 1;
             ShakerFpga.Instance.Run();
             Log.Default.Info("初始化FPGA");
             RTInitFifo();

+ 0 - 1
Shaker/Service.cs

@@ -28,7 +28,6 @@ namespace ShakerService
                     x.GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
                     .FirstOrDefault(y => y.PropertyType == x)?.GetValue(null, null);
                 });
-
             InitControl();
         }
 

+ 14 - 13
Shaker/ShakerService.CalcDisplacement.cs

@@ -7,6 +7,7 @@ using System.Linq;
 using System.Linq.Expressions;
 using System.Text;
 using System.Threading.Tasks;
+using ShakerService.Tools;
 
 namespace ShakerService
 {
@@ -18,36 +19,36 @@ namespace ShakerService
         private void CalcDisplacement()
         {
             if (ViewModel.ServiceShakerControlViewModel.Instance.SweepControlItems.Count == 0) return;
-            _CycleCount++;
             double freq = ShakerFpga.Instance.CurrentFrequency.Value;
             var config = ViewModel.ServiceShakerControlViewModel.Instance.SweepControlItems.FirstOrDefault(x => freq <= x.Frequency)?.Model;
             config ??= ViewModel.ServiceShakerControlViewModel.Instance.SweepControlItems.Last().Model;
-            if (config.UpDateInvert<=1 || _CycleCount % config.UpDateInvert ==0)
+            if (config.UpDateInvert <= 1 || _CycleCount % config.UpDateInvert == 0)
             {
-                int freqindex = ViewModel.ServiceSweepConfigViewModel.Instance.Model.FindFrequencyIndex(freq);
-                var accv = Shaker.Models.Tools.Tools.QuantitiesToVoltage(ViewModel.ServiceSweepConfigViewModel.Instance.Model.CalcAmpt(freq),ViewModel.ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
-                if ((Shaker.Models.SweepStep)ShakerFpga.Instance.SweepStep.Value == Shaker.Models.SweepStep.SignalGen)
+                if (ShakerFpga.Instance.SweepStep.Value != (byte)SweepStep.SignalGen)
                 {
-                    CalcSynthesisAmplitude(freq);
-                    double ampt = ServiceSweepConfigViewModel.Instance.SweepData.CurrentAcceleration;
-                    CalcNextDisp(freq, accv, ampt, _RA_k, config, ref _D_k);
-                    ShakerFpga.Instance.GivenDisplacement.Value = _D_k;
+                    _D_k = ShakerFpga.Instance.CurrentGivenDispAmpt.Value;
+                    _RA_k = Shaker.Models.Tools.Tools.QuantitiesToVoltage(ServiceSweepConfigViewModel.Instance.Model.CalcAmpt(freq), ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
+
                 }
                 else
                 {
-                    _D_k = ShakerFpga.Instance.CurrentGivenDispAmpt.Value;
+                    var accv = Shaker.Models.Tools.Tools.QuantitiesToVoltage(ViewModel.ServiceSweepConfigViewModel.Instance.Model.CalcAmpt(freq), ViewModel.ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
+                    CalcSynthesisAmplitude(freq);
+                    CalcNextDisp(freq, accv, ServiceSweepConfigViewModel.Instance.SweepData.CurrentAcceleration, _RA_k, config, ref _D_k);
+                    ShakerFpga.Instance.GivenDisplacement.Value = _D_k;
+                    _RA_k = accv;
                 }
-                _RA_k = accv;
             }
+            _CycleCount++;
         }
         private void CalcNextDisp(double freq, double nextaccv, double a_k, double ra_k_1,SweepControlItemModel item,ref double d_k_1)
         {
             double mincorrect = freq >= ServiceSweepConfigViewModel.Instance.CrossoverPoint ? ServiceSweepConfigViewModel.Instance.HigthFrequencyMinCorrect : ServiceSweepConfigViewModel.Instance.LowFrequencyMinCorrect;
             double maxcorrect = freq >= ServiceSweepConfigViewModel.Instance.CrossoverPoint ? ServiceSweepConfigViewModel.Instance.HigthFrequencyMaxCorrect : ServiceSweepConfigViewModel.Instance.LowFrequencyMaxCorrect;
             var v1= Math.Pow(ra_k_1 / a_k, item.ExponentialCoefficients);
-            var factor = d_k_1 / nextaccv;
+            var factor = a_k / nextaccv;
             var changeratio = factor >= 1 ? ((item.CompressionRate + 1) / ((Math.Clamp(factor, 0.1f, 10f)) + item.CompressionRate)) : (((1 / (Math.Clamp(factor, 0.1f, 1))) + item.CompressionRate) / (item.CompressionRate + 1));
-            d_k_1= Math.Clamp(d_k_1 * v1, mincorrect, maxcorrect) * changeratio;
+            d_k_1= Math.Clamp(v1*d_k_1*changeratio, mincorrect*d_k_1, maxcorrect*d_k_1);
         }
 
     }

+ 2 - 5
Shaker/ShakerService.ReadConfig.cs

@@ -25,9 +25,7 @@ namespace ShakerService
                             ServiceSweepConfigViewModel.Instance.SweepData.CurrentFrequency = ShakerFpga.Instance.CurrentFrequency.Value;
                             CalcSynthesisAmplitude(ServiceSweepConfigViewModel.Instance.SweepData.CurrentFrequency);
                             CalcDowntime(ServiceSweepConfigViewModel.Instance.SweepData.CurrentFrequency);
-                            Console.WriteLine(ServiceSweepConfigViewModel.Instance.SweepData);
                             ServiceSweepConfigViewModel.Instance.SweepData.ReadFpgaData();
-                            Console.WriteLine(ServiceSweepConfigViewModel.Instance.SweepData.ToString());
                         }
                         break;
                     case Shaker.Models.MainPageType.StartPage:
@@ -45,7 +43,6 @@ namespace ShakerService
             Calc.FFT.FFT(real, img);
             double fftacc = Math.Sqrt(real[1] * real[1] + img[1] * img[1])/(real.Length/2);
             real = ShakerFpga.Instance.DisplacementData.Value;
-            Console.WriteLine(string.Join(',', real.Select(x => x.ToString())));
             img = new double[real.Length];
             Calc.FFT.FFT(real, img);
             double fftdisp =DispToAcc(Math.Sqrt(real[1] * real[1] + img[1] * img[1])/(real.Length/2),currentfreq);
@@ -55,11 +52,11 @@ namespace ShakerService
             {
                 ampt = fftdisp;
             }
-            else if(currentfreq<= ServiceSweepConfigViewModel.Instance.HighFreq)
+            else if(currentfreq<= ServiceSweepConfigViewModel.Instance.HighFreq && currentfreq>ServiceSweepConfigViewModel.Instance.LowFreq)
             {
                 double disp = ServiceShakerControlViewModel.Instance.SelfLoop ? identifydisp : identifyacc;
                 double v1 = (ServiceSweepConfigViewModel.Instance.HighFreq - currentfreq) / (ServiceSweepConfigViewModel.Instance.HighFreq - ServiceSweepConfigViewModel.Instance.LowFreq) * fftdisp;
-                double v2 = (ServiceSweepConfigViewModel.Instance.HighFreq - ServiceSweepConfigViewModel.Instance.LowFreq) / (currentfreq - ServiceSweepConfigViewModel.Instance.LowFreq) * disp;
+                double v2 = (currentfreq - ServiceSweepConfigViewModel.Instance.LowFreq) / (ServiceSweepConfigViewModel.Instance.HighFreq - ServiceSweepConfigViewModel.Instance.LowFreq) * disp;
                 ampt = v1 + v2;
             }
             else

+ 1 - 0
Shaker/ViewModel/ServiceShakerControlViewModel.cs

@@ -76,6 +76,7 @@ namespace ShakerService.ViewModel
                 ShakerFpga.Instance.DisplacementBias.Value = DisplacementBias;
                 ShakerFpga.Instance.DisplacementI.Value = DisplacementI / ServiceShakerConfigViewModel.Instance.SampleRate;
                 ShakerFpga.Instance.DisplacementP.Value = DisplacementP;
+                ShakerFpga.Instance.MaxDisplacementIntegral.Value = MaxDisplacementIntegral;
                 ShakerFpga.Instance.SelfLoop.Value = SelfLoop;
                 ShakerFpga.Instance.Debug.Value = Debug;
                 ShakerFpga.Instance.FlutterAmpt.Value = FlutterAmpt;

+ 5 - 0
Shaker/ViewModel/ServiceShakerStatusViewModel.cs

@@ -9,6 +9,7 @@ namespace ShakerService.ViewModel
 {
     internal class ServiceShakerStatusViewModel:BaseServiceViewModel<ShakerStatusModel>
     {
+        DateTime dateTime = DateTime.MinValue;
         private ServiceShakerStatusViewModel()
         {
 
@@ -19,6 +20,7 @@ namespace ShakerService.ViewModel
         }
         public void ReadFpgaData()
         {
+            _NeedSendData = false;
             RTStatus = (RTStatus)ShakerFpga.Instance.RTStatus.Value;
             var val = ShakerFpga.Instance.Rised.Value;
             if(val!=IsTableRised)
@@ -56,6 +58,9 @@ namespace ShakerService.ViewModel
             ZeroChangedCount = ShakerFpga.Instance.ZeroChangedIndex.Value;
             WarnCode = ShakerFpga.Instance.WarnCode.Value;
             ErrorCode = ShakerFpga.Instance.ErrorCode.Value;
+            if (!_NeedSendData) return;
+            //if ((DateTime.Now - dateTime).TotalMilliseconds < 20) return;
+            //dateTime = DateTime.Now;
             SendData();
         }
         public static ServiceShakerStatusViewModel Instance { get; } = new ServiceShakerStatusViewModel();

+ 3 - 0
Shaker/ViewModel/ServiceSineDataViewModel.cs

@@ -4,6 +4,7 @@ namespace ShakerService.ViewModel
 {
     internal class ServiceSineDataViewModel:BaseServiceViewModel<SineDataModel>,IData
     {
+        DateTime lastsendtime = DateTime.MinValue;
         public uint SweepIndex {get=>Model.SweepIndex; set=>SetProperty(ref Model.SweepIndex , value); }
         public double TotalTime { get => Model.TotalTime; set => SetProperty(ref Model.TotalTime, value); }
         public double RunTime { get => Model.RunTime; set => SetProperty(ref Model.RunTime, value); }
@@ -20,6 +21,8 @@ namespace ShakerService.ViewModel
             RunTime = ShakerFpga.Instance.FixedFrequencyTime.Value / (float)ServiceShakerConfigViewModel.Instance.SampleRate;
             SweepStep = (SweepStep)ShakerFpga.Instance.SweepStep.Value;
             SweepDirection = ShakerFpga.Instance.CurrentSweepDirection.Value ? SweepDirection.Down : SweepDirection.Up;
+            if ((DateTime.Now - lastsendtime).TotalMilliseconds < 20) return;
+            lastsendtime = DateTime.Now;
             SendData();
         }
         public override string ToString()