Open PLC System

PLC (Programmable Logic Controllers) have been around for years. It usually is a modular system of electronic boxes with IO capabilities that can be assembled into a system for automation purposes. PLC have 5 “standard” languages that are not really that much standard. The standards tend to serve as minimum list of features, but as the vendors add much proprietary stuff the PLC applications end up being very proprietary. Plain have a much higher possibility of actually being portable.

A PLC system cost a lot of money, but as making custom electronics and writing code in C/C++ cost more the vendors get away with high pricing on electronics, tools and HMI. Also – the hard fact is that it is not much I can do with a professional PLC that I can’t do better, faster and with less cost using Arduino or Raspberry PI these days.

I have briefly mentioned HMI – I will return to that later. But, my Raspberry PI Hat’s and RS-X modules powered by Plain is an excellent PLC substitute. I do however fancy a more dedicated, modular system that can compete with classic PLC in a smaller space. My Hat’s are great, but it’s limited what I can create on the size of a Hat + the Raspberry PI is often not needed. I want to keep the option to add a RPI module with a Hat, but I want a new system.

Using Ethernet as backbone I would like to create a motherboard that control 4 x IO modules. Using RS-X as bus allows me to use the modules stand-alone or plugged them into a assembled system. Adding more motherboards I can scale up with 4+4+4+ modules as much as I have space. I believe I can do this on very small Space.

The major restriction I have on the Hat’s is connector space. I want to use standard connectors with standard cabling to avoid the need for custom cabling as much as possible. My “PLC” language will obviously be Plain.

What needs to be different from what I have done so far is Galvanic Isolation on all communication to limit the chain reaction if something backfires – because it will!

The added work-load on coding does not worry me because we can re-use things that I am in the process of creating anyway + I think this will be fun. 10 x 10 cm comes to mind as a size factor. It is easy to create modules that are 5 x 10,  10 x 5 or 10 x 10 to be mounted as part of the same system so it gives us freedom. It is also easy to create a 10×10 carrier module for Raspberry PI so a RPI+ Hat’s can become a module. But, I will look for standard, low cost project boxes before I decide on size.

It will be fun if nothing else and thats why I am here in the first place, so lets crack on with an open source, home made, low cost PLC system. My home is an excellent testing ground – assuming it don’t burn to the ground in the process 🙂

Proof of life

Wow – it is actually ticking -at least blinking the leds. Been a bit forth and back – this is a STM32F105RB – I connected it using zero resistors on the VCAP as I could not get STM32F405RG to work. Turned out the problem seems to be my Mini ST-link’s. Well be back With STM32F405RG, but this was a struggle to get ticking!

Update (28.mar.2017) F105 working well, but F405 still not ticking. According to my notes the only difference should be two capacitors from pin 31 and 47 to ground. My challenge with this board is that it is quite small, tight and contains 7 new modules that I have not coded before. This could be a test of my electronic skills.

I still suspect bad soldering that tend to be the case – this is the drawback with hand-soldered prototypes – so I will make a fresh attempt later – these MCU’s have been dead easy to get going so far – connect power and a SWD and your up. I can’t complain – I had a pretty free ride getting very over-confident so far

Update (29.Mar.2017)It is still a mystery why the F405 will not work. I applied the 100nF capacitor on NRST, but it made no difference. I did however discover a soldering technique to minimize shortcuts on these LQFP packages. As for the board – F105 is working perfectly if I replace VCAP capacitors with zero resistors, so the board is ok – I don’t need the F405 for this board, but I wanted to test F405.  I still have a few things to try. I have MCU’s from two batches, so I will start fresh on a new board with a different MCU batch later.

After that I will update my Rx breakout to have VCAP capacitors and jumpers to use both F1 and F4. It should be this simple. A breakout board is better to do this level of testing on as I need a proof of concept on a F405.

I did test my ST-Link on a F407 and it worked fine – this is more or less the same MCU. The initial error was “No Communication”, but as I removed one MCU and fixed a shortcut the error change to “Failure on Flash Erase” – I have seen this on other board that I later got working with F105 as well. This means it has some initial communication with the MCU, but the erase operation fails. If I skip Erase it fails on Program – it sounds like an incompatible protocol.

I have four suspicions: (1) Bad/Fake batch. I am buying from various sources on-line to get samples at a decent cost, but I have so far never had a problem with this. (2) SWD wiring to long for this MCU, (3) my ST-Link is incompatible with this MCU batch. I somehow don’t think so since the F407 worked with the same wiring, but you never know. (4) I will try different capacitor sizes on the VCAP.

I would like to update the Rx breakout anyway, so I will order that and see how we can move on. I also realize that I need to add a few extras to make it easier to scope these boards. I am notorious for not adding test points on early proto-types and I just paid the consequence for that.

A 168Mhz design is a bit more than I want to do. But, all the high frequency stuff should be on the inside of the SoC in this case. The issue with high frequencies is that lanes start to behave more like capacitors and coils by accident, so you need a much better analogue skill-set and awareness of what you do on PCB routing. To my knowledge this should not be the problem, but at the moment I need to question everything.

STM32F405RG

I did at one point assume that STM32F105Rx and STM32F405Rx was identical on schematics – they actually are with the exception of two pins. Notice the VCAP pins connected to capacitors at bottom – on a STM32F103 or STM32F105 these are connected to ground.

Graphical Programming Languages

I have always fancied making a graphical programming language. I have also used a few of these as well as done some experimental development myself.

The first challenge is that graphics tend to take up a majority of your time, so you need to carefully select or build a graphic 2D foundation before you start. Unlike a text based language where you can start with any editor and experiment with syntax, you will have to create a complex, 2D graphical design tool before you see your errors. So in my previous attempts I ended up doing a lot of fun graphic work and very little programming language development.

The second challenge is that while some parts do very well in graphic tools, others struggle a bit more. Let me give you examples:

Screen based user interfaces will usually do very well on the design side and is well accepted. Graphic designers have had great success in this for years.

Database design do well because you have established diagram techniques that is well suited to describe a relational database. This is also an area where it is rather easy to auto-generate software due to the high repeatability of tables, columns, relations etc.

Logic is however more difficult. You have little or no auto-generation support, and while a diagram of some kind make the illusion that this is easy it also hides a lot of details. Experienced developers will often work faster in any text based editor, something that defeat the very purpose of our graphical toys.

My conclusion is that I still believe we can dramatically increase our productivity with graphical languages. But, a graphical Language needs to be merged with a text based one – and the graphical part need to be designed with input from a thoroughly study of what new challenges they create for the developers.

Communication Adapter

I have a lot of electronics that I had little time to work on. This communication adapter is one of them. Using a STM32F405RG it communicate between 6 different wired/wireless methods.

The picture on the top show the 3D model, the picture on bottom show the PCB. I had this stack of PCB’s next to me for a while, so I want to assemble the board and see if it work.

  • 10/100Mbps Ethernet using Wiznet W5500
  • USB connection using CH340G
  • Wireless Ethernet using either ESP-01 or ESP-12E
  • NRF24L01 using either breakout or mini adapter.
  • CAN HS with Galvanic Isolation
  • RS485 with Galvanic Isolation
  • MCU STM32F405RG
  • 1Mb Flash
  • 196Kb SRAM
  • 168Mhz ARM M4
  • 8 Leds
  • Full BasicPI SWD Adapter
  • A lot of fun in the waiting.

I will be assembling this tomorrow so look for my next entry…

Plain Libraries

One lesson learned from C#/Java versus other languages is that we need to include standard libraries as part of the language standard. C/C++ do not do this and suffer the consequences of lower portability between platforms as a result. The challenge is that libraries will be larger than the VM itself and many of them will need to be implemented in C/C++. The smaller MCU’s can not be expected to support the same C libraries as we expect to find on Linux/Windows level implementations.

The Assembler and RTL will sort this automatically. As we use a repository we also decide platform and what it contains. The assembler will generate an error if we attempt using content not present on a system. And the RTL will fail at binding the same rejecting any module that require content it does not support.

The following libraries are planned

System has a mandatory content and optional content – all of which is implemented in the host language to allow Plain access to the core system parts. System will cover all basic features needed to actually write a module – including access to RTOS and generic system.

HMI – Human Machine Interface cover standard keyboard, mouse and display as well as buttons, leds etc. Due to the nature of Plain we can easily create a user interface on Raspberry PI operated from an embedded device or wise versa – HMI cover standards to do this so we don’t end up with too much proprietary solutions.

Database library giving us access to any standard database as well as our own proprietary ones. The library will cover a standard way to access data and a standards to include proprietary solutions to ensure that modules accessing a database is portable. The proposal will also include a proprietary, distributed database solution that either can be used stand-alone or as a real-time, distributed front-end to 3rd party solutions. Again- due to the nature of Plain it is straight forward for an embedded device to access a database located anywhere in the network – but, we need to include this in the Plain language definition to secure portability.

Communication. We have an implicit inclusion of easyIPC since it is used by Plain VM, but we need a way to access & control other communication protocols.

Advanced math library – hard to avoid in any system that require math. Standards to let any module access and execute advanced math using resources available in the system.

 Others ? I believe the more stuff we can define & support through standards the better.                        

 

Plain Assembler Design

This is not my first language as I done some proprietary scripting and experimental parsers in the past. This did not lead anywhere expect to influence how I want Plain Assembler to be designed.

The drawing above illustrate the main components.

Repository is a fancy word for a database. Plain is unique as it start by demanding a database in XML format to describe our platform. This file get read into the internal repository before parsing starts. As we parse we build the complete repository that also can be saved back out in XML format and used for the next assembly process so that we don’t have to re-parse everything. Using XML rather than a binary format makes sense because it enable me a way to inspect content + parsing xml is actually far faster than reading a binary file – I know this will surprise some.

The parser read the system diagram and module(s). Each module generate a RTL file that is used to download the plain module(s) one by one. Parsing needs to be 2-pass. We first parse the file and secondly solve “forward assumptions”.

The code generator uses the repository to generate a RTL (Real Time Linker) file. The RTL file is sent to the VM that will link together the final binary module that we execute.

All in all it is a bit of work, but it is not that complicated once you get started. The key is that we need to be systematic as we will have parsing and code generator for each statement – which is why I want to use C++ because we take advantage of object orientation and let each statement be a C++ class that sustain parsing, repository management, code generation and in general everything for that statement. Using C++ this way also give me a single file for “if” etc making it easy to track and maintain. It creates more code, but it makes a lot of sence as the code get readable and easy to maintain.

Plain Roadmap

I Introduced the Plain concept 28th January, we are now 2 months into the making and I start seeing the end of the draft and need to consolidated a specification. I like where I am heading with Plain as it has grown from an experimental idea into something that I look forward to use myself. But, I have a big load of C & C++ coding before we get there.

Plain VM is started and is being written in C. I initially had plans to manage a minimum on STM32F030F4 with only 16Kb Flash – I am not sure that is realistic. I probably CAN get a minimalistic version to run on this device, but lets see – I have to weight in how much work it will be.

Plain Assembler will be written in C++ running as command line on Windows and Linux. The same with the command line utilities. The only dependency will be a library I made some time ago that is dedicated for embedded C++ stuff.

Plain – Functions

Functions in Plain are similar to functions in any language with a few important differences. A function in Plain will return an event with parameters, meaning we return a different set of parameters depending on what even we raise.

The second difference is that we let a function call be an implicit state-engine where we override optional or mandatory event with an “On” statement.

The third difference is that we allow a function call to act like a control statement by merging the body between the call and the first On into the function. This allows us to create new control statements.

The fourth difference is that I want to introduce named parameters.

And we need a way to make a function accessible from expressions.

use System
Func Parallel(uint32 Timeout)
            Timer(Timeout)
                        ExecuteBody
                        While ThreadsRunning()
                                   Sleep(10)
                        End
                        Raise Synchronize()
            On Timeout()
                        Raise Parallel.Timeout()
            End
On Timeout()
On Synchronize() Mandatory
End

Parallel ( Timeout=10000 )
            for x=1 to 20
                        spawn Math[x] transaction arr[x]
                                   arr[x] = Compute(x)
                                   state (Compute)
                                   on Error(..)
                                               // todo
                                   end
                        update
            end
On Timeout()
            //
On Synchronize()
            //
End

This example create a function Parallel that use experimental Syntax “ExecuteBody” to “call” the embedded, main body. After that we loop checking if threads are running – again using experimental RTOS functions. The example use a different function Timer that also act as a control statement itself. I could have used “Parallel(10000)”, but chose to write “Parallel(Timeout=10000)” since the parameter name add readability.

I mentioned “named parameters” – we sometime have functions with many parameters that can be given a default value in declaration. The classic solution is that if you want to override default parameters you start from left to right leaving out those on the far right side – I want to introduce is an option to do this by using an embedded assign to the parameters name.

func foo(uint32 something=10, uint32 somethingelse=20, uint32 mypar=30)
...
end

foo(mypar=40)

In this example the assembler will create a call to foo with 10,20,40 as parameters as we use the name of the 3rd parameter to specify only this. We can leave parameter 1 & 2 out because they have a default value – if they did not the assembler must give an error – missing parameter.

As to making a function accessible from inside an expression I suggest using either “Raise Continue” or “Return” – with one parameter. I am considering syntax like “x,y = foo()” where we Return multiple parameters – but, let us wait a bit with that one.

func foo(uint32 x)
            raise continue(x)
Event continue(uint32 x)
end

uint32 xx = foo(2)

We still have loose ends here, but I finally start to see syntax that I feel solve the Parallelism riddle and add something to Plain. The actual functions Parallel and Timer will be C functions – we will need to include a library of System functions anyway. At the end I also need to review if this actually serve the main objectives of Plain – ideas are ideas – they do not always stand their ground.

Plain – Parallelism Part 3

I must admit that I find it hard to create syntax supporting parallelism that I like and does what I want. I have looked into other languages for ideas, but the solutions are either too implicit or to manual. I insist on having a syntax that force us to write code in a way that automatically will solve the technical issues involved – and yet provide us with an option to manually control things if we need to – and I insist on code being readable.

My previous example uses “Spawn” to mark a statement or block that we execute in background. I used this on transaction, but we could in theory apply that as a prefix/postfix to any statement to create a background process. I need the background process because I need the logic that control and respond to a remote function Call that is not blocking.

for x=1 to 20
            spawn transaction arr[x]
                        arr[x] = Compute(x)
                        state (Compute)
                        on Error(..)
                                   // todo
                        end
            update
end

If I limit this to transaction I also force the usage of a mechanism that will sort out the multi-threading issues and using spawn as a prefix (or postfix maybe) to transaction avoid that we need to create a new control mechanism.

The challenge here is that I will be allowing 20 background processes while I continue executing the foreground process – so we will have 21 VM’s active with a bit of code. At some point we might need to collect those process and wait until they are all completed as well as respond to error situations.

Parallel( timeout=10000)
            for x=1 to 20
                        spawn Math[x] transaction arr[x]
                                    arr[x] = Compute(x)
                                    state (Compute)
                                    on Error(..)
                                               // todo
                                    end
                        update
            end
On Timeout()
            //
On Synchronize
            //
End

My first proposal was Parallel..end. End will not work so I replace it with “Synchronize”. – just playing around with ideas here – but using our new State mechanism might be an idea except that “State” is already used for a purpose. I can however use implicit state and allow Parallel to be a function where we allow the main code block to be embedded inside a function. I will need added syntax to functions, but this would allow us to treat timeout and synchronize as events + give us a powerfully new mechanism to actually create new control structures in Plain itself.