We believe SPLat's programming language is the easiest in the world for embedded OEM control applications. SPLat's language was originally devised, and has evolved over time, with embedded machine control as its main driver.
The example below shows off just a few of the language features that make SPLat so easy for control programming. Compared to C, Basic and other general purpose computer languages, SPLat focusses on those language elements that are important for programing controls, which is very different to general computing. SPLat lets you express the concepts of logic, sequence and time quickly and easily. Compared to ladder, SPLat lets you tell the controller what to do, rather than what to be (in ladder you emulate a circuit made up of relays, timers etc, so in reality you are designing a circuit that will solve the problem rather than simply solving the problem directly).
... You compare, you decide!
In the two side-by-side windows below you can compare the same program written in several languages that are used for programming controls. Just click on the language names to select.
What the program does Is this comparison honest? What about my favourite language?
Click a key word below to show the code
[SPLat] [SPLatOS C] [Ladder] [Statement list] [Dynamic C] [Basic]Click a key word below to show the code
[SPLat] [SPLatOS C] [Ladder] [Statement list] [Dynamic C] [Basic]Start: LaunchTask FirstIn LaunchTask PushOnPushOff LaunchTask LongShort RunTasksForever ** First button pressed (Sale of the Century) ** FirstIn: YieldTask GoIfInOn 4,FirstIn_Got_4 GoIfInOn 7,FirstIn_Got_7 GoTo FirstIn FirstIn_Got_4: On 4 Pause 100 Off 4 GoTo FirstIn_WaitBothOff FirstIn_Got_7: On 7 Pause 100 Off 7 FirstIn_WaitBothOff: WaitOff 4 GoIfInOn 7,FirstIn_WaitBothOff GoTo FirstIn ** Push ON/ Push OFF button ** PushOnPushOff: WaitOnK 5 On 5 WaitOnK 5 Off 5 GoTo PushOnPushOff ** Short pulse = ON, Long pulse = OFF ** LongShort: WaitOnK 6 WaitOffT 6,100 GoIfT LongShort_1 Off 6 GoTo LongShort LongShort_1: On 6 GoTo LongShort
//SPLatOS C void main(void) { SPLAT_vInitialise(); THREAD_vIgnite(); mFOREVER { } } //** First button pressed (Sale of the Century) ** void APP_vMsgGameShow( APPtbMSG bMsg, uint8 bData ) { switch( bMsg ) { case APPkeMSG_Timer_GameShowLight: DIGITAL_vClrLed1(); DIGITAL_vClrLed4(); break; default: if( !TIMER_oIsRunning( APPkeMSG_Timer_GameShowLight ) && bData == DIGITALkeS_Pressed ) { DIGITAL_vWrite( bMsg == APPkeMSG_IP_BtnLeft ? DIGITALkeOP_Led1 : DIGITALkeOP_Led4, TRUE ); TIMER_vStart( APPkeMSG_Timer_GameShowLight, 1000, FALSE ); } break; } } //** Push ON/ Push OFF button ** void APP_vMsgPushy( APPtbMSG bMsg, uint8 bData ) { if( bData == DIGITALkeS_Pressed ) DIGITAL_vToggle( DIGITALkeOP_Led2 ); } //** Short pulse = ON, Long pulse = OFF ** void APP_vMsgShorty( APPtbMSG bMsg, uint8 bData ) { if( bData == DIGITALkeS_Released ) DIGITAL_vSetLed3(); else if( bData == DIGITALkeS_Held ) DIGITAL_vClrLed3(); }
//Dynamic C™ main() { char SwitchStateA; char SwitchStateB; char LastStateA; char LastStateB; char LampState; char Running; char Changed; char FlashCount; char LastStateSL; char SwitchStateSL; char LampStateSL; unsigned long LastPressSL; unsigned long DiffSL; char LastStateT; char SwitchStateT; char LampStateT; brdInit(); LastStateA=1; LastStateB=1; Running=0; LastStateSL=1; LampStateSL=0; LastStateT=1; LampStateT=0; while(1) { ////////////////Sale of the Century costate { SwitchStateA=digIn(1); SwitchStateB=digIn(2); if( Running==0 ) { Changed=0; if( SwitchStateA==0 && SwitchStateA!=LastStateA && SwitchStateB==1 ) { Running=1; Changed=1; } if( SwitchStateB==0 && SwitchStateB!=LastStateB && SwitchStateA==1 ) { Running=2; Changed=1; } if( Changed==1 ) { LampState=1; FlashCount=0; digOut( Running,1 ); } } LastStateA=SwitchStateA; LastStateB=SwitchStateB; } costate { waitfor(DelayMs(500)); if( Running > 0 ) { if( FlashCount++ < 4 ) { LampState=LampState==0 ? 1 : 0; digOut(Running,LampState ); } else { digOut(Running,0); Running=0; } } } /////////////Push ON-Push OFF button costate { SwitchStateT=digIn(3); if( SwitchStateT==0 && SwitchStateT!=LastStateT ) { LampStateT=LampStateT==1 ? 0 : 1; digOut( 3, LampStateT ); } LastStateT=SwitchStateT; } /////////// Short pulse = ON, Long pulse = OFF costate { SwitchStateSL=digIn(0); if( SwitchStateSL!=LastStateSL ) { if( SwitchStateSL==0 ) LastPressSL=MS_TIMER; else { DiffSL=labs( MS_TIMER-LastPressSL ); if( DiffSL >= 1000 ) LampStateSL=0; else LampStateSL=1; digOut(0,LampStateSL); } } LastStateSL=SwitchStateSL; } }
Statement list. * First button pressed (Sale of the Century) * LD 0004 ANB 0507 LD 0504 AND 1004 ORL OUT 0504 LD 0007 ANB 0504 LD 0507 AND 1004 ORL OUT 0507 LD 0004 OR 0007 LD 1004 ANB T002 ORL OUT 1004 LD 0504 OR 0507 TMR 002 #00040 LDB T002 AND 0507 OUT 1010 LDB T002 AND 0504 OUT 1009 ;****** Push on/ Push off function *** LD 0005 ANB 1006 AND 0512 OUT 1005 LD 0005 ANB 1006 OR 0512 ANB 1005 OUT 0512 LD 0005 OUT 1006 LD 0512 OUT 0505 ;** Short pulse = ON, Long pulse = OFF ** LDB 0000 ANB 1008 AND 1001 OUT 1007 LDB 0000 OUT 1008 LD 0000 OUT 1001 LD 1007 ANB T000 SET 1003 LD 1007 AND T000 RES 1003 LD 0000 TMR 000 #00030 LD 1003 OUT 0500 END ENDH
Trio Basic™ *** Prog Sale_Century: Run on Process 0 WHILE 1=1 WAIT UNTIL IN(8,9)=0 WAIT UNTIL IN(8,9)<>0 IF IN(8,9)=1 THEN GOSUB set_10 ELSEIF IN(8,9)=2 THEN GOSUB set_11 ENDIF WEND set_10: OP(10,1):WA(1000):OP(10,0) RETURN set_11: OP(11,1):WA(1000):OP(11,0) RETURN **** Prog Push_on_off: Run on Process 1 WHILE 1=1 IF IN(12,13)=1 AND allow_switch=1 THEN OP(13,1) allow_switch=0 ENDIF IF IN(12,13)=3 AND allow_switch=1 THEN OP(13,0) allow_switch=0 ENDIF IF IN(12)=0 THEN allow_switch=1 WEND *** Prog Pulse_control: Run on Process 2 timing=0 WHILE 1=1 IF IN(14)=ON AND timing=0 THEN GOSUB start_timing IF IN(14)=OFF AND timing=1 THEN GOSUB output_decision WEND start_timing: t2=TICKS timing=1 RETURN output_decision: IF t2-TICKS<=500 THEN OP(15,1) IF t2-TICKS>500 THEN OP(15,0) timing=0 RETURN
Dynamic C
The C program is written in Dynamic C™. This version of C is designed specifically for embedded control systems based on a well-known brand of controller products, and provides built in multitasking.
The sample program was provided by Mike Randall of Monitor Software, a leading Australian supplier of industrial control and programming solutions. Mike is an extremely experienced C programmer, and has worked with Dynamic C for somewhat longer than he really cares to admit. Thanks Mike!
LaunchTask
A MultiTrack instructionSPLat contains a built in multitasking system to make your programming life easier. That means a SPLat program can be written to do many "things" at once, with very little effort. Each "thing" is called a task (other languages use terms like thread or co-task).
The LaunchTask instruction sets up the named task, in this case FirstIn, to be run.
RunTasksForever
A MultiTrack instructionOnce you have listed all the tasks you want to run in LaunchTask instructions, a RunTasksForever will start them running.
It is possible, by the way, to have tasks dynamically launched and to have them kill themselves, so the SPLat MultiTrack system will support quite elaborate schemes if required. However, as with everything in SPLat programming the simple case is always made as simple as possible to program.
YieldTask
A MultiTrack instructionThe YieldTask instruction forces a task to relinquish use of the processor, so other tasks can get processor time.
Note that delay and wait instructions like for example Pause and WaitOn automatically yield the processor, so if one of those is being executed there is no need for an explicit yield.
GoIfInOn
A FastTrack instructionThe GoIfInOn instruction simply tests the nominated input, in this case 4 and redirects program execution to the named line, in this case FirstIn_Got_4, if the input is found to be on.
This is a FastTrack instruction. FastTrack is a set of just 14 instructions that can be used for a large range of the relatively simple timing and sequencing jobs. Combine these with just two more instructions for MultiTrack, and you can be writing sophisticated multitasking programs in a few hours.
The total instruction repertoire of SPLat is over 400 instructions. You won't learn them all in the first day, but it's nice to know that as you expand your skills you won't suddenly get "dead ended", which is what happens with many competing controller products in a similar price range.
On
A FastTrack instructionThe On instruction simply turns on the named output, in this case 4. That output will then stay on until it is programmed off again.
This is a FastTrack instruction. FastTrack is a set of just 14 instructions that can be used for a large range of the relatively simple timing and sequencing jobs. Combine these with just two more instructions for MultiTrack, and you can be writing sophisticated multitasking programs in a few hours.
The total instruction repertoire of SPLat is over 400 instructions. You won't learn them all in the first day, but it's nice to know that as you expand your skills you won't suddenly get "dead ended", which is what happens with many competing controller products in a similar price range.
Pause
A FastTrack instructionThe Pause instruction introduces a programmed delay of the nominated multiple of 10mS (0.01S). In this case the delay is 1000mS (1 second). When executed as part of a MultiTrack task, as is the case here, the current task will stop for 1S but other tasks will continue to run.
Pause is the simplest of the timing functions in SPLat. It can produce program delays from 10mS to about 46 hours in one instruction. There are a range of other timing functions that cover the same range. They allow interval measurement, fixed or variable timers and event timouts. In addition some models have built in real time clock with a versatile 7-day clock function.
Off
A FastTrack instructionThe Off instruction simply turns off the named output, in this case 4. That output will then stay off until it is programmed on again.
This is a FastTrack instruction. FastTrack is a set of just 14 instructions that can be used for a large range of the relatively simple timing and sequencing jobs. Combine these with just two more instructions for MultiTrack, and you can be writing sophisticated multitasking programs in a few hours.
The total instruction repertoire of SPLat is over 400 instructions. You won't learn them all in the first day, but it's nice to know that as you expand your skills you won't suddenly get "dead ended", which is what happens with many competing controller products in a similar price range.
WaitOff
A FastTrack instructionThe WaitOff instruction simply waits until the named input, in this case 4, is off. Once that happens the program moves on to the next instruction. If executed in a MultiTrack task, the task is held up (blocked) until the condition is met, but other tasks continue normally.
Most machine controllers spend most of their time waiting for something to happen, be it in the outside world or in another program task. We have therefore created a number of instructions in SPLat that wait for something to happen (not just on inputs), and we will be adding more as time goes by. This is one of the reasons SPLat is so easy to program for controller applications: We are constantly thinking about what things are done frequently in the real world of machine controls and then devise features to address those things. (Which may also explain why, unlike one of our competitors, we don't support 8 dimensional arrays!)
WaitOnK
A FastTrack instructionThe WaitOnK instruction waits for an off to on transition on the named input, in this case 5. Once that happens the program moves on to the next instruction. If executed in a MultiTrack task, the task is held up (blocked) until the condition is met, but other tasks continue normally. The "K-class" input instructions were initially devised to simplify reading of operator push buttons (the K stands for Key).
SPLat pioneered the concept of a controller with built in operator interface, with the MMi88 in 1998. They were the world's most cost-effective HMI solution then, and remain so today, with a range of products that support LCD and real time clock.
WaitOffT
A FastTrack instructionThe WaitOffT instruction waits for the named input, in this case 6, to be off, but it will only wait for a maximum time. The time limit is specificed in multiples of 10mS, in this case 100 (1 second). The instruction will complete either when the expected input condition occurs or the time limit expires. Control then passes to the next instruction along with an indicator to tell it what the outcome was.
This is another example of how we create instructions that are relevant to machine control. Does any other controller product have a single instruction that will wait for an input and has built in timeout, and which can be invoked by typing a simple instruction?
GoIfT
A FastTrack instructionIn this instance GoIfT tests the outcome of the preceding WaitOffT instruction. It will go to the named line, LongShort_1, if the expected input condition was met within the time allowed. Otherwise the instruction directly under the GoIfT is executed.
In general GoIfT (Go If True) does a conditional jump depending on the True/False outcome of a previous logical operation. There is a complementary instruction GoIfF (Go If False).
SPLatOS C
This C program uses the SPLatOS operating system.
SPLatOS is a fully preemptive multi-tasking operating system. Therefore it includes traditional real time OS features like Mutexes, Semaphores, Messages, Threads and an application manager.
However, one key differentiator between off the shelf Embedded Real Time Operating Systems and SPLatOS is the inclusion of functions that permit immediate access to on board peripherals such as the LCD and modules that provide high level software functionality such as a Menu System and Flash Permanent Storage.
To make the example program work, the following items must also be made before compilation
//== in def_osconfig.m == APP_DEF( GameShow ) TIMER1ms_DEF( GameShowLight, A(GameShow) ) APP_DEF( Pushy ) APP_DEF( Shorty ) //== in def_osconfig_app.m == THREAD_DEF( App, 50 ) //== in your def_brd.m file, register threads that want button messages == IO_BUTTON( BtnRight, PORTn, n, NOPULLUP, ACTIVEHIGH, A(GameShow) ) IO_BUTTON( BtnMid, PORTn, n, NOPULLUP, ACTIVEHIGH, A(Pushy) | A(Shorty) ) IO_BUTTON( BtnLeft, PORTn, n, NOPULLUP, ACTIVEHIGH, A(GameShow) )
Notes on ladder program
The sample ladder program was produced using Keyence Ladder Builder V1.5. The program was tested in the simulator. To get a graphic image we took several screen captures and pasted them together in an image editor. We then reduced the width to fit the available window space to save you having to scroll horizontally. We did this by chopping out a lot of empty horizontal space.
And why did we select Keyence? Quite simply, theirs was the first "free to try" ladder programming software we came across for this exercise. As it turns out, the Keyence KV series is a range of small PLCs that you would quite naturally compare with SPLat, so the choice was quite relevant.
Incidentally, our programming software is totally free, not just free to try.
Statement List program
Statement list is an alternative view of ladder logic. Essentially, a ladder diagram gets translated into a series of low level instructions for the target processor, and the result is the statement list.
There are times when a ladder logic PLC is programmed directly in statement list, for example using a hand held programming terminal. Some ladder programmers maintain it is quicker to program using statement list than constructing ladder diagrams on a computer screen.
This statement list was generated by the Keyence Ladder Builder software from our ladder diagram.
Basic
The Basic program was written by Jonathan Tulley from Guildtown, Scotland. The Basic version Jonathan used is for the Trio range of motion controllers, and supports intrinsic multitasking. With this particular controller the commands that set the multiple tasks running are not part of the executable code, so you can't see them here. Rather, the procedure for downloading to the controller includes instructions on how to assign individual programs to separate execution windows.
Thank you Jonathan!