ihmcrobotics / ihmc-ethercat-master

Java EtherCAT master based on the SOEM EtherCAT master
Apache License 2.0
21 stars 14 forks source link

Issue with example #3

Closed ghost closed 7 years ago

ghost commented 7 years ago

Hey again :) I tried to run the DC example with the following command:

java -cp ethercat.jar us.ihmc.etherCAT.examples.DCExample

It resulted in the following exception: C:\Users\valkov\Desktop\test>java -cp ethercat.jar us.ihmc.etherCAT.examples.DCExample Exception in thread "main" java.lang.NoClassDefFoundError: us/ihmc/realtime/PriorityParameters at us.ihmc.etherCAT.examples.DCExample.(DCExample.java:40) at us.ihmc.etherCAT.examples.DCExample.main(DCExample.java:85) Caused by: java.lang.ClassNotFoundException: us.ihmc.realtime.PriorityParameters at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 2 more

When I provide it in eclipse with the PriorityParameters class from us.ihmc.realtime, more errors occur about missing libraries. I want to run the example (and other code from the library) on a working Beckhoff master and Hilscher slave, on a computer running on Windows 7 without internet access. The model of the slave is CIX50. How should I proceed ? I've considered cloning the repository for all libraries and importing them into Eclipse, but this feels like a dirty solution. If it is somehow maven or gradle related, I have maven on my machine that will compile the module for communication with Ethercat. The idea is to talk between Java and Ethercat with simple messages. Thank you :)

dljsjr commented 7 years ago

@veli4ko91 If you are familiar with Maven or Gradle you can pull in IHMC EtherCAT Master as a Maven dependency instead of building it from source which should resolve a lot of these issues for you. IHMC Realtime also has a native component to it as well so if you're pulling that in from source you'll have to build its native component as well. You'll also need IHMC Native Library Loader on your class path if you're doing it from source.

I just read that you're running from Windows. We only provide Maven releases for Linux unfortunately. SOEM works under Windows but our Realtime library does not, so I'm not sure if there's an easy way forward for this; by default the IHMC EtherCAT Master library expects to be able to start a real-time priority thread on the OS that it's running to make sure that timing guarantees are met. The library would need to be heavily customized to do realtime on Windows.

ghost commented 7 years ago

So technically,if I compile with Eclipse and Maven under Linux this could work out? How can I set up Maven to include the library,and thus use it? My experience so far with settings.xml and the repository from bintray was that Eclipse couldn't import its classes. There is a possibility to run the Ethercat Master under Linux aswell.

Also , note that once I include this library, more libraries pop up , so an automatic solution would be best.

dljsjr commented 7 years ago

Unfortunately compiling under Linux won't help you because there are native (C++ libraries bridged via JNI) components for both IHMC EtherCAT Master as well as IHMC Realtime so the native libraries will be compiled for Linux, not Windows. IHMC EtherCAT Master only works with Linux as its runtime because of our requirement for IHMC Realtime to make sure the software meets its realtime timing requirements.

As for using Maven, I'm not necessarily suggesting you use it to compile our software. I would suggest that you set up your personal project as a Maven or Gradle style project that you can use pre-built versions of our software by depending on our releases in your pom.xml (for Maven) or your build.gradle dependencies block (for Gradle). You can see the Gradle example of this in the README; if you're more comfortable with Maven the repo for the releases of IHMC EtherCAT Master can be found here: https://bintray.com/ihmcrobotics/maven-release/IHMCEtherCATMaster if you click "Set Me Up" in the top right, there are instructions for adding the software to your pom.xml.

ghost commented 7 years ago

Okay, so in case I want to use the library, I will have to set up a maven project in Linux (since there is Eclipse for Linux, this might work) and run Ethercat under Linux. So far I have more experience with Maven, so I will stick to it. I will ask if anything pops up :)

ghost commented 7 years ago

One more thing - how can I identify the artifact IDs, group IDs and versions in the Maven dependency in pom.xml? I added the "set me up" properties to my settings.xml, but I could not get it to find the libraries.

dljsjr commented 7 years ago

I'm not sure :-/

We use Gradle for everything. I have no experience with Maven.

But the GAV data should be:

<dependency>
  <groupId>us.ihmc</groupId>
  <artifactId>IHMCEtherCATMaster</artifactId>
  <version>0.10.2</version>
  <type>pom</type>
</dependency>
ghost commented 7 years ago

Alright, since I use Maven a lot (and Gradle is more or less a side tool for me), I will have to research it a bit. There is Gradle integration for Eclipse,so it might work too. Thank you , nevertheless.

dljsjr commented 7 years ago

No problem. I'll leave this issue open for a bit if you have any more questions.

ghost commented 7 years ago

After some tweaking with gradle and a Virtualbox virtual machine with Ubuntu, I arrived at the following exception: Cannot read current coalesce options from network card [989336207033] Cannot configure distrubed clocks, running without. Exception in thread "realtime-thread-1" java.lang.RuntimeException: java.io.IOException: Not all registeredSlaves are online and requireAllSlaves is true, got 0 registeredSlaves, expected 3 at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:220) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.access$000(EtherCATRealtimeThread.java:25) at us.ihmc.etherCAT.master.EtherCATRealtimeThread$1.run(EtherCATRealtimeThread.java:87) at us.ihmc.realtime.RealtimeThread.run(RealtimeThread.java:179) at us.ihmc.realtime.RealtimeThread.runFromNative(RealtimeThread.java:171) Caused by: java.io.IOException: Not all registeredSlaves are online and requireAllSlaves is true, got 0 registeredSlaves, expected 3 at us.ihmc.etherCAT.master.Master.init(Master.java:291) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:216) ... 4 more

It's rather nice to read this,as I really don't have any registered Ethercat master or slave devices at this time :) We'll see how this turns out.

ghost commented 7 years ago

I'm curious, since the next logical step is actually trying out the devices - do I require any additional drivers to run the master/slave system? I plan to test it out with the virtual machine first.

dljsjr commented 7 years ago

You will need implementations for the slaves you would like to test, written in Java. You can see examples of how to do this by looking at the us.ihmc.etherCat.slaves package in the src source set. Pattern matching off these slaves is probably easiest.

You will need to override the Slave abstract class and define a few fields overriding particular types to define the TxPDO and RxPDO structures.

ghost commented 7 years ago

Hey :) I have received the hardware on which to test the master-slave connection. What I currently have is an ethercat master card on my own computer (which is running a Linux virtual machine, where I have the eclipse-gradle-java workspace working), and an industrial computer with an already installed and configured ethercat slave card. I want to write a simple application which tests the connection between the two. I have connected one of the two ethernet slots of the master card with one of the two ethernet slots of the slave card. I tried overriding the Slave class and writing the product code and vendor ID constants, using the default constructor, and modified the DCExample a bit so that only one slave is included. For some reason, the slave seems to be offline. Any tips on how to proceed?:) Thanks a lot in advance :)

ghost commented 7 years ago

Here is the exception I am getting :)

Attaching native thread 2641 with priority 50 to JVM Cannot read current coalesce options from network card [1986464214293] Cannot configure distrubed clocks, running without. Exception in thread "realtime-thread-1" java.lang.RuntimeException: java.io.IOException: Not all registeredSlaves are online and requireAllSlaves is true, got 0 registeredSlaves, expected 1 at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:220) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.access$000(EtherCATRealtimeThread.java:25) at us.ihmc.etherCAT.master.EtherCATRealtimeThread$1.run(EtherCATRealtimeThread.java:87) at us.ihmc.realtime.RealtimeThread.run(RealtimeThread.java:179) at us.ihmc.realtime.RealtimeThread.runFromNative(RealtimeThread.java:171) Caused by: java.io.IOException: Not all registeredSlaves are online and requireAllSlaves is true, got 0 registeredSlaves, expected 1 at us.ihmc.etherCAT.master.Master.init(Master.java:291) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:216) ... 4 more

dljsjr commented 7 years ago

Did you call master.registerSlave(slave) after constructing your Slave? That error message is telling you that the slave is in fact online but you didn't register it with the software master so there's a mismatch between the EtherCAT topology defined in software vs the physical one.

I totally misread that exception, my apologies. Your original claim was correct. Do you have the SOEM native code compiled? It would help if you had access to their slaveinfo binary to do diagnostics.

dljsjr commented 7 years ago

We also expose this functionality via the Java library, if you can run the class us.ihmc.etherCAT.master.SlaveInfo. It takes as an argument the interface that the master is on, e.g. us.ihmc.etherCAT.master.SlaveInfo eth0 and if you pass in --pdo you can also see what the current process map is for the slaves.

jespersmith commented 7 years ago

@veli4ko91 When running on a Virtual Machine, make sure you directly attach the network card. If you use NAT or Host Only networking, the network card is controlled by the host system. Because EtherCAT does not use the IP headers, it will not go trough the host to the EtherCAT network.

When I do EtherCAT development in a VM I usually use a USB to Ethernet adapter. In Virtual Box, you can attach USB devices directly to the VM. This way, the USB device is directly controlled by the VM and you can send raw ethernet frames. I generally run Linux and use Windows to run the Beckhoff EtherCAT configurator this way.

ghost commented 7 years ago

Thank you both for the quick responses :) So far, I think that the virtual machine is not recognizing the Ethercat master card. It is a network adapter, PCI-based, with two slots, one of which is connected to the slave on the industrial PC. The card is a Beckhoff one FC9002. I currently don't have a USB Ethernet adapter,so I will have to figure out how to use it on the virtual machine. I have also considered installing some kind of diagnostic tool on the Windows the virtual box is running on, perhaps I can send some kind of ping to the Ethercat through it. Any recommendations? I searched the Beckhoff site for useful software today. I will check the SlaveInfo class at work on Monday. Maybe it will shed some light onto the situation.

dljsjr commented 7 years ago

Beckhoff provides TwinCAT and Configurator with free trials. TwinCAT is probably a good place to start.

https://www.beckhoff.com/english.asp?press/pr3412.htm

jespersmith commented 7 years ago

TwinCAT is pretty hard to use. I recommend the EtherCAT configurator (ET9000), you can get it here https://www.beckhoff.com/english.asp?download/ethercat_dev_software.htm

As EtherCAT doesn't use normal IP networking, the only way to make it work in a Virtual Machine is to have the VM directly acces the ethernet card. I only have experience with Virtual Box, and that only supports directly accessing USB devices.

I would recommend setting up a dual boot and run Linux directly though, it is the least error prone.

ghost commented 7 years ago

Hey :) Thanks again for the advice. I tried installing EtherCAT Configurator with an evaluation license, and I think I managed to get it working. One of the two ethernet ports (which is connected to the slave machine) managed to be able to switch states (init,pre-op, safe-op,op) and is also displaying a topology diagram. The topology diagram appears as one green line (when online) in a white canvas. Is it supposed to be that way? ^^ I have just one master,and one slave for now. I am searching for a way to send a packet to the slave machine. There is a tool there (netX configuration tool) which I can use to see how the packet was structured in bits. Concerning the virtual box linux machine, I guess it is not possible to use it at this moment.

ghost commented 7 years ago

It seems there is a "Toggle free run state" button in the abovementioned configurator tool :) with it,I managed to see that the connection is working.That's something ^^ Even managed to set some RxPDO bits in a direct manner and get them to display in in the netX configuration tool on the slave machine.

ghost commented 7 years ago

Things have continued to go nicely. I installed a linux dualboot on my computer and got the gradle/eclipse/jdk workspace going. Now there is a connection to the slave , the following error appears:

Attaching native thread 2939 with priority 50 to JVM Cannot read current coalesce options from network card Exception in thread "realtime-thread-1" java.lang.RuntimeException: java.io.IOException: Unconfigured slave on alias 0:0. Make sure to power cycle after changing alias addresses. at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:220) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.access$000(EtherCATRealtimeThread.java:25) at us.ihmc.etherCAT.master.EtherCATRealtimeThread$1.run(EtherCATRealtimeThread.java:87) at us.ihmc.realtime.RealtimeThread.run(RealtimeThread.java:179) at us.ihmc.realtime.RealtimeThread.runFromNative(RealtimeThread.java:171) Caused by: java.io.IOException: Unconfigured slave on alias 0:0. Make sure to power cycle after changing alias addresses. at us.ihmc.etherCAT.master.Master.init(Master.java:335) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:216) ... 4 more

Any tips?:)

dljsjr commented 7 years ago

Does the slave device you're using have an alias saved on the EEPROM?

ghost commented 7 years ago

It's possible, as the slave device came with the machine already pre-configured. How can I check this?:)

Here is the SlaveInfo from the master: Found 1 slaves 1 - 0:0 netX Manufacturer: 0x23091861 Product code: 0x00010020 Revision: 4 Distributed Clocks: yes SM(0) Address: 0x1000, length: 128 Flags: 65590 Type: Mailbox messages receive SM(1) Address: 0x1080, length: 128 Flags: 65586 Type: Mailbox messages transmit SM(2) Address: 0x1100, length: 200 Flags: 65652 Type: Cyclic process data receive SM(3) Address: 0x1400, length: 200 Flags: 65584 Type: Cyclic process data transmit

dljsjr commented 7 years ago

I think that I will show up in Configurator or TwinCAT but I don't remember how to see off the top of my head. You can also use our Java implementation of SlaveInfo that I mentioned above or the eepromtool binary that gets built when you build SOEM from source. If you use our SlaveInfo, the Slave Index, Alias, and Position will be the first thing printed for every device.

ghost commented 7 years ago

Aye,it is visible in the SlaveInfo class printed information (the one above :) ). Should I configure it somehow in my implementation?

dljsjr commented 7 years ago

alias and position should be constructor arguments for your Java slave implementation. Just pass in the correct numbers. Position is usually "0". We use that in cases where we have Slaves that cannot save an alias to their EEPROM so we can index them from the previous slave in the chain.

I just refreshed the page and saw your comment update with the SlaveInfo output. It's showing 0, 0, so make sure you're passing that in to the constructor when you instantiate your device on the Java side.

ghost commented 7 years ago

Awesome :)

Next thing is to configure the PDO structures,I guess:

Cannot read current coalesce options from network card Exception in thread "realtime-thread-1" java.lang.RuntimeException: java.io.IOException: Slave [name=EK1101, aliasAddress=0, position=0]: Slave [name=EK1101, aliasAddress=0, position=0]: 1024 unmapped bits in the input mappping. Make sure that your PDO configuration matches the slave information. at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:220) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.access$000(EtherCATRealtimeThread.java:25) at us.ihmc.etherCAT.master.EtherCATRealtimeThread$1.run(EtherCATRealtimeThread.java:87) at us.ihmc.realtime.RealtimeThread.run(RealtimeThread.java:179) at us.ihmc.realtime.RealtimeThread.runFromNative(RealtimeThread.java:171) Caused by: java.io.IOException: Slave [name=EK1101, aliasAddress=0, position=0]: Slave [name=EK1101, aliasAddress=0, position=0]: 1024 unmapped bits in the input mappping. Make sure that your PDO configuration matches the slave information. at us.ihmc.etherCAT.master.Slave.linkBuffers(Slave.java:744) at us.ihmc.etherCAT.master.Master.init(Master.java:396) at us.ihmc.etherCAT.master.EtherCATRealtimeThread.run(EtherCATRealtimeThread.java:216) ... 4 more

dljsjr commented 7 years ago

Rail gateways/couplers typically don't have any TxPDOs or RxPDOs, I skimmed the data sheet for the EK1101 on the Beckhoff website and it seems to confirm that there is no process object for this device… so I'm not sure why you'd be getting that error.

ghost commented 7 years ago

It is possible that the device is not EK1101. This is how I named my class in Java. Is there a quick way to check the device, without opening up the hardware industrial computer? It has windows 7 on it.

dljsjr commented 7 years ago

Ah, I see. I would suggest not using EK1101 as the name of your class as it conflicts with the name of a real Beckhoff device that is a dumb rail coupler.

You can pass in a --pdo argument to our SlaveInfo implementation to get a rough idea of the current PDO mapping, and you can use this to populate TxPDO and RxPDO implementations for your device. You can see examples of this in some of the other Slave examples included with this repo. You will also want to consult the data sheet for the device as provided from the manufacturer though to make sure you have a good understanding of what each entry does and to make sure that there are no mistakes in data types or addresses (what's in the data sheet vs. what's being reported by SlaveInfo).

ghost commented 7 years ago

Alright,I guess I was just overenthusiastic that I got it working. Renamed it to fit the theme now ^^ It seems it is populated by a huge number of UNSIGNED8 elements,so this is how I will structure my PDOs, and consult with the people behind the mapping. I will look into the Slave implementations so I can send a sample datagram (something filled with 7 values for the UNSIGNED8 elements,I guess :) )

ghost commented 7 years ago

It seems the device is stuck in the "ready/run" device state (out of communicating/run/ready/error), the network state being "stop" (out of operate/idle/stop/offline) in the netX Configuration Tool. Is there a way to programatically enable the communication?:)

When I get the state of the Slave with the getState() method,it appears as OFFLINE (if I put in a sleeping interval of 6 seconds for the main thread, it appears as SAFE_OP). The isOperational() method returns 'false' both ways. How do I set the state to "OP", so that I can start to exchange PDOs?

EDIT: When I turned off the "distributed clocks" functionality, the state changed automatically to "OP".I guess it wasn't supported.

For now,I linked the two PDOs (RxPDO, TxPDO) to the Slave implementation, however I do not seem to be able to force some bits in the communication to prove that it is working. Here's the code snippet of the slave so far:

public class MySlave extends Slave {

static final int vendorID = 0x23091861; static final int productCode = 0x00010020;

public MySlave(int alias, int position) { super(vendorID, productCode, alias, position); registerSyncManager(new SyncManager(2, true)); registerSyncManager(new SyncManager(3, true)); for (int i=0; i<128;i++) { slaveToMaster .data[i].set((short)7); masterToSlave.data[i].set((short)7); } sm(2).registerPDO(slaveToMaster); sm(3).registerPDO(masterToSlave); this.configurePDOWatchdog(1000000000); }

MyRxPDO slaveToMaster = new MyRxPDO(0x1600); MyTxPDO masterToSlave = new MyTxPDO(0x1a00);

public void test() { for (int i=0; i<128;i++) { slaveToMaster .data[i].set((short)7); masterToSlave.data[i].set((short)7); } }

The following information gets printed during launch: Cannot read current coalesce options from network card [787301730317] Slave [name=MySlave, aliasAddress=0, position=0] sm(2): Cannot configure PDO size on index 1c12. Object is read-only [787316503648] Slave [name=MySlave, aliasAddress=0, position=0] sm(2): Cannot Write PDO 1 configuration to index 1c12:1600. Object is read-only. [787331133376] Slave [name=MySlave, aliasAddress=0, position=0] sm(2): Cannot configure PDO size on index 1c12. Object is read-only [787345764069] Slave [name=MySlave, aliasAddress=0, position=0] sm(3): Cannot configure PDO size on index 1c13. Object is read-only [787360337027] Slave [name=MySlave, aliasAddress=0, position=0] sm(3): Cannot Write PDO 1 configuration to index 1c13:1a00. Object is read-only. [787374940227] Slave [name=MySlave, aliasAddress=0, position=0] sm(3): Cannot configure PDO size on index 1c13. Object is read-only

It's possible that the addresses have been mixed up. Here is the information I am getting from the SlaveInfo:

Found 1 slaves 1 - 0:0 netX Manufacturer: 0x23091861 Product code: 0x00010020 Revision: 4 Distributed Clocks: yes SM(0) Address: 0x1000, length: 128 Flags: 65590 Type: Mailbox messages receive SM(1) Address: 0x1080, length: 128 Flags: 65586 Type: Mailbox messages transmit SM(2) Address: 0x1100, length: 200 Flags: 65652 Type: Cyclic process data receive RxPDO 0x1600 1. RxPDO 0x2000:0x01 UNSIGNED8 1 Byte Out (0) .. 0x2000:0x80 UNSIGNED8 1 Byte Out (127) SM(3) Address: 0x1400, length: 200 Flags: 65584 Type: Cyclic process data transmit TxPDO 0x1a00 1. TxPDO 0x3000:0x01 UNSIGNED8 1 Byte In (0) .. 0x3000:0x7f UNSIGNED8 1 Byte In (126) 0x3000:0x80 UNSIGNED8 1 Byte In (127)

The application is running now,it doesn't throw any exceptions :) By the way, thanks for the timely support. My tests are slowly starting to work right :)

EDIT: It's beautiful xD I managed to fill the input in the industrial PC with '7' numbers :) So I guess the software is working great :)

Feel free to close the issue. I will open a new one if something shows up :)

DanielsMaCoogan commented 7 years ago

I realise this is not normal practice to append something to the end of a closed issue but as I am not familiar with Github I wasn't sure where else to place comment. Anyway my comment is that I found your library a good way to get ethercat communications working with 2 slaves. The issue discussion above helped me through some issues I was having. I slightly modified your elmo example to do a couple of simple motion tests with a Yaskawa SGD7S drive using profile position mode. I also did a simple test of an Wago I/O module. I will most likely fork this repository to attempt to provide more detailed slave info for the slaves I intend on using as well as provide some more functionality for movement commands. Just wondering if any of the authors of this code have have any recommendations for how to use it for servo motion given that the setting of the controlword and response to the statusword that is required to achieve motion is embedded in slave classes. Anyway regardless of anyone getting back to me good work with the library. I appreciate you sharing all your hard work. thanks Matt

dljsjr commented 7 years ago

@veli4ko91 Glad you figured it out! Don't worry about the comments about certain objects being read-only. Some slaves allow for multiple PDO configurations, some don't, and the "true" argument to registerSyncManager tells it to try and do that rewrite. But if the Tx and Rx structs you laid out match what's already on the device then you don't need to worry about that reconfiguration failing.

dljsjr commented 7 years ago

@DanielsMaCoogan The doControl method that you see in the Elmo example (which is a method on the EtherCAT Realtime Thread class) gets called periodically, add some getters and setters to your slave and then perform your control logic in the doControl method, doing any off-board feedback required. If you set the control word from the doControl method it will go out automatically on the RxPDO.

DanielsMaCoogan commented 7 years ago

@dljsjr Thanks for the suggestion. I believe I am more or less on the right track. Out of interest is there an appropriate forum for discussion on your work? This issue section doesn't seem appropriate as I'm not reporting an issue as such. I say this as it might be a while before I could propose any additions to your code (if at all) and the least I could do is provide talking points that might help people find a quicker path to applying the code.

jespersmith commented 7 years ago

@DanielsMaCoogan For now we only have the issue tracker, this is also a good place to ask for help (use either a help wanted or question label). As for general comments and proposals for new features, you can use the enhancement tag. In my opinion any question or comment how to use the library is a bug in the documentation and examples.

You can also create your slave implementations in your own project. The DSP402 class is a general class for motion drives and you should be able to extend it for the Yaskawa drive (the class works with both the Elmo and Copley drives we have).