From: Proctor, K. <Kel...@al...> - 2001-11-06 08:40:55
|
> Well I have a design that works out with the javax.comm API ;) > The idea I had was to use a Pipe for "pumping" the incoming data through > on > the respective registered event: > > public void serialEvent(SerialPortEvent e) { > // Determine type of event. > switch (e.getEventType()) { > //pump data through the pipe > case SerialPortEvent.DATA_AVAILABLE: > try { > while (m_SerialIn.available()>0) { > try { > int b=m_SerialIn.read(); > //DEBUG: m_Pipe.write(m_SerialIn.read()); > m_Pipe.write(b); > //DEBUG: System.out.println("Piped byte "+b+"="+(char)b); > [Proctor, Kelvin] The section above would be better if you had an array as large as the largest message and used block reads and writes (only partially filling the array usually) here instead of doing everything a single byte at a time. > } catch (IOException ex) { > System.err.println(ex); > return; > } > } > } catch (Exception ex) { > //handle > > } > break; > > } > }//serialEvent > > Just to get the idea.... > [Proctor, Kelvin] I like the idea above. Have you tested that this actually works and can recognise frames that only have a 4ms break between them? (4ms for 9600 bps) I had a few ways that *should* have worked with the javax.comm API but I am having difficulty in getting them to detect the frame break, even on a PII, let alone a TINI where the processing speed will be much slower. You would also want to be careful when you react to serial port events, particularly on the master. A master should never react to unsolicited packets in any way. > I have also provided the infrastructure like for TCP, i.e. there is now > a ModbusSerialListener, and a SerialConnection, and a > ModbusSerialTransaction. > > > > I have also done a LRC, it would be good to have some results to test > > against..it is much simpler then the version you created, and it gives > > the same results but anyway, maybe there is some official way to test > > this. > > > > [Proctor, Kelvin] > > I'll be fascinated to see this, the version I came up with was > >pretty small already. With a function like this (and more importantly > for > >the CRC for RTU) getting a fast implementation is the most important > issue, > >even at he expense of 10 vs 5 lines of code. I have not had a serious > think > >out run time of my algorithm yet, I just hacked up something that > worked. > > I made a trial and error approach, and I realized that Java naturally > does the job: > > private final int getLRC(byte[] data,int tailskip) { > byte lrc=0; > for (int i = 0; i < data.length-tailskip; i++) { > lrc+=data[i]; > } > return (int)-lrc; > }//getLRC > > The tailskip is just to skip the LRC byte that is part of the byte[] > data (because that one represents the complete > frame without FRAME_START and FRAME_END). > > You see it is a one line algorithm, however, there is one thing I am not > exactly sure about and that is the > minus in the return. This way the result is exactly the same as coming > from your algorithm. > [Proctor, Kelvin] I would be interested to test the speed of the two implementations. While I agree yours looks nicer there is a problem in the way the JVM does maths. All byte and short values are converted to int values before any maths is done and then converted back to there original data types. While the difference will be very minimal if any at all it would be interesting to do a test to see how much difference there is. (Maybe I'll do that one day when I have nothing better to do :) > > >> [Wimberger, Dieter] > >> Another point I did not have the time to figure out are the > >> specifications for the serial communication. As each cycle is a > >> Transaction (Request by Master, Response by addressed Client) there > must > >> be some mechanism that repeats frames if there is no answer from any > >> client (timeout??) or to notify the master that a frame is corrupt > etc. > >> Any clue about this so far? > >> > > > [Proctor, Kelvin] > > You are correct here. The spec is a little vague about how all > of > >this should be handled. My original code does not handle any of this > at all > >really, only working out if a packet was sent correctly or not and > returning > >true or false. The method you have used in creating a Connection class > is a > >good solution to this. You can set it up to know how many times to > retry, > >set the timeouts etc.. and it can reference the transport. It adds > another > >layer but I think it is justified. > > Well this is a bit what I did, as I already mentioned above. It looks > pretty much the same as for TCP now, it > is just that a few of those mechanisms are not hooked up yet (i.e. the > exception handling etc.). > However, there must be a schema for reactions, as this is supposed to be > an industrial field bus. I will plunge into a research session, when I > find some time. We have resources here probably, as some guys are > teaching data transmission and industrial field bus lectures :) > > > > > [Proctor, Kelvin] > > This was always likely to be that hardest part of the design. > My > >design was written with the TINI in mind and written to be able to act > as a > >master or a slave. You code was written with the master only in mind > and > >designed to be run from a PC or similar. These two setups have very > >different requirements. > > Hmm yes. Well one thing is that it runs on TINI, and I am testing this, > however, to be optimized to > run there and to run there are two different things. I'll say with a bit > of work we get results that will > be fine for us. > > > Until we work out where we want to go with this I'll keep > plugging > >away with my transport code under my old architecture (as it's more > basic > >and hence a little simpler to integrate into). I'll have another go at > the > >serial stuff tonight and see where it gets me. > > Well that I agree, still it is nice to see that most of the > infrastructure as I put it up seems to work out > also for the serial transport flavors :) > I will try to put up the package as soon as possible, so that you can > take a look at things, and judge > were you want to go. I guess with the RTU it is going to be another > challenge, because I wonder how to > measure 3.5 character times etc. Without a Mechanism to ensure that a > message was received or not, > there is not much chance to get this going nicely from Java (with this > high level view of the system...) > [Proctor, Kelvin] Yes, this is a tricky one. I'm playing with some test code in a very basic app and I'm having trouble getting it to detect really sort breaks (like 4ms breaks) and I think it is time to get the digital scope out to see how long some of these breaks really are. I have the serial cable running through a break out box and I have a decent digital scope with 1 shot triggering so I'll probably use that to have a look at things soon. > > I'm interested in what you would intend to use the ObjectPool > for? > >I have usually seen this term used in the context of web servers where > a set > >of threads is created and then reset after a connection assigned to > them > >dies, as opposed to creating a new thread each time. If this is the > case > >I'm note sure it would really help this all that much. In my > experience of > >control type application this is not as much of a problem. In the case > of a > >web server you will have a lot of very short sessions open and closed > all > >the time, each dealing with only a single request. In the case of > ModbusTCP > >this is unlikely as most application will open a single connect and > keep it > >open send possibly millions of requests across a single connection. > > > If I have your definition of an ObjectPool wrong let me know. > > What you are describing is a so called thread pool. I have implemented > this for the TCPSlave, as it is perfectly > suited for multithreaded handling of Request-Response problems :) > Runs also nicely on Tini..... > An ObjectPool is to recycle instances at runtime. This would prevent the > code from constantly creating new instances and garbage collecting > unreferenced old ones. This is not the best practice for all cases, as > the trade off on present up to date computers with an up-to date JVM is > low compared to the additional cost on creating and garbage collecting. > At least this is what "Effective Java" author Joshua Bloch believes. > However, we are dealing with an embedded system, and probably the trade > off balance is better for the pool implementation. > This would clutter the code a little bit more, and needs care when > Recycling (to assert that the object is like newly created), > but maybe it is worth a try..... > [Proctor, Kelvin] I'm note sure which objects you wish to recycle. If this is for all the command objets etc... then this sounds like a good idea. I'm just note sure which objects you wish to add to the pool. As for the thread pool for the TCPSlave I'm still unsure of how useful this really is given the nature of the type of systems that are likely to be talking to this, as per my comparison with the web server examples from my last post. I'm not yet convinced that the benefit in run time justifies they increase in complexity given the relative infrequency with which new connections are likely to be created. In the case of a SCADA link to a TINI sitting in the field the connection might stay open for months. With a setup like this with only 1 new connection every 3 months (approx for example) it hardly justifies all the code and effort to create a thread pool. This is a *very* different scenario from a web server...... > Best regards, > Dieter > > _______________________________________________ > jModbus-devel mailing list > jMo...@li... > https://lists.sourceforge.net/lists/listinfo/jmodbus-devel Alcoa World Alumina Australia is a trading name of Alcoa of Australia Limited, ACN 004 879 298 |