Auslesen von SMB-Werten aus dem TwinCAT I/O Treiber
Falls statt einer TwinCAT PLC Laufzeitumgebung nur TwinCAT-CP zur Verfügung steht, kann das SMB-Gerät auch mit Hilfe des ADS-Clients ausgelesen werden. Die Visualisierung erlaubt ein ständiges Überwachen der gewünschten Temperatur- oder Lüfterwerte. Somit kann frühzeitig erkannt werden, ob sich die aktuelle Temperatur einem kritischen Wert annähert. Nachfolgend ein Beispiel einer möglichen Implementierung in Java (Für eine korrekte Funktionsweise muss ein SMB-Gerät in der aktuellen System Manager-Konfiguration eingetragen sein)
Beispielprogramm 'Auslesen von SMB-Werten aus dem TwinCAT I/O Treiber' entpacken: sample10.zip
- Um das *.jar Sample ausführen zu können, muss in der Konsole im korrekten Verzeichnis der Befehl 'java -classpath "Sample10.jar;[Pfad zu TcJavaToAds.jar] Main' ausgeführt werden (Beispielpfad: "C:TwinCAT\Ads Api\AdsToJava\*"). Dazu muss java in den Umgebungsvariablen eingetragen sein.
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 dieser Ansicht kann der jeweilige IndexOffset der verschiedenen Eingänge abgelesen werden.
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()));
}
}
}