The following information may have errors; It is not permissible to be read by anyone who has ever met a lawyer. Use is confined to Engineers with more than 370 course hours of electronic engineering for theoretical studies.

ph +1(785) 841 3089 Email inform@xtronics.com

Computer to PLC

From Transwiki
Jump to: navigation, search

Contents

[edit] Computer Link Protocol

The computer link protocol is very useful. PLC's are meant to dependably run on their own without the need for a more advanced host computer to intervene and tell it what to do. For the Lidar project, we had to be able to start the PLC's program and control it over a computer network. Presented here is a crash course along with an example C program designed for the Linux operating system.

If you'd like more information, please refer to the -Computer Link Function- user's manual. It has helpful diagrams, tables and technical information.

Computer link is so easy that the hardest part is setting up the ports correctly. The manual has a sample basic program with it, written in GW basic. I couldn't make it work. Somewhere along the line of computer evolution, the ancient language just can't access the new hardware correctly. I tried the program on 3 PCs and a laptop, and the port timed out on all of them. The program won't work in Q basic either. (Qbasic won't even allow the necessary port settings.) However, if you get the manual and you're dead set on getting the sample program to work, Toshiba assured us that it does work in Intel Basic 52.

The serial RS232 port needs to be set to 9600 baud rate, 1 stop bit, 1 start bit (note: in Linux, and it seems in other platforms, you don't need to explicitly set the start bit), 8 data bits.

Once you have the port set up right though it's smooth sailing. If you're using Linux you are all set just use the C program as a basis for your own project.

[edit] ASCII strings

The computer link function works by sending the PLC a string of ASCII characters over a serial port connection that tells the PLC to either change the registers values or to send you back a register's contents or status information.

[edit] There are five commands you have to keep in mind

  1. TS test,
  2. ST PLC status read,
  3. ER PLC error status read,
  4. DR data read
  5. DW data write

Let me give you an example of something that you might send to the PLC and what it's output would be.

 (A01TS55)
 (A01TS55&01)
 
Note that instead of new line or new line and carriage return you want only a carriage return (that turned out to be my big problem) after the string.

Each command string must start with a '(' and end with a ')' along with a carriage return. The 'A01' specifies the address of the PLC you want to talk to. You set the PLC's address in the Ladder Logic program. It's possible to control many PLC's on one RS232 port. The PLC will only accept the command string or send something back when it's address is in the string.

After the address is the actual command, in this case TS (for Test Command). The test command lets you send the PLC a series of characters that it echoes back to you. This is great for testing the PLC to computer link. The '&' and the numbers after it are a check sum. (A check sum is the simple addition of the string throwing away any carries) for error checking. It is optional for commands you send to the PLC.

[edit] Tests are nice, but the whole point is to read and write to the PLC's registers

(A01DWD0ED,3,0001,0002,0003)

You'll notice that where 'TS' was before we are now requesting a 'DS' (data write). We tell it the first register we want to write to 'D100' and then the ' 3' tells how many registers we want to write to. The first number 0001 is put into register D0ED and the number 0003 is put in register D0EE and number 0002 is put in register D0ED. If the numbering of the data registers seems confusing that's because all numbering in the command string has to be done in hexadecimal.

(If you don't know hexadecimal here is a quick run through: Instead of base ten: 0 1 2 3 4 5 6 7 8 9 you have base sixteen 0 1 2 3 4 5 6 7 8 9 A B C D E F. So, instead of there being nine tens in 90 there would be nine sixteen's in 90, about 54 more. )

The PLC's response is a status message telling us that it didn't find an error with our command and will execute it.

To find out if the values of the registers have actually changed you need to do a data read. Simply replace DW with DR and don't specify any values for the registers (A01DRD100,3) in this case the PLC's output would be (A01DR001002003&33). To give a relay or an input or output an on state give it the value of 0001 and to turn them off give them a value of 0000. However I don't recommend that you directly change the state of the inputs or outputs through the computer link function. There's no need for it in debugging, the T-PDS ladder logic programming software will let you change registers values while the PLC is running for debugging. If in the field you make a mistake while writing to an internal relay or data register then probably, depending on you program, nothing will happen. If you make a mistake while writing to an output you could start turning on machines you don't want on and depending on what you're automating that that can be very dangerous. In the ladder logic have the outputs wired to internal relays or conditional data statements. This may be confusing if you don't keep good notes but this way you can have an output turn on by more than just one condition throughout the ladder logic.

Here is the sample C program under Linux. Even if you're not using Linux it might be a good idea to look through the annotations in the code while I'm setting up the port so you can get an idea of what you need to put in your own program.

[edit] Sample Function]

/*This is to see if the functions I'm making in plc.h are actually working*/


#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include "plc_cb98.h"


main() {
 
  int x;
 
  
 
  plc_init();
  printf("The file descriptor: %d \n", plc_.pd);
  x=plc_test();
  printf("The plc test was: %d\n\n", x);
  x=plc_status();
  printf("\n if 1 you're in good shape: %d \n",x);
  x=plc_write("D140","0001");
  printf("Number of charectors sent: %d \n", x);
  x=plc_relay_stat("Y23");
  printf("Relay 23 is 1=on 0=off: %d \n",x);
  close(plc_.pd);
}

[edit] Header File

/*
 * $Source $
 * $Log: plc_cb98.h,v $
 * Revision 1.15  1999/03/27 02:41:44  acme
 * added a declaration for another radiometer pin
 * \.
 *
 * Revision 1.14  1998/08/19 00:36:40  richy
 * added the definitions of lsr_on() and lsr_off()
 *
 * Revision 1.13  1998/08/19 00:18:46  richy
 * changed RAD_PIN to LSR_PIN because we will use that to cycle power on BigSky
 *
 * Revision 1.12  1998/07/01 21:12:02  richy
 * changed some of the register definitions.
 *
 * Revision 1.11  1998/06/30 20:00:49  richy
 * changed DTIME_CLOSE_REG from D170 to D160
 *
 * Revision 1.10  1998/06/29 18:47:33  richy
 * RAD_ON_REG was changed to D350 like how it should have been in the first place
 *
 * Revision 1.9  1998/06/29 18:01:51  richy
 * added RAD_ON_REG to be "Y020" and int rad_cycle()
 *
 * Revision 1.8  1998/04/24 21:19:17  richy
 * there was a problem compiling so I moved things around
 *
 * Revision 1.7  1998/04/24 18:20:07  richy
 * forgot to add door_open() and door_close()
 *
 * Revision 1.6  1998/04/24 18:07:22  richy
 * added function declarations
 *
 * Revision 1.5  1998/04/03 20:35:19  richy
 * changed door_open_pin and DOOR_CLOSE_PIN to represent the inputs from limit switches insteaad of outputs that oepen and close door. Now DOOR_PIN Y22 represents single door output
 *
 * Revision 1.4  1997/02/27 18:40:07  richy
 * more new pin definitions
 *
 * Revision 1.3  1997/02/27 17:00:57  richy
 * fixed a definition
 *
 * Revision 1.2  1997/02/27 16:22:52  richy
 * Modr�[D�[Dre definitio    return(-1);}
ns.
 *
 * Revision 1.1  1997/02/24 17:41:13  richy
 * Initial revision
 *
*/


#ifndef _PLC_
#define _PLC_

#define BRAKE_PIN "Y27"
#define BRAKE_REG "D172"
#define DOOR_REG "D140"
#define DOOR_OPEN_PIN "X00"
#define DOOR_CLOSE_PIN "X01"  
#define DOOR_PIN "Y22"
#define LSR_PIN "Y25"
#define PIN_ON "0001"
#define PIN_OFF "0000"
#define D_OPEN "0001"
#define D_CLOSE "0002"
#define DTIME_CLOSE_REG "D160" 
#define RAD_PIN "Y24"

#define RAD_ON_REG "D135" 
#define PLC_DEVICE "/dev/cua1" /*linux treats serial ports as files
				*this is the file linux uses to point to 
				*the serial port attached to our plc*/ 



int plc_init();
int plc_write(char reg[10], char value[10]);
int plc_relay_stat(char reg[10]);
int plc_test();
int plc_status();
int door_open();
int door_close();
int rad_cycle();
int lsr_on();
int lsr_off();
typedef struct
{




  int pd;    /* io unit for toshiba PLC */
  
} plc_cb98_common ;

extern plc_cb98_common plc_ ; 





#endif

[edit] Sample C program to use the PLC computer link function


/* This is a sample C program to use the PLC computer link function*/
/* on linux you must complie this as gcc -O -o prac2 prac2.c*/
/* if you have any questions about port programming under linux refer to*/
/*http://www.kiarchive.ru/pub/linux/slackware/docs/mini/Serial-Port-Programming*/
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>

/*This program writes to the port almost as as if it were a file*/
/*Our ports name is cua1 and is in a /dev/ or device directory*/
#define MODEMDEVICE "/dev/cua1"





main()
{
  int fd, c, res,x,y;
  char buf[255], bufout[150], message[149];
  struct termios options; /*define options to be a structure of type termios*/
  /*we're going to put the new port settings into options so we can send them*/
  /*all to the proper functions at the same time*/
  

  fd = open(MODEMDEVICE, O_RDWR | O_NDELAY);
  if(fd<0){printf("error opening modem");exit(-1);}
  fcntl(fd, F_SETFL, FNDELAY); /*configure port reading*/
  tcgetattr(fd, &options);  /*get current options for the port*/
  
  cfsetispeed(&options, B9600); /*set baud rates to 9600*/
  cfsetospeed(&options, B9600);
  /*Makes it so that the program dosen't own the port and other things can use it*/
  options.c_cflag |= (CLOCAL | CREAD);
  
  /*the following five lines set odd parity*/
  options.c_cflag |= PARENB;
  options.c_cflag |= PARODD;
  options.c_cflag &= ~CSTOPB;
  options.c_cflag |= CREAD;
  options.c_cflag |=PARENB;
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;/*this sets 8 data bits*/
  /*This disables  clear to send and request to send stuff*/
  options.c_cflag &= ~CRTSCTS;

  
  /* Enable data to be processed as raw input would be an & before =* and an ISIG instead of an ECHOE*/
  options.c_lflag &= ~(ICANON | ECHOE | ISIG);
  
  /* this will set new line as carriage return*/
  options.c_oflag |=ONLCR;
  
  
  /* Set the new options for the port */
  tcsetattr(fd, TCSANOW, &options);
  
  /*http://www.kiarchive.ru/pub/linux/slackware/docs/mini/Serial-Port-Programming/*/
  
  if (fd <0) {perror(MODEMDEVICE); exit(-1);}
  printf("3 \n");
  printf("What message whould you like to send?\n");
  scanf("%s",&message);

  sprintf(bufout, "%s\r",message);
  printf("printing bufout to be sent : %s \n", bufout);
  c=write(fd,bufout,sizeof(bufout));
  printf("%d\n",c);
  printf("4 \n");
  usleep(200000);
  c=read(fd,&buf,sizeof(buf));
  printf("%d\n",c);
  printf("5 \n");
  printf(" %s\n\n", buf);
  close(fd);
}

Personal tools