We've Moved!

Please update your bookmarks from embeddedarm.com to embeddedts.com. You've already been redirected and may close this modal to continue.

TS-PLC Manual

Published as a Documentation on Jan 10, 2019
This document provides a technical introduction to the TS-PLC products.  The sections titled in red contain advanced material that may not be as useful to the average user, and can safely be skimmed over or skipped without losing any basic information on the usage of the product.

General PLC operation

A programmable logic controller (PLC) is a device which has some physical I/Os such as relays, switches, LEDs, and so forth, and which performs a dedicated function in order to process its inputs and generate its outputs.  In general what happens is that the PLC performs this same task over and over.  We call this task a scan cycle and the interval at which the task is performed we call the scan period.  In general the scan period is very short, on the order of milliseconds.  The scan cycle can be divided into sub-tasks which we call phases.  The phases, in the order they occur, are: wait, input, compute, and output, which are described in the table below.

The PLC monitors serial ports for input, but otherwise does nothing while waiting for the scan period of the previous cycle to expire.  This insures that scan cycles occur at a fairly constant frequency.
All physical inputs are sampled and the values obtained are stored in registers (memory locations) accessible to software.
Stored functionality is executed to perform computations on the registers as required.
All physical outputs are driven according to the values stored in the corresponding registers in the PLC.  In addition, the TS-PLC also performs a second operation during this phase in which it flushes "virtual outputs".  These are signals that are propagated between PLC units.

Introduction to the TS-PLC family

The TS-PLC family consists of two components: devices, which are small, self-contained units which have I/O and computational resources to process their inputs in order to determine the current outputs; and controllers which are centralized units which perform the tasks of interfacing TS-PLC devices to the user, synchronizing access to slave devices when it is required (i.e. on RS-485 networks), and which provide for additional specialized functionality common to all devices.   In normal operation there will only be one controller for one or more devices connected through either a RADIO or RS-485 serial network.

TS-PLC devices

A TS-PLC device consists of two aspects: hardware, which determines what kinds of inputs and outputs it has (for example, Analog to Digital converters, high-drive or low-drive switches, relays, LEDs, and so forth), and the software which is common to all device and which provides for communications over various serial devices and a common interface to the hardware.

Functionality common to all models

The TS-PLC software model defines three layers: the BIOS, the application, and the user program.


The BIOS is a set of routines providing access to the serial ports, IRQs, and general system information.  Hardware specific functions are not defined as these can be accessed directly in the microcontroller environment.   The main reason for implementing serial access (other then for convenience) is that the BIOS monitors all serial transmissions and provides an escape sequence for reprogramming the device.

The BIOS exposes a mechanism to reprogram the application and user program portions of the device through any serial port.  This is accomplished by sending the escape sequence "@@@" with a one second guard time before at after it.  When the BIOS recognizes the escape sequence it enters command mode, which is denoted by a special LED flash sequence on devices which have LEDs.  In command mode the BIOS recognizes the following commands:

"Annnn" addresses the device to be programmed
nnnn is the 32-bit address (device id) of the unit in big endian
If the specified device hears the request, it will return "K".
A device will not send any bytes or perform any actions when it is not being addressed.
"En" erases sector (if n is in '1'..'H'), returning "J" on start and "K" on success or "Z" on failure
'1'-'3' is sector 1-3  (auxiliary program sectors)
'4' is sector 4 (the application program sector)
'@' is sector 16 (first sector for user program/data)
'A' is sector 17 (second sector for user program/data)
All other values are reserved
where n-'0' is the 8k pseudo-sector to checksum
returns a 4 byte little endian value
'W' returns "D" and enters write mode
Next send aaaa (24-bit offset from the start of sector 1)
Then send a one byte value denoting the number of dwords to follow.
(Note: must be non-negative and less then 64; 0 means 64)
Next send the data bytes to be sequentially written to the flash.
Finally send a one byte checksum calculated by 0xFF-SUM(data bytes)
if the checksum passes, "J" is returned, the data is written to flash, and then "K".
On error "Z" is returned.
"4mmmmnnnn" performs an RS-485 discovery query
mmmm is the 32-bit minimum device id to respond
nnnn is the 32-bit maximum device id to respond
If a device is in the range specified, it will send a serial BREAK character.
'X' exits command mode (reboots, no reply is sent)
'+' and '@' are silently discarded, allowing for synchronization in case of error.

In general a return value of "Z" means an error occurred or unexpected data was received.

The BIOS functions available are exposed through a C API as follows:
  • int UartTx(int port,unsigned char *data,int len);
    • Queues bytes for transmission over a serial port
    • port is an architecture specific number indicating which serial port to send on
    • data points to the data to send
    • len contains the length of the data to send
    • returns the number of bytes queued for sending
  • int IrqRegister(int irq,void (*irqh)(void *));
    • Registers an IRQ to the application
    • irq is an architecture specific IRQ number
    • irqh points to the callback function to be called in interrupt context when the IRQ fires
    • returns true on success, or false on failure
  • int TxReady(int port);
    • port is an architecture specific number indicating which serial port to query
    • returns the number of bytes that can be queued on the specified port
  • unsigned RxReady(int port);
    • port is an architecture specific number indicating which serial port to query
    • returns the number of bytes that are ready to be read from the specified port
  • int UartRx(int port,unsigned char *data,int len);
    • port is an architecture specific number indicating which serial port to send on
    • data points to the buffer to store the received data
    • len contains the length of the buffer
    • returns the number of bytes actually received
  • int RxRegister(int port,void (*Rx)(int,unsigned char));
    • port is an architecture specific number indicating which serial port to send on
    • Rx points to the callback function to be called in interrupt context when a byte is received
    • returns true on success, or false on failure
  • void RxPreprocess(int port,char data);
  • unsigned Time(int *v);
  • unsigned GetId();

To assist you in debugging your programs and knowing the current state of the unit, the red and green LEDs have various blinking patterns which have meaning to the BIOS and/or default shipping software:

green LED
red LED
Default meaning
fast blink fast blink command mode
slow blink off default user program
off slow blink watchdog timer
off fast blink exception

The TS-PLC application

The TS-PLC application utilizes the BIOS and implements the general PLC operation as described earlier.  It maps all physical inputs and outputs, as well as various internal control functions, to specific signal names.  The signal names available will depend on the TS-PLC model.  Each signal is between 1 and 32 bits in size, and takes up part or all of a 32-bit register.  The TS-PLC architecture defines 2048 registers; those not used by pre-defined signals are available to the user.

Any register in a device can be specified as either a virtual input (VIN) or a virtual output (VOUT).   When a register marked as VOUT changes during the compute phase, it is marked for flushing during the output phase.  When an output is "flushed" this means that its value is sent over the serial network to all the other devices on the network.  If the corresponding register is marked as VIN on another device, it will copy the sent value into its own local copy of that register.  In this way register values are propagated between devices.  Note that just because a register is marked for flushing does not guarantee that it will be sent before the value changes again, or that the value will be successfully received by all other devices that want to use it.  The user program is responsible for taking any measures necessary to ensure the degree of reliability needed for a specific application.

It is important to note that it is registers, not signals which are virtual I/Os.  The practical limitations of this are two-fold: first, a register containing pre-defined signal names that is VOUT will always propagate all the values in the register, even if only one of them has changed; and second, a user program that defines a register as VOUT may not be able to use the rest of the register for anything.

From a software perspective, the TS-PLC hardware is identified by an "architecture" identifier, or arch. All TS-PLC units with a given arch will have the same I/O and software interface to that I/O. The software interface for a particular arch consists of a list of signal names stored as specific bit ranges of registers at fixed memory locations. Normally all I/Os will have a corresponding signal name, but in addition there will always be signal names that do not correspond to any actual physical I/O. These signals allow the user to obtain internal PLC information and to control the internal operation of the device.

User program

When using the ladder logic editor, the user program is generated automatically from the saved ladder logic program when the commit button is pressed.  However it is also possible to write the user program directly in C.  In order to do this it is necessary to understand how the TS-PLC application will interface with the user program.

The compute phase is performed by calling the user program, which has the following C prototype:
where "_REGS_" can be viewed either as a structure containing all the signals in the device, or as an array of 2048 integers (32-bit) plus 256 additional elements containing control bits for those registers.

The user program is restricted to accessing only the 2304 double-word array passed to it; that is it's sole interface, and it is forbidden to access any other memory or I/O location save for any local variables it requires.  As such, the definition of the signals available to the user program is key to the functioning of the PLC.

Pre-defined signals

In addition to defining their own unique signals, all TS-PLC devices share a common set of signals, listed in the table below.

signal name bit size Read Only? description
TICK 32 yes Contains the number of milliseconds since the last scan cycle
NAME 32 yes Contains the factory assigned unique identifier ("device id") for the device
ARCH 32 yes Architecture identifier
For  Model 701 this value will be 0x31303754 ("T701")
COMP_SS 1 no When this bit is set, the TS-PLC will only perform one compute phase and will then disable computation. Useful for debugging, although presently it is unused.
COMP_EN 1 no When this bit is set, the TS-PLC will perform the compute phase of the current scan cycle; when it is clear it will not, nor will virtual inputs be registered in the device. For debugging use; this bit is set during normal operation.
INIT_COMPLETE 1 no This bit is cleared during the first scan cycle of operation after power-up. When this bit is cleared, the ladder logic program can count on all general purposes registers (those not listed herein) to be initialized to zero. After the first cycle is complete this bit is set automatically. Ladder logic can use this bit to condition initialization logic; it is not necessary to condition other (non-initialization) logic on this bit; simply put other logic after initialization logic. Ladder logic can also set this bit to force re-initialization on the next scan cycle.
ScanPeriod 16 no Desired length of each scan cycle in milliseconds. The actual length could be slightly more under heavy loads. If this value is zero, the unit will execute each scan cycle back to back without any delay. The minimum effective value is current around 10; the default (power-up) value is 16.
DayOfWeek 3 no This and the following five signals are VINs, supplied by the TS-PLC controller approximately once per second when the real-time clock option is present.
This field contains the day of the week, where 1=Sunday, 2=Monday, ... 7=Saturday
Month 4 no 1=January, 2=February, ... 12=December
DayOfMonth 5 no A value between 1 and 31 (or less, depending on the month)
Hour 5 no A value from 0-23 representing the number of hours since midnight "local" time
Minute 6 no A value from 0-59 representing the number of minutes since the top of the hour
Second 6 no A value from 0-59 representing the number of seconds past the current minute

Model 701

The "T701" arch defines the following signals.

signal name bit size description
Contains the last ADC voltage value sampled from pin 2, scaled to as follows:
BIASen2 is
BIAS2 is
0V Vcc 0 0 or 1
-Vcc +Vcc 1 1
0V 2*Vcc 1 0

Nominal Vcc is 3.3V.
Note that it is possible to increase the voltage range in the last case by adding an external series resistor. For example, an external series resistor of 22kOhms would produce a calibration range of 0=0V to 0x3FF=3*Vcc.
Same as ADC2/BIAS2/BIASen2, except with pin 3.
Same as ADC2/BIAS2/BIASen2, except with pin 4.
Same as ADC2/BIAS2/BIASen2, except with pin 5.
Same as ADC2/BIAS2/BIASen2, except with pin 6.
Same as ADC2/BIAS2/BIASen2, except with pin 7.
Same as ADC2/BIAS2/BIASen2, except with pin 8.
OUT4 1 Set to '1' to assert pin 4 (actively drive it low), clear to '0' to de-assert and turn pin 4 into an input.
OUT5 1 Set to '1' to assert pin 5 (actively drive it low), clear to '0' to de-assert and turn pin 5 into an input.
OUT6 1 Set to '1' to assert pin 6 (actively drive it low), clear to '0' to de-assert and turn pin 6 into an input.
Set OUT7 to '1' to assert pin 7, clear to '0' to de-assert it and turn pin 7 into an input.
POL7 selects the polarity of the output: when POL7 is '1', the output is actively driven high when asserted; when POL7 is '0' the output is actively driven low when asserted.
Set OUT8 to '1' to assert pin 8, clear to '0' to de-assert it and turn pin 8 into an input.
POL8 selects the polarity of the output: when POL8 is '1', the output is actively driven high when asserted; when POL8 is '0' the output is actively driven low when asserted.
GLED 1 When set to '1', the green LED is turned on, when cleared to '0' it is turned off. Note that the green LED may flicker slightly or be affected by other processes such as USB and temperature conversion, as well as by the TS-PLC-BIOS.
RLED 1 When set to '1', the red LED is turned on, when cleared to '0' it is turned off. Note that the red LED may flicker slightly or be affected by other processes such as USB and temperature conversion, as well as by the TS-PLC-BIOS.
8 Sets the protocol to be spoken on the following ports, respectively: RS-232, RS-485, RADIO, and USB. (Note: USB support is not included with this release.) A valid of "0" corresponds to Technologic Systems\' Luna protocol, which is used to communicate state changes between devices. Use a value of "1" to disable a port for generating or responding to Luna packets. The RS485_PROT value is special: if it is "0", then the device also operates in SLAVE mode: it will only respond to addressed Luna packets, to avoid collisions on the RS485 bus. If this value is "1" then the unit will operate in Peer mode, and may transmit state changes during the flush phase of any scan cycle without waiting for other communication. Normally you will want to set RS485_PROT to "1" in programs destined for a device using the wireless radio as its communication device, in order to reduce signal latency, and especially if you are moving devices out of range of the TS-PLC Controller. Other protocol values are reserved for future use. The current release only supports a baud rate of 115200baud, 8 data bits, no parity, and 1 stop bit on all ports.
TEMP 13 (OPTIONAL) This value is sampled at a low rate (normally every 100 scan cycles). Its value is a signed number representing 1/128th of a degree C. If the temperature sensor option is not present, this value will be -7/128C.

TS-PLC controller

There are two models of the TS-PLC controller available: the RS-485 model and the RADIO model.  The only difference between models is which serial network the TS-PLC controller connects to.  If your TS-PLC units use RS-485 to communicate, then you will need the former model, while if your TS-PLC units have the RADIO option, then you will need the latter model.

The TS-PLC controller performs the following functionality:

  • Interfacing to the TS-PLC units through a web browser interface
    The ladder logic editor is the main interface for interacting with the TS-PLC units. With it you can detect which units are visible to the TS-PLC controller, give them meaningful names, map signal names to logical names, create, load and save ladder logic programs, and commit a saved ladder logic program to the devices on the PLC network.
  • Acting as a Master
    All TS-PLC devices operate in one of two modes: master/slave mode or peer mode. In master/slave mode a unit can only send information in response to the master. This is useful for RS-485 networks, which require the operation of a master to prevent collisions. In master mode the controller will detect devices, and then poll them as fast as it can.
  • Supplementary common functionality
    With the real-time clock option, the controller will provide a 1Hz update of current time information to all listening units. This might be useful if you require control logic that needs to know (for example) the day of the week or the time of day in making decisions. For example, a PLC device controlling a lock might be programmed to not unlock during certain times or on certain days.  Additional functionality is possible in the future.

Introduction to Ladder Logic

Ladder logic is a visual representation in which you connect graphical elements in a way that is analogous to how an actual electrical circuit would work. Each element has an input and an output "pin", which can be viewed as a single bit (wire) which can be TRUE (on) or FALSE (off), and may correspond to a physical I/O signal on the TS-PLC which can be in a logic HIGH or LOW state.

There are several constructs available with various relationships between the input and output pins, as well as any side-effects of the element. For example an element may change the value of internal registers when its input pin is HIGH. The most basic elements are the contact which represents a single-bit that you want to get the value of, and the coil which represents a single-bit that you want to change the state of in your program. Even more basic are the short which merely propagates its input to its output, and the open which has an output value of FALSE regardless of its input value. However short and open are typically only used for debugging or formatting purposes.

Ladder logic is organized into rungs. The operation of the ladder logic program occurs in the compute phase of each scan cycle, and can be viewed as the propagation of the "rung-in condition" from left to right, top to bottom, one rung at a time. This "rung-in condition" is normally always TRUE (unless changed by a special construct), but output of each element is determined by the value of its input combined with element specific conditions.  In many cases, the output of a ladder logic element will be conditioned on its input pin being true, such that if its input pin is false then its output pin will always be false as well, and any side effects of the element will not occur.  The ladder logic editor provides online help for each construct which describes the functionality it performs.

As this is only a basic introduction you may wish to follow up this introduction with other sources which discuss ladder logic in more depth.

Programming for the TS-PLC family
Using the Mappings Editor

The first step in designing your ladder logic program is to determine the mappings for your program.  There are two types of mappings which you must create.  The first is the mapping between device ids and device names, which we call device mappings.  Each device has a unique number which is its device id.   This number can be found somewhere on the device itself, or by scanning for the device when it is by itself on the serial network.  The default device name is the same as the device id, but most likely you will want to change this to something more descriptive and meaningful.  You might choose a name representing the location of the device or the function it performs.  It is strongly recommended that you not use a device name that is a number (unless it is equal to the unit's device id), to avoid possible conflicts with other devices you might add later.  

The second type of mappings which you must create are signal mappings.  For every signal you use in your ladder logic program which corresponds to a pre-defined signal you must define a signal mapping which specifies the model id of the device (the arch), which device the signal is in (the device name), and which pre-defined signal name in the device your name is referring to (signal name).  It is necessary to specify the arch first, in order to see which devices of that arch are known, and which signals you can choose between.  The signal mappings table provides a way to create meaningful names to refer to specific signals on specific logical devices. For example, if device signal "OUT8" on logical device "OFFICE" was connected to an alarm, you might wish to use the informational name "ALARM" for that signal. 

All signal names you specify in your ladder logic which do not have a signal mapping are assumed to be user-defined registers to be assigned to the device containing the first rung on which they are written to.  Subsequent occurrences on other rungs will generate a warning and will access the VIN copy of the register, which may or may not be what you want.

To bring up the Mappings Editor, click on the Mappings link around the top right of the Ladder Logic Editor.  The Mappings Editor will come up in a separate window or tab. The top half of the window will show device mappings and the bottom half will show signal mappings.  You can delete existing signals by clicking the appropriate delete button, and create new signals by clicking on the new button at the bottom of the list.  In the middle are control buttons. The Scan button is used to search for devices connected to the TS-PLC-CONTROLLER. This should be done if the devices you expect to see are not present in the device mappings list. In order to allow for offline devices to be referenced, the scan function does not delete previously discovered devices which are not found in the current scan. If you wish to delete any device from the list, simply click on the delete button for that device. The Revert button will undo any changes made since you last saved. The Save button will store the current values of all tables on the page to the TS-PLC controller. You must perform this step before attempting to commit your ladder logic program in the Ladder Logic Editor.

The mapping editor provides a way to create ladder logic programs which are independent of specific devices.  All the example ladder logic programs distributed with the TS-PLC controller only require that you create a device mapping for each device required by the program.  If you have a unit fail or wish to re-assign it to another location you can also easily update your PLC programs by simply changing (and saving!) the device mappings and re-committing your program.  Warning: When you change which device id is associated with with a device name, the old device is not automatically unprogrammed. This may result in confusion or erroneous operation if the old device remains active but is not associated with a new device name and reprogrammed with a different function. Please ensure that you remove the existing program from the old device (for example, by assigning new logic to the old device) if the old device is to remain connected to the network, in order to ensure that this will not occur.

Using the Ladder Logic Editor

The ladder logic editor consists of three panes.

The info pane
This multi-purpose pane is on the bottom.  It contains context sensitive help or information about the currently selected element.  It can also contain the file selection when you click on the load button.

The construct pane
This pane is on the left side of the window, and contains a list of buttons corresponding to ladder logic constructs. Clicking on these buttons will insert the corresponding element into the edit pane. Clicking on the question mark to the right of the button will display information about that element in this info pane.

The edit pane
The top pane in the window; it displays the current ladder logic program. The cursor shows the location of the insertion point and (if the current cell is not empty) the direction the next element will be inserted in. The buttons at the top of the edit pane operate on the entire ladder logic program, except for the Help button which will bring this help up in a new window or tab.

The typical flow of using the ladder logic editor is as follows:

At startup the current program will automatically be loaded into the editor. If the current program is empty you will be presented with an empty program. To select a new program to edit press the Load button, which will prompt you to either click on the name of an existing program, or to enter a new name to create a new program. The currently selected program will be used for all further actions even into future sessions until you use load to change the current program again.

Click on "Mappings" to open the mapping editor in another window.

Click on elements from the left side to insert them into the document at the cursor location. If an element has a short-cut key you can also press that to insert the element. The arrow keys and mouse can be used to move the cursor: note that the cursor points in the direction the next element will be inserted: before, after, above, or below. If the selected element is a short or open it will be replaced. Hit the delete key to delete the element at the cursor. Hit enter to toggle focus between the selected element and the information panel for that element.  Note that some browsers have slightly differing focus behaviors and thus the arrow keys, page up/down keys, enter keys, and switching between windows may produce different focus in different situations.  If in doubt, the scroll bars can be used to scroll through the page, and the desired element can be clicked on to be selected.

The Above and Below buttons allow to to create a new rung above and below the rung containing the currently selected element. Do not try to create more then one empty rung at a time.  You can also click the Delete button to completely delete the current rung.

If at any time you decide you are not happy with the current state of the program and want to start over, press the Clear button.

You will periodically want to press the Save button in order to ensure that your work is not lost. If after you save your work you make a mistake, you can press the Revert button to re-load the state of the current program as you last saved it.

When you finished with your program and have saved it, press the Commit button to transfer the saved state of the program to the TS-PLC network.  If there are any warnings or errors they will be displayed when the process is finished.  Currently there is no progress indicator, but you should expect to at least half a minute for a successful finish.

Using the Example Programs
Simple example of capturing a switch value and displaying it on the LED.  Connected a SPDT switch as follows: Contact 1 to GND, Contact 3 to OUT8, Common to IN4.  Sets up OUT8 as a high side switch and turns it on; the switch will either select Vcc or GND.  We read the switch value through ADC4 which we have named "SWITCH".  We set the LED when the switch voltage goes above a certain threshold, and reset it when the switch voltage goes below a different threshold.

Uses two devices, "TALKER" and "LISTENER".  The TALKER device generates a periodic (10Hz) beacon.  The beacon is always high; this example illustrates a method of forcing a signal to be flushed without changing it's value, as the ladder logic will be evaluated from top to bottom.  By resetting and setting the beacon we effectively mark the beacon as changed, so that its value will be sent to the network.  When the beacon is "refreshed" the green LED will blink, and also will be sent over the Luna network as signal "BEACON".  The LISTENER device uses this signal as a virtual input (contact BEACON in rung 2) and drives its own green LED with this signal.  If LISTENER misses two consecutive beacons it will turn on the red LED until the beacon returns.  If the listener_RLED coil was changed to a set-only coil, the red LED would stay lit even when the beacon returned, allowing for persistent fault detection.  Also note that due to the way the beacon is generated it will also work well across 485 so long as the polling period remains less then the listener timeout.   This would not be true if the beacon did not always remain high.

Same basic functionality as the beacon sample program, plus the addition of a third unit which acts as an "override".  A SPDT switch is connected as follows: center on IN4, ends on GND and OUT8.  When the switch is off, beacon program runs normally.  When switch is on, it overrides the listener so that it ignores the beacon (doesn't time out, green led stays on).  Note that this example doesn't provide any protection against the switch output value being lost across the network.


This example demonstrates how individual devices in PEER mode can relay signals to extend the range of the TS-PLC radio network.  It uses three devices, "SWITCH", "RELAY", and "LIGHT".  The green LED on LIGHT is supposed to track the on/off state of the SPDT switch connected to SWITCH in the same way as in example switch.  It does this by acting on both the original signal from SWITCH and from a duplicated signal in RELAY.  In this manner, the switch value can be propagate if RELAY is not present, or if it is present and LIGHT goes beyond the range of SWITCH but not RELAY, while RELAY remains in the range of SWITCH:


This example demonstrates how a signal can be reliably transmitted across a radio network.  It uses two devices: "SWITCH", which has a SPDT switch connected to SWITCH in the same way as in example switch, and "LIGHT" which is similar to the device in example relay, except that it does not look for a possible relay.  This example uses an acknowledgment from LIGHT back to SWITCH to confirm that a state change was received.  If the acknowledgment is not received in a timely manner, then SWITCH will re-send the changed value of the switch and not listen to any changes in the actual switch until an acknowledgment is received.