aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimeRuler.cs
blob: 552f8f416a1f9f15540edfacc511e0b8db9c054f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Tango.MachineStudio.Logging.Controls
{
    public class TimeRuler : Control
    {
        private double _smallStep;
        private double _bigStep;

        #region Private Methods

        private static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
        {
            // get parent item
            DependencyObject parentObject = VisualTreeHelper.GetParent(child);

            // we’ve reached the end of the tree
            if (parentObject == null) return null;

            // check if the parent matches the type we’re looking for
            T parent = parentObject as T;
            if (parent != null)
            {
                return parent;
            }
            else
            {
                // use recursion to proceed with next level
                return FindVisualParent<T>(parentObject);
            }
        }

        #endregion

        #region Properties

        public double RenderWidth
        {
            get { return (double)GetValue(RenderWidthProperty); }
            set { SetValue(RenderWidthProperty, value); }
        }
        public static readonly DependencyProperty RenderWidthProperty =
            DependencyProperty.Register("RenderWidth", typeof(double), typeof(TimeRuler), new FrameworkPropertyMetadata(400.0, FrameworkPropertyMetadataOptions.AffectsRender));

        public double HorizontalOffset
        {
            get { return (double)GetValue(HorizontalOffsetProperty); }
            set { SetValue(HorizontalOffsetProperty, value); }
        }
        public static readonly DependencyProperty HorizontalOffsetProperty =
            DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(TimeRuler), new PropertyMetadata(0.0, HorizontalOffsetChanged));

        private static void HorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as TimeRuler;
            control.Margin = new Thickness(-control.HorizontalOffset, 0, 0, 0);
            control.InvalidateVisual();
        }



        #region Zoom
        /// <summary>
        /// Gets or sets the zoom factor for the ruler. The default value is 1.0. 
        /// </summary>
        public double Zoom
        {
            get
            {
                return (double)GetValue(ZoomProperty);
            }
            set
            {
                SetValue(ZoomProperty, value);
                this.InvalidateVisual();
            }
        }

        private void SetSteps(double value)
        {
            if (value >= 50)
            {
                _smallStep = 0.25;
                _bigStep = 1;
            }
            else if (value >= 40)
            {
                _smallStep = 0.25;
                _bigStep = 2;
            }
            else if (value >= 30)
            {
                _smallStep = 0.5;
                _bigStep = 2;
            }
            else if (value >= 20)
            {
                _smallStep = 1;
                _bigStep = 5;
            }
            else if (value >= 10)
            {
                _smallStep = 1;
                _bigStep = 10;
            }
            else if (value >= 5)
            {
                _smallStep = 2;
                _bigStep = 20;
            }
            else if (value >= 3)
            {
                _smallStep = 5;
                _bigStep = 30;
            }
            else if (value >= 1)
            {
                _smallStep = 30;
                _bigStep = 300;
            }
            else if (value >= 0.5)
            {
                _smallStep = 60;
                _bigStep = 600;
            }
        }

        /// <summary>
        /// Identifies the Zoom dependency property.
        /// </summary>
        public static readonly DependencyProperty ZoomProperty =
            DependencyProperty.Register("Zoom", typeof(double), typeof(TimeRuler), new FrameworkPropertyMetadata((double)1.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomChanged)));

        private static void ZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as TimeRuler).SetSteps((double)e.NewValue);
        }


        #endregion

        #endregion

        #region Constructor

        public TimeRuler()
        {
            _smallStep = 1;
            _bigStep = 10;
            FontSize = 10;
            this.Loaded += TimeRuler_Loaded;
        }

        private void TimeRuler_Loaded(object sender, RoutedEventArgs e)
        {
            this.InvalidateVisual();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Participates in rendering operations.
        /// </summary>
        /// <param name="drawingContext">The drawing instructions for a specific element. This context is provided to the layout system.</param>
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);

            double xDest = RenderWidth;
            int start = (int)(HorizontalOffset / Zoom);

            drawingContext.DrawRectangle(Background, new Pen(BorderBrush, 0), new Rect(new Point(start * Zoom, 0.0), new Point(xDest + (start * Zoom) + 100, Height)));
            drawingContext.DrawLine(new Pen(BorderBrush, 1), new Point(start * Zoom, Height - 1), new Point(xDest + (start * Zoom) + 100, Height));


            double l = (start % _smallStep);
            while (l != 0) //I don't know why, but this is needed in order to prevent ruler from flickering on some lower scale factors :/
            {
                start += 1;
                l = (start % _smallStep);
            }

            for (double dUnit = start; dUnit < (RenderWidth / Zoom) + (start) + 10; dUnit += _smallStep)
            {
                double d = dUnit * (this.Zoom);

                double startHeight;
                double endHeight;

                startHeight = Height;
                endHeight = ((dUnit % _bigStep == 0) ? (this.ActualHeight / 5) * 1.5 : this.ActualHeight / 5);

                drawingContext.DrawLine(new Pen(Foreground, 1), new Point(d, startHeight), new Point(d, (startHeight - endHeight)));

                double uu = (dUnit % _bigStep);

                if ((dUnit != 0.0) && (uu == 0) && (dUnit < (RenderWidth / Zoom) + start + 10))
                {
                    double u = dUnit;
                    TimeSpan t = TimeSpan.FromSeconds((u));

                    FormattedText ft = new FormattedText(t.ToString("g"),
                            CultureInfo.CurrentCulture,
                            FlowDirection.LeftToRight,
                            new Typeface(FontFamily.ToString()),
                            FontSize,
                            Foreground);
                    ft.SetFontWeight(FontWeight);
                    ft.TextAlignment = TextAlignment.Center;
                    drawingContext.DrawText(ft, new Point(d, (Height / 2) - (ft.Height / 2) - 2));
                }
            }
        }

        #endregion
    }
}
/span>HARDWARE_MOTOR_TYPE__MOTO_WINDER,HARDWARE_MOTOR_TYPE__MOTO_SCREW}; HardwareDancerType ThreadMotorIdToDancerId[MAX_THREAD_MOTORS_NUM] = {FEEDER_DANCER,NUM_OF_DANCERS,POOLER_DANCER,WINDER_DANCER,NUM_OF_DANCERS}; uint32_t ControlIdtoMotorId [MAX_THREAD_MOTORS_NUM] = {0xFF,0xFF,0xFF,0xFF,0xFF}; uint32_t SpeedControlId=0xFF; uint32_t PoolerSpeedControlId=0xFF; double DancerError[NUM_OF_DANCERS] = {0.0}; double OriginalMotorSpd_2PPS[MAX_THREAD_MOTORS_NUM] = {0}; double InitialDryerSpeed = 0.0; uint32_t JobCounter = 0; MotorControlConfig_t MotorControlConfig[MAX_THREAD_MOTORS_NUM]; uint32_t DeviceId2Motor[MAX_THREAD_MOTORS_NUM]; uint32_t PreviousPosition = 0, CurrentPosition = 0; double CurrentRequestedLength = 0.0; double CurrentProcessedLength = 0.0; double TotalProcessedLength = 0.0; double LengthCalculationMultiplier; uint32_t PoolerPreviousPosition = 0, PoolerCurrentPosition = 0; double PoolerTotalProcessedLength = 0.0; double PoolerLengthCalculationMultiplier; double TempPoolerTotalProcessedLength = 0.0; double TempTotalProcessedLength = 0.0; bool InitialProcess = false; bool PrepareState = false; // job parameters bool EnableLubrication = false; bool EnableIntersegment = false; double IntersegmentLength = 0; bool Thread_Rockers_Bypass = false; int CurrentSegmentId = 0; typedef void (* ProcessedLengthFunc)(void); ProcessedLengthFunc ProcessedLengthFuncPtr = NULL; // segment/intersegment/distance to spool finished void ThreadSegmentEnded(void); void ThreadInterSegmentEnded(void); void ThreadDistanceToSpoolEnded(void); uint32_t ThreadControlCBFunction(uint32_t IfIndex, uint32_t ReadValue); bool SegmentState = false; bool PreSegmentState = false; bool DTSState = false; void SendSegmentFail(void); double KeepNormalizedError = 0; bool ThreadControlActive = false; ////////////////////////Slow Motor State//////////////////////////////////// //uint32_t ThreadPreSegmentState(void *JobDetails); //////////////////////////////////////////////////////////////////////////// /******************************************************************** * * Name : GTIME_Delta_Time_Pass * * Parameters : start_time. * * Return : time pass from start time * * Description : * *********************************************************************/ uint32_t Control_Delta_Position_Pass(uint32_t Current_Read,uint32_t Previous_Read) { uint32_t Time_Pass; // #define MAX_COUNTER 0x3FFF //14 bits #define MAX_COUNTER 0x3FFFFF //22 bits if (Current_Read < Previous_Read) { Time_Pass = (MAX_COUNTER - Previous_Read) + Current_Read + 1; ReportWithPackageFilter(ThreadFilter,"Length rollover",__FILE__,Time_Pass,(int)Current_Read,RpWarning,(int)Previous_Read,0); } else Time_Pass = Current_Read - Previous_Read; return (Time_Pass); } /***************************************************************************************** * * * * * * * **************************************************************************************/ uint32_t initialpos = 0xFFFF; uint32_t Poolerinitialpos = 0xFFFF; void ThreadUpdateProcessLength (double length, void *Funcptr) { REPORT_MSG(length,"ThreadUpdateProcessLength"); CurrentRequestedLength = length*100;//Centimetres CurrentProcessedLength = 0; ProcessedLengthFuncPtr = (ProcessedLengthFunc)Funcptr; } char Lenstr[160]; uint32_t ThreadLengthCBFunction(uint32_t IfIndex, uint32_t ReadValue) { uint32_t positionDiff = 0,prevprev; double length = 0.0; int index = MAX_THREAD_MOTORS_NUM; #ifndef FEEDER_LENGTH_CALCULATION if (ThreadControlActive == false) return OK; if (PrepareState == true) return OK; #endif if (IfIndex>>8 != IfTypeThread) { ReportWithPackageFilter(ThreadFilter,"Wrong Interface type",__FILE__,__LINE__,(int)IfIndex,RpError,(int)PoolerTotalProcessedLength,0); return 0xFFFFFFFF; } index = IfIndex&0xFF; // if (CurrentRequestedLength == 0.0) // return OK; if (index != FEEDER_MOTOR) { ReportWithPackageFilter(ThreadFilter,"Wrong Motor",__FILE__,__LINE__,(int)IfIndex,RpError,(int)index,0); return 0xFFFFFFFF; } CurrentPosition = MotorGetPosition(ThreadMotorIdToMotorId[index]); if (CurrentPosition != 0) { if (initialpos == 0xFFFF) { PreviousPosition = CurrentPosition; initialpos = 0; } prevprev = PreviousPosition; if (Extended_Motor_Param[ThreadMotorIdToMotorId[index]] == true) //powerstep driver reverses the direction positionDiff = Control_Delta_Position_Pass(PreviousPosition,CurrentPosition); else positionDiff = Control_Delta_Position_Pass(CurrentPosition,PreviousPosition); //positionDiff = positionDiff / MotorsCfg[ThreadMotorIdToMotorId[index]].microstep; PreviousPosition = CurrentPosition; // total length = (position diff / full cycle) * pulley perimeter //(positionDiff/pulseperround)*((2*PI*motor_Radius) //positionDiff = positionDiff / MotorsCfg[ThreadMotorIdToMotorId[index]].microstep; length = (double)(positionDiff)*LengthCalculationMultiplier; if (length > 1000) { usnprintf(Lenstr, 100, "length huge: length %d, diff 0x%x, pos 0x%x prev 0x%x",(int)length*100,(int)positionDiff,PreviousPosition,prevprev); SendJobProgress(0.0,0,false, Lenstr); ReportWithPackageFilter(ThreadFilter,Lenstr,__FILE__,__LINE__,(int)TotalProcessedLength,RpWarning,(int)PoolerTotalProcessedLength,0); length = 0; } } TotalProcessedLength += (length/100); TempTotalProcessedLength = TotalProcessedLength; #ifdef FEEDER_LENGTH_CALCULATION CurrentProcessedLength+=length; static int feeder_counter = 0; feeder_counter++; if (feeder_counter%10 == 0) { if (PrepareState == true) { //later - add temperatures TemperatureListString(Lenstr); SendJobProgress(0.0,0,false, Lenstr); } else { SendJobProgress(TotalProcessedLength,0,false, NULL); } } if ((CurrentProcessedLength>=CurrentRequestedLength )&&(CurrentRequestedLength > 0.0)) { usnprintf(Lenstr, 100, "Total processed length: Feeder: %d Pooler %d",(int)TotalProcessedLength,(int)PoolerTotalProcessedLength); SendJobProgress(0.0,0,false, Lenstr); ReportWithPackageFilter(ThreadFilter,Lenstr,__FILE__,__LINE__,(int)TotalProcessedLength,RpWarning,(int)PoolerTotalProcessedLength,0); // segment/intersegment/distance to spool finished if (ProcessedLengthFuncPtr) ProcessedLengthFuncPtr(); } #endif return OK; } uint32_t PoolerThreadLengthCBFunction(uint32_t IfIndex, uint32_t ReadValue) { uint32_t positionDiff = 0,prevprev; double length = 0.0; int index = MAX_THREAD_MOTORS_NUM; #ifdef FEEDER_LENGTH_CALCULATION if (ThreadControlActive == false) return OK; if (PrepareState == true) return OK; #endif if (IfIndex>>8 != IfTypeThread) { ReportWithPackageFilter(ThreadFilter,"Wrong Interface type",__FILE__,__LINE__,(int)IfIndex,RpError,(int)PoolerTotalProcessedLength,0); return 0xFFFFFFFF; } index = IfIndex&0xFF; // if (CurrentRequestedLength == 0.0) // return OK; if (index != POOLER_MOTOR) { ReportWithPackageFilter(ThreadFilter,"Wrong Motor",__FILE__,__LINE__,(int)IfIndex,RpError,(int)index,0); return 0xFFFFFFFF; } PoolerCurrentPosition = MotorGetPosition(ThreadMotorIdToMotorId[index]); //if (PoolerCurrentPosition != 0) //{ if (Poolerinitialpos == 0xFFFF) { PoolerPreviousPosition = PoolerCurrentPosition; Poolerinitialpos = 0; } prevprev = PoolerPreviousPosition; if (Extended_Motor_Param[ThreadMotorIdToMotorId[index]] == true) //powerstep driver reverses the direction positionDiff = Control_Delta_Position_Pass(PoolerPreviousPosition,PoolerCurrentPosition); else positionDiff = Control_Delta_Position_Pass(PoolerCurrentPosition,PoolerPreviousPosition); //positionDiff = positionDiff / MotorsCfg[ThreadMotorIdToMotorId[index]].microstep; PoolerPreviousPosition = PoolerCurrentPosition; // total length = (position diff / full cycle) * pulley perimeter //(positionDiff/pulseperround)*((2*PI*motor_Radius) //positionDiff = positionDiff / MotorsCfg[ThreadMotorIdToMotorId[index]].microstep; length = (double)(positionDiff)*PoolerLengthCalculationMultiplier; if (length > 1000) { usnprintf(Lenstr, 100, "length huge: length %d, diff 0x%x, pos 0x%x prev 0x%x",(int)length*100,(int)positionDiff,PreviousPosition,prevprev); SendJobProgress(0.0,0,false, Lenstr); ReportWithPackageFilter(ThreadFilter,Lenstr,__FILE__,__LINE__,(int)TotalProcessedLength,RpWarning,(int)PoolerTotalProcessedLength,0); length = 0; } //} PoolerTotalProcessedLength+= (length/100); TempPoolerTotalProcessedLength = PoolerTotalProcessedLength; #ifndef FEEDER_LENGTH_CALCULATION CurrentProcessedLength+=length; static int puller_counter = 0; puller_counter++; if (puller_counter%10 == 0) { if (PrepareState == true) { TemperatureListString(Lenstr); SendJobProgress(0.0,0,false, Lenstr); } else { SendJobProgress(PoolerTotalProcessedLength,0,false, NULL); } } if ((CurrentProcessedLength>=CurrentRequestedLength )&&(CurrentRequestedLength > 0.0)) { usnprintf(Lenstr, 100, "Total processed length: Feeder: %d Pooler %d",(int)TotalProcessedLength,(int)PoolerTotalProcessedLength); SendJobProgress(0.0,0,false, Lenstr); ReportWithPackageFilter(ThreadFilter,Lenstr,__FILE__,__LINE__,(int)TotalProcessedLength,RpWarning,(int)PoolerTotalProcessedLength,0); // segment/intersegment/distance to spool finished if (ProcessedLengthFuncPtr) ProcessedLengthFuncPtr(); } #endif return OK; } float SpeedSamples[MAX_CONTROL_SAMPLES] = {0}; uint32_t ThreadSpeedControlCBFunction(uint32_t IfIndex, uint32_t ReadValue) { //read value is the dancer angle int index=MAX_THREAD_MOTORS_NUM; int32_t i, avreageSampleValue = 0; //double tempcalcspeed = 0; double calculated_speed; float speed = getSensorSpeedData(); if (IfIndex>>8 != IfTypeThread) { ReportWithPackageFilter(ThreadFilter,"Wrong Interface type",__FILE__,__LINE__,(int)IfIndex,RpError,(int)PoolerTotalProcessedLength,0); return 0xFFFFFFFF; } index = IfIndex&0xFF; SpeedSamples[MotorSamplePointer[index]] = speed;//(-1 * TranslatedReadValue); MotorSamplePointer[index]++; if (MotorSamplePointer[index] >= (int)MotorsControl[index].pvinputfilterfactormode) MotorSamplePointer[index] = 0; for (i=0;i<(int)MotorsControl[index].pvinputfilterfactormode;i++) avreageSampleValue += SpeedSamples[i]; avreageSampleValue = avreageSampleValue / (int)MotorsControl[index].pvinputfilterfactormode; if(MotorControlConfig[index].m_isEnabled && (MotorControlConfig[index].m_SetParam != 0)) { MotorControlConfig[index].m_mesuredParam = ReadValue; MotorControlConfig[index].m_calculatedError = PIDAlgorithmCalculation(MotorControlConfig[index].m_SetParam , MotorControlConfig[index].m_mesuredParam, &MotorControlConfig[index].m_params, &MotorControlConfig[index].m_preError, &MotorControlConfig[index].m_integral); //SetMotorFreq (index, MotorControlConfig[index].m_calculatedError); calculated_speed = (1-MotorControlConfig[index].m_calculatedError)*OriginalMotorSpd_2PPS[index]; if (fabs(calculated_speed-CurrentControlledSpeed[index])>2) { CurrentControlledSpeed[index] = calculated_speed; MotorSetSpeed(ThreadMotorIdToMotorId[index], calculated_speed); } } return OK; } float _speed; uint32_t ThreadControlSpeedReadFunction(uint32_t IfIndex, uint32_t ReadValue) { int index; if (IfIndex>>8 != IfTypeThread) { ReportWithPackageFilter(ThreadFilter,"Wrong Interface type",__FILE__,__LINE__,(int)IfIndex,RpError,(int)PoolerTotalProcessedLength,0); return 0xFFFFFFFF; } index = IfIndex&0xFF; if(MotorControlConfig[index].m_isEnabled ) { int MotorId = ThreadMotorIdToMotorId[index]; _speed = MotorGetSpeedFromFPGA_Res ((TimerMotors_t)MotorId); } return OK; } int controlIndex = 0; bool keepdata = true; int32_t KeepReadValue = 0; //double eNormalizedError[100]; //int TranslatedreadValue[100]; #ifdef TEST_PID_THREAD #define MAX_THREAD_CONTROL_LOG 100 double calculatedError[MAX_THREAD_CONTROL_LOG+1]; double NormError[MAX_THREAD_CONTROL_LOG+1]; double mIntegral[MAX_THREAD_CONTROL_LOG+1]; int MotorId[MAX_THREAD_CONTROL_LOG+1]; int readValue[MAX_THREAD_CONTROL_LOG+1]; int AveragereadValue[MAX_THREAD_CONTROL_LOG+1]; int calculatedspeed[MAX_THREAD_CONTROL_LOG+1]; int timestamp[MAX_THREAD_CONTROL_LOG+1]; void testDancersControl() { int mm20,mm10,mm5,mm2,mm1; mm20 = (20*DancerStopActivityLimit[FEEDER_MOTOR])/(DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].maximalmovementmm*2); mm2 = mm20/10; mm5 = mm20/4; mm10 = mm20/2; mm1 = mm20/20; char time[150]; int len; ThreadControlActive = true; SetOriginMotorSpeed(50.0); MotorControlConfig[FEEDER_MOTOR].m_params.epsilon = 0; MotorsControl[FEEDER_MOTOR].controloutputtype = 0.001; MotorControlConfig[FEEDER_MOTOR].m_params.dt = 0.001; DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint = 10000; MotorsControl[FEEDER_MOTOR].pvinputfilterfactormode = 1; len = usnprintf(time, 150, "params: speed 50, divider %d p %d * %d i %d * %d Dt*1000 %d Norm Coef %d initial speed %d",NORMAL_COEF_DIVIDER,(int)MotorsControl[FEEDER_MOTOR].proportionalgain,(int)MotorsControl[FEEDER_MOTOR].outputonoffhysteresisvalue, (int)MotorsControl[FEEDER_MOTOR].integraltime,(int)MotorsControl[FEEDER_MOTOR].setpointramprateorsoftstartramp,(int)(MotorsControl[FEEDER_MOTOR].controloutputtype*1000), (int)(NormalizedErrorCoEfficient[FEEDER_MOTOR]*1000000000),OriginalMotorSpd_2PPS[FEEDER_MOTOR]); ReportWithPackageFilter(ThreadFilter,time,__FILE__,__LINE__,111,RpError,111,0); Task_sleep(100); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm20); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm10); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm5); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm2); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm1); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm1); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm2); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm5); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm10); ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm20); ThreadControlActive = false; } #endif int MotorFailedSample[MAX_THREAD_MOTORS_NUM] = {0,0,0,0,0}; char TMessage[150]; //char time[150]; uint16_t BreakSensorCounter = 0; uint16_t BreakSensorLatchCounter = 0; bool FirstCalcInJob = true; uint32_t ThreadControlCBFunction(uint32_t IfIndex, uint32_t ReadValue) { //#define MAX_CONTROL_SAMPLES 6 //extern uint32_t MotorSamples[MAX_THREAD_MOTORS_NUM][MAX_CONTROL_SAMPLES]; //extern int MotorSamplePointer[MAX_THREAD_MOTORS_NUM]; //read value is the dancer angle int i,index=MAX_THREAD_MOTORS_NUM; int len; int DancerId; int32_t TranslatedReadValue, avreageSampleValue = 0;//,avreageMotorSampleValue = 0; //double tempcalcspeed = 0; double calculated_speed; double NormalizedError; if (ThreadControlActive == false) return OK; #ifndef TEST_PID_THREAD if (PrepareState == true) return OK; #endif if (IfIndex>>8 != IfTypeThread) { ReportWithPackageFilter(ThreadFilter,"Wrong Interface type",__FILE__,__LINE__,(int)IfIndex,RpError,(int)PoolerTotalProcessedLength,0); return 0xFFFFFFFF; } index = IfIndex&0xFF; if(MotorControlConfig[index].m_isEnabled ) { //if (MotorDriverResponse[ThreadMotorIdToMotorId[index]].Busy == true) // return OK; DancerId = ThreadMotorIdToDancerId[index]; /* if (ReadValue < 10) { MotorFailedSample[index]++; ReportWithPackageFilter(ThreadFilter,"Dancer value read too small.",__FILE__,__LINE__,DancerId,RpError,ReadValue,0); return OK; }*/ if (ReadValue == 0x3FFF) { if (Read_Dryer_Status(DancerId) != OK) { ReportWithPackageFilter(ThreadFilter,"Dancer value invalid.",__FILE__,ReadValue,(int)DancerId,RpError,(int)Read_Dryer_Status(DancerId),0); MotorFailedSample[index]++; return OK; } } KeepReadValue = ReadValue; TranslatedReadValue = ReadValue - DancersCfg[DancerId].zeropoint; if (abs(TranslatedReadValue) > 0x2000) { TranslatedReadValue = 0x3FFF- TranslatedReadValue; //overcome zero environment } if ((index == POOLER_MOTOR)||((index == FEEDER_MOTOR)&&(DancersCfg[DancerId].assemblydirectionright == true))) { //pooler dancer is right sided: data is opposite TranslatedReadValue = (-1*TranslatedReadValue); } if (index == POOLER_MOTOR) { //pooler dancer is right sided: data is opposite JobCounter++; } //TranslatedReadValue = 0;//test MotorSamples[index][MotorSamplePointer[index]] = TranslatedReadValue;//(-1 * TranslatedReadValue); MotorSamplePointer[index]++; if (MotorSamplePointer[index] >= (int)MotorsControl[index].pvinputfilterfactormode) MotorSamplePointer[index] = 0; #ifdef TEST_LONGER_PID_THREAD else // test: handle tension once in pvinputfilterfactormode milliseconds return OK; #endif for (i=0;i<(int)MotorsControl[index].pvinputfilterfactormode;i++) avreageSampleValue += MotorSamples[index][i]; avreageSampleValue = avreageSampleValue / (int)MotorsControl[index].pvinputfilterfactormode; if (BreakSensorenabled == true) { if (index == POOLER_MOTOR) { if (JobCounter > eOneSecond) { if (ReadBreakSensor()==ERROR) { BreakSensorCounter++; BreakSensorLatchCounter++; if (BreakSensorCounter>=BreakSensordebouncetimemilli) { //consider applying the debouce parameters later usnprintf(TMessage, 60, "ReadBreakSensor Error"); //BreakSensordebouncetimemilli JobEndReason = JOB_THREAD_BREAK; ThreadControlActive = false; SendJobProgress(0.0,0,false, TMessage); SendSegmentFail(); //AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_BREAK,true); //EndState(CurrentJob,"ReadBreakSensor Error" ); ReportWithPackageFilter(ThreadFilter,"ReadBreakSensor Error",__FILE__,BreakSensorCounter,(int)index,RpError,(int)JobCounter,0); return OK; } //passed limit }//ReadBreakSensor()==ERROR else //reset counter - we are looking for consequent calls { if (BreakSensorCounter) { ReportWithPackageFilter(ThreadFilter,"ReadBreakSensor Spike",__FILE__,BreakSensorCounter,(int)index,RpError,(int)JobCounter,0); } BreakSensorCounter = 0; } if (CurrentControlledSpeed[index] < (OriginalMotorSpd_2PPS[index]/3)) { BreakSensorCounter++; BreakSensorLatchCounter++; if (BreakSensorCounter>=BreakSensordebouncetimemilli) { //consider applying the debouce parameters later usnprintf(TMessage, 60, "thread speed too low"); JobEndReason = JOB_THREAD_BREAK; ThreadControlActive = false; SendJobProgress(0.0,0,false, TMessage); SendSegmentFail(); //AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_BREAK,true); //EndState(CurrentJob,"ReadBreakSensor Error" ); ReportWithPackageFilter(ThreadFilter,"thread speed too low Error",__FILE__,BreakSensorCounter,(int)index,RpError,(int)JobCounter,0); return OK; } } } } } //Stop Execution if the dancer moves too much if ((abs(avreageSampleValue)> DancerStopActivityLimit[index])&&(JobCounter > eOneSecond)) { keepdata = false; usnprintf(TMessage, 60, "Dancer %d limit %d value %d Zero %d",DancerId,DancerStopActivityLimit[index],avreageSampleValue,DancersCfg[DancerId].zeropoint); ReportWithPackageFilter(ThreadFilter,TMessage,__FILE__,__LINE__,avreageSampleValue,RpWarning,DancerStopActivityLimit[index],0); //JobAbortedByUser = true; ThreadControlActive = false; //MotorGetStatusFromFPGA(ThreadMotorIdToMotorId[index]); JobEndReason = JOB_WINDER_DANCER_FAIL+DancerId; SendJobProgress(0.0,0,false, TMessage); //EndState(CurrentJob,TMessage ); SendSegmentFail(); /*switch (index) { case POOLER_MOTOR: AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_PULLER_DANCER,true); break; case FEEDER_MOTOR: AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_FEEDER_DANCER,true); break; case WINDER_MOTOR: AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_WINDER_DANCER,true); break; }*/ ReportWithPackageFilter(ThreadFilter,"Dancer Failure",__FILE__,DancerId,(int)avreageSampleValue,RpError,(int)JobCounter,0); return OK; } NormalizedError = avreageSampleValue*NormalizedErrorCoEfficient[index]; if ((index != FEEDER_MOTOR)||(MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_RDRIVING].speedmaster == false)) //feeder unit handles errors opposite to left unit { NormalizedError = (-1*NormalizedError); } MotorControlConfig[index].m_mesuredParam = NormalizedError; DancerError[DancerId] = NormalizedError; MotorControlConfig[index].m_calculatedError = PIDAlgorithmCalculation((float)MotorControlConfig[index].m_SetParam , (float)MotorControlConfig[index].m_mesuredParam, &MotorControlConfig[index].m_params, &MotorControlConfig[index].m_preError, &MotorControlConfig[index].m_integral); /*else { //KeepNormalizedError = NormalizedError; }*/ /*if ((JobCounter % 100) == 0) { //if (index == WINDER_MOTOR) //feeder unit handles errors opposite to left unit //{ // ReportWithPackageFilter(ThreadFilter,"MotorSpeedUpdated",__FILE__,index,OriginalMotorSpd_2PPS[index],RpWarning,CurrentControlledSpeed[index],0); //} /`*if (JobCounter >= 3000) { MotorSpeedSamples[index][MotorSpeedSamplePointer[index]] = CurrentControlledSpeed[index];//(-1 * TranslatedReadValue); MotorSpeedSamplePointer[index]++; if (MotorSpeedSamplePointer[index] >= MAX_CONTROL_SAMPLES) MotorSpeedSamplePointer[index] = 0; for (i=0;i<MAX_CONTROL_SAMPLES;i++) avreageMotorSampleValue += MotorSpeedSamples[index][i]; avreageMotorSampleValue = avreageMotorSampleValue / MAX_CONTROL_SAMPLES; //ReportWithPackageFilter(ThreadFilter,"MotorSpeedUpdated",__FILE__,index,OriginalMotorSpd_2PPS[index],RpWarning,avreageMotorSampleValue,0); OriginalMotorSpd_2PPS[index] = avreageMotorSampleValue; }*`/ }*/ calculated_speed = (1-MotorControlConfig[index].m_calculatedError)*OriginalMotorSpd_2PPS[index]; //calculated_speed = (1-MotorControlConfig[index].m_calculatedError)*CurrentControlledSpeed[index]; if (FirstCalcInJob == true) { if (index == FEEDER_MOTOR) { FirstCalcInJob = false; len = usnprintf(TMessage, 150, "read %d avg %d error(6) %d integral(9) %d,delta(9) %d, calc(3) %d speed %d", ReadValue,avreageSampleValue,(int)(MotorControlConfig[index].m_mesuredParam*1000000), (int)(MotorControlConfig[index].m_integral*1000000000),(int)((MotorControlConfig[index].m_mesuredParam*MotorControlConfig[index].m_params.dt)*1000000000), (int)(MotorControlConfig[index].m_calculatedError*1000),(int)calculated_speed); ReportWithPackageFilter(ThreadFilter,TMessage,__FILE__,__LINE__,DancerId,RpError,ReadValue,0); } } #ifndef TEST_PID_THREAD if (fabs(calculated_speed-CurrentControlledSpeed[index])> MotorControlConfig[index].m_ingnoreValue) #else if (index == FEEDER_MOTOR) //feeder unit handles errors opposite to left unit #endif { if (calculated_speed>5.0) { CurrentControlledSpeed[index] = calculated_speed; MotorSetSpeed(ThreadMotorIdToMotorId[index], calculated_speed); } else { if (calculated_speed<0) ReportWithPackageFilter(ThreadFilter,"Negative speed",__FILE__,index,(int)OriginalMotorSpd_2PPS[index],RpWarning,(int)CurrentControlledSpeed[index],0); } /*if (((JobCounter % 2000) == index*100)&&(index == WINDER_MOTOR)) //feeder unit handles errors opposite to left unit { ReportWithPackageFilter(ThreadFilter,"MotorSpeedUpdated",__FILE__,index,(int)OriginalMotorSpd_2PPS[index],RpWarning,(int)CurrentControlledSpeed[index],0); }*/ #ifdef TEST_PID_THREAD int len; if ((JobCounter % 2000) == index*100) //if (keepdata == true) { /*calculatedError[controlIndex] = MotorControlConfig[index].m_calculatedError; MotorId[controlIndex] = index; readValue[controlIndex] = ReadValue; AveragereadValue[controlIndex] = avreageSampleValue; calculatedspeed[controlIndex] = calculated_speed; NormError[controlIndex] = MotorControlConfig[index].m_mesuredParam; mIntegral[controlIndex] = MotorControlConfig[index].m_integral; timestamp[controlIndex] = msec_millisecondCounter;*/ len = usnprintf(TMessage, 150, "read %d avg %d error(6) %d integral(9) %d,delta(9) %d, calc(3) %d speed %d", ReadValue,avreageSampleValue,(int)(MotorControlConfig[index].m_mesuredParam*1000000), (int)(MotorControlConfig[index].m_integral*1000000000),(int)((MotorControlConfig[index].m_mesuredParam*MotorControlConfig[index].m_params.dt)*1000000000), (int)(MotorControlConfig[index].m_calculatedError*1000),(int)calculated_speed); ReportWithPackageFilter(ThreadFilter,TMessage,__FILE__,__LINE__,DancerId,RpError,ReadValue,0); //Task_sleep(100); //if (controlIndex++>=MAX_THREAD_CONTROL_LOG) // controlIndex = 0; } #endif } else { MotorFailedSample[index]++; //LOG_ERROR(index,"No change in speed"); } } return OK; } //******************************************************************************************************************** double ThreadGetMotorSpeed(threadMotorsEnum MotorId) { return CurrentControlledSpeed[MotorId]; } //******************************************************************************************************************** double ThreadGetMotorCalculatedError(int DancerId) { switch (DancerId) { case FEEDER_DANCER: return (double)MotorControlConfig[FEEDER_MOTOR].m_calculatedError; case POOLER_DANCER: return (double)MotorControlConfig[POOLER_MOTOR].m_calculatedError; case WINDER_DANCER: return (double)MotorControlConfig[WINDER_MOTOR].m_calculatedError; } return 0; } //******************************************************************************************************************** uint32_t ThreadInitialTestStub(HardwareMotor * request) { //MotorsConfigMessage(request); ThreadPrepareState(request); ThreadPreSegmentState(request,0); return OK; } uint32_t HandleJobThreadControlParameters(ThreadParameters* ThreadParams) { /* FEEDER_MOTOR, DRYER_MOTOR, POOLER_MOTOR, WINDER_MOTOR, MotorControlConfig[Motor_i].m_params.Kd = MotorsControl[Pid_Id].derivativetime; MotorControlConfig[Motor_i].m_params.Kp = MotorsControl[Pid_Id].proportionalgain; MotorControlConfig[Motor_i].m_params.Ki = MotorsControl[Pid_Id].integraltime; */ if (ThreadParams == NULL) { return OK; } if(ThreadParams->feederp) MotorControlConfig[FEEDER_MOTOR].m_params.Kd = ThreadParams->feederp; if(ThreadParams->feederi) MotorControlConfig[FEEDER_MOTOR].m_params.Ki = ThreadParams->feederi; if(ThreadParams->feederd) MotorControlConfig[FEEDER_MOTOR].m_params.Kd = ThreadParams->feederd; if(ThreadParams->pullerp) MotorControlConfig[POOLER_MOTOR].m_params.Kd = ThreadParams->pullerp; if(ThreadParams->pulleri) MotorControlConfig[POOLER_MOTOR].m_params.Ki = ThreadParams->pulleri; if(ThreadParams->pullerd) MotorControlConfig[POOLER_MOTOR].m_params.Kd = ThreadParams->pullerd; if(ThreadParams->winderp) MotorControlConfig[WINDER_MOTOR].m_params.Kd = ThreadParams->winderp; if(ThreadParams->winderi) MotorControlConfig[WINDER_MOTOR].m_params.Ki = ThreadParams->winderi; if(ThreadParams->winderd) MotorControlConfig[WINDER_MOTOR].m_params.Kd = ThreadParams->winderd; if(ThreadParams->bypassrockers) Thread_Rockers_Bypass = true; return OK; } uint32_t ThreadPrepare_Tension (int DancerId, double tension) { int current, request = (int)tension,movement; int HW_Motor_Id; bool direction; uint32_t status = OK, address = 0; switch (DancerId) { case HARDWARE_DANCER_TYPE__LeftDancer: address = EEPROM_WINDER_TENSION_POSITION; HW_Motor_Id = HARDWARE_MOTOR_TYPE__MOTO_LDANCER1; break; case HARDWARE_DANCER_TYPE__MiddleDancer: if (Is_PP_Machine() == false) //LP machine - old LTFU return OK; address = EEPROM_PULLER_TENSION_POSITION; HW_Motor_Id = HARDWARE_MOTOR_TYPE__MOTO_LDANCER2; break; case HARDWARE_DANCER_TYPE__RightDancer: return ERROR; default: return ERROR; } status |= MCU_E2PromRead(address,&current); if ((status!= OK )||(current == 0)||(current == 0xFFFF)) return status; if (abs(current - request)<100) return status; else { if (current < request) //go down { direction = MotorsCfg[HW_Motor_Id].directionthreadwize; movement = request - current; } else { direction = 1-MotorsCfg[HW_Motor_Id].directionthreadwize; movement = current - request; } MotorSetMaxSpeed (HW_Motor_Id, 500); MotorMoveWithCallback (HW_Motor_Id, direction, (movement*MotorsCfg[HW_Motor_Id].microstep), NULL,20000); status |= MCU_E2PromProgram(address,request); } usnprintf(Lenstr, 100, "ThreadPrepare_Tension Dancer %d Request: %d Current %d movement %d dir %d motor %d address %d", DancerId,request,current,movement,direction,HW_Motor_Id,address); ReportWithPackageFilter(ThreadFilter,Lenstr,__FILE__,address,HARDWARE_MOTOR_TYPE__MOTO_DH_LID,RpFatalError,LIMIT,0); return status; } //******************************************************************************************************************** uint32_t ThreadPrepareState(void *JobDetails) { int Motor_i,i, HW_Motor_Id, Pid_Id; JobTicket* JobTicket = JobDetails; uint32_t status = OK; CurrentSegmentId = 0; JobCounter = 0; TotalProcessedLength = 0.0; PoolerTotalProcessedLength = 0.0; InitialProcess = true; initialpos = 0xFFFF; Poolerinitialpos = 0xFFFF; PrepareState = true; AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_BREAK,false); AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_PULLER_DANCER,false); AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_FEEDER_DANCER,false); AlarmHandlingSetAlarm(EVENT_TYPE__THREAD_TENSION_CONTROL_FAILURE_WINDER_DANCER,false); AlarmHandlingSetAlarm(EVENT_TYPE__WINDER_CONE_DOES_NOT_EXIST,false); AlarmHandlingSetAlarm(EVENT_TYPE__FPGA_WATCHDOG_ACTIVATED,false); // status |= MCU_E2PromProgram(EEPROM_STORAGE_DANCER_0,DancersCfg[0].zeropoint); // double feedertension = 0; // double pullertension = 0; // double windertension = 0; EnableLubrication = JobTicket->enablelubrication; EnableIntersegment = JobTicket->enableintersegment; IntersegmentLength = JobTicket->intersegmentlength; status = ThreadPrepare_Tension (HARDWARE_DANCER_TYPE__LeftDancer, windertension); ReportWithPackageFilter(ThreadFilter,"ThreadPrepare_Tension",__FILE__,HARDWARE_DANCER_TYPE__LeftDancer,status,RpFatalError,(int)windertension,0); status = ThreadPrepare_Tension (HARDWARE_DANCER_TYPE__MiddleDancer, pullertension); ReportWithPackageFilter(ThreadFilter,"ThreadPrepare_Tension",__FILE__,HARDWARE_DANCER_TYPE__MiddleDancer,status,RpFatalError,(int)pullertension,0); status = ThreadPrepare_Tension (HARDWARE_DANCER_TYPE__RightDancer, feedertension); ReportWithPackageFilter(ThreadFilter,"ThreadPrepare_Tension",__FILE__,HARDWARE_DANCER_TYPE__RightDancer,status,RpFatalError,(int)feedertension,0); FirstCalcInJob = true; if(MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_RDRIVING].speedmaster == false) { ThreadMotorIdToMotorId[FEEDER_MOTOR] = HARDWARE_MOTOR_TYPE__MOTO_DRYER_DRIVING; ThreadMotorIdToMotorId[DRYER_MOTOR] = HARDWARE_MOTOR_TYPE__MOTO_RDRIVING; } else { ThreadMotorIdToMotorId[FEEDER_MOTOR] = HARDWARE_MOTOR_TYPE__MOTO_RDRIVING ; ThreadMotorIdToMotorId[DRYER_MOTOR] = HARDWARE_MOTOR_TYPE__MOTO_DRYER_DRIVING; } MotorStop(HARDWARE_MOTOR_TYPE__MOTO_DRYER_LOADARM, Hard_Stop); if (FPGA_Read_limit_Switches(Motor_Id_to_LS_IdDown[HARDWARE_MOTOR_TYPE__MOTO_DH_LID]) != LIMIT) { ReportWithPackageFilter(ThreadFilter,"Dyeing head is open!!!",__FILE__,__LINE__,HARDWARE_MOTOR_TYPE__MOTO_DH_LID,RpFatalError,LIMIT,0); //JobEndReason = JOB_LIDS_OPEN; //PrepareReady(Module_Thread,ModuleFail); //return ERROR; } if (FPGA_Read_limit_Switches(Motor_Id_to_LS_IdDown[HARDWARE_MOTOR_TYPE__MOTO_DRYER_LID]) != LIMIT) { ReportWithPackageFilter(ThreadFilter,"Dryer lid is open!!!",__FILE__,__LINE__,HARDWARE_MOTOR_TYPE__MOTO_DRYER_LID,RpFatalError,LIMIT,0); //JobEndReason = JOB_LIDS_OPEN; //PrepareReady(Module_Thread,ModuleFail); //return ERROR; } //start thread control for all motors for (Motor_i = 0;Motor_i < MAX_THREAD_MOTORS_NUM;Motor_i++) { HW_Motor_Id = ThreadMotorIdToMotorId[Motor_i]; Pid_Id = Motor_i;/*ThreadMotorIdToControlId[Motor_i];*/ MotorControlConfig[Motor_i].m_params.MAX = 1; MotorControlConfig[Motor_i].m_params.MIN = MotorsControl[Pid_Id].outputproportionalpowerlimit*-1; MotorControlConfig[Motor_i].m_params.Kd = MotorsControl[Pid_Id].derivativetime; MotorControlConfig[Motor_i].m_params.Kp = MotorsControl[Pid_Id].proportionalgain; MotorControlConfig[Motor_i].m_params.Ki = MotorsControl[Pid_Id].integraltime; MotorControlConfig[Motor_i].m_params.IntegralErrorMultiplier = MotorsControl[Pid_Id].setpointramprateorsoftstartramp; MotorControlConfig[Motor_i].m_params.ProportionalErrorMultiplier = MotorsControl[Pid_Id].outputonoffhysteresisvalue; MotorControlConfig[Motor_i].m_params.epsilon = MotorsControl[Pid_Id].epsilon; MotorControlConfig[Motor_i].m_params.dt = MotorsControl[Pid_Id].controloutputtype; MotorControlConfig[Motor_i].m_ingnoreValue = MotorsControl[Pid_Id].sensorcorrectionadjustment; // the minimal change required to change the motor speed in pulses MotorControlConfig[Motor_i].m_calculatedError = 0; MotorControlConfig[Motor_i].m_integral = 0; MotorControlConfig[Motor_i].m_isEnabled = true; MotorControlConfig[Motor_i].m_isReady = true; MotorControlConfig[Motor_i].m_mesuredParam = 0; MotorControlConfig[Motor_i].m_preError = 0; MotorControlConfig[Motor_i].m_SetParam = 0;//need to update SetParams on presegment stage ////////////////////////////////////////////////// for (i = 0;i < (int)MotorsControl[Motor_i].pvinputfilterfactormode; i++) { //if (Motor_i == DRYER_MOTOR) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will not be controlled MotorSamples[Motor_i][i] = Control_Read_Dancer_Position(ThreadMotorIdToDancerId[Motor_i],0); //reset the samples value for control beginning // else if ((Motor_i == POOLER_MOTOR)||(Motor_i == FEEDER_MOTOR)) // MotorSamples[Motor_i][i] = DancersCfg[ThreadMotorIdToDancerId[Motor_i]].zeropoint; //MotorSpeedSamples[Motor_i][i] = 0; } MotorSamplePointer[Motor_i] = 0; ///////////////////////////////////////////////////// MotorSetDirection((TimerMotors_t)HW_Motor_Id,MotorsCfg[HW_Motor_Id].directionthreadwize); if (Motor_i == FEEDER_MOTOR) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will not be controlled { ReportWithPackageFilter(ThreadFilter,"Feeder Control",__FILE__,Motor_i,MotorControlConfig[Motor_i].m_params.Kp,RpWarning,MotorControlConfig[Motor_i].m_params.Ki,0); if (SpeedControlId != 0xFF) { RemoveControlCallback(SpeedControlId,ThreadLengthCBFunction); SpeedControlId = 0xFF; } //SetMotHome(ThreadMotorIdToMotorId[Motor_i]); LengthCalculationMultiplier = (MotorsCfg[ThreadMotorIdToMotorId[Motor_i]].pulleyradius*2*PI)/(MotorsCfg[ThreadMotorIdToMotorId[Motor_i]].pulseperround*MotorsCfg[ThreadMotorIdToMotorId[Motor_i]].microstep); SpeedControlId = AddControlCallback(NULL,ThreadLengthCBFunction, eHundredMillisecond,MotorGetPositionFromFPGA,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToMotorId[Motor_i],Motor_i); } if (Motor_i == POOLER_MOTOR) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will not be controlled { ReportWithPackageFilter(ThreadFilter,"Puller Control",__FILE__,Motor_i,MotorControlConfig[Motor_i].m_params.Kp,RpWarning,MotorControlConfig[Motor_i].m_params.Ki,0); if (PoolerSpeedControlId != 0xFF) { if (RemoveControlCallback(PoolerSpeedControlId,PoolerThreadLengthCBFunction)!=OK) ReportWithPackageFilter(ThreadFilter,"Remove Control Failed.",__FILE__,__LINE__,(int)Motor_i,RpError,(int)PoolerSpeedControlId,0); PoolerSpeedControlId = 0xFF; } //SetMotHome(ThreadMotorIdToMotorId[Motor_i]); PoolerLengthCalculationMultiplier = (MotorsCfg[ThreadMotorIdToMotorId[Motor_i]].pulleyradius*2*PI)/(MotorsCfg[ThreadMotorIdToMotorId[Motor_i]].pulseperround*MotorsCfg[ThreadMotorIdToMotorId[Motor_i]].microstep); PoolerSpeedControlId = AddControlCallback(NULL,PoolerThreadLengthCBFunction, eHundredMillisecond,MotorGetPositionFromFPGA,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToMotorId[Motor_i],Motor_i); } if (Motor_i == FEEDER_MOTOR) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will not be controlled { if (ControlIdtoMotorId[Motor_i] != 0xFF) { if(RemoveControlCallback(ControlIdtoMotorId[Motor_i],ThreadControlCBFunction)!=OK) ReportWithPackageFilter(ThreadFilter,"Remove Control Failed.",__FILE__,__LINE__,(int)Motor_i,RpError,(int)PoolerSpeedControlId,0); ControlIdtoMotorId[Motor_i] = 0xFF; CurrentControlledSpeed[Motor_i] = 0; } #ifndef TEST_PID_THREAD ControlIdtoMotorId[Motor_i] = AddControlCallback(NULL,ThreadControlCBFunction, eOneMillisecond,Control_Read_Dancer_Position,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToDancerId[Motor_i],Motor_i); //AddControlCallback(NULL,ThreadControlSpeedReadFunction, eHundredMillisecond,MotorGetSpeedFromFPGA,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToMotorId[Motor_i],Motor_i); #endif } if (Motor_i == POOLER_MOTOR) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will n//ot be controlled { if (ControlIdtoMotorId[Motor_i] != 0xFF) { if(RemoveControlCallback(ControlIdtoMotorId[Motor_i],ThreadControlCBFunction)!=OK) ReportWithPackageFilter(ThreadFilter,"Remove Control Failed.",__FILE__,__LINE__,(int)Motor_i,RpError,(int)PoolerSpeedControlId,0); CurrentControlledSpeed[Motor_i] = 0; ControlIdtoMotorId[Motor_i] = 0xFF; } #ifndef TEST_PID_THREAD ControlIdtoMotorId[Motor_i] = AddControlCallback(NULL,ThreadControlCBFunction, eOneMillisecond,Control_Read_Dancer_Position,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToDancerId[Motor_i],Motor_i); #endif } if (Motor_i == WINDER_MOTOR) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will n//ot be controlled { ReportWithPackageFilter(ThreadFilter,"Winder Control",__FILE__,Motor_i,MotorControlConfig[Motor_i].m_params.Kp,RpWarning,MotorControlConfig[Motor_i].m_params.Ki,0); if (ControlIdtoMotorId[Motor_i] != 0xFF) { if(RemoveControlCallback(ControlIdtoMotorId[Motor_i],ThreadControlCBFunction)!=OK) ReportWithPackageFilter(ThreadFilter,"Remove Control Failed.",__FILE__,__LINE__,(int)Motor_i,RpError,(int)PoolerSpeedControlId,0); CurrentControlledSpeed[Motor_i] = 0; ControlIdtoMotorId[Motor_i] = 0xFF; } #ifndef TEST_PID_THREAD ControlIdtoMotorId[Motor_i] = AddControlCallback(NULL,ThreadControlCBFunction, eOneMillisecond,Control_Read_Dancer_Position,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToDancerId[Motor_i],Motor_i); #endif } // if (HW_Motor_Id == HARDWARE_MOTOR_TYPE__MOTO_DRYER_DRIVING) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will not be controlled // AddControlCallback(ThreadSpeedControlCBFunction, eOneMillisecond,TemplateDataReadCBFunction,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToMotorId[Motor_i],0); if (Motor_i == ThreadMotorIdToMotorId[DRYER_MOTOR]) // dryer motor is speed controlled. later a speed sensor will be utilized, but for now it will not be controlled continue; } HandleJobThreadControlParameters(JobTicket->threadparameters); //OVERRIDES CONFIGURATION PARAMETERS!!! #ifdef TEST_PID_THREAD testDancersControl(); #endif PrepareReady(Module_Thread,ModuleDone); //set 3 dancers to the profile positions return OK; } void SetOriginMotorSpeed(float process_speed) { int Motor_i, HW_Motor_Id; for (Motor_i = 0; Motor_i <= WINDER_MOTOR; Motor_i++) { HW_Motor_Id = ThreadMotorIdToMotorId[Motor_i]; //(Speed*uStep*PPR)/((2*PI*motor_Radius) // double motor_speed = (process_speed * MotorsCfg[HW_Motor_Id].pulseperround * MotorsCfg[HW_Motor_Id].microstep)/(2*PI* MotorsCfg[HW_Motor_Id].pulleyradius); double motor_speed = (process_speed * MotorsCfg[HW_Motor_Id].pulseperround) / (2 * PI * MotorsCfg[HW_Motor_Id].pulleyradius); //MotorControlConfig[Motor_i].m_SetParam = motor_speed; OriginalMotorSpd_2PPS[Motor_i] = (int) motor_speed; InitialDryerSpeed = 0.0; CurrentControlledSpeed[Motor_i] = (int) motor_speed; if (process_speed > 1) ReportWithPackageFilter(ThreadFilter,"Original Speed",__FILE__,Motor_i,(int)motor_speed,RpWarning,process_speed,0); // for (i = 0; i <= MAX_CONTROL_SAMPLES; i++) // MotorSpeedSamples[Motor_i][i] = motor_speed; } } void ThreadPreSegmentEnded(void) { InitialProcess = false; REPORT_MSG (0,"First ThreadPreSegmentEnded"); PreSegmentReady(Module_Thread,ModuleDone); } int DrierDivider = 20; uint32_t ThreadDryerRampUp(uint32_t IfIndex, uint32_t BusyFlag) { InitialDryerSpeed += (OriginalMotorSpd_2PPS[DRYER_MOTOR]/DrierDivider); if (InitialDryerSpeed >= OriginalMotorSpd_2PPS[DRYER_MOTOR]) { InitialDryerSpeed = OriginalMotorSpd_2PPS[DRYER_MOTOR]; SafeRemoveControlCallback(ControlIdtoMotorId[DRYER_MOTOR], ThreadDryerRampUp ); ControlIdtoMotorId[DRYER_MOTOR] = 0xFF; //ReportWithPackageFilter(ThreadFilter,"ThreadDryerRampUp end",__FILE__,ControlIdtoMotorId[DRYER_MOTOR],(int)InitialDryerSpeed,RpWarning,(int)OriginalMotorSpd_2PPS[DRYER_MOTOR],0); } if (InitialDryerSpeed == 0) { //ReportWithPackageFilter(ThreadFilter,"ThreadDryerRampUp Stopped",__FILE__,ControlIdtoMotorId[DRYER_MOTOR],(int)InitialDryerSpeed,RpWarning,(int)OriginalMotorSpd_2PPS[DRYER_MOTOR],0); return OK; } MotorSetSpeed(ThreadMotorIdToMotorId[DRYER_MOTOR],InitialDryerSpeed ); //ReportWithPackageFilter(ThreadFilter,"ThreadDryerRampUp",__FILE__,ControlIdtoMotorId[DRYER_MOTOR],(int)InitialDryerSpeed,RpWarning,(int)OriginalMotorSpd_2PPS[DRYER_MOTOR],0); return OK; } bool Set_Thread_Rockers_Bypass (int value) { if (value == 0) Thread_Rockers_Bypass = false; else Thread_Rockers_Bypass = true; return Thread_Rockers_Bypass; } //******************************************************************************************************************** uint32_t ThreadPreSegmentState(void *SegmentDetails, uint32_t SegmentId) { //set the speed only before the first segment, speed is constant across all job segments and intersegments //JobSegment* Segment = SegmentDetails; float process_speed = dyeingspeed; if (dyeingspeed == 0) { ReportWithPackageFilter(ThreadFilter,"job speed zero.",__FILE__,__LINE__,(int)dyeingspeed,RpError,(int)SegmentId,0); return ERROR; } ReportWithPackageFilter(ThreadFilter,"ThreadPreSegmentState",__FILE__,__LINE__,(int)dyeingspeed,RpWarning,(int)SegmentId,0); if (SegmentId == 0) // do all this only in the beginning of the job. do not touch after that (assuming spool does not change mid job) { SetOriginMotorSpeed(process_speed); ThreadControlActive = true; PrepareState = false; #ifndef TEST_PID_THREAD // set the new speed in the dryer motor to the speed of the new segment if(MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_RDRIVING].speedmaster == false) { DrierDivider = dyeingspeed/3; //ramp up drier in 5 cm/sec steps } else { DrierDivider = dyeingspeed/5; //ramp up drier in 5 cm/sec steps } ReportWithPackageFilter(ThreadFilter,"Drier ramp up",__FILE__,__LINE__,(int)dyeingspeed,RpWarning,(int)DrierDivider,0); InitialDryerSpeed = OriginalMotorSpd_2PPS[DRYER_MOTOR]/DrierDivider; MotorSetSpeed(ThreadMotorIdToMotorId[DRYER_MOTOR],InitialDryerSpeed ); ControlIdtoMotorId[DRYER_MOTOR] = AddControlCallback("DryerRampUp",ThreadDryerRampUp, 200,TemplateDataReadCBFunction,0,0,0); #endif #ifdef HUNDRED_MICROSECONDS_DANCER_READ MillisecLogInit(); #endif if (Thread_Rockers_Bypass == false) { if (MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_RLOADING].maxfrequency > 0) { MotorSetDirection((TimerMotors_t)HARDWARE_MOTOR_TYPE__MOTO_RLOADING,MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_RLOADING].directionthreadwize); MotorSetSpeed(HARDWARE_MOTOR_TYPE__MOTO_RLOADING, 1); } if (MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_LLOADING].maxfrequency > 0) { MotorSetDirection((TimerMotors_t)HARDWARE_MOTOR_TYPE__MOTO_LLOADING,MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_LLOADING].directionthreadwize); MotorSetSpeed(HARDWARE_MOTOR_TYPE__MOTO_LLOADING, 1); } } if (EnableLubrication == true) { IDS_StartLubrication(); } } // activate control fr all motors //set speed for both rocker motors //wait for all motors to get to the required speed (set the target speed for the control to check) //call the job state machine when the thread system is ready if ((InitialProcess==false) && (EnableIntersegment == true)) //&& (IntersegmentLength >= 1.0)) //fix - avoid intersegment length 0 {//add initial presegment and cleaning before first segment ThreadUpdateProcessLength (IntersegmentLength,(void *)ThreadInterSegmentEnded); REPORT_MSG (IntersegmentLength," ThreadPreSegmentState IntersegmentLength"); SegmentState = false; PreSegmentState = true; DTSState = false; } /*else if (InitialProcess==true) { ThreadUpdateProcessLength (dryerbufferMeters,(void *)ThreadPreSegmentEnded); REPORT_MSG (dryerbufferCentimeters," ThreadPreSegmentState DTS length (sample)"); SegmentState = false; PreSegmentState = true; DTSState = false; }*/ else { ThreadUpdateProcessLength (0,(void *)NULL); PreSegmentReady(Module_Thread,ModuleDone); JobCounter = 0; InitialProcess = false; } return OK; } int REPSegmentId = 0; void SendSegmentFail(void) { if (SegmentState == true) SegmentReady(Module_Thread,ModuleFail); else if (PreSegmentState == true) PreSegmentReady(Module_Thread,ModuleFail); else if (DTSState == true) DistanceToSpoolReady(Module_Thread,ModuleFail); } void ThreadInterSegmentEnded(void) { REPORT_MSG (REPSegmentId,"ThreadInterSegmentEnded"); //ThreadUpdateProcessLength (0,(void *)NULL); PreSegmentReady(Module_Thread,ModuleDone); } void ThreadSegmentEnded(void) { REPORT_MSG (REPSegmentId," ThreadSegmentEnded"); SegmentReady(Module_Thread,ModuleDone); } void ThreadDistanceToSpoolEnded(void) { REPORT_MSG (REPSegmentId," ThreadDistanceToSpoolEnded"); DistanceToSpoolReady(Module_Thread,ModuleDone); } double seglength = 0.0; //******************************************************************************************************************** uint32_t ThreadSegmentState(void *SegmentDetails, int SegmentId) { JobSegment* Segment = SegmentDetails; REPSegmentId = SegmentId; seglength = Segment->length; CurrentSegmentId = SegmentId; REPORT_MSG (seglength," ThreadSegmentState"); ThreadUpdateProcessLength (seglength,(void *)ThreadSegmentEnded); SegmentState = true; PreSegmentState = false; DTSState = false; return OK; } //******************************************************************************************************************** uint32_t ThreadDistanceToSpoolState(void ) { seglength = dryerbufferMeters; REPORT_MSG (seglength,"ThreadDistanceToSpoolState"); //#ifdef FEEDER_LENGTH_CALCULATION ThreadUpdateProcessLength (seglength,(void *)ThreadDistanceToSpoolEnded); /*#else ThreadUpdateProcessLength (0,(void *)NULL); //move DTS to job start DistanceToSpoolReady(Module_Thread,ModuleDone); #endif*/ SegmentState = false; PreSegmentState = false; DTSState = true; return OK; } char Endstr[150]; //******************************************************************************************************************** uint32_t ThreadEndState(void ) { int Motor_i; ThreadControlActive = false; uint32_t status = OK; usnprintf(Endstr, 100, "Total _processed length: Feeder: %d Pooler %d",(int)TotalProcessedLength,(int)PoolerTotalProcessedLength); SendJobProgress(0.0,0,false, Endstr); ReportWithPackageFilter(ThreadFilter,Endstr,__FILE__,__LINE__,(int)TotalProcessedLength,RpWarning,(int)PoolerTotalProcessedLength,0); ThreadUpdateProcessLength (0.0,(void *)NULL); //TotalProcessedLength = 0.0; SetOriginMotorSpeed(0); #ifdef HUNDRED_MICROSECONDS_DANCER_READ MillisecLogClose(); #endif if (SpeedControlId != 0xFF) { if(RemoveControlCallback(SpeedControlId,ThreadLengthCBFunction)!=OK) ReportWithPackageFilter(ThreadFilter,"Remove Control Failed.",__FILE__,__LINE__,(int)ThreadLengthCBFunction,RpError,(int)SpeedControlId,0); SpeedControlId = 0xFF; } if (PoolerSpeedControlId != 0xFF) { if(RemoveControlCallback(PoolerSpeedControlId,PoolerThreadLengthCBFunction)!=OK) ReportWithPackageFilter(ThreadFilter,"Remove Control Failed.",__FILE__,__LINE__,(int)PoolerThreadLengthCBFunction,RpError,(int)PoolerSpeedControlId,0); PoolerSpeedControlId = 0xFF; } for ( Motor_i = 0;Motor_i <= WINDER_MOTOR;Motor_i++) { if (ControlIdtoMotorId[Motor_i] != 0xFF) { status = RemoveControlCallback(ControlIdtoMotorId[Motor_i],ThreadControlCBFunction); if(status == OK) ControlIdtoMotorId[Motor_i] = 0xFF; else ReportWithPackageFilter(ThreadFilter,"Remove Control Failed.",__FILE__,__LINE__,(int)Motor_i,RpError,(int)ControlIdtoMotorId[Motor_i],0); } } Task_sleep(100); for ( Motor_i = 0;Motor_i <= WINDER_MOTOR;Motor_i++) { MotorStop(ThreadMotorIdToMotorId[Motor_i],Hard_Hiz); } MotorStop(HARDWARE_MOTOR_TYPE__MOTO_RLOADING,Hard_Hiz); MotorStop(HARDWARE_MOTOR_TYPE__MOTO_LLOADING,Hard_Hiz); IDS_StopLubrication(); return OK; } //******************************************************************************************************************** void ThreadStartPrinting(void) { //PrintingIterate(); } //******************************************************************************************************************** //******************************************************************************************************************** void ThreadStopPrinting(void) { //PrintingIterate(); }