-
Notifications
You must be signed in to change notification settings - Fork 2
Automatic update of signals using intrinsic functions
You can learn here:
- how to use intrinsic functions to automatically update signals from cycle to cycle
HINT: A brief description of more elbfisch features you can find here
HINT: A brief lecture you can find here
Intrinsic functions are available since Elbfisch V2.×. Look here on how to install the latest version
They are helpful to continously update the value of signals during the life time of an elbfisch module. This mechanism frees the programmer from dealing with the calculation of signals in every state a certain module runs through.
The example below shows a module called “IntrinsicFunctionModule” which receives the actual position of an axis, for instance from a rotary encoder (in this example simulated by a module called “MovementSimulationModule”), and continously calculates the actual velocity (signal Velocity) of a body driven by the axis.
The signal “Velocity” is instantiated in the constructor of IntrinsicFunctionModule as follows:
velocity = new Decimal(this,"Velocity", () -> computeVelocity());Check the code of the IntrinsicFunctionModule below for details of computeVelocity().
- The signal changes its state to invalid whenever the computation of its intrinsic functions fails (throws an exception).
- If the module invalidates the signal explicitly by use of invalidate() its intrinsic function is dropped and cannot be reactivated.
- Signals driven by an intrinsic functions cannot be connect()’ed as target.
- Computation of intrinsic functions is automatically stopped when the containing module is terminated (returns from work()).
Module “IntrinsicFunctionModule”:
/**
* PROJECT : Elbfisch - java process automation controller (jPac)
* MODULE : IntrinsicFunctionModule.java
* VERSION : -
* DATE : -
* PURPOSE :
* AUTHOR : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
* REMARKS : -
* CHANGES : CH#n <Kuerzel> <datum> <Beschreibung>
*
* This file is part of the jPac process automation controller.
* jPac is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jPac is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the jPac If not, see <http://www.gnu.org/licenses/>.
*/
package org.elbfisch.elbfisch.samples;
import org.jpac.Decimal;
import org.jpac.InputInterlockException;
import org.jpac.Logical;
import org.jpac.Module;
import org.jpac.OutputInterlockException;
import org.jpac.PeriodOfTime;
import org.jpac.ProcessEvent;
import org.jpac.ProcessException;
import org.jpac.ShutdownRequestException;
import org.jpac.SignalInvalidException;
/**
*
* @author berndschuster
*/
public class IntrinsicFunctionModule extends Module{
private Decimal velocity;
private Decimal position;
private Logical positionValid;
private Long lastNanoTime;
private Double lastPosition;
private MovementSimulationModule movementSimulationModule;
public IntrinsicFunctionModule(Module containingModule, String identifier){
super(containingModule, identifier);
try{
lastNanoTime = System.nanoTime();
position = new Decimal(this,"Position");
velocity = new Decimal(this,"Velocity", () -> computeVelocity());
positionValid = new Logical(this,"PositionValid",() -> position.isValid());
//instantiate the module, which simulates the movement of a physical body
movementSimulationModule = new MovementSimulationModule(this, "MovementSimulationModule");
//connect its positon signal to my own position
movementSimulationModule.getPosition().connect(position);
}
catch(Exception exc){
Log.error("Error: ", exc);
}
}
@Override
public void start(){
//start movement simulation module
movementSimulationModule.start();
// start myself
super.start();
}
@Override
protected void work() throws ProcessException {
boolean done = false;
ProcessEvent pot = new PeriodOfTime(500 * ms);
Log.info("started ...");
do{
try{
pot.await();
Log.info(velocity.toString());
} catch(ShutdownRequestException exc){
done = true;
}
}
while(!done);
try{Thread.sleep(500);}catch(Exception exc){};
Log.info("finished.");
}
public double computeVelocity() throws SignalInvalidException{
long actualNanoTime;
double deltaTime;
double deltaPosition;
actualNanoTime = System.nanoTime();
deltaTime = ((double)(actualNanoTime - lastNanoTime))/(double)sec;
lastNanoTime = actualNanoTime;
if (!position.isValid()){
//velocity is invalid since the position gets valid ...
lastPosition = null;
throw new SignalInvalidException(position.getQualifiedIdentifier());
}
if (lastPosition == null){
//Initialize lastPosition on first cycle "position" gets valid
lastPosition = position.get();
//but the velocity can't be computed in this state either
throw new SignalInvalidException(position.getQualifiedIdentifier());
}
//position is valid and lastPosition is initialized
deltaPosition = position.get() - lastPosition;
lastPosition = position.get();
return deltaPosition/deltaTime;
}
@Override
protected void preCheckInterlocks() throws InputInterlockException {
//nothing to do here
}
@Override
protected void postCheckInterlocks() throws OutputInterlockException {
//nothing to do here
}
@Override
protected void inEveryCycleDo() throws ProcessException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
Module “MovementSimulationModule”:
/**
* PROJECT : Elbfisch - java process automation controller (jPac)
* MODULE : MovementSimulationModule.java
* VERSION : -
* DATE : -
* PURPOSE :
* AUTHOR : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
* REMARKS : -
* CHANGES : CH#n <Kuerzel> <datum> <Beschreibung>
*
* This file is part of the jPac process automation controller.
* jPac is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jPac is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the jPac If not, see <http://www.gnu.org/licenses/>.
*/
package org.elbfisch.elbfisch.samples;
import org.jpac.Decimal;
import org.jpac.InputInterlockException;
import org.jpac.Module;
import org.jpac.NextCycle;
import org.jpac.OutputInterlockException;
import org.jpac.PeriodOfTime;
import org.jpac.ProcessException;
/**
*
* @author berndschuster
*/
public class MovementSimulationModule extends Module{
private Decimal position;
private double rad;
public MovementSimulationModule(Module containingModule, String identifier){
super(containingModule, identifier);
this.rad = 0.0;
try{
position = new Decimal(this,"Position",0.0);
}
catch(Exception exc){
Log.error("Error: ", exc);
}
}
@Override
protected void work() throws ProcessException {
NextCycle nextCycle = new NextCycle();
PeriodOfTime pot5sec = new PeriodOfTime(5 * sec);
try{
do{
Log.info("started...");
//generate a position signal for 100 cycles
for(int i = 0; i < 100; i++){
position.set(Math.sin(rad += 0.1));
nextCycle.await();
}
//simulate a sensor failure which longs for 5 sec.
position.invalidate();
pot5sec.await();
} while(true);
} finally{
Log.info("finished.");
}
}
public Decimal getPosition(){
return this.position;
}
@Override
protected void preCheckInterlocks() throws InputInterlockException {
//nothing to do here
}
@Override
protected void postCheckInterlocks() throws OutputInterlockException {
//nothing to do here
}
@Override
protected void inEveryCycleDo() throws ProcessException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
That’s all you need to know !