/************************************************************************************************************************ * Ids_print.c * Printing module is responsible for : * 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/MillisecTask.h" #include "../general/process.h" #include "../control/pidalgo.h" #include "../thread/thread.h" #include "PMR/Hardware/Hardwaremotor.pb-c.h" #include "PMR/Hardware/HardwareDispenser.pb-c.h" #include "PMR/Printing/JobDescriptionFileBrushStop.pb-c.h" #include "PMR/Printing/JobDescriptionFileSegment.pb-c.h" #include "PMR/Printing/JobUploadStrategy.pb-c.h" #include "PMR/Printing/JobSegment.pb-c.h" #include "PMR/Printing/JobTicket.pb-c.h" #include "StateMachines/Printing/printingSTM.h" #include "drivers/motors/motor.h" #include "drivers/valves/valve.h" #include "Common/SWUpdate/FileSystem.h" #include "drivers/Flash_Memory/fatfs/ff.h" #include "modules/heaters/heaters.h" #include "../AlarmHandling/AlarmHandling.h" #include "drivers/Flash_ram/FlashProgram.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; HardwarePidControl DispensersCtrl[MAX_SYSTEM_DISPENSERS]; #define IDS_PRESEGMENT_TIME_STEP 50 #define INITIAL_CLEANER_SPEED 300 int32_t minimal_intersegment_length = 0; int32_t DispenserSamples[MAX_SYSTEM_DISPENSERS][MAX_CONTROL_SAMPLES] = {0}; int DispenserSamplePointer[MAX_SYSTEM_DISPENSERS] = {0}; double DispenserNormalizedErrorCoEfficient[MAX_SYSTEM_DISPENSERS] = {0}; double lubricant_speed = 0.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}; JobUploadStrategy uploadstrategy = JOB_UPLOAD_STRATEGY__Default; bool DispenserReady[MAX_SYSTEM_DISPENSERS] = {true}; bool IDS_Active = false; bool ActuatorsCleaningSequence = true; bool Special_Dispensers = false; /******************** STRUCTURES AND ENUMs ********************************************/ uint32_t IDS_Valve_DistanceToSpoolReady(uint32_t deviceID, uint32_t ReadValue); uint32_t IDS_Valve_PresegmentReady(uint32_t deviceID, uint32_t ReadValue); uint32_t IDSBrushStopRestartCallback(uint32_t IfIndex, uint32_t readValue); //bool IDS_isDispenserUsedNextSegment(void *JobDetails,int DispenserId, int SegmentId); /******************** GLOBAL PARAMETERS ********************************************/ //DispenserControlConfig_t DispenserControlConfig[MAX_SYSTEM_DISPENSERS]; uint32_t ControlIdtoDispenserId [MAX_SYSTEM_DISPENSERS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; int OriginalDispenserSpd_2PPS[MAX_SYSTEM_DISPENSERS] = {0,0,0,0,0,0,0,0}; bool DispenserPreSegmentReady[MAX_SYSTEM_DISPENSERS] = {true,true,true,true,true,true,true,true}; bool DispenserSegmentReady[MAX_SYSTEM_DISPENSERS] = {true,true,true,true,true,true,true,true}; bool DispenserDistanceToSpoolReady[MAX_SYSTEM_DISPENSERS] = {true,true,true,true,true,true,true,true}; bool DispenserUsedInJob[MAX_SYSTEM_DISPENSERS] = {false,false,false,false,false,false,false,false}; bool DispenserUsedInSegment[MAX_SYSTEM_DISPENSERS] = {false,false,false,false,false,false,false,false}; bool DispensersAlarmState[ MAX_SYSTEM_DISPENSERS] = {false,false,false,false,false,false,false,false}; int JobBrushStopId = 0; int lInterSegmentLength = 0; int InterSegmentStepsLimit = 0,InterSegmentStepsCount = 0; bool PreSegmentWCFStarted = false; bool PreSegmentPrepareStarted = false; char* LiquidTypes[10] = {"Cy","Ma","Ye","Bl","TI","Lu","Cl","LC","LM","LY"}; uint32_t InterSegmentStartSprayCleaner = 0; uint32_t InterSegmentStartRocking = 0; uint32_t InterSegmentCenterRockers = 0; uint32_t LeftRockerSpeed = 20; uint32_t RightRockerSpeed = 20; uint32_t CleaningDispenserSpeed = 40; uint32_t InterSegmentStartWFCFDispensers; uint32_t WFCF = 80; bool EnableCleaning = true; bool JobEndSequence = false; double Get_WFCF(void) { return WFCF; } double Get_WFCF_Time(void) { return InterSegmentStartWFCFDispensers; } void IDS_Dispenser_SetPreSegmentWFCFValues(double dispenserpresegmentwfcf, double ids_presegment_wfcf_timebeforesegment) { if (ids_presegment_wfcf_timebeforesegment) InterSegmentStartWFCFDispensers = ids_presegment_wfcf_timebeforesegment; if (dispenserpresegmentwfcf) WFCF = dispenserpresegmentwfcf; ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_SetPreSegmentWFCFValues ",__FILE__,__LINE__,dispenserpresegmentwfcf,RpWarning,(int)ids_presegment_wfcf_timebeforesegment,0); } void IDS_Dispenser_SetPreSegmentCleaningValues(double ids_cleaningspeed,double ids_cleaningstartspraypresegmenttime ,double ids_cleaningstopbeforesegmenttime,double ids_leftcleaningmotorspeed,double ids_rightcleaningmotorspeed) { if ( ids_cleaningspeed) CleaningDispenserSpeed = ids_cleaningspeed; if ( ids_cleaningstartspraypresegmenttime ) { InterSegmentStartSprayCleaner = ids_cleaningstartspraypresegmenttime; InterSegmentStartRocking = ids_cleaningstartspraypresegmenttime + 1000; } if ( ids_cleaningstopbeforesegmenttime) InterSegmentCenterRockers = ids_cleaningstopbeforesegmenttime; if ( ids_leftcleaningmotorspeed) LeftRockerSpeed = ids_leftcleaningmotorspeed; if ( ids_rightcleaningmotorspeed) RightRockerSpeed = ids_rightcleaningmotorspeed; minimal_intersegment_length = ids_cleaningstopbeforesegmenttime+ids_cleaningstartspraypresegmenttime+2000; ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_SetPreSegmentCleaningValues ",__FILE__,__LINE__,RightRockerSpeed,RpWarning,(int)LeftRockerSpeed,0); ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_SetPreSegmentCleaningValues ",__FILE__,minimal_intersegment_length,InterSegmentStartSprayCleaner,RpWarning,(int)InterSegmentCenterRockers,0); ReportWithPackageFilter(IDSFilter,"IDS_Dispenser actuator times ",__FILE__,(int)LeftRockerSpeed/100*IDS_PRESEGMENT_TIME_STEP,(int)LeftRockerSpeed%100*IDS_PRESEGMENT_TIME_STEP,RpWarning,(int)RightRockerSpeed*IDS_PRESEGMENT_TIME_STEP,0); } uint32_t DispenserPreSegmentControlId = 0xFF; uint32_t BrushStopControlId = 0xFF; //uint32_t PreSegmentControlId = 0xFF; /*uint32_t IDS_DispenserControlInit() { DispensersControl = (void *)(?/); DispensersControl = DispensersCtrl; //EraseFlashSection(DispensersControl,sizeof(HardwarePidControl)*MAX_SYSTEM_DISPENSERS); return OK; }*/ uint32_t IDS_DispenserPidRequestMessage(HardwarePidControl* request) { /*int Dispenser_i,i; //int temp; for (i=0;ihardwarepidcontroltype) { Dispenser_i = i; break; } } memcpy (&DispensersCtrl[Dispenser_i],request,sizeof(HardwarePidControl)); //ReadAppAndProgram(&DispensersControl[Dispenser_i], sizeof(HardwarePidControl), request); for (i = 0;i < DispensersControl[Dispenser_i].pvinputfilterfactormode; i++) DispenserSamples[Dispenser_i][i] = 0; //reset the samples value for control beginning DispenserControlConfig[Dispenser_i].m_params.MAX = 1; DispenserControlConfig[Dispenser_i].m_params.MIN = DispensersCtrl[Dispenser_i].outputproportionalpowerlimit*-1; DispenserControlConfig[Dispenser_i].m_params.Kd = DispensersCtrl[Dispenser_i].derivativetime; DispenserControlConfig[Dispenser_i].m_params.Kp = DispensersCtrl[Dispenser_i].proportionalgain; DispenserControlConfig[Dispenser_i].m_params.Ki = DispensersCtrl[Dispenser_i].integraltime; DispenserControlConfig[Dispenser_i].m_params.IntegralErrorMultiplier = DispensersCtrl[Dispenser_i].setpointramprateorsoftstartramp; DispenserControlConfig[Dispenser_i].m_params.ProportionalErrorMultiplier = DispensersCtrl[Dispenser_i].outputonoffhysteresisvalue; DispenserControlConfig[Dispenser_i].m_params.epsilon = DispensersCtrl[Dispenser_i].epsilon; DispenserControlConfig[Dispenser_i].m_params.dt = DispensersCtrl[Dispenser_i].controloutputtype; //DispenserControlConfig[Dispenser_i].m_ingnoreValue = DispensersCtrl[Dispenser_i].sensorcorrectionadjustment; // the minimal change required to change the motor speed in pulses DispenserControlConfig[Dispenser_i].m_calculatedError = 0; DispenserControlConfig[Dispenser_i].m_integral = 0; DispenserControlConfig[Dispenser_i].m_isEnabled = true; DispenserControlConfig[Dispenser_i].m_isReady = true; DispenserControlConfig[Dispenser_i].m_mesuredParam = 0; DispenserControlConfig[Dispenser_i].m_preError = 0; DispenserControlConfig[Dispenser_i].m_SetParam = DispensersCtrl[Dispenser_i].outputproportionalcycletime;//need to update SetParams on presegment stage */ return OK; } uint32_t DispenserPidControlId[MAX_SYSTEM_DISPENSERS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; /*uint32_t IDS_Pid_Testing_Func(uint32_t DispenserId, uint32_t ReadValue) { float calculated_speed; DispenserControlConfig[DispenserId].m_mesuredParam = MillisecGetPressures(DispenserId); DispenserControlConfig[DispenserId].m_calculatedError = PIDAlgorithmCalculation((float)DispenserControlConfig[DispenserId].m_SetParam , (float)DispenserControlConfig[DispenserId].m_mesuredParam, &DispenserControlConfig[DispenserId].m_params, &DispenserControlConfig[DispenserId].m_preError, &DispenserControlConfig[DispenserId].m_integral); DispenserControlConfig[DispenserId].m_calculatedError = (-1*DispenserControlConfig[DispenserId].m_calculatedError); calculated_speed = (1-DispenserControlConfig[DispenserId].m_calculatedError)*CurrentDispenserSpeed[DispenserId]; ReportWithPackageFilter(IDSFilter,"IDS_Pid_Testing_Func ",__FILE__,DispenserId,(int)(DispenserControlConfig[DispenserId].m_mesuredParam*1000),RpWarning,(int)calculated_speed,0); return OK; } void IDS_Start_Pid_Testing(int DispenserId) { DispenserPidControlId[DispenserId] = AddControlCallback(NULL, IDS_Pid_Testing_Func,eOneSecond , TemplateDataReadCBFunction,DispenserId,DispenserId, DispenserId ); ReportWithPackageFilter(IDSFilter,"IDS_Start_Pid_Testing ",__FILE__,__LINE__,DispenserId,RpWarning,(int)DispenserPidControlId[DispenserId],0); } void IDS_Stop_Pid_Testing(int DispenserId) { //stop this control loop RemoveControlCallback(DispenserPidControlId[DispenserId], IDS_Pid_Testing_Func ); DispenserPidControlId[DispenserId] = 0xFF; ReportWithPackageFilter(IDSFilter,"IDS_Stop_Pid_Testing ",__FILE__,__LINE__,DispenserId,RpWarning,(int)DispenserPidControlId[DispenserId],0); }*/ /* * 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 * * */ // /* void OpenJobFile(); void CloseJobFile(); JobDescriptionFileSegment *GetNextSegmentFromJobFile(); void FreeSegmentFileData(JobDescriptionFileSegment *Segment); JobDescriptionFileBrushStop *GetNextBrushStopFromJobFile(); void FreeBrushStopFileData(JobDescriptionFileBrushStop *BrushStop); */ JobDescriptionFileBrushStop *FirstBrushStop = NULL; //******************************************************************************************************************** //************************** IDS JOB BUILDUP ************************************************************************* //******************************************************************************************************************** /************************************************************************************************************************************/ uint32_t IDS_MapDispenserUsedinFileJob(void *JobDetails) { JobTicket* JobTicket = JobDetails; JobDescriptionFileBrushStop *BrushStop = NULL; JobDescriptionFileSegment *Segment = NULL; int Dispenser_i, Brush_i,DispenserId; FRESULT Fresult = FR_OK; uint32_t status = OK; bool lookForLubrication = false; int brushCounter = 0; //GeneralHwReady = false; for (Dispenser_i = 0;Dispenser_ienablelubrication == true) { //DispenserUsedInJob[LUBRICANT_DISPENSER] = true; lookForLubrication = true; } Fresult = OpenJobFile(); if (Fresult == FR_OK) { Segment = GetNextSegmentFromJobFile(); while(Segment) { n_segments++; if ((Segment->has_brushstopscount)&&(Segment->brushstopscount)) { for (Brush_i=0;Brush_ibrushstopscount;Brush_i++) { BrushStop = GetNextBrushStopFromJobFile(); if (BrushStop) { if (FirstBrushStop == NULL) FirstBrushStop = BrushStop; if ((brushCounter % 100)==0) { SendJobProgress(0.0,0,false, "Processing file"); Control_WD(ENABLE,55); //activate heaters/dispenser watchdog, 0.5 seconds } if ((brushCounter % 1000)==900) { Task_sleep(200); ReportWithPackageFilter(IDSFilter,"Sleep in file parsing",__FILE__, BrushStop->index, brushCounter, RpWarning, Segment->brushstopscount, 0); Control_WD(ENABLE,55); //activate heaters/dispenser watchdog, 0.5 seconds } brushCounter++; if (BrushStop->n_dispensers) { for (Dispenser_i = 0;Dispenser_i < BrushStop->n_dispensers;Dispenser_i++) { //prepare the SW structures DispenserId = BrushStop->dispensers[Dispenser_i]->index; if (BrushStop->dispensers[Dispenser_i]->nanolitterpersecond>0.0) { DispenserUsedInJob[DispenserId] = true; if ((lookForLubrication == true)&&(DispenserId == LUBRICANT_DISPENSER)) { lookForLubrication = false; lubricant_speed = BrushStop->dispensers[Dispenser_i]->nanolitterpersecond/BrushStop->dispensers[Dispenser_i]->nanoliterperpulse; REPORT_MSG (BrushStop->dispensers[Dispenser_i]->nanolitterpersecond*100, "LUBRICANT nl / sec"); REPORT_MSG (BrushStop->dispensers[Dispenser_i]->nanoliterperpulse*100, "LUBRICANT nl / pulse"); REPORT_MSG (BrushStop->dispensers[Dispenser_i]->dispenserstepdivision, "step division"); if (BrushStop->dispensers[Dispenser_i]->dispenserstepdivision != DISPENSER_STEP_DIVISION__Auto) { //MotorSetMicroStep(HW_Motor_Id, Dispensers[Dispenser_i]->dispenserstepdivision); lubricant_speed /= BrushStop->dispensers[Dispenser_i]->dispenserstepdivision; //the dye supply is calculated based on a 1/8 microstep } else { lubricant_speed/=8;//MotorsCfg[HW_Motor_Id].microstep; //the dye supply is calculated based on a 1/8 microstep } REPORT_MSG (lubricant_speed*100, "LUBRICANT_SPEED*100"); } } }//for dispenser }//if dispensers else { ReportWithPackageFilter(IDSFilter,"no dispensers in brushstop",__FILE__,__LINE__,(int)BrushStop->index,RpError,(int)BrushStop->n_dispensers,0); } if (FirstBrushStop!= BrushStop) FreeBrushStopFileData(BrushStop); BrushStop = NULL; } else { ReportWithPackageFilter(IDSFilter,"malloc error",__FILE__,__LINE__,(int)0,RpError,(int)0,0); status = ERROR; } }//for brushstops }// if brush stop count FreeSegmentFileData(Segment); Segment = GetNextSegmentFromJobFile(); } FreeSegmentFileData(Segment); CloseJobFile(); } else { ReportWithPackageFilter(IDSFilter,"Error Opening the file", __FILE__, __LINE__, Fresult, RpWarning, 0, 0); return false; } //GeneralHwReady = true; int ActiveDispensers = 0; for (Dispenser_i = 0; Dispenser_i < MAX_DYE_DISPENSERS; Dispenser_i++) { if (DispenserUsedInJob[Dispenser_i] == true) //we actually should check for all dispensers { ActiveDispensers++; } } ReportWithPackageFilter(IDSFilter,"Finished checking the file", __FILE__, __LINE__, n_segments, RpWarning, ActiveDispensers, 0); return status; } /*************************************************************************************************************************************/ /* Parsing the job description file. The job description file simply contains an array of segments and their brush stops. The job description file is meant to be read brush stop by brush stop while the job is in progress. The following diagram represents a single job description file segment structure. The process of reading the whole file is simply repeating that reading order. Each JobDescriptionFileSegment contains a “BrushStopsCount” field that should be used to determine how many brush stops are associated with the current segment and how many times the process of reading brush stops should be repeated. 1. 32bit integer containing the next JobFileDescriptionSegment message byte count 2. JobDescriptionFileSegment message 3. 32bit integer containing the next JobDescriptionFileBrushStop message byte count 4. JobDescriptionFileBrushStop message 1. Read segment message length. 2. Read segment message. a. Read brush stop message length. b. Read brush stop message. c. Go to step 2.a x Segment.BrushStopsCount. 3. Go to step 1 until end of file. ************************************************************************************************************************************/ bool IDS_MapDispenserUsedinJob(void *JobDetails) { JobTicket* JobTicket = JobDetails; int Dispenser_i, Segment_i,Brush_i,DispenserId; uploadstrategy = JobTicket->uploadstrategy; if (JobTicket->uploadstrategy == JOB_UPLOAD_STRATEGY__JobDescriptionFile) { return (IDS_MapDispenserUsedinFileJob(JobDetails)); //return (IDS_MapDispenserUsedinFileJobshort(JobDetails)); } else { for (Dispenser_i = 0;Dispenser_isegments[Segment_i]->n_brushstops;Brush_i++) { if (JobTicket->segments[Segment_i]->brushstops[Brush_i]->n_dispensers) { for (Dispenser_i = 0;Dispenser_i < JobTicket->segments[Segment_i]->brushstops[Brush_i]->n_dispensers;Dispenser_i++) { //prepare the SW structures DispenserId = JobTicket->segments[Segment_i]->brushstops[Brush_i]->dispensers[Dispenser_i]->index; if (JobTicket->segments[Segment_i]->brushstops[Brush_i]->dispensers[Dispenser_i]->nanolitterpersecond>0.0) { DispenserUsedInJob[DispenserId] = true; if(DispenserId == LUBRICANT_DISPENSER) { lubricant_speed = JobTicket->segments[0]->brushstops[0]->dispensers[Dispenser_i]->nanolitterpersecond/ JobTicket->segments[0]->brushstops[0]->dispensers[Dispenser_i]->nanoliterperpulse; if (JobTicket->segments[0]->brushstops[0]->dispensers[Dispenser_i]->dispenserstepdivision != DISPENSER_STEP_DIVISION__Auto) { //MotorSetMicroStep(HW_Motor_Id, Dispensers[Dispenser_i]->dispenserstepdivision); lubricant_speed /= JobTicket->segments[0]->brushstops[0]->dispensers[Dispenser_i]->dispenserstepdivision; //the dye supply is calculated based on a 1/8 microstep } else { lubricant_speed/=8;//MotorsCfg[HW_Motor_Id].microstep; //the dye supply is calculated based on a 1/8 microstep } REPORT_MSG (lubricant_speed*100, "LUBRICANT_SPEED*100"); } } }//for dispenser }//if dispensers }//for brush }//for segments } return true; } //******************************************************************************************************************** //************************** IDS PREPARE BUILDUP ********************************************************************* //******************************************************************************************************************** //******************************************************************************************************************** uint32_t DispenserPrepareControlId = 0xFF; int NumOfActiveDispensers = 0; int DispenserBuildTimeCounter = 0; double TargetNumberOfStepsPreRun,MaximalPressurePreRun; int DispenserTotalPrepareSteps[MAX_SYSTEM_DISPENSERS]; bool DispenserLastMovementDown[MAX_SYSTEM_DISPENSERS]; #define PRESSURE_READ_TIME_GAP 100 uint32_t InactiveDispenserHome(uint32_t DispenserId, uint32_t ReadValue) { if (AutoHoming_Config >= AutoHoming_JobEnd_PowerOn_off) { if ((HomingActive[DispenserId] == false)&&(PrimingActive[DispenserId] == false)) { ReportWithPackageFilter(IDSFilter,"Homing Inactive dispenser",__FILE__,DispenserId,HomingActive[DispenserId],RpWarning,PrimingActive[DispenserId],0); IDS_HomeDispenser (DispenserId, 1000 , NULL); } else { ReportWithPackageFilter(IDSFilter,"Inactive dispenser already homing",__FILE__,DispenserId,HomingActive[DispenserId],RpWarning,PrimingActive[DispenserId],0); } } return OK; } void DispenserPrepareReady(void) { int i; for (i=0;i RefMaxPressure*1.03) { tempSpeed = CurrentDispenserSpeed[DispenserId]; //updatedSpeed = (tempSpeed * 0.992 > 100) ? tempSpeed * 0.992 : 100; updatedSpeed = tempSpeed*0.98; MotorSetSpeed(HW_Motor_Id, updatedSpeed); CurrentDispenserSpeed[DispenserId] = updatedSpeed; //ReportWithPackageFilter(IDSFilter,"IDS decrease speed",__FILE__,DispenserId,(int)updatedSpeed,RpWarning,(int)(pressure*100),0); //return true; //ready } else if (pressure < RefMaxPressure*0.97) { tempSpeed = CurrentDispenserSpeed[DispenserId]; if (tempSpeed<50) tempSpeed = 50; updatedSpeed = (tempSpeed * 1.02 < InitialDispenserSpeed) ? tempSpeed * 1.02 : InitialDispenserSpeed; MotorSetSpeed(HW_Motor_Id, updatedSpeed); CurrentDispenserSpeed[DispenserId] = updatedSpeed; //ReportWithPackageFilter(IDSFilter,"IDS increase speed",__FILE__,DispenserId,(int)updatedSpeed,RpWarning,(int)(pressure*100),0); //return false; //not ready } if ((pressure>RefMaxPressure)&&(pressure<(RefMaxPressure+0.1))) return true; return false; } //******************************************************************************************************************** uint32_t IDS_Prepare_Callback(uint32_t DispenserId, uint32_t ReadValue) { int i; int NumofReadyDispensers = 0; TimerMotors_t HW_Motor_Id; JobDispenser **Dispensers; //set the speed only before the first segment, speed is constant accros job int Dispenser_i,n_dispensers; double segmentfirst_speed; double pressure; ModuleStateEnum result = ModuleDone; bool DispenserReady[MAX_SYSTEM_DISPENSERS] = {false,false,false,false,false,false,false,false}; //REPORT_MSG((int)DispenserPrepareControlId, "Prepare Callback"); DispenserBuildTimeCounter+=PRESSURE_READ_TIME_GAP; if (pressureReady == false) { if (DispenserBuildTimeCounter<(2*eOneSecond)) { for (i = 0; i < MAX_DYE_DISPENSERS; i++) { DispenserTotalPrepareSteps[i]+=(CurrentDispenserSpeed[i]*PRESSURE_READ_TIME_GAP/eOneSecond); DispenserLastMovementDown[i] = false; } //REPORT_MSG(DispenserBuildTimeCounter,"waiting 2 seconds for pressure changes"); return OK; } for (i = 0; i < MAX_DYE_DISPENSERS; i++) { pressure = GetDispenserPressure(i); //IDS_StopHomeDispenser(i); if (DispenserUsedInJob[i] == true) //we actually should check for all dispensers { DispenserTotalPrepareSteps[i]+=(CurrentDispenserSpeed[i]*PRESSURE_READ_TIME_GAP/eOneSecond); HW_Motor_Id = DispenserIdToMotorId[i]; /*if ((DispenserTotalPrepareSteps[i]>TargetNumberOfStepsPreRun)&&(DispenserTotalPrepareSteps[i]<(TargetNumberOfStepsPreRun+InitialDispenserSpeed))) { ReportWithPackageFilter(IDSFilter,"IDS dispenser pre-run ended",__FILE__,i,(int)DispenserTotalPrepareSteps[i],RpWarning,(int)(pressure*100),0); }*/ if (DispenserTotalPrepareSteps[i] DispenserPreparePressure*1.2) { MotorStop(HW_Motor_Id, Hard_Hiz); CurrentDispenserSpeed[i] = 1; } else { if (AdjustDispenserSpeedToPressure(i,DispenserPreparePressure,pressure) == true) { NumofReadyDispensers++; DispenserReady[i] = true; } } //ReportWithPackageFilter(IDSFilter,"IDS prepare",__FILE__,i,(int)DispenserTotalPrepareSteps[i],RpWarning,(int)(CurrentDispenserSpeed[i]*100),0); } else DispenserReady[i] = true; } #ifndef LIGHT_COLORS pressure = GetDispenserPressure(CLEANER_DISPENSER); if (pressure > 0.02) { HW_Motor_Id = DispenserIdToMotorId[CLEANER_DISPENSER]; MotorStop(HW_Motor_Id, Hard_Hiz); if (CurrentDispenserSpeed[CLEANER_DISPENSER]) ReportWithPackageFilter(IDSFilter,"IDS stop cleaner",__FILE__,CLEANER_DISPENSER,(int)(pressure*100),RpWarning,(int)CurrentDispenserSpeed[CLEANER_DISPENSER] ,0); CurrentDispenserSpeed[CLEANER_DISPENSER] = 0; } #endif if ((NumofReadyDispensers)&&(DispenserBuildTimeCounter%1000 == 0)) { ReportWithPackageFilter(IDSFilter,"IDS_Prepare_Callback",__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)NumOfActiveDispensers,0); } if (NumofReadyDispensers>=NumOfActiveDispensers) { pressureReady = true; usnprintf(IdMessage, 80,"setting pressureReady = true %d K %d,C %d,M %d,Y %d,TI %d",(int)TargetNumberOfStepsPreRun,DispenserTotalPrepareSteps[0],DispenserTotalPrepareSteps[1], DispenserTotalPrepareSteps[2],DispenserTotalPrepareSteps[3],DispenserTotalPrepareSteps[4]); ReportWithPackageFilter(IDSFilter,IdMessage,__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)NumOfActiveDispensers,0); } if (pressureReady == true) { usnprintf(IdMessage, 80,"pressureReady = true %d K %d,C %d,M %d,Y %d,TI %d",(int)(DispenserPreparePressure*100),(int)(GetDispenserPressure(0)*100),(int)(GetDispenserPressure(1)*100) ,(int)(GetDispenserPressure(2)*100),(int)(GetDispenserPressure(3)*100),(int)(GetDispenserPressure(4)*100)); ReportWithPackageFilter(IDSFilter,IdMessage, __FILE__, __LINE__, DispenserBuildTimeCounter, RpWarning, NumofReadyDispensers, 0); DispenserBuildTimeCounter = 0; //ReportWithPackageFilter(IDSFilter,"pressureReady = true",__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)(DispenserPreparePressure*100),0); } if (DispenserBuildTimeCounter >= DispenserPrepareTimeout) { endOfPrepareWCF = true; result = ModuleFail; JobEndReason = JOB_PRESSURE_ALARM; usnprintf(AlarmReasonStr, 100, "IDS pressure timeout %d ",DispenserPrepareTimeout); pressureReady = true; ReportWithPackageFilter(IDSFilter,"pressure timeout!",__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)(DispenserPreparePressure*100),0); for (i = 0; i < MAX_DYE_DISPENSERS; i++) { if (DispenserReady[i] == false) //we actually should check for all dispensers { AlarmHandlingSetAlarm (EVENT_TYPE__DISPENSER_1_UNDERPRESSURE+i,ON); //handle alarm detection and operation } } } } else if (endOfPrepareWCF == false) { if ((DispenserBuildTimeCounter == PRESSURE_READ_TIME_GAP)&&(FirstBrushStop)) { ReportWithPackageFilter(IDSFilter,"start prepare dispensers at rate * WFCF",__FILE__,__LINE__,InterSegmentStepsCount,RpWarning,(int)lInterSegmentLength,0); if (FirstBrushStop) { REPORT_MSG(FirstBrushStop->index,"WFCFBrushStopRead Index"); Dispensers = FirstBrushStop->dispensers; n_dispensers = FirstBrushStop->n_dispensers; if (n_dispensers) { for (Dispenser_i = 0; Dispenser_i < n_dispensers; Dispenser_i++) { DispenserId = Dispensers[Dispenser_i]->index; HW_Motor_Id = DispenserIdToMotorId[DispenserId]; if (MotorsCfg[HW_Motor_Id].hardwaremotortype != DispenserIdToMotorId[DispenserId]) continue; if ((DispenserId == CLEANER_DISPENSER)||(DispenserId == LUBRICANT_DISPENSER)) { continue; } if (DispenserId!=Dispenser_i) ReportWithPackageFilter(IDSFilter,"DispenserId!=Dispenser_i",__FILE__,__LINE__,DispenserId,RpWarning,(int)Dispenser_i,0); //(Speed*uStep*PPR)/((2*PI*Dispenser_Radius) segmentfirst_speed = Dispensers[Dispenser_i]->nanolitterpersecond / Dispensers[Dispenser_i]->nanoliterperpulse; if (Dispensers[Dispenser_i]->dispenserstepdivision != DISPENSER_STEP_DIVISION__Auto) { //MotorSetMicroStep(HW_Motor_Id, Dispensers[Dispenser_i]->dispenserstepdivision); segmentfirst_speed /= Dispensers[Dispenser_i]->dispenserstepdivision; //the dye supply is calculated based on a 1/8 microstep } else { segmentfirst_speed/=8;//MotorsCfg[HW_Motor_Id].microstep; //the dye supply is calculated based on a 1/8 microstep } if (segmentfirst_speed > MINIMAL_MOTOR_SPEED) { segmentfirst_speed *= (100+WFCF); segmentfirst_speed /= 100; DispenserSegmentReady[DispenserId] = false; //Control3WayValvesWithCallback (DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer if (Special_Dispensers == true) { IDS_Dispenser_Start_Motor_and_Open_Valve(DispenserId,segmentfirst_speed,NULL); } else { MotorSetSpeed(HW_Motor_Id, segmentfirst_speed); } CurrentDispenserSpeed[DispenserId] = segmentfirst_speed; /*usnprintf(IdMessage, 80, "WFCF Dispenser %d nl/sec %d nl/pulse %d Pulse/sec %d speed %d", DispenserId, (int) Dispensers[Dispenser_i]->nanolitterpersecond, (int) (Dispensers[Dispenser_i]->nanoliterperpulse*100), (int) Dispensers[Dispenser_i]->pulsepersecond*1000, (int) segmentfirst_speed*1000); //REPORT_MSG(segmentfirst_speed,IdsMessage); ReportWithPackageFilter(IDSFilter,IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); //SendJobProgress(0.0, 0, false, IdsMessage);*/ } else { if (DispenserUsedInJob[DispenserId] == true) { MotorStop(HW_Motor_Id, Hard_Hiz); CurrentDispenserSpeed[DispenserId] = 0; //usnprintf(IdsMessage, 80,"WFCF Prepare Dispenser %d stopped",DispenserId,(int) segmentfirst_speed); //ReportWithPackageFilter(IDSFilter,IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); } } }//for //usnprintf(IdMessage, 80,"WFCF %d K %d,C %d,M %d,Y %d,TI %d",WFCF,CurrentDispenserSpeed[0], // CurrentDispenserSpeed[1],CurrentDispenserSpeed[2],CurrentDispenserSpeed[3],CurrentDispenserSpeed[4]); if (BuildIdsJobPrintString(IdMessage,"WFCF ",WFCF)) ReportWithPackageFilter(IDSFilter,IdMessage, __FILE__, __LINE__, DispenserBuildTimeCounter, RpWarning, WFCF, 0); }//if n_dis } } if ((InterSegmentStartWFCFDispensers > 0)&&((InterSegmentStartWFCFDispensers-1000) == DispenserBuildTimeCounter)) { //close waste valve one second before segment - trial Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Head); } if (DispenserBuildTimeCounter >= InterSegmentStartWFCFDispensers) { endOfPrepareWCF = true; FreeBrushStopFileData(FirstBrushStop); FirstBrushStop =NULL; ReportWithPackageFilter(IDSFilter,"endOfPrepareWCF = true;",__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)NumOfActiveDispensers,0); } } //start new stage if (endOfPrepareWCF == true) { #ifndef LIGHT_COLORS if (CurrentDispenserSpeed[CLEANER_DISPENSER]) { HW_Motor_Id = DispenserIdToMotorId[CLEANER_DISPENSER]; MotorStop(HW_Motor_Id, Hard_Hiz); CurrentDispenserSpeed[CLEANER_DISPENSER] = 0; ReportWithPackageFilter(IDSFilter,"IDS stop cleaner",__FILE__,CLEANER_DISPENSER,(int)(pressure*100),RpWarning,(int)CurrentDispenserSpeed[CLEANER_DISPENSER] ,0); } #endif SafeRemoveControlCallback(DispenserPrepareControlId, IDS_Prepare_Callback ); DispenserPrepareControlId = 0xFF; ReportWithPackageFilter(IDSFilter,"IDS_Prepare_Callback SafeRemoveControlCallback",__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)NumOfActiveDispensers,0); setRapidPressureRead(false); pressureReady = false; endOfPrepareWCF = false; //DispenserPrepareReady(); PrepareReady(Module_IDS,result); } return OK; } //******************************************************************************************************************** //******************************************************************************************************************** uint32_t IDSPrepareState(void *JobDetails) { int Motor_i; //start IDS control for all motors IDS_Active = true; double cleanerFlow = 0; Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Waste); JobTicket* JobTicket = JobDetails; JobEndSequence = false; if ((pressurebuildup>0.1)&&(pressurebuildup<4.5)) { ReportWithPackageFilter(IDSFilter,"Setting pressure from RML pressure buildup",__FILE__,__LINE__,(int)(pressurebuildup*100),RpWarning,(int)(DispenserPreparePressure*100),0); DispenserPreparePressure = pressurebuildup; } if (JobTicket->headcleaningparameters) { if (JobTicket->headcleaningparameters->has_cleanerflow) cleanerFlow = JobTicket->headcleaningparameters->cleanerflow; if (JobTicket->headcleaningparameters->has_archeadcleaningmotorspeed) ArcCleaningMotorSpeed = JobTicket->headcleaningparameters->archeadcleaningmotorspeed; } if ((cleanerFlow>200)&&(cleanerFlow<1150)) { ReportWithPackageFilter(IDSFilter,"Setting cleanerFlow from RML cleanerFlow",__FILE__,__LINE__,(int)(cleanerFlow),RpWarning,(int)CleaningDispenserSpeed,0); CleaningDispenserSpeed = cleanerFlow; } else if (cleanerFlow <= 10) { CleaningDispenserSpeed = 0; EnableCleaning = false; } TargetNumberOfStepsPreRun = InitialDispenserTimeout; MaximalPressurePreRun = InitialDispenserPressure; for (Motor_i = 0;Motor_i < MAX_SYSTEM_DISPENSERS;Motor_i++) { TimerMotors_t 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 /*Start the dispensers to build initial pressure * check different handling for dispensers that participate in the first segment and idle dispensers * start control for initial pressure * */ //ValveCommand (Enable,MixerDirection); } if (HeaterCheckReady() == true) { REPORT_MSG(1,"heaters ready, starting"); IDSPrepareStart(); } return OK; } void IDSPrepareStart(void) { int i; double dispenserspeed = 0; if (IDS_Active == false) { ReportWithPackageFilter(IDSFilter,"IDSPrepareStart Not in a job",__FILE__,__LINE__,(int)0,RpError,(int)0,0); return; } NumOfActiveDispensers = 0; #ifndef LIGHT_COLORS if (lubricant_speed > 0.1) IDS_StopHomeDispenser(LUBRICANT_DISPENSER); if ((EnableIntersegment == true)&&(IntersegmentLength>0)) IDS_StopHomeDispenser(CLEANER_DISPENSER); #endif for (i = 0; i < MAX_DYE_DISPENSERS; i++) { if (DispenserUsedInJob[i] == true) //we actually should check for all dispensers { NumOfActiveDispensers++; if (HomingActive[i] == true) { ReportWithPackageFilter(IDSFilter,"Stop active dispenser homing ",__FILE__,i,HomingActive[i],RpWarning,CurrentDispenserSpeed[i],0); IDS_StopHomeDispenser(i); } DispenserTotalPrepareSteps[i] = 0; ReportWithPackageFilter(IDSFilter,"Dispenser total prepare steps zero",__FILE__,i,DispenserTotalPrepareSteps[i],RpWarning,IDS_Dispenser_Data[i].consumedinnanolitter,0); } else { DispenserTotalPrepareSteps[i] = 0; if (AutoHoming_Config >= AutoHoming_JobEnd_PowerOn_off) { if ((HomingActive[i] == false)&&(PrimingActive[i] == false)) { ReportWithPackageFilter(IDSFilter,"Homing Inactive dispenser",__FILE__,i,HomingActive[i],RpWarning,PrimingActive[i],0); if (IDS_HomeDispenser (i, 1000 , NULL) == ERROR) Control3WayValvesWithCallback (i, MidTank_Dispenser, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer; } else { ReportWithPackageFilter(IDSFilter,"Inactive dispenser already homing",__FILE__,i,HomingActive[i],RpWarning,PrimingActive[i],0); } } #ifdef DISPENSER_VALVES_OPEN else // turn inactive dispenser valve toward the midtank during job { if (HomingActive[i] == false) Control3WayValvesWithCallback ((Valves_t)i, MidTank_Dispenser, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer } #endif } } if (NumOfActiveDispensers) { REPORT_MSG((int)NumOfActiveDispensers, "Num Of Active Dispensers"); for (i = 0; i < MAX_DYE_DISPENSERS; i++) { dispenserspeed = DispenserPrepareSpeed; if (Special_Dispensers == true) { dispenserspeed = 300; } TimerMotors_t HW_Motor_Id = DispenserIdToMotorId[i]; if (DispenserUsedInJob[i] == true) //we actually should check for all dispensers { //if (HomingActive[i] == false) { ReportWithPackageFilter(IDSFilter,"Prepare Speed",__FILE__,HomingActive[i],i,RpWarning,(int)dispenserspeed,0); MotorSetDirection((TimerMotors_t)HW_Motor_Id,MotorsCfg[HW_Motor_Id].directionthreadwize); //set the dispenser to the if (Special_Dispensers == true) { MotorSetSpeed((TimerMotors_t)HW_Motor_Id,dispenserspeed); //set the dispenser to the } else { IDS_Dispenser_Start_Motor_and_Open_Valve(i,dispenserspeed, NULL); } } /*else { ReportWithPackageFilter(IDSFilter,"IDSPrepare Stop Dispenser Homing",__FILE__,__LINE__,i,RpWarning,(int)HomingActive[i],0); IDS_HomeDispenserWaitForHomingEnd(i, DispenserPrepareTimeout/2 , IDSPrepareStartDispenserAfterHoming); }*/ } } #ifndef LIGHT_COLORS if (GetDispenserPressure(CLEANER_DISPENSER) < 0.01) { TimerMotors_t HW_Motor_Id = DispenserIdToMotorId[CLEANER_DISPENSER]; MotorSetSpeed((TimerMotors_t)HW_Motor_Id,INITIAL_CLEANER_SPEED ); //set the dispenser to the CurrentDispenserSpeed[CLEANER_DISPENSER] = INITIAL_CLEANER_SPEED; } ReportWithPackageFilter(IDSFilter,"IDS start cleaner",__FILE__,CLEANER_DISPENSER,(int)(GetDispenserPressure(CLEANER_DISPENSER)*100),RpWarning,(int)CurrentDispenserSpeed[CLEANER_DISPENSER] ,0); #endif } DispenserBuildTimeCounter = 0; DispenserPrepareControlId = AddControlCallback(NULL, IDS_Prepare_Callback, PRESSURE_READ_TIME_GAP,TemplateDataReadCBFunction ,0, 0, 0 ); setRapidPressureRead(true); } //******************************************************************************************************************** //************************** IDS PRESEGMENT BUILDUP ****************************************************************** //******************************************************************************************************************** JobDescriptionFileBrushStop * FileBrushStop; //******************************************************************************************************************** uint32_t IDS_PreSegmentPrepare_Callback(uint32_t DispenserId, uint32_t ReadValue) { bool PSpressureReady = false; int i; int NumofReadyDispensers = 0; TimerMotors_t HW_Motor_Id; float updatedSpeed,tempSpeed; //REPORT_MSG((int)DispenserPrepareControlId, "Prepare Callback"); DispenserBuildTimeCounter+=IDS_PRESEGMENT_TIME_STEP; if (DispenserBuildTimeCounter<(1*eOneSecond)) { //REPORT_MSG(DispenserBuildTimeCounter,"waiting 1 seconds for pressure changes"); return OK; } if (PreSegmentWCFStarted == true) { REPORT_MSG(PreSegmentWCFStarted,"PreSegmentWCFStarted is true, stopping prepare stage"); //SafeRemoveControlCallback(DispenserPrepareControlId, IDS_Prepare_Callback ); setRapidPressureRead(false); return OK; } for (i = 0; i < MAX_DYE_DISPENSERS; i++) { //IDS_StopHomeDispenser(i); if (DispenserUsedInSegment[i] == true) //we actually should check for all dispensers { HW_Motor_Id = DispenserIdToMotorId[i]; if (GetDispenserPressure(i) > DispenserPreparePressure) { NumofReadyDispensers++; tempSpeed = CurrentDispenserSpeed[i]; updatedSpeed = (tempSpeed*0.98>100)?tempSpeed*0.98:100; MotorSetSpeed(HW_Motor_Id, updatedSpeed); CurrentDispenserSpeed[i] = updatedSpeed; //ReportWithPackageFilter(IDSFilter,"IDS PreSegment reduce speed",__FILE__,i,(int)tempSpeed,RpWarning,(int)updatedSpeed,0); } else { tempSpeed = CurrentDispenserSpeed[i]; updatedSpeed = (tempSpeed*1.04<1100)?tempSpeed*1.04:1100; MotorSetSpeed(HW_Motor_Id, updatedSpeed); CurrentDispenserSpeed[i] = updatedSpeed; //ReportWithPackageFilter(IDSFilter,"IDS PreSegment accelerate speed",__FILE__,i,(int)tempSpeed,RpWarning,(int)updatedSpeed,0); } } } if ((NumofReadyDispensers)&&(DispenserBuildTimeCounter%1000 == 0)) ReportWithPackageFilter(IDSFilter,"IDS_PreSegmentPrepare_Callback",__FILE__,DispenserBuildTimeCounter,InterSegmentStepsCount,RpWarning,(int)NumOfActiveDispensers,0); if (NumofReadyDispensers>=NumOfActiveDispensers) PSpressureReady = true; if ((DispenserBuildTimeCounter >= DispenserPrepareTimeout)||(PSpressureReady == true)) { ReportWithPackageFilter(IDSFilter,"IDS_PreSegmentPrepare_Callback SafeRemoveControlCallback",__FILE__,DispenserPrepareControlId,InterSegmentStepsCount,RpWarning,(int)NumOfActiveDispensers,0); SafeRemoveControlCallback(DispenserPrepareControlId, IDS_Prepare_Callback ); DispenserPrepareControlId = 0xFF; PreSegmentWCFStarted = true; setRapidPressureRead(false); } return OK; } //******************************************************************************************************************** void IDSPresegmentPrepareStart(void) { int Dispenser_i,n_dispensers,DispenserId; TimerMotors_t HW_Motor_Id; double segmentfirst_speed; JobDispenser **Dispensers; for (Dispenser_i = 0; Dispenser_i < MAX_DYE_DISPENSERS; Dispenser_i++) { DispenserUsedInSegment[Dispenser_i] = false; } if (FileBrushStop) { ReportWithPackageFilter(IDSFilter,"start dispensers pre segment pressure build",__FILE__,__LINE__,FileBrushStop->index,RpWarning,(int)FileBrushStop->n_dispensers,0); NumOfActiveDispensers = FileBrushStop->n_dispensers; Dispensers = FileBrushStop->dispensers; n_dispensers = FileBrushStop->n_dispensers; if (n_dispensers) { for (Dispenser_i = 0; Dispenser_i < n_dispensers; Dispenser_i++) { DispenserId = Dispensers[Dispenser_i]->index; HW_Motor_Id = DispenserIdToMotorId[DispenserId]; if (MotorsCfg[HW_Motor_Id].hardwaremotortype != DispenserIdToMotorId[DispenserId]) continue; if ((DispenserId == CLEANER_DISPENSER)||(DispenserId == LUBRICANT_DISPENSER)) { continue; } //(Speed*uStep*PPR)/((2*PI*Dispenser_Radius) segmentfirst_speed = Dispensers[Dispenser_i]->nanolitterpersecond / Dispensers[Dispenser_i]->nanoliterperpulse; if (segmentfirst_speed > MINIMAL_MOTOR_SPEED) { DispenserUsedInSegment[DispenserId] = true; MotorSetSpeed(HW_Motor_Id, DispenserPrepareSpeed); CurrentDispenserSpeed[DispenserId] = DispenserPrepareSpeed; //usnprintf(IdsMessage, 80,"Presegment Prepare Dispenser %d speed %d",DispenserId,(int) DispenserPrepareSpeed); //REPORT_MSG(segmentfirst_speed,IdsMessage); //ReportWithPackageFilter(IDSFilter,IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, DispenserPrepareSpeed, 0); //SendJobProgress(0.0, 0, false, IdsMessage); } else { if (DispenserUsedInJob[DispenserId] == true) { if (Special_Dispensers == true) { IDS_Dispenser_Close_Valve_And_Stop_Motor(DispenserId,NULL); } else { MotorStop(HW_Motor_Id, Hard_Hiz); } CurrentDispenserSpeed[DispenserId] = 0; //usnprintf(IdsMessage, 80,"Presegment Prepare Dispenser %d stopped",DispenserId,(int) segmentfirst_speed); //ReportWithPackageFilter(IDSFilter,IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); } } }//for //usnprintf(IdMessage, 80,"Presegment Prepare K %d,C %d,M %d,Y %d,TI %d",CurrentDispenserSpeed[0], // CurrentDispenserSpeed[1],CurrentDispenserSpeed[2],CurrentDispenserSpeed[3],CurrentDispenserSpeed[4]); if (BuildIdsJobPrintString(IdMessage,"Presegment Prepare ",0)) ReportWithPackageFilter(IDSFilter,IdMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); DispenserBuildTimeCounter = 0; //DispenserPrepareControlId = AddControlCallback( IDS_PreSegmentPrepare_Callback, IDS_PRESEGMENT_TIME_STEP,TemplateDataReadCBFunction ,0, 0, 0 ); setRapidPressureRead(true); } } } //******************************************************************************************************************** uint32_t IDS_Valve_PresegmentValveReady(uint32_t deviceID, uint32_t ReadValue) { //TimerMotors_t HW_Motor_Id = DispenserIdToMotorId[deviceID]; //MotorStop(HW_Motor_Id,Hard_Hiz); //REPORT_MSG(deviceID,"Dispenser PreSegment called"); IDS_Valve_PresegmentReady( deviceID, ReadValue); return OK; } //******************************************************************************************************************** uint32_t IDS_Valve_PresegmentReady(uint32_t deviceID, uint32_t ReadValue) { int i; if (IDS_Active == false) return ERROR; DispenserPreSegmentReady[deviceID] = true; //REPORT_MSG(deviceID,"IDS_Valve_Presegment Ready"); for (i=0;i= lInterSegmentLength) { //IDS_Valve_PresegmentReady(1,0); ReportWithPackageFilter(IDSFilter,"End of Pre-segment Handling",__FILE__,__LINE__,InterSegmentStepsCount,RpWarning,(int)lInterSegmentLength,0); //PreSegmentReady(Module_IDS,ModuleDone); SafeRemoveControlCallback(DispenserPreSegmentControlId,IDSPreSegmentStateCallbackRunner); #ifndef LIGHT_COLORS if (CurrentDispenserSpeed[CLEANER_DISPENSER]>0) IDS_Cleaning_Stop_Cleaning_Solution (NULL); #endif setRapidPressureRead(false); //if (JobEndSequence == true) // DistanceToSpoolReady(Module_IDS,ModuleDone); } if (EnableCleaning == true) { if (( InterSegmentStartSprayCleaner )&&(InterSegmentStartSprayCleaner == InterSegmentStepsCount)) { ReportWithPackageFilter(IDSFilter,"Start Spray Cleaner",__FILE__,__LINE__,InterSegmentStepsCount,RpWarning,(int)lInterSegmentLength,0); IDS_Cleaning_Spray_Cleaning_Solution (CleaningDispenserSpeed,NULL); } /*if (InterSegmentStartRocking == InterSegmentStepsCount) { ReportWithPackageFilter(IDSFilter,"Start cleaning rockers",__FILE__,__LINE__,InterSegmentStepsCount,RpWarning,(int)lInterSegmentLength,0); //IDS_Cleaning_Move_Rockers (int LeftRockerSpeed,int RightRockerSpeed); }*/ if (( InterSegmentStartSprayCleaner )&& ((InterSegmentStepsCount>InterSegmentStartSprayCleaner)&&(InterSegmentStepsCount<(lInterSegmentLength-InterSegmentCenterRockers) ))) { if (ActuatorsCleaningSequence) IDS_Cleaning_Move_Actuators(); } if (( InterSegmentCenterRockers)&&(InterSegmentCenterRockers == (lInterSegmentLength-InterSegmentStepsCount-2000))) { if(Head_Type == HEAD_TYPE_ARC) { MotorStop(HARDWARE_MOTOR_TYPE__MOTO_DH_LID,Soft_Stop); } } if (( InterSegmentCenterRockers)&&(InterSegmentCenterRockers == (lInterSegmentLength-InterSegmentStepsCount))) { ReportWithPackageFilter(IDSFilter,"Stop spray and center rockers",__FILE__,__LINE__,InterSegmentStepsCount,RpWarning,(int)lInterSegmentLength,0); IDS_Cleaning_Stop_Cleaning_Solution (NULL); //IDS_Cleaning_Center_And_Stop_Rockers (int timeout,callback_fptr callback); } } if (FileBrushStop == NULL) { //cleaning return OK; } if ((InterSegmentStartWFCFDispensers > 12000)&&(InterSegmentStartWFCFDispensers == (InterSegmentStepsCount+12000))) { //start prepare 4 seconds before wcf IDSPresegmentPrepareStart(); PreSegmentPrepareStarted = true; } if ((PreSegmentWCFStarted == false)&&(PreSegmentPrepareStarted == true)) { IDS_PreSegmentPrepare_Callback(0,0); } if ((InterSegmentStartWFCFDispensers > 0)&&(InterSegmentStartWFCFDispensers == InterSegmentStepsCount)) { ReportWithPackageFilter(IDSFilter,"start dispensers at rate * WFCF",__FILE__,__LINE__,InterSegmentStepsCount,RpWarning,(int)lInterSegmentLength,0); PreSegmentWCFStarted = true; // stop any presegment prepare stages, if still exist PreSegmentPrepareStarted = false; setRapidPressureRead(false); if (FileBrushStop) { REPORT_MSG(FileBrushStop->index,"WFCFBrushStopRead Index"); Dispensers = FileBrushStop->dispensers; n_dispensers = FileBrushStop->n_dispensers; if (n_dispensers) { for (Dispenser_i = 0; Dispenser_i < n_dispensers; Dispenser_i++) { DispenserId = Dispensers[Dispenser_i]->index; HW_Motor_Id = DispenserIdToMotorId[DispenserId]; if (MotorsCfg[HW_Motor_Id].hardwaremotortype != DispenserIdToMotorId[DispenserId]) continue; if ((DispenserId == CLEANER_DISPENSER)||(DispenserId == LUBRICANT_DISPENSER)) { continue; } //(Speed*uStep*PPR)/((2*PI*Dispenser_Radius) segmentfirst_speed = Dispensers[Dispenser_i]->nanolitterpersecond / Dispensers[Dispenser_i]->nanoliterperpulse; if (Dispensers[Dispenser_i]->dispenserstepdivision != DISPENSER_STEP_DIVISION__Auto) { //MotorSetMicroStep(HW_Motor_Id, Dispensers[Dispenser_i]->dispenserstepdivision); segmentfirst_speed /= Dispensers[Dispenser_i]->dispenserstepdivision; //the dye supply is calculated based on a 1/8 microstep } else { segmentfirst_speed/=8;//MotorsCfg[HW_Motor_Id].microstep; //the dye supply is calculated based on a 1/8 microstep } if (segmentfirst_speed > MINIMAL_MOTOR_SPEED) { //char IdMessage[100]; segmentfirst_speed *= (100+WFCF); segmentfirst_speed /= 100; DispenserSegmentReady[DispenserId] = false; //Control3WayValvesWithCallback (DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer //IDS_Dispenser_Start_Motor_and_Open_Valve(DispenserId,segmentfirst_speed,NULL); MotorSetSpeed(HW_Motor_Id, segmentfirst_speed); CurrentDispenserSpeed[DispenserId] = segmentfirst_speed; /*usnprintf(IdMessage, 80, "WFCF Dispenser %d nl/sec %d nl/pulse %d Pulse/sec %d speed %d", DispenserId, (int) Dispensers[Dispenser_i]->nanolitterpersecond, (int) Dispensers[Dispenser_i]->nanoliterperpulse, (int) Dispensers[Dispenser_i]->pulsepersecond*1000, (int) segmentfirst_speed*1000); //REPORT_MSG(segmentfirst_speed,IdsMessage); ReportWithPackageFilter(IDSFilter,IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); //SendJobProgress(0.0, 0, false, IdsMessage);*/ } }//for //usnprintf(IdMessage, 80,"Presegment WFCF %d K %d,C %d,M %d,Y %d,TI %d",WFCF,CurrentDispenserSpeed[0], // CurrentDispenserSpeed[1],CurrentDispenserSpeed[2],CurrentDispenserSpeed[3],CurrentDispenserSpeed[4]); if (BuildIdsJobPrintString(IdMessage,"Presegment WFCF ",WFCF)) ReportWithPackageFilter(IDSFilter,IdMessage, __FILE__, __LINE__, FileBrushStop->index, RpWarning, lInterSegmentLength, 0); } } //startDispensersAtSegmentSpeed*1=WFCFClenerSpray(speed); } if ((InterSegmentStartWFCFDispensers > 0)&&((lInterSegmentLength-1000) == InterSegmentStepsCount)) { //close waste valve one second before segment - trial Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Head); } return OK; } uint32_t IDSCheckSegmentData(void *SegmentDetails, int SegmentId) { JobDescriptionFileSegment* PrevSegment = SegmentDetails; uint32_t status = OK; JobDescriptionFileBrushStop * tFileBrushStop; int Brush_i; Task_Stat statbuf; //check and close previous segment RemoveControlCallback(BrushStopControlId,IDSBrushStopRestartCallback); BrushStopControlId = 0xFF; if (PrevSegment) { if (JobBrushStopIdbrushstopscount) //we did not finish reading the brushstops of the previous segment { ReportWithPackageFilter(IDSFilter,"Unhandled brushstops remained",__FILE__,__LINE__,(int)JobBrushStopId,RpWarning,(int)PrevSegment->brushstopscount,0); //REPORT_MSG (Segment->brushstopscount, "Segment->brushstopscount"); //for (Brush_i=JobBrushStopId;Brush_ibrushstopscount;Brush_i++) #bug 3348 - unhandled jobstops stops too soon for (Brush_i=JobBrushStopId;Brush_ibrushstopscount;Brush_i++) { if (status == ERROR) break; tFileBrushStop = GetNextBrushStopFromJobFile(); if (tFileBrushStop) { FreeBrushStopFileData(tFileBrushStop); ReportWithPackageFilter(IDSFilter,"Unhandled brushstops handled",__FILE__,__LINE__,(int)Brush_i,RpWarning,(int)PrevSegment->brushstopscount,0); } else { Task_stat(Task_self(),&statbuf); ReportWithPackageFilter(IDSFilter,"Unhandled BrushStopRead Error",__FILE__,statbuf.used,(int)statbuf.stackSize,RpWarning,(int)statbuf.stackHeap,0); //JobEndReason = JOB_OUT_OF_DYE; //SegmentReady(Module_IDS,ModuleFail); ReportWithPackageFilter(IDSFilter,"Unhandled brushstops ERROR",__FILE__,__LINE__,(int)tFileBrushStop,RpWarning,(int)PrevSegment->brushstopscount,0); status = ERROR; break; } }//for brushstops } } ReportWithPackageFilter(IDSFilter,"Unhandled brushstops result",__FILE__,__LINE__,(int)Brush_i,RpWarning,(int)PrevSegment->brushstopscount,0); return OK; } uint32_t IDSPreSegmentState(void *SegmentDetails, int SegmentId) { JobSegment* Segment = SegmentDetails; JobDispenser **Dispensers; //set the speed only before the first segment, speed is constant accros job int Dispenser_i,n_dispensers,DispenserId; TimerMotors_t HW_Motor_Id; JobBrushStopId = 0; // activate control fr all motors /* wait for all dispensers to get to the required pressure * move the presegment ready when all dispensers are ready. */ ReportWithPackageFilter(IDSFilter,"IDSPreSegmentState",__FILE__,__LINE__,(int)Segment->n_brushstops,RpError,(int)SegmentId,0); if (JobBrushStopId>=Segment->n_brushstops) { ReportWithPackageFilter(IDSFilter,"Error JobBrushStopId",__FILE__,__LINE__,(int)Segment->n_brushstops,RpError,(int)0,0); JobEndReason = JOB_OUT_OF_DYE; usnprintf(AlarmReasonStr, 100, "IDS brushstop error %d above %d ",JobBrushStopId,Segment->n_brushstops); PreSegmentReady(Module_IDS,ModuleFail); return ERROR; } if (FileBrushStop) { //REPORT_MSG(FileBrushStop->index,"calling Free BrushStop file Read Index"); FreeBrushStopFileData(FileBrushStop); } if ((EnableIntersegment == true)&&(IntersegmentLength>0)) { Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Waste); //if intersegment is defined throw the ink away if (SegmentId>0) { lInterSegmentLength = ((IntersegmentLength*100)*1000/dyeingspeed); lInterSegmentLength-=(lInterSegmentLength%100); //round to a 100 multiplication InterSegmentStepsCount = 0; if (minimal_intersegment_length<((IntersegmentLength*100)*1000/dyeingspeed)) { DispenserPreSegmentControlId = AddControlCallback(NULL,IDSPreSegmentStateCallbackRunner, IDS_PRESEGMENT_TIME_STEP,TemplateDataReadCBFunction ,0, 0, 0 ); if (DispenserPreSegmentControlId == 0xFF) { ReportWithPackageFilter(IDSFilter,"Add control callback failed",__FILE__,__LINE__,(int)100,RpWarning,(int)0,0); return ERROR; } ReportWithPackageFilter(IDSFilter,"Add control callback ",__FILE__,__LINE__,(int)100,RpWarning,(int)lInterSegmentLength,0); } } } if (uploadstrategy == JOB_UPLOAD_STRATEGY__Default) { Dispensers = Segment->brushstops[JobBrushStopId]->dispensers; n_dispensers = Segment->brushstops[JobBrushStopId]->n_dispensers; } else { if (BrushStopControlId != 0xFF) { RemoveControlCallback(BrushStopControlId,IDSBrushStopRestartCallback); BrushStopControlId = 0xFF; } FileBrushStop = GetNextBrushStopFromJobFile(); if (FileBrushStop) { REPORT_MSG(FileBrushStop->index,"BrushStopRead Index"); Dispensers = FileBrushStop->dispensers; n_dispensers = FileBrushStop->n_dispensers; } else { ReportWithPackageFilter(IDSFilter,"End run - BrushStopReadError",__FILE__,__LINE__,(int)FileBrushStop,RpError,(int)0,0); JobEndReason = JOB_OUT_OF_DYE; usnprintf(AlarmReasonStr, 100, "IDS brushstop read error"); PreSegmentReady(Module_IDS,ModuleFail); } } if (n_dispensers) { for (Dispenser_i = 0;Dispenser_i < n_dispensers;Dispenser_i++) { DispenserId = Dispensers[Dispenser_i]->index; DispenserPreSegmentReady[DispenserId] = false; } for (Dispenser_i = 0;Dispenser_i < n_dispensers;Dispenser_i++) { DispenserId = Dispensers[Dispenser_i]->index; HW_Motor_Id = DispenserIdToMotorId[DispenserId]; if (MotorsCfg[HW_Motor_Id].hardwaremotortype != DispenserIdToMotorId[DispenserId])//unconfigured dispenser { REPORT_MSG(DispenserId,"Dispenser PreSegment not configured"); DispenserPreSegmentReady[DispenserId] = true; //27/03/19 check if job should be stopped IDS_Valve_PresegmentReady(DispenserId,0); //27/03/19 to be removed when the presegment handler will be added continue; } if ((DispenserId == CLEANER_DISPENSER)||(DispenserId == LUBRICANT_DISPENSER)) { REPORT_MSG(DispenserId,"Dispenser PreSegment cleaner or lubricant"); DispenserPreSegmentReady[DispenserId] = true; //27/03/19 check if job should be stopped IDS_Valve_PresegmentReady(DispenserId,0); //27/03/19 to be removed when the presegment handler will be added continue; } //REPORT_MSG(DispenserId,"IDS_Valve_Presegment start"); if (Dispensers[Dispenser_i]->dispenserstepdivision != DISPENSER_STEP_DIVISION__Auto) { MotorSetMicroStep(HW_Motor_Id, Dispensers[Dispenser_i]->dispenserstepdivision); } else { MotorSetMicroStep(HW_Motor_Id, MotorsCfg[HW_Motor_Id].microstep); } if ((EnableIntersegment == true)&&(IntersegmentLength>0.1)&&(SegmentId>0)) { if (DispenserUsedInJob[DispenserId] == true) { if (Special_Dispensers == true) { IDS_Dispenser_Close_Valve_And_Stop_Motor(DispenserId,NULL); } else { MotorStop(HW_Motor_Id,Soft_Hiz); //26/03/19 test without valves } CurrentDispenserSpeed[DispenserId] = 0; DispenserPreSegmentReady[DispenserId] = true; //27/03/19 check if job should be stopped REPORT_MSG(DispenserId,"Dispenser stopped pre Segment"); } } IDS_Valve_PresegmentReady(DispenserId,0); //27/03/19 to be removed when the presegment handler will be added } } //Task_sleep(5); PreSegmentWCFStarted = false; PreSegmentPrepareStarted = false; //REPORT_MSG(PreSegmentWCFStarted,"START IDSPresegmentPrepareStart"); // IDSPresegmentPrepareStart(); return OK; } //******************************************************************************************************************** uint32_t SegmentNumOfBrushStops = 0; double BrushStopTime = 0; uint32_t BrushStopCounter = 0; uint32_t BrushStopStartTime = 0,BrushStopLength = 0; void IDS_StartBrushStop(int n_dispensers, JobDispenser** Dispensers) { int Dispenser_i,DispenserId; TimerMotors_t HW_Motor_Id; double segmentfirst_speed; //ReportWithPackageFilter(IDSFilter,"IDS_StartBrushStop",__FILE__,__LINE__,(int)JobBrushStopId,RpWarning,(int)0,0); if (n_dispensers) { for (Dispenser_i = 0; Dispenser_i < n_dispensers; Dispenser_i++) { DispenserId = Dispensers[Dispenser_i]->index; HW_Motor_Id = DispenserIdToMotorId[DispenserId]; if (MotorsCfg[HW_Motor_Id].hardwaremotortype != DispenserIdToMotorId[DispenserId]) continue; if ((DispenserId == CLEANER_DISPENSER)||(DispenserId == LUBRICANT_DISPENSER)) { continue; } //(Speed*uStep*PPR)/((2*PI*Dispenser_Radius) segmentfirst_speed = Dispensers[Dispenser_i]->nanolitterpersecond / Dispensers[Dispenser_i]->nanoliterperpulse; if (Dispensers[Dispenser_i]->dispenserstepdivision != DISPENSER_STEP_DIVISION__Auto) { //MotorSetMicroStep(HW_Motor_Id, Dispensers[Dispenser_i]->dispenserstepdivision); segmentfirst_speed /= Dispensers[Dispenser_i]->dispenserstepdivision; //the dye supply is calculated based on a 1/8 microstep } else { segmentfirst_speed/=8;//MotorsCfg[HW_Motor_Id].microstep; //the dye supply is calculated based on a 1/8 microstep } if (segmentfirst_speed > MINIMAL_MOTOR_SPEED) { DispenserSegmentReady[DispenserId] = false; //Control3WayValvesWithCallback (DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer /*IDS_Dispenser_Start_Motor_and_Open_Valve(DispenserId, segmentfirst_speed, NULL);*/ //Control3WayValvesWithCallback (DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer if (Special_Dispensers == true) { IDS_Dispenser_Start_Motor_and_Open_Valve(DispenserId,segmentfirst_speed, NULL); } else { MotorSetSpeed(HW_Motor_Id, segmentfirst_speed); } CurrentDispenserSpeed[DispenserId] = segmentfirst_speed; /*usnprintf(IdsMessage, 80, "Dispenser %d nl/sec %d nl/pulse %d Pulse/sec %d speed %d steps %d/%d", DispenserId, (int) Dispensers[Dispenser_i]->nanolitterpersecond, (int) Dispensers[Dispenser_i]->nanoliterperpulse, (int) Dispensers[Dispenser_i]->pulsepersecond*1000, (int) (segmentfirst_speed*1000),Dispensers[Dispenser_i]->dispenserstepdivision,MotorsCfg[HW_Motor_Id].microstep); //REPORT_MSG(segmentfirst_speed,IdsMessage); ReportWithPackageFilter(IDSFilter,IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); //SendJobProgress(0.0, 0, false, IdsMessage);*/ } else { DispenserSegmentReady[DispenserId] = true; //IDS_Dispenser_Close_Valve_And_Stop_Motor(DispenserId,NULL);*/ if (DispenserUsedInJob[DispenserId] == true) { if (Special_Dispensers == true) { IDS_Dispenser_Close_Valve_And_Stop_Motor(DispenserId,NULL); } else { MotorStop(HW_Motor_Id, Hard_Hiz); } CurrentDispenserSpeed[DispenserId] = 0; } //ReportWithPackageFilter(IDSFilter,"inActive dispenser stopped", __FILE__, __LINE__, DispenserId, RpWarning, segmentfirst_speed, 0); } } //for } //usnprintf(IdMessage, 80,"IDS_StartBrushStop %d/%d K %d,C %d,M %d,Y %d,TI %d",FileBrushStop->index,SegmentNumOfBrushStops,CurrentDispenserSpeed[0], // CurrentDispenserSpeed[1],CurrentDispenserSpeed[2],CurrentDispenserSpeed[3],CurrentDispenserSpeed[4]); if (BuildIdsJobPrintString(IdMessage,"IDS_StartBrushStop ",FileBrushStop->index)) ReportWithPackageFilter(IDSFilter,IdMessage, __FILE__, SegmentNumOfBrushStops, FileBrushStop->index, RpWarning,(int)FileBrushStop->offsetmeters, 0); } uint32_t IDSBrushStopRestartCallback(uint32_t IfIndex, uint32_t readValue) { JobDispenser **Dispensers = NULL; int n_dispensers = 0; JobSegment* Segment = (void *)IfIndex; Task_Stat statbuf; if(BrushStopStartTime+BrushStopLength+100 < msec_millisecondCounter ) { ReportWithPackageFilter(IDSFilter,"!!!!!!!!!!!!Overtime!",__FILE__,msec_millisecondCounter,(int)BrushStopStartTime,RpWarning,(int)BrushStopLength,0); } if(++BrushStopCounter < BrushStopTime) { return OK; } BrushStopCounter = 0; BrushStopStartTime = msec_millisecondCounter; if (BrushStopControlId == 0xFF) { ReportWithPackageFilter(IDSFilter,"!!!BrushStopControlId = 0xFF",__FILE__,msec_millisecondCounter,(int)BrushStopStartTime,RpWarning,(int)BrushStopLength,0); return OK; } if (JobEndSequence == true) { ReportWithPackageFilter(IDSFilter,"JobEndSequence",__FILE__,__LINE__,(int)JobBrushStopId,RpWarning,(int)SegmentNumOfBrushStops,0); SafeRemoveControlCallback(BrushStopControlId,IDSBrushStopRestartCallback); BrushStopControlId = 0Xff; return OK; } if (uploadstrategy == JOB_UPLOAD_STRATEGY__Default) { Dispensers = Segment->brushstops[JobBrushStopId]->dispensers; n_dispensers = Segment->brushstops[JobBrushStopId]->n_dispensers; } else { if (FileBrushStop) FreeBrushStopFileData(FileBrushStop); FileBrushStop = GetNextBrushStopFromJobFile(); if (FileBrushStop) { Task_stat(Control_Task_Handle,&statbuf); //REPORT_MSG(FileBrushStop->index,"BrushStopRead Index"); //ReportWithPackageFilter(IDSFilter,"BrushStopRead Index",__FILE__,BrushStopTime,(int)FileBrushStop->index,RpWarning,(int)BrushStopStartTime,0); Dispensers = FileBrushStop->dispensers; n_dispensers = FileBrushStop->n_dispensers; } else { Task_stat(Task_self(),&statbuf); ReportWithPackageFilter(IDSFilter,"BrushStopRead Error",__FILE__,statbuf.used,(int)statbuf.stackSize,RpWarning,(int)statbuf.stackHeap,0); usnprintf(AlarmReasonStr, 100, "IDS brushstop error"); JobEndReason = JOB_OUT_OF_DYE; SegmentReady(Module_IDS,ModuleFail); } } if (n_dispensers) { IDS_StartBrushStop(n_dispensers, Dispensers); } JobBrushStopId++; //ReportWithPackageFilter(IDSFilter,"brushstop",__FILE__,__LINE__,(int)JobBrushStopId,RpMessage,(int)SegmentNumOfBrushStops,0); if (JobBrushStopId >= SegmentNumOfBrushStops) { ReportWithPackageFilter(IDSFilter,"last brushstop",__FILE__,__LINE__,(int)JobBrushStopId,RpWarning,(int)SegmentNumOfBrushStops,0); SafeRemoveControlCallback(BrushStopControlId,IDSBrushStopRestartCallback); BrushStopControlId = 0Xff; } return OK; } #define VALVE_DELAY 1 #ifdef VALVE_DELAY uint32_t IDSValveControlId = 0xFF; uint32_t IDSSegmentStateSetValve(uint32_t IfIndex, uint32_t BusyFlag) { SafeRemoveControlCallback(IDSValveControlId,IDSSegmentStateSetValve); Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Head); ReportWithPackageFilter(IDSFilter,"IDSSegmentState set valve after 1 second",__FILE__,__LINE__,(int)0,RpWarning,(int)0,0); return OK; } #endif //******************************************************************************************************************** uint32_t IDSSegmentState(void *SegmentDetails, int SegmentId) { JobSegment* Segment = SegmentDetails; JobDispenser **Dispensers; int n_dispensers; #ifdef VALVE_DELAY IDSValveControlId = AddControlCallback("VALVE_DELAY",IDSSegmentStateSetValve, eOneSecond,TemplateDataReadCBFunction,0,0,0); #else Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Head); #endif #ifndef LIGHT_COLORS if (CurrentDispenserSpeed[CLEANER_DISPENSER]>0) IDS_Cleaning_Stop_Cleaning_Solution(NULL); #endif SegmentNumOfBrushStops = Segment->n_brushstops; BrushStopTime = Segment->length*1000/(double)SegmentNumOfBrushStops; //brushstop in meters //brushstop in millisecond BrushStopTime = ((BrushStopTime*100)/dyeingspeed);//brushstop in seconds //BrushStopTime *= 1000; ReportWithPackageFilter(IDSFilter,"IDSSegmentState bss time, num of bss",__FILE__,__LINE__,(int)(BrushStopTime),RpWarning,(int)SegmentNumOfBrushStops,0); if (uploadstrategy == JOB_UPLOAD_STRATEGY__Default) { Dispensers = Segment->brushstops[JobBrushStopId]->dispensers; n_dispensers = Segment->brushstops[JobBrushStopId]->n_dispensers; } else { if (FileBrushStop) { Dispensers = FileBrushStop->dispensers; n_dispensers = FileBrushStop->n_dispensers; } else { ReportWithPackageFilter(IDSFilter,"BrushStopRead Error",__FILE__,__LINE__,(int)FileBrushStop,RpError,(int)0,0); } } //handle ending of presegment if (DispenserPreSegmentControlId != 0xFF) { ReportWithPackageFilter(IDSFilter,"IDS presegment not yet ended!!",__FILE__,DispenserPreSegmentControlId,(int)InterSegmentStepsCount,RpWarning,(int)lInterSegmentLength,0); RemoveControlCallback(DispenserPreSegmentControlId, IDSPreSegmentStateCallbackRunner ); DispenserPreSegmentControlId = 0xFF; } IDS_StartBrushStop(n_dispensers, Dispensers); JobBrushStopId++; if ((BrushStopTime)&&(SegmentNumOfBrushStops > 1)) { //BrushStopCounter = BrushStopTime+3; //move the IDS brush stop handling to highest priority in timing BrushStopControlId = AddControlCallback(NULL, IDSBrushStopRestartCallback, eOneMillisecond,TemplateDataReadCBFunction ,SegmentDetails, 0, 0 ); BrushStopStartTime = msec_millisecondCounter; BrushStopLength = BrushStopTime; if (BrushStopControlId == 0xFF) { ReportWithPackageFilter(IDSFilter,"Add control callback failed",__FILE__,__LINE__,(int)BrushStopTime,RpWarning,(int)0,0); return ERROR; } ReportWithPackageFilter(IDSFilter,"Add control callback ",__FILE__,__LINE__,(int)BrushStopTime,RpWarning,(int)n_dispensers,0); } else { if (FileBrushStop) FreeBrushStopFileData(FileBrushStop); FileBrushStop = NULL; } return OK; } //******************************************************************************************************************** uint32_t IDS_Valve_DistanceToSpoolValveReady(uint32_t deviceID, uint32_t ReadValue) { //TimerMotors_t HW_Motor_Id = DispenserIdToMotorId[deviceID]; //MotorStop(HW_Motor_Id,Hard_Hiz); //REPORT_MSG(deviceID,"Dispenser DTS called"); IDS_Valve_DistanceToSpoolReady( deviceID, ReadValue); return OK; } //******************************************************************************************************************** uint32_t IDS_Valve_DistanceToSpoolReady(uint32_t deviceID, uint32_t ReadValue) { int i; DispenserDistanceToSpoolReady[deviceID] = true; REPORT_MSG(deviceID,"IDS_Valve_DistanceToSpoolReady End called"); for (i=0;i= AutoHoming_JobEnd_PowerOn_off) { if (deviceID!=LUBRICANT_DISPENSER) { ReportWithPackageFilter(IDSFilter,"IDS_Valve_EndValveReady start homing",__FILE__,deviceID,(int)AutoHoming_Config,RpWarning,(int)AutoHoming_JobEnd_PowerOn_off,0); IDS_HomeDispenser (deviceID, 1000 , NULL); } } return OK; } //******************************************************************************************************************** uint32_t IDSEndState(void ) { int Dispenser_i; IDS_Active = false; Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Waste); REPORT_MSG(0,"Dispenser End Start"); if (BrushStopControlId != 0xFF) { RemoveControlCallback(BrushStopControlId,IDSBrushStopRestartCallback); BrushStopControlId = 0xFF; } if (FileBrushStop) FreeBrushStopFileData(FileBrushStop); FileBrushStop = NULL; FirstBrushStop = NULL; pressureReady = false; endOfPrepareWCF = false; if (DispenserPrepareControlId != 0xFF) { RemoveControlCallback(DispenserPrepareControlId, IDS_Prepare_Callback ); DispenserPrepareControlId = 0xFF; } if (DispenserPreSegmentControlId != 0xFF) { RemoveControlCallback(DispenserPreSegmentControlId, IDSPreSegmentStateCallbackRunner ); DispenserPreSegmentControlId = 0xFF; } //IDS_Dispenser_Store_Data (); for ( Dispenser_i = 0;Dispenser_i < MAX_SYSTEM_DISPENSERS;Dispenser_i++) { if (DispenserUsedInJob[Dispenser_i] == true) { AlarmHandlingSetAlarm (EVENT_TYPE__DISPENSER_1_UNDERPRESSURE+Dispenser_i,OFF); //handle alarm detection and operation if (Special_Dispensers == true) { IDS_Dispenser_Close_Valve_And_Stop_Motor(Dispenser_i,NULL); } else { MotorStop(DispenserIdToMotorId[Dispenser_i],Hard_Hiz); } #ifdef DISPENSER_VALVES_OPEN Control3WayValvesWithCallback (Dispenser_i, Dispenser_Mixer, IDS_Valve_EndValveReady); //direction: MidTank_Dispenser or Dispenser_Mixer #else Control3WayValvesWithCallback (Dispenser_i, MidTank_Dispenser, IDS_Valve_EndValveReady); //direction: MidTank_Dispenser or Dispenser_Mixer #endif CurrentDispenserSpeed[Dispenser_i] = 0; //IDS_Dispenser_Close_Valve_And_Stop_Motor(Dispenser_i,IDS_Valve_EndValveReady); } else { // RemoveControlCallback(ControlIdtoInactiveDispenserId[Dispenser_i], IDS_Check_Pressure_Callback ); // ControlIdtoInactiveDispenserId[Dispenser_i] = 0xFF; #ifdef DISPENSER_VALVES_OPEN Control3WayValvesWithCallback (Dispenser_i, Dispenser_Mixer, IDS_Valve_EndValveReady); //direction: MidTank_Dispenser or Dispenser_Mixer #endif IDS_Valve_EndValveReady(Dispenser_i,false); } } #ifndef LIGHT_COLORS if (CurrentDispenserSpeed[CLEANER_DISPENSER]>0) IDS_Cleaning_Stop_Cleaning_Solution(NULL); #endif IDS_StopLubrication(); Init_CleaningStageCounter();//set the counter before relocating IDS_Cleaning_stop_cleaner_motor(); HeadCard_Actuators_Relocate(); return OK; } uint32_t IDS_StartLubrication(void) { #ifdef LIGHT_COLORS #else IDS_Dispenser_Start_Motor_and_Open_Valve(LUBRICANT_DISPENSER,lubricant_speed,NULL); CurrentDispenserSpeed[LUBRICANT_DISPENSER] = lubricant_speed; Lubricant_2Way_Valve (START); #endif REPORT_MSG (lubricant_speed, "IDS_StartLubrication"); return OK; } uint32_t IDS_StopLubrication(void) { REPORT_MSG (lubricant_speed, "IDS_StopLubrication and home dispenser"); #ifdef LIGHT_COLORS #else Lubricant_2Way_Valve (STOP); //IDS_Dispenser_Close_Valve_And_Stop_Motor(LUBRICANT_DISPENSER,IDS_Valve_EndValveReady); TimerMotors_t HW_Motor_Id = DispenserIdToMotorId[LUBRICANT_DISPENSER]; MotorStop(HW_Motor_Id,Hard_Hiz); CurrentDispenserSpeed[LUBRICANT_DISPENSER] = 0; //IDS_HomeDispenser (LUBRICANT_DISPENSER, 1000 , NULL); do not fill lubricant between jobs #endif return OK; }