# Help?

M

#### Mike Whiteley

I am in urgent need or raising a Square D PLC from the dead.

It has the SY/MAX 400 processors and a SyMate Class 8010 TypeSFW374

No one knows anything about it (including me), but I have been charged with its resurrection. It has not worked been used in over 10 years.

The technology is somewhat foreign to me so I feel
underqualified to re-write new drivers and the current interface is a less than desirable DOS application.

Does this group assist in the use of Linux to talk with this beast?

I would like to use it to collect data and send it to an oracle database, then redistribute it out to JAVA applets served from an Apache server on the same box (as Oracle). This would be harder to do if I try to use the DOS app. It may run in win95, but I prefer to have it be reliable.

Mike

Michael Whiteley
Test Systems Engineering
Thiokol Propulsion
(435) 863-2561

C

#### Curt Wuollet

I can try to help, unfortunately I don't know much about SquareD stuff either. It's probably possible to reverse engineer the programming interface if it's serial as is typical for the time frame. You put a comm analyzer (datascope)between the DOS app and the PLC and note what happens when you do various things. The datascope can store the interchange and you write Linux code to send the same strings, etc. Then if the protocol isn't obvious you can twiddle bits until you understand what's going on. I can get you started with the framework to open a port and communicate. The datascope I use is DOS freeware. (I've been meaning to write a Linux version for years). Between this and some research you oughta be able to get it working. Perhaps if you were to detail what you know about the interface and exactly what you want to do, I can help and it would be instructive for those unfamiliar with Linux serial comms. We will probably have to do some of this down the road a bit. It's not too difficult once you get the hang of it.

Regards

cww

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

T

#### Tony Robohn

I replied to your post under Applications, this post has a little more info. The SFW374 is the programming software (the older version). If you want to collect data out of this PLC, your best bet may be one of the Niobrara (www.niobrara.com) cards that will let you communicate with the PLC with Modbus. Once the information is available via Modbus, you can use Java to communicate. I remember seeing some Modbus Java classes that someone developed available on the internet. A search with any search engine should locate them.

Hope this helps,

Tony

M

#### Mauricio Pupo

I am very interested on this discussion, since I am working on something similar for my graduate project. I have used a comm analyzer to spy the serial communication with a commercial PLC and got the Modbus strings sent by the configurator for an AND function programmed in Ladder. The objective is to copy this string to Linux C code so that it will do the same for the PLC as the proprietary configuration software does. After that I plan to add a Web interface via CGI. Right now I am stuck in how to do the coding, as I lack proper C programming skills. So far, I have only experimented unsuccessfully with some Modbus RTU code from the cvs directory. Can someone advice me on how to start a C code in Linux for sending a Modbus RTU string to the PLC ?, say for example [01][3e][00][59][01][00][79][0c] (this is the start for downloading the AND function)
Thanks,
Mauricio S. Pupo

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

C

#### Curt Wuollet

Hi Mauricio

I'll be happy to send you the boilerplate I use to init a serial port and start sending data. For now, if you understand printf, sprintf is about the easiest way to format packets or strings to send. you simply declare an array, int buff[80} and sprintf lets you format the data in many different ways. e.g. sprintf(buff,"%h%h%h%h\0",a,b,c,d); Then, make sure the string is terminated with a null and use : write( fd, buff, sizeof(buff)); This is fairly automatic and lets you concentrate on the data.

I'm not sure whether Modbus RTU sends the ascii representation or the actual bytes represented by the hex notation in your example. If you can fill me in, I'll include code that should get you started. Linux serial facilities are truly excellent and great for automation projects.

Regards

cww

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

J

#### Jeff Thurman

Curt:

Would you post this on the list. I have written modbus ascii and rtu in basic but not "c" and would be interested in seeing what your "boilerplate" is that you use to init a serial port.

jeff

C

#### Curt Wuollet

Hi Jeff,

No problem! It might be later on today or tonight as I've got some day job issues to deal with. In the meantime does anyone know just what actually hits the wire for Modbus RTU? I don't have anything handy that spells it out. I'm assuming from Jeff's mention of "ascii" and "rtu" that the bytes are binary. But, I have found the assuming anything in the weird world of
automation protocols is a bad idea. It only chenges the format string for sprintf but I'd like to get it right.

Regards

cww

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

C

#### Curt Wuollet

OK

Here's a small program I hacked together to demo a Matrix Orbital display with a keypad.

(program is an attachment to the following message: http://www.control.com/control_com/990552516/index_html)

Demonstrates setting up a port and reading and writing along with catching signals and restoring the port settings on exit. Please put on
your peril sensitive sunglasses and remember this was a hack. It does about everything you commonly need to do with a serial port. This is by the way an inexpensive way to do an operator interface unit :^). If anyone's interested I'll hunt down the Matrix Orbital PN.

Regards

cww

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

P

#### Philip Costigan

On Tue, 22 May 2001 08:38, cww wrote:

> In the meantime does anyone know just what actually
> hits the wire for Modbus RTU? I don't have anything handy that spells it
> out.
>

In the reference guide it explains that RTU is basically raw byte data, It is sent with an address as a byte a function as a byte then a bunch of bytes for data followed by a 16 bit crc checksum. There is also a 3.5 character delay between transmissions so if the port falls asleep mid transmission then it is interpreted as end of transmission and an error will arise.

I hope this is what you are after.

--

Regards

Philip Costigan

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

C

#### Curt Wuollet

Thank you Phil.

This would mean that you simply replace the %h's in the sprintf with %c (char).
I put up some code and will help with questions. The timing issue is quite interesting,
perhaps retry on error ?. I have a crc algorithm around someplace as well.
I think.

Regards.

cww

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

J

#### Jiri Baum

Curt Wuollet:
> I'm assuming from Jeff's mention of "ascii" and "rtu" that the bytes are
> binary.
...
> It only chenges the format string for sprintf but I'd like to get it
> right.

If you have a list of bytes, sprintf is an over-kill. Just do
buf[0] = byte1;
buf[1] = byte2;
buf[2] = byte3;
etc.

That way you can set each byte either as a number (42) or as a character ('*'), depending on what it is.

If it's a fixed-length packet, it's probably better to define a struct for it, anyway...

typedef struct {
char data[10];
char CRC[2];
} FooPacket;

(Probably better to avoid int', though, on account of byte-order issues.)

Just pass that directly to write(2) and it'll do what you want.

Jiri
--
Jiri Baum <[email protected]>
"In my opinion, the GPL is optimized to build a strong software community at the expense of a strong commercial software business model."
--Craig Mundie, Senior VP, Microsoft; 17 May 2001

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

C

#### Curt Wuollet

Hi Jiri!
All quite true, but the first things most folks get familiar with in C is the
printf
family. Forgive my horrible hack. I do like your Mundie-ism. He's smarter than I thought. Substitute monopoly for "strong commercial software business model" and I think he's "got it".

Regards

cww

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

J

#### Jiri Baum

Curt Wuollet:
> All quite true, but the first things most folks get familiar with in C is
> the printf family.

I guess it doesn't matter either way; I guess my point was that there's no magic about binary - it just is in the computer and can continue to be in
there...

> Forgive my horrible hack.

No worries.

> I do like your Mundie-ism. He's smarter than I thought. Substitute
> monopoly for "strong commercial software business model" and I think he's
> "got it".

I think even without the substitution he's got it''... and he's bagging the GPL because he's on the `strong commercial software business'' side.

Jiri
--
Jiri Baum &lt;[email protected]>
"In my opinion, the GPL is optimized to build a strong software community at the expense of a strong commercial software business model."
--Craig Mundie, Senior VP, Microsoft; 17 May 2001

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

G

#### Greg Goodman

> If it's a fixed-length packet, it's probably better to define a struct for
> it, anyway...
>
> typedef struct {
> char data[10];
> char CRC[2];
> } FooPacket;

You have to be careful building structures to represent byte-streams. Depending on your platform, compiler, and compile-time options, the
compiler may pad a structure with extra bytes to force the structure's elements to align on a specific boundary. For example, a system that
requires structure elements to align on 4-byte boundaries would add two bytes of padding between FooPacket.data and FooPacket.CRC.

Something to beware of when writing code meant to be portable.

Greg Goodman
Chiron Consulting

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

J

#### Jiri Baum

> > If it's a fixed-length packet, it's probably better to define a struct
> > for it, anyway...

> > typedef struct {
> > char data[10];
> > char CRC[2];
> > } FooPacket;

Greg Goodman:
> You have to be careful building structures to represent byte-streams.
> Depending on your platform, compiler, and compile-time options, the
> compiler may pad a structure with extra bytes to force the structure's
> elements to align on a specific boundary.

Yes, that's the other reason to avoid ints.

> For example, a system that requires structure elements to align on 4-byte
> FooPacket.CRC.

For a char[] ? What a weird platform that'd be...

For an int I wouldn't be surprised.

Jiri
--
Jiri Baum <[email protected]>
"In my opinion, the GPL is optimized to build a strong software community at the expense of a strong commercial software business model."
--Craig Mundie, Senior VP, Microsoft; 17 May 2001

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

A

#### Andrew Kohlsmith

> > For example, a system that requires structure elements to align on
4-byte
> > boundaries would add two bytes of padding between FooPacket.data and
> > FooPacket.CRC.

> For a char[] ? What a weird platform that'd be...
> For an int I wouldn't be surprised.

It's not expanding the char, it's making sure that the next variable is on a word/dword/qword boundary. You can make any compiler do it, or not do it with special #pragmas in relevant sections of your code or a global compiler
switch, although I'd suggest against the latter. Alignment of code and data makes things faster overall but when you're trying to make a very particular type of structure you should turn it off with a #pragma pack 0.

At least, that's how I remember #pragma pack. It's been a while.

Regards,
Andrew

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

C

#### Curt Wuollet

Gentlemen, please remember we're trying to help a beginner here. While I have always been intrigued by the subtleties of the GCC compiler
implementation, the reason I used the library functions I did was to avoid the esoteric and let the compiler deal with it. For Linux on an x86 for the moment. And using an array with a write that checks for length, while possibly not as space efficient as a struct, (although you'ld have to look at the machine code generated to be sure), let's you do things like printf and use the string functions avoiding overt pointer manipulation. After many years, I have found few instances where absolutely obvious code is improved by obfustication. Also Modbus packets are variable length and the simple code is reusable anyplace you have a file pointer. To do
Modbus/TCP you just open a socket and build your packet a little differently. And yes, there probably should be a few (unsigned char) in
there but it's readable and it works. I compiled and ran it before I sent it.

On a related note, my effort to become reacquainted with the code base has been delayed by rain in my computer room brought about by a week of foul weather. Fortunately, as a long time Linux fan I am well versed in tar and patches and after applying quantities to roof-0.2.1-17, I should be able to proceed. roof-0.2.1-18 seems to be working :^)

Regards

cww

PS For the uninitiated, I simply incremented the patch level. but we're nowhere near a release. Wife-1.0.0 has not interacted well, but will
provide me with diff output.

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc

A

#### Andrew Kohlsmith

> moment. And using an array with a write that checks for length, while
> possibly not as space efficient as a struct, (although you'ld have to look
> at the machine code generated to be sure), let's you do things like printf
> and use the string functions avoiding overt pointer manipulation. After

You most certainly cannot use the string functions with arrays containing ModBUS data. All string functions stop at a NULL and that NULL is way too common in ModBUS packet data.

I'm a big proponent of KISS -- the stupider your software, the less chance it has of biting you in the ass. But as Einstein said, "Things should be
made as simple as possible -- but no simpler." Using string functions for binary data is breaking this rule.

> many years, I have found few instances where absolutely obvious code
> is improved by obfustication. Also Modbus packets are variable length
> and the simple code is reusable anyplace you have a file pointer. To do
> Modbus/TCP you just open a socket and build your packet a little
> differently. And yes, there probably should be a few (unsigned char) in
> there but it's readable and it works. I compiled and ran it before I sent
it.

I agree with you that things should be simple (see above) -- At the same time though I must speak out when you claim that using structs and/or unions over array data is too complex. I can read all the data into a struct with a simple file pointer, just as you can. However my data is now structured; I can pull out the address or checksum or specific structured elements
without resorting to pointer arithmetic or clunky #DEFINEs. Avoiding arrays because of possible padding issues is silly. Everyone was a newbie at one time; how do you learn?

> On a related note, my effort to become reacquainted with the code base
> has been delayed by rain in my computer room brought about by a week
> of foul weather. Fortunately, as a long time Linux fan I am well versed in
> tar and patches and after applying quantities to roof-0.2.1-17, I should
be
> able to proceed. roof-0.2.1-18 seems to be working :^)

Ahh yes.. I have this problem as well on my garage. I had to apply the deshingle toolset and then use pry(1) to pull up the old tongue-and-groove roof boards to replace with chipboard. Unfortunately I threw out my back doing so and I have my roof temporarily functioning by use of the
undocumented tarp tool. With a little luck I should be able to shingle in the next bit.

Regards,
Andrew

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc