/************************************************************************************************************************ * 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 "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; #define MAX_DYE_DISPENSERS 6 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}; bool DispenserReady[MAX_SYSTEM_DISPENSERS] = {true}; bool IDS_Active = 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); bool JobStartStopBackLash[MAX_SYSTEM_DISPENSERS] = {false,false,false,false,false,false,false,false}; /******************** 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; uint32_t InterSegmentStartSprayCleaner = 0; uint32_t InterSegmentStartRocking = 0; uint32_t InterSegmentCenterRockers = 0; uint32_t LeftRockerSpeed = 20; uint32_t RighttRockerSpeed = 20; uint32_t CleaningDispenserSpeed = 40; uint32_t InterSegmentStartWFCFDispensers; uint32_t WFCF = 80; bool EnableCleaning = true; 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; Report("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) RighttRockerSpeed = ids_rightcleaningmotorspeed; Report("IDS_Dispenser_SetPreSegmentCleaningValues ",__FILE__,__LINE__,CleaningDispenserSpeed,RpWarning,(int)LeftRockerSpeed,0); Report("IDS_Dispenser_SetPreSegmentCleaningValues ",__FILE__,__LINE__,InterSegmentStartSprayCleaner,RpWarning,(int)InterSegmentCenterRockers,0); } uint32_t DispenserPreSegmentControlId = 0xFF; uint32_t BrushStopControlId = 0xFF; uint32_t PreSegmentControlId = 0xFF; uint32_t IDS_DispenserControlInit() { DispensersControl = (void *)(DISPENSERS_MAP_IN_FLASH); //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; } } if (request->pvinputfilterfactormode > MAX_CONTROL_SAMPLES) request->pvinputfilterfactormode = MAX_CONTROL_SAMPLES; //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 /*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 * * */ // /* void OpenJobFile(); void CloseJobFile(); JobDescriptionFileSegment *GetNextSegmentFromJobFile(); void FreeSegmentFileData(JobDescriptionFileSegment *Segment); JobDescriptionFileBrushStop *GetNextBrushStopFromJobFile(); void FreeBrushStopFileData(JobDescriptionFileBrushStop *BrushStop); */ //******************************************************************************************************************** //************************** 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 ((brushCounter % 100)==0) { SendJobProgress(0.0,0,false, "Processing file"); 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 { LOG_ERROR (BrushStop->index, "no dispensers in brushstop"); } FreeBrushStopFileData(BrushStop); BrushStop = NULL; } else { LOG_ERROR (BrushStop, "malloc error"); status = ERROR; } }//for brushstops }// if brush stop count FreeSegmentFileData(Segment); Segment = GetNextSegmentFromJobFile(); } FreeSegmentFileData(Segment); CloseJobFile(); } 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++; } } Report("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; 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; #define PRESSURE_READ_TIME_GAP 100 void DispenserPrepareReady(void) { int i; for (i=0;i DispenserPreparePressure) { NumofReadyDispensers++; tempSpeed = CurrentDispenserSpeed[i]; updatedSpeed = (tempSpeed*0.985>100)?tempSpeed*0.985:100; MotorSetSpeed(HW_Motor_Id, updatedSpeed); CurrentDispenserSpeed[i] = updatedSpeed; //Report("IDS reduce speed",__FILE__,i,(int)tempSpeed,RpWarning,(int)updatedSpeed,0); } else { tempSpeed = CurrentDispenserSpeed[i]; updatedSpeed = (tempSpeed*1.02<1000)?tempSpeed*1.02:1000; MotorSetSpeed(HW_Motor_Id, updatedSpeed); CurrentDispenserSpeed[i] = updatedSpeed; //Report("IDS accelerate speed",__FILE__,i,(int)tempSpeed,RpWarning,(int)updatedSpeed,0); } } } if ((NumofReadyDispensers)&&(DispenserBuildTimeCounter%1000 == 0)) Report("IDS_Prepare_Callback",__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)NumOfActiveDispensers,0); if (NumofReadyDispensers>=NumOfActiveDispensers) pressureReady = true; if ((DispenserBuildTimeCounter >= DispenserPrepareTimeout)||(pressureReady == true)) { SafeRemoveControlCallback(DispenserPrepareControlId, IDS_Prepare_Callback ); DispenserPrepareControlId = 0xFF; Report("IDS_Prepare_Callback SafeRemoveControlCallback",__FILE__,DispenserBuildTimeCounter,NumofReadyDispensers,RpWarning,(int)NumOfActiveDispensers,0); setRapidPressureRead(false); //DispenserPrepareReady(); PrepareReady(Module_IDS,ModuleDone); } return OK; } //******************************************************************************************************************** //******************************************************************************************************************** uint32_t IDSPrepareState(void *JobDetails) { int Motor_i, Pid_Id; //start IDS control for all motors IDS_Active = true; Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Waste); //JobTicket* JobTicket = JobDetails; if ((feedertension>0.1)&&(feedertension<1.5)) { Report("Setting pressure from RML feeder tension",__FILE__,__LINE__,(int)(feedertension*100),RpWarning,(int)(DispenserPreparePressure*100),0); DispenserPreparePressure = feedertension; } if ((pullertension>200)&&(pullertension<1150)) { Report("Setting pressure from RML feeder tension",__FILE__,__LINE__,(int)(pullertension),RpWarning,(int)CleaningDispenserSpeed,0); CleaningDispenserSpeed = pullertension; } 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; } uint32_t IDSPrepareStartDispenserAfterHoming(uint32_t DispenserId, uint32_t Result) { double dispenserspeed = 0; Report("IDSPrepare Start Dispenser After Homing",__FILE__,__LINE__,DispenserId,RpWarning,(int)Result,0); dispenserspeed = DispenserPrepareSpeed; if (DispenserUsedInJob[DispenserId] == true) //we actually should check for all dispensers { Report("Prepare Speed",__FILE__,__LINE__,DispenserId,RpWarning,(int)dispenserspeed,0); IDS_Dispenser_Start_Motor_and_Open_Valve(DispenserId,dispenserspeed, NULL); } return OK; } void IDSPrepareStart(void) { int i; double dispenserspeed = 0; if (IDS_Active == false) { LOG_ERROR(IDS_Active,"IDSPrepareStart Not in a job"); return; } NumOfActiveDispensers = 0; for (i = 0; i < MAX_DYE_DISPENSERS; i++) { if (DispenserUsedInJob[i] == true) //we actually should check for all dispensers { IDS_StopHomeDispenser(i); JobStartStopBackLash[i] = true; NumOfActiveDispensers++; } else { if (AutoHoming_Config >= AutoHoming_JobEnd_PowerOn_off) { REPORT_MSG((int)i, "Homing inactive dispenser"); IDS_HomeDispenser (i, 1000 , NULL); } } } if (NumOfActiveDispensers) { REPORT_MSG((int)NumOfActiveDispensers, "Num Of Active Dispensers"); for (i = 0; i < MAX_DYE_DISPENSERS; i++) { dispenserspeed = DispenserPrepareSpeed; TimerMotors_t HW_Motor_Id = DispenserIdToMotorId[i]; if (DispenserUsedInJob[i] == true) //we actually should check for all dispensers { if (HomingActive[i] == false) { Report("Prepare Speed",__FILE__,__LINE__,i,RpWarning,(int)dispenserspeed,0); MotorSetDirection((TimerMotors_t)HW_Motor_Id,MotorsCfg[HW_Motor_Id].directionthreadwize); //set the dispenser to the IDS_Dispenser_Start_Motor_and_Open_Valve(i,dispenserspeed, NULL); } else { Report("IDSPrepare Stop Dispenser Homing",__FILE__,__LINE__,i,RpWarning,(int)HomingActive[i],0); IDS_HomeDispenserWaitForHomingEnd(i, DispenserPrepareTimeout/2 , IDSPrepareStartDispenserAfterHoming); } } } } DispenserBuildTimeCounter = 0; DispenserPrepareControlId = AddControlCallback(NULL, IDS_Prepare_Callback, PRESSURE_READ_TIME_GAP,TemplateDataReadCBFunction ,0, 0, 0 ); setRapidPressureRead(true); } //******************************************************************************************************************** //************************** IDS PRESEGMENT BUILDUP ****************************************************************** //******************************************************************************************************************** JobDescriptionFileBrushStop * FileBrushStop; char IdsMessage[100]; //******************************************************************************************************************** uint32_t IDS_PreSegmentPrepare_Callback(uint32_t DispenserId, uint32_t ReadValue) { bool pressureReady = false; int i; int NumofReadyDispensers = 0; TimerMotors_t HW_Motor_Id; float updatedSpeed,tempSpeed; //REPORT_MSG((int)DispenserPrepareControlId, "Prepare Callback"); DispenserBuildTimeCounter+=PRESSURE_READ_TIME_GAP; 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; //Report("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; //Report("IDS PreSegment accelerate speed",__FILE__,i,(int)tempSpeed,RpWarning,(int)updatedSpeed,0); } } } if ((NumofReadyDispensers)&&(DispenserBuildTimeCounter%1000 == 0)) Report("IDS_PreSegmentPrepare_Callback",__FILE__,DispenserBuildTimeCounter,InterSegmentStepsCount,RpWarning,(int)NumOfActiveDispensers,0); if (NumofReadyDispensers>=NumOfActiveDispensers) pressureReady = true; if ((DispenserBuildTimeCounter >= DispenserPrepareTimeout)||(pressureReady == true)) { Report("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) { Report("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[Dispenser_i] = true; MotorSetSpeed(HW_Motor_Id, DispenserPrepareSpeed); CurrentDispenserSpeed[Dispenser_i] = DispenserPrepareSpeed; usnprintf(IdsMessage, 80,"Presegment Prepare Dispenser %d speed %d",DispenserId,(int) DispenserPrepareSpeed); //REPORT_MSG(segmentfirst_speed,IdsMessage); Report(IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, DispenserPrepareSpeed, 0); //SendJobProgress(0.0, 0, false, IdsMessage); } else { MotorStop(HW_Motor_Id, Hard_Hiz); CurrentDispenserSpeed[Dispenser_i] = 0; usnprintf(IdsMessage, 80,"Presegment Prepare Dispenser %d stopped",DispenserId,(int) segmentfirst_speed); Report(IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); } } DispenserBuildTimeCounter = 0; //DispenserPrepareControlId = AddControlCallback( IDS_PreSegmentPrepare_Callback, PRESSURE_READ_TIME_GAP,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 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)) { Report("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[Dispenser_i] = segmentfirst_speed; usnprintf(IdMessage, 80, "WFCF Dispenser %d nl/sec %d nl/pulse %d speed %d", DispenserId, (int) Dispensers[Dispenser_i]->nanolitterpersecond, (int) Dispensers[Dispenser_i]->nanoliterperpulse, (int) segmentfirst_speed); //REPORT_MSG(segmentfirst_speed,IdsMessage); Report(IdsMessage, __FILE__, __LINE__, Dispenser_i, RpWarning, segmentfirst_speed, 0); //SendJobProgress(0.0, 0, false, IdsMessage); } } } } //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; //check and close previous segment if (PrevSegment) { if (JobBrushStopIdbrushstopscount) //we did not finish reading the brushstops of the previous segment { Report("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++) { if (status == ERROR) break; tFileBrushStop = GetNextBrushStopFromJobFile(); if (tFileBrushStop) { FreeBrushStopFileData(tFileBrushStop); Report("Unhandled brushstops handled",__FILE__,__LINE__,(int)Brush_i,RpWarning,(int)PrevSegment->brushstopscount,0); } else { status = ERROR; break; } }//for brushstops } } return status; } 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. */ REPORT_MSG(Segment->n_brushstops,"IDSPreSegmentState"); if (JobBrushStopId>=Segment->n_brushstops) { LOG_ERROR(Segment->n_brushstops,"Error JobBrushStopId"); JobEndReason = JOB_OUT_OF_DYE; 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; DispenserPreSegmentControlId = AddControlCallback(NULL,IDSPreSegmentStateCallbackRunner, 100,TemplateDataReadCBFunction ,0, 0, 0 ); if (DispenserPreSegmentControlId == 0xFF) { Report("Add control callback failed",__FILE__,__LINE__,(int)100,RpWarning,(int)0,0); return ERROR; } Report("Add control callback ",__FILE__,__LINE__,(int)100,RpWarning,(int)IntersegmentLength,0); /*if (EnableCleaning == true) { InterSegmentStartSprayCleaner = 500; InterSegmentStartRocking = 1000; InterSegmentCenterRockers = 3000; }*/ //InterSegmentStartWFCFDispensers = (lInterSegmentLength>5000)?lInterSegmentLength-5000:lInterSegmentLength; } } /*if (SegmentId == 0)//first segment - running the DTS out of the drier { Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Waste); //if intersegment is defined throw the ink away for (Dispenser_i = 0; Dispenser_i < MAX_SYSTEM_DISPENSERS; Dispenser_i++) { HW_Motor_Id = DispenserIdToMotorId[Dispenser_i]; //MotorStop(HW_Motor_Id,Hard_Hiz); //26/03/19 test without valves if (DispenserUsedInJob[Dispenser_i]==true)//unconfigured dispenser { MotorStop(HW_Motor_Id, Soft_Hiz); CurrentDispenserSpeed[Dispenser_i] = 0; } } lInterSegmentLength = (dryerbufferCentimeters*1000/dyeingspeed); lInterSegmentLength-=(lInterSegmentLength%100); //round to a 100 multiplication InterSegmentStepsCount = 0; DispenserPreSegmentControlId = AddControlCallback( IDSPreSegmentStateCallbackRunner, 100,TemplateDataReadCBFunction ,0, 0, 0 ); if (DispenserPreSegmentControlId == 0xFF) { Report("Add control callback failed",__FILE__,__LINE__,(int)100,RpWarning,(int)0,0); return ERROR; } Report("Add control callback ",__FILE__,__LINE__,(int)100,RpWarning,(int)lInterSegmentLength,0); if (EnableCleaning == true) { InterSegmentStartSprayCleaner = 500; InterSegmentStartRocking = 1000; InterSegmentCenterRockers = 3000; } InterSegmentStartWFCFDispensers = lInterSegmentLength-5000; }*/ 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 { LOG_ERROR(FileBrushStop,"BrushStopReadError"); JobEndReason = JOB_OUT_OF_DYE; 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)) { MotorStop(HW_Motor_Id,Soft_Hiz); //26/03/19 test without valves CurrentDispenserSpeed[DispenserId] = 0; //MotorSetSpeed(HW_Motor_Id, 5); //CurrentDispenserSpeed[Dispenser_i] = 5; 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; void IDS_StartBrushStop(int n_dispensers, JobDispenser** Dispensers) { int Dispenser_i,DispenserId; TimerMotors_t HW_Motor_Id; double segmentfirst_speed; Report("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 MotorSetSpeed(HW_Motor_Id, segmentfirst_speed); CurrentDispenserSpeed[DispenserId] = segmentfirst_speed; usnprintf(IdsMessage, 80, "Dispenser %d nl/sec %d nl/pulse %d speed %d steps %d/%d", DispenserId, (int) Dispensers[Dispenser_i]->nanolitterpersecond, (int) Dispensers[Dispenser_i]->nanoliterperpulse, (int) (segmentfirst_speed*1000),Dispensers[Dispenser_i]->dispenserstepdivision,MotorsCfg[HW_Motor_Id].microstep); //REPORT_MSG(segmentfirst_speed,IdsMessage); Report(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);*/ MotorStop(HW_Motor_Id, Hard_Hiz); CurrentDispenserSpeed[DispenserId] = 0; //Report("inActive dispenser stopped", __FILE__, __LINE__, DispenserId, RpWarning, segmentfirst_speed, 0); } } } } uint32_t IDSBrushStopRestartCallback(uint32_t IfIndex, uint32_t readValue) { JobDispenser **Dispensers = NULL; int n_dispensers = 0; JobSegment* Segment = (void *)IfIndex; 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) { REPORT_MSG(FileBrushStop->index,"BrushStopRead Index"); Dispensers = FileBrushStop->dispensers; n_dispensers = FileBrushStop->n_dispensers; } else { LOG_ERROR(FileBrushStop,"BrushStopReadError"); JobEndReason = JOB_OUT_OF_DYE; SegmentReady(Module_IDS,ModuleFail); } } if (n_dispensers) { IDS_StartBrushStop(n_dispensers, Dispensers); } JobBrushStopId++; Report("brushstop",__FILE__,__LINE__,(int)JobBrushStopId,RpWarning,(int)SegmentNumOfBrushStops,0); if (JobBrushStopId >= SegmentNumOfBrushStops) { Report("last brushstop",__FILE__,__LINE__,(int)JobBrushStopId,RpWarning,(int)SegmentNumOfBrushStops,0); SafeRemoveControlCallback(BrushStopControlId,IDSBrushStopRestartCallback); BrushStopControlId = 0Xff; } return OK; } //******************************************************************************************************************** uint32_t IDSSegmentState(void *SegmentDetails, int SegmentId) { JobSegment* Segment = SegmentDetails; JobDispenser **Dispensers; int n_dispensers; Valve_Set(VALVE_MIXCHIP_WASTECH, Mixer_Head); SegmentNumOfBrushStops = Segment->n_brushstops; BrushStopTime = Segment->length/SegmentNumOfBrushStops; //brushstop in meters BrushStopTime = ((BrushStopTime*100)/dyeingspeed);//brushstop in seconds BrushStopTime *= 1000; //brushstop in millisecond Report("IDSSegmentState",__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 { LOG_ERROR(FileBrushStop,"BrushStopReadError"); } } IDS_StartBrushStop(n_dispensers, Dispensers); JobBrushStopId++; if ((BrushStopTime)&&(SegmentNumOfBrushStops > 1)) { BrushStopControlId = AddControlCallback(NULL, IDSBrushStopRestartCallback, BrushStopTime,TemplateDataReadCBFunction ,SegmentDetails, 0, 0 ); if (BrushStopControlId == 0xFF) { Report("Add control callback failed",__FILE__,__LINE__,(int)BrushStopTime,RpWarning,(int)0,0); return ERROR; } Report("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; for (i=0;i= AutoHoming_JobEnd_PowerOn_off) { Report("IDS_Valve_EndValveReady start homing",__FILE__,deviceID,(int)AutoHoming_Config,RpWarning,(int)AutoHoming_JobEnd_PowerOn_off,0); if (deviceID!=LUBRICANT_DISPENSER) 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; if (DispenserPrepareControlId != 0xFF) { RemoveControlCallback(DispenserPrepareControlId, IDS_Prepare_Callback ); DispenserPrepareControlId = 0xFF; } if (DispenserPreSegmentControlId != 0xFF) { RemoveControlCallback(DispenserPreSegmentControlId, IDSPreSegmentStateCallbackRunner ); DispenserPreSegmentControlId = 0xFF; } for ( Dispenser_i = 0;Dispenser_i < MAX_SYSTEM_DISPENSERS;Dispenser_i++) { if (DispenserUsedInJob[Dispenser_i] == true) { MotorStop(DispenserIdToMotorId[Dispenser_i],Hard_Hiz); Control3WayValvesWithCallback (Dispenser_i, MidTank_Dispenser, IDS_Valve_EndValveReady); //direction: MidTank_Dispenser or Dispenser_Mixer CurrentDispenserSpeed[Dispenser_i] = 0; //IDS_Dispenser_Close_Valve_And_Stop_Motor(Dispenser_i,IDS_Valve_EndValveReady); } else { IDS_Valve_EndValveReady(Dispenser_i,false); } } IDS_StopLubrication(); return OK; } uint32_t IDS_StartLubrication(void) { IDS_Dispenser_Start_Motor_and_Open_Valve(LUBRICANT_DISPENSER,lubricant_speed,NULL); CurrentDispenserSpeed[LUBRICANT_DISPENSER] = lubricant_speed; REPORT_MSG (lubricant_speed, "IDS_StartLubrication"); Lubricant_2Way_Valve (START); return OK; } uint32_t IDS_StopLubrication(void) { Lubricant_2Way_Valve (STOP); IDS_Dispenser_Close_Valve_And_Stop_Motor(LUBRICANT_DISPENSER,IDS_Valve_EndValveReady); CurrentDispenserSpeed[LUBRICANT_DISPENSER] = 0; REPORT_MSG (lubricant_speed, "IDS_StopLubrication"); return OK; }