A fault routine can absolutely be used to clear a fault and continue running. However, there has been a problem. Clearing the fault doesn't fix that problem. Often times we will use the fault routine to clear the fault while we start an orderly shutdown. Once the shutdown is complete, the fault routine may allow the controller to enter Fault Mode.
When created, A fault routine exists within a Program. If a major recoverable fault occurs while scanning within that Program, then your fault routine will execute. If the scan is in another Program or Task, your fault routine will not execute. If the fault is not related to logic, such as the failure of a required I/O module, your fault routine will not execute.
Within a fault routine I typically include logic to do three things.
- Set a bit to indicate there has been a fault. I create a BOOL tag for this. I can then use that tag in my normal logic to alert that we have had a fault. I might call it ProgramName_Fault_Flag or something along those lines.
- Capture the fault information. Use a GSV instruction to capture this information so I have it stored. This requires creating a UDT and then a tag using that UDT to capture the structured data.
- Clear the fault. I use an SSV with a separate fault tag using that same UDT. That tag has all zeroes for its data which will clear out the fault in the controller. You might choose to have conditions to examine what the fault code was and then decide if you want to allow the fault to be cleared.
So, the process would be that when your fault occurs, the scan will interrupt and jump to your fault routine. It will scan through that fault routine and let's say that we clear the fault. At the end of the fault routine the scan will return to the next instruction from where it was interrupted and resume scanning at that point.
Now, let's say that the fault routine did not clear the fault. At the end of the scan of the fault routine the controller will check to see if there is a Controller Fault Handler (CFH). If there is one, the scan will jump to the Fault Handler. If there is no CFH, then the controller will enter Fault Mode and stop scanning.
Now let's assume that the fault is unrelated to logic. If the connection to a required I/O module fails, the Fault Routine will NOT execute and the controller will interrupt the scan wherever it is and jump to the CFH if it exists. If it does not exist, then the controller will fault.
The Controller Fault Handler is sort of a catch all, or last resort for capturing faults. It can be tricky when you set it up because you have to create a Program and a Main routine, but not a fault routine. I would include the same three things here that I would include in a normal fault routine.
If your project contains multiple Programs, then you would have to create a Fault Routine for each Program. Alternatively, you could instead create one CFH that could handle faults for all Programs. And remember that the Fault Handler is the only way to react to I/O type faults.
Same rule applies. If at the end of the scan of the CFH if you have cleared the fault, the scan resumes with the next instruction from where it was interrupted. If the fault has not been cleared, then the controller will enter Fault Mode and shut down.
Example of my typical Fault Routine or CFH logic (with a special nod to theColonel26)
OG