Reading SMB values from the TwinCAT I/O driver
If only TwinCAT-CP is available instead of a TwinCAT PLC runtime environment, the SMB device can also be read out using the ADS client. The visualization allows constant monitoring of the desired temperature or fan values. Thus, it can be detected at an early stage whether the current temperature is approaching a critical value. The following is a sample of a possible implementation in Java (for correct operation, an SMB device must be entered in the current System Manager configuration)
Unpack the sample program 'Reading SMB values from the TwinCAT I/O driver': sample10.zip
- To execute the *.jar sample, the command 'java -classpath "Sample10.jar;[path to TcJavaToAds.jar] Main' must be executed in the console in the correct directory (example path: "C:TwinCAT\Ads Api\AdsToJava\*"). For this, java must be entered in the environment variables.
import de.beckhoff.jni.Convert;
import de.beckhoff.jni.JNIByteBuffer;
import de.beckhoff.jni.tcads.AdsCallDllFunction;
import de.beckhoff.jni.tcads.AdsState;
import de.beckhoff.jni.tcads.AmsAddr;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.ByteBuffer;
import java.util.Timer;
public class Main {
final static short SMB_ID = 32;
public static void main(String[] args) {
long err = 0;
AmsAddr addr = new AmsAddr();
Visualization visu = new Visualization();
visu.addWindowListener(new WindowAdapter() {
// When the form is closed the ADS port is closed as well
@Override
public void windowClosing(WindowEvent e) {
AdsCallDllFunction.adsPortClose();
}
});
try {
// Open communication
AdsCallDllFunction.adsPortOpen();
err = AdsCallDllFunction.getLocalAddress(addr);
addr.setPort(AdsCallDllFunction.AMSPORT_R0_PLC_RTS1);
if (err != 0) {
System.out.println("Error: Open communication: 0x"
+ Long.toHexString(err));
} else {
System.out.println("Success: Open communication!");
}
//Gets the device count of devices appended to active configuration
//if TwinCAT is in run mode
AdsState adsState = new AdsState();
AdsState deviceState = new AdsState();
err = AdsCallDllFunction.adsSyncReadStateReq(addr,
adsState,
deviceState);
if(err!=0) {
visu.setInfoMsg("Error: Read device state: 0x"
+ Long.toHexString(err));
}
if (adsState.getState() != AdsState.ADSSTATE_RUN ) {
visu.setInfoMsg("Bad TwinCAT state: "
+ "Please restart the application.");
} else {
//Get devices count
JNIByteBuffer deviceCountBuff = new JNIByteBuffer(Integer.SIZE / Byte.SIZE);
int devCount = 0;
err = AdsCallDllFunction.adsSyncReadReq(addr,
0x5000,
0x2,
deviceCountBuff.getUsedBytesCount(),
deviceCountBuff);
if(err!=0) {
visu.setInfoMsg("Error: Read device count: 0x"
+ Long.toHexString(err));
}
devCount = Convert.ByteArrToInt(
deviceCountBuff.getByteArray()) + 1;
//Gets the device count of devices appended to active
//configuration as zero-based index and gets the devices ID's of
//all active devices for the remaining indices (inverted sort)
JNIByteBuffer deviceBuff = new JNIByteBuffer(
(Short.SIZE * devCount) / Byte.SIZE);
ByteBuffer devices;
err = AdsCallDllFunction.adsSyncReadReq(addr,
0x5000,
0x1,
deviceBuff.getUsedBytesCount(),
deviceBuff);
if(err!=0) {
visu.setInfoMsg("Error: Read devices: 0x"
+ Long.toHexString(err));
}
devices = ByteBuffer.wrap(deviceBuff.getByteArray());
for (int i = 1; i <= devCount; i++) {
JNIByteBuffer identNrBuff =
new JNIByteBuffer(Short.SIZE / Byte.SIZE);
short identNr = 0;
//gets the device identification number
//(Motherboard System Management Bus(SMB) => 32)
err = AdsCallDllFunction.adsSyncReadReq(addr,
0x5000 + devices.getShort(i),
0x7,
identNrBuff.getUsedBytesCount(),
identNrBuff);
if(err!=0) {
visu.setInfoMsg("Error: Read ident numbers: 0x"
+ Long.toHexString(err));
} else {
identNr = Convert.ByteArrToShort(
identNrBuff.getByteArray());
//checks whether the device is of type SMB
if (identNr == SMB_ID) {
int indexGroup = 0x9000 + devices.getShort(i);
// If a SMB-Device was found a TimerTask is started
// to read the specified input from the device once
// every second
Timer tmr = new Timer();
tmr.schedule(new SMBTask(indexGroup, addr, visu),
0,
1);
break;
}
}
}
}
} catch (Exception ex) {
visu.setInfoMsg(ex.getMessage());
}
}
}
In this view the respective IndexOffset of the different inputs can be read.
import de.beckhoff.jni.Convert;
import de.beckhoff.jni.JNIByteBuffer;
import de.beckhoff.jni.tcads.AdsCallDllFunction;
import de.beckhoff.jni.tcads.AmsAddr;
import java.util.TimerTask;
class SMBTask extends TimerTask {
private int indexGroup;
private AmsAddr addr;
private Visualization visu;
public SMBTask(int indexGroup, AmsAddr addr, Visualization visu) {
this.indexGroup = indexGroup;
this.addr = addr;
this.visu = visu;
}
@Override
public void run() {
long err = 0;
JNIByteBuffer valueBuff = new JNIByteBuffer(Integer.SIZE / Byte.SIZE);
//IOffset may be adjusted to monitor different inputs e.g. temperature
err = AdsCallDllFunction.adsSyncReadReq(this.addr,
this.indexGroup,
0x4,
valueBuff.getUsedBytesCount(),
valueBuff);
if(err!=0) {
visu.setInfoMsg("Error: Retrieve value: 0x" + Long.toHexString(err));
} else {
visu.setCurValue(Convert.ByteArrToInt(valueBuff.getByteArray()));
}
}
}