aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Embedded_SW/Embedded/Modules/IDS/IDS_print.c
blob: 62911f34b916f91326565c0aef499a8f430f0f73 (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
/************************************************************************************************************************
 * Ids_print.c
 * Printing module is responsible for :
     * operating diffrent winding algorithms with predefined parameters from the UI
     * operating the dispensers according to predefined dispensing rate from the UI
 **************************************************************************************************************************/
#include "include.h"
#include "ids.h"
#include "ids_ex.h"
#include "../control/control.h"
#include "../control/pidalgo.h"
#include "../thread/thread.h"
#include "PMR/Hardware/Hardwaremotor.pb-c.h"
#include "PMR/Hardware/HardwareDispenser.pb-c.h"
#include "StateMachines/Printing/printingSTM.h"
#include "drivers/motors/motor.h"


typedef struct
{
    bool                m_isEnabled;
    float            m_SetParam;
    float            m_mesuredParam;
    float               m_preError;
    float               m_integral;
    float               m_calculatedError;
    bool                m_isReady;
    PID_Config_Params   m_params;
}DispenserControlConfig_t;
HardwarePidControl DispensersControl[MAX_SYSTEM_DISPENSERS] = {0};

int32_t DispenserSamples[MAX_SYSTEM_DISPENSERS][MAX_CONTROL_SAMPLES] = {0};
int DispenserSamplePointer[MAX_SYSTEM_DISPENSERS] = {0};
double DispenserNormalizedErrorCoEfficient[MAX_SYSTEM_DISPENSERS] = {0};

HardwarePidControlType ThreadDispenserIdToControlId[MAX_SYSTEM_DISPENSERS] = {  HARDWARE_PID_CONTROL_TYPE__Dispenser1,HARDWARE_PID_CONTROL_TYPE__Dispenser2,HARDWARE_PID_CONTROL_TYPE__Dispenser3,HARDWARE_PID_CONTROL_TYPE__Dispenser4,HARDWARE_PID_CONTROL_TYPE__Dispenser5,HARDWARE_PID_CONTROL_TYPE__Dispenser6,HARDWARE_PID_CONTROL_TYPE__Dispenser7,HARDWARE_PID_CONTROL_TYPE__Dispenser8};


/******************** STRUCTURES AND ENUMs  ********************************************/
/******************** GLOBAL PARAMETERS  ********************************************/
DispenserControlConfig_t DispenserControlConfig[MAX_SYSTEM_DISPENSERS];
uint32_t    ControlIdtoDispenserId [MAX_SYSTEM_DISPENSERS] = {0xFF};
int OriginalDispenserSpd_2PPS[MAX_SYSTEM_DISPENSERS] = {0};
int JobBrushStopId = 0;

uint32_t DispenserPidRequestMessage(HardwarePidControl* request)
{
    int Dispenser_i,i;
    int temp;
    for (i=0;i<MAX_SYSTEM_DISPENSERS;i++)
    {
        if (ThreadDispenserIdToControlId[i] == request->hardwarepidcontroltype)
        {
            Dispenser_i = i;
            break;
        }
    }
    memcpy (&DispensersControl[Dispenser_i],request,sizeof(HardwarePidControl));
    if (DispensersControl[Dispenser_i].pvinputfilterfactormode > MAX_CONTROL_SAMPLES)
        DispensersControl[Dispenser_i].pvinputfilterfactormode = MAX_CONTROL_SAMPLES;
    for (i = 0;i < DispensersControl[Dispenser_i].pvinputfilterfactormode; i++)
        DispenserSamples[Dispenser_i][i] = 0;  //reset the samples value for control beginning
    /*DispenserNormalizedErrorCoEfficient[Dispenser_i] = (2*PI*DancersCfg[ThreadDispenserIdToDancerId[Dispenser_i]].armlength);
    temp = 1<<(DancersCfg[ThreadDispenserIdToDancerId[Dispenser_i]].resolutionbits);
    temp=(100*(temp-1)*DancersCfg[ThreadDispenserIdToDancerId[Dispenser_i]].maximalmovementmm);
    DispenserNormalizedErrorCoEfficient[Dispenser_i] = DispenserNormalizedErrorCoEfficient[Dispenser_i] / temp;*/

    return OK;
}

/*
 * IDS Printing support
 * Prepare: build pressure in all participating dispensers
 * Print - dispense ink to the printing head
 * stop - stop dispensing
 *
 * control processes:
 * on prepare stage - each 10msec against the pressure sensors
 * on print stage - every 10/100 msec against the speed sensor
 *
 * */
//Dispenser Pressure control
//callback - calls printing stm with the result

// registration - 10 msec, dispenser pressure sensor
//    AddControlCallback(DeviceId2Heater[HeaterId], HeaterControlCBFunction, eHundredMillisecond);
// start the dispenser pressure building - move up in a TBD speed, valve closed
//Dispenser Speed control
//callback - handles speed
// registration - 10msec, dispenser speed senseo
// start the dispensing - move up according to the segment defined speed and microstepping, valve opened
//

//********************************************************************************************************************
 uint32_t IDSPrepareState(void *JobDetails)
{
    int Motor_i, HW_Motor_Id, Pid_Id;
    //start IDS control for all motors
    for (Motor_i = 0;Motor_i < MAX_SYSTEM_DISPENSERS;Motor_i++)
    {
        HW_Motor_Id = DispenserIdToMotorId[Motor_i];
        Pid_Id = Motor_i;/*IDSMotorIdToControlId[Motor_i];*/
            DispenserControlConfig[Motor_i].m_params.MAX = 1;
            DispenserControlConfig[Motor_i].m_params.MIN = DispensersControl[Pid_Id].outputproportionalpowerlimit*-1;
            DispenserControlConfig[Motor_i].m_params.Kd = DispensersControl[Pid_Id].derivativetime;
            DispenserControlConfig[Motor_i].m_params.Kp = DispensersControl[Pid_Id].proportionalgain;
            DispenserControlConfig[Motor_i].m_params.Ki = DispensersControl[Pid_Id].integraltime;
            DispenserControlConfig[Motor_i].m_params.epsilon = 0.01;
            DispenserControlConfig[Motor_i].m_params.dt = eHundredMillisecond;
            DispenserControlConfig[Motor_i].m_calculatedError = 0;
            DispenserControlConfig[Motor_i].m_integral = 0;
            DispenserControlConfig[Motor_i].m_isEnabled = true;
            DispenserControlConfig[Motor_i].m_isReady = true;
            DispenserControlConfig[Motor_i].m_mesuredParam = 0;
            DispenserControlConfig[Motor_i].m_preError = 0;
            DispenserControlConfig[Motor_i].m_SetParam = 0;//need to update SetParams on presegment stage

            MotorSetDirection((TimerMotors_t)HW_Motor_Id,MotorsCfg[HW_Motor_Id].directionthreadwize); //set the dispenser to the
#warning activate valve
            //ValveCommand (Enable,MixerDirection);
    #ifdef DEBUG_TEST_FUNCTIONS
// add control here
    #else
    #endif
    }
    //set 3 dancers to the profile positions

    return OK;
}

//********************************************************************************************************************
uint32_t IDSPreSegmentState(void *JobDetails, int SegmentId)
{
//set the speed only before the first segment, speed is constant accros job
    JobTicket* JobTicket = JobDetails;
    int Dispenser_i, HW_Motor_Id;
    int segmentfirst_speed;
int CurrentSegment = 0;
    JobBrushStopId = 0;

    for (Dispenser_i = 0;Dispenser_i <= MAX_SYSTEM_DISPENSERS;Dispenser_i++)
    {
        HW_Motor_Id = DispenserIdToMotorId[Dispenser_i];
        //(Speed*uStep*PPR)/((2*PI*Dispenser_Radius)
        segmentfirst_speed = JobTicket->segments[CurrentSegment]->brushstops[JobBrushStopId]->dispensers[Dispenser_i]->pulsepersecond;
        double Dispenser_speed = (segmentfirst_speed *  MotorsCfg[HW_Motor_Id].pulseperround *  MotorsCfg[HW_Motor_Id].microstep)/(2*PI* MotorsCfg[HW_Motor_Id].pulleyradius);
        //DispenserControlConfig[Dispenser_i].m_SetParam = Dispenser_speed;
        OriginalDispenserSpd_2PPS[Dispenser_i] = (int)Dispenser_speed;
    }
    //ControlStart();
    // set the new speed in the dryer Dispenser to the speed of the new segment
    MotorSetSpeed(HW_Motor_Id, OriginalDispenserSpd_2PPS[HW_Motor_Id],  MotorsCfg[HW_Motor_Id].microstep);

    // 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
    PreSegmentReady(Module_IDS,ModuleDone);

    return OK;
}

//********************************************************************************************************************
 uint32_t IDSSegmentState(void *JobDetails, int SegmentId)
{
    return OK;
}

//********************************************************************************************************************
 uint32_t IDSEndState(void *JobDetails)
{
     int Motor_i;
     for ( Motor_i = 0;Motor_i < MAX_THREAD_MOTORS_NUM;Motor_i++)
     {
        StopMotor(ThreadMotorIdToMotorId[Motor_i],Hard_Hiz);
     }
     StopMotor(HARDWARE_MOTOR_TYPE__MOTO_RLOADING,Hard_Hiz);
     StopMotor(HARDWARE_MOTOR_TYPE__MOTO_LLOADING,Hard_Hiz);

    return OK;
}