Category Archives: easyIPC

easyIPC Format

Message Header

This is the new message format that I will use on SPI, RS485 and Ethernet. For CAN I am not sure yet. I might want to take more advantage of the strong capabilities in CAN, but lets see.

The format above allows me to communicate device to device in a network, but at the same time also allow for streams of information that is not device depending. A device number is local for the network, meaning that all 1:1 messages on the link etc uses this format. Right now I want to establish a RS485 protocol that can support CLI as well as more advanced schemes. Next I want to bring up SPI and later CAN. But, I also want to add Modbus and CANopen support later – loads of fun.

RS485 is in this case running 2Mbps, so I want top-side to send a Start TDM signal with a list of devices that will respond. Device 0, Device1 etc. The logic is simple – Device 0 is always Network Master starting the loop by sending a list of devices that need to respond. At the end of it’s own sequence it sends EOT and device 1 starts within 4 ms etc.

I have 3 XPortHub devices I can add into the network for testing so we can get this off the ground.

TDM Sequence

This illustrate the TDM scheme between 2 nodes in a Network. Start TDM is only sent from device=0.

Start TDM

The content of Start TDM is a list of devices that will respond and in what order. Each device have a time-slot of 4ms to respond before the next takes over. Devices not on the list will be silent.

End of TS

End of TS (Time-Slot) is the last message send by all devices. This is broadcast and gives the next device a 4ms window to start sending it’s Messages. This scheme is used on RS485 and SPI. RS232 and Ethernet are full duplex and I want to evaluate options for CAN a bit later.

HMI Designer

One of the applications I want to create is a “HMI Designer”. This is technically very easy as I have done similar applications before. What I will do is to create a graphical application that can design square objects on a form. Each object will have a name that we can use for IO through a serial line. To make the designer a bit more WYSIWYG we animate the objects as if they where “furniture” like Text Edit, Graphic Plot, Grid, Button etc. Each object will have a list of properties that are set/get design and run-time. The result is stored as an XML file and executed by a “HMI Browser”, a special application that download the XML and interact with the system.

This way we can design config HMI’s stored in the embedded devices as XML files and we only need to re-create the HMI Browser to support HMI on Windows, Linux, OSX, Android etc. The concept is not so unlike a Web Browser with the exception that the server here can be small embedded system in a closed loop. Nextion are selling displays build on a similar concept, so in time we can do our own embedded graphics displays as well. I do however want to do tings a bit different from Nextion.

One of the differences is usage of Plain as “scripting” language and interfacing using easyIPC and RSX as well as Ethernet/Wifi. The other difference is that I want a significantly larger object library and take advantage of GPU’s on Raspberry PI etc. I also want this to be a portable software package, not locked to proprietary hardware.

The most important difference is however system thinking. I want HMI Designer & HMI Browser to be building blocks in the CASE (Computer Aided Software Engineering) Tool I want to create on top of Plain. For now we will use Plain and the HMI Designer, but I do plan a fully graphical programming concept later.

As mentioned before with my Plain blogs I want to evolve the way we do software based system development. The network I build here have plenty of fun for C programmers and electronic hobbyists, but we need to create infrastructure and tools enabling this for non-specialists.

easyIPC Design

I have written a lot about the intentions with easyIPC so it’s time we dig into the details of the protocol. easyIPC will follow the OSI model on a pragmatic level as illustrated below.

Smart SPI, RS-X and CAN-X are layer 2 links. Their only responsibility is to transport generic data between two nodes and maintain that link.

Stream routing is a small layer that will look-up DID & SID, replace them and forward messages either to a different Link or to an application.

Managing Entity is a database maintaining status over the tree of devices and it’s resources. This is the more complex part where we provide plug & play, dynamic resource allocation, redundancy and all the complex features in easyIPC.

The API is a thin layer interfacing easyIPC into various applications and programming languages. On Linux this will be running as a daemon (Service on Windows) with applications connecting as they start/stop. On an embedded device we use a tighter technique written in C/C++.

Watch out for updates on the doc pages.

Smart SPI

Smart SPI is a Layer 1 – 2 protocol using SPI to establish a direct communication link between Raspberry PI and Hat’s. SPI itself is a bit oriented full duplex protocol where the master control the speed by ticking a CLK signal. For every cycle on the clock we transfer a bit on both MOSI and MISO. Using SPI in 1:1 we only need GND, MOSI, MISO and CLK, but a CS (Chip Select) is needed for communication with several devices.

In a classic SPI design we would set a Chip Select pin and communicate with that device, select the next and communicate with that in a sequence.

All easyIPC aware Raspberry PI Hat’s use a technique called “Smart SPI” that implement several tricks to optimize SPI usage.

  • The stream on MOSI include target address allowing 8 Hat’s to read the message and filter out the messages they want to see. This allows Linux to send continuous on SPI without doing a bit-bang on CS pins that would slow down sending.
  • The message stream also include a Chip Select Message in software. As this is read by all Hat’s only the Hat selected will activate MISO. This allows the RPI driver to select MISO independent from MOSI stream.
  • MISO Send algorithm will enable Hat’s in sequence and automatically switch to the next after 1ms or as soon as the Hat report 0 messages. Bit padding is supported on both MOSI and MISO to complete a message.

Start-Up Procedure

The Start-Up procedure consist of a sequence of operations that must be executed as the system is powering on. The Hat’s will at this time not know their own Hat-number and as such not be able to communicate using Smart SPI.

  1. We Set Chip Select to 1 and send Device Identification Request with number “1”. The Hat that see it’s CS enabled will consume this message and set it’s id to 1. All others will ignore the message.
  2. The Hat will respond with a short Device ID Response. This is a short message to tell the master that the device is active. Master will on a slower scheme attempt to send Device Identification request to device numbers that are not active to enable Hat’s at a later point. Device ID Response tell the Master that the device is active and ready to communicate using Smart SPI.

Normal operation

  1. Once a full iteration through all 8 Hat’s are completed we start using Smart SPI. The Master will on regular intervals continue to send Device ID Request to Hat’s that’s not active. If a Hat fail to answer normal messaging it will be moved to Non-Active list until Master can perform a successfully ID request.

Note that the full start-up procedure for easyIPC consist of other sequences, but Smart SPI is a layer 2 link only responsible for sending/receiving between Raspberry PI and the Hat’s. See easyIPC for the higher level start-up procedure.

Smart SPI Message format

Length is a 8 bit unsigned integer that indicate the total length of the message in bytes. Minimum length value is 6 bytes since minimum payload is 1 byte. Payload length = Length-5.

DID (Device ID) is a physical address needed by layer 2 for message transfer. This is always the device ID. MOSI will contain the destination ID, MISO will contain the Source ID.

DID=0 is used for broadcast. Device 1-31 is a physical Device #.

SID (Stream ID) is the ID of a point to point stream. Stream 0 is always the device and layer 2 link. Stream is used for internal addressing on a node.

SEQ (Sequence Number) is a 1 byte number that start on 1 and wrap at 255. The value 0 is used for none-sequence. Each side in a Smart SPI need to remember the last messages sent and be able to repeat them on request. The receiver will verify that the SEQ increment with one, and if not issue a MessageMessage Repeat Request. MISO Switch Request also contain the last message received in case the last message was cut short. Sequence is unique per device and only intended to guarantee that all messages are transferred.

MID (Message ID) is actually the first byte in the payload. The meaning of the payload needs only be known by the stream end-points.

Payload is the actual message parameters/data.

CRC is a 2 byte CRC to ensure message integrity.

Device ID Request

Device ID Request is sent to a device that also will be selected by a Chip Select pin. Any device receiving this with CS set to 1 will accept this as it’s ID and respond with Device ID Response. The device will accept the address in the DID field as it’s address

The device ID procedure will send a Device ID Request on MOSI and then start padding with zero’s for a selected response time of x ms. The device needs to respond within this time or it will be marked as inactive and not included in the active iteration.

Master will attempt to re-connect to inactive devices ca once per sec.

Device ID Response

Device IS response is send by a device that receive Device ID request while chip select is active. This indicate that the device have received it’s address and established a link capable of communicating on Smart SPI.

Devices that fail to respond before Chip Select goes 0 (Zero) will be listed as inactive. SPI will always have a number of fixed slots that in theory is max 31, but the current limitation on Hat’s are 8.

Inactive Devices are listed separately and Master will use Idle time to attempt to re-connect to devices. See Device ID Request.

MISO Switch Request

MISO Switch Request is used to switch MISO Sender. All devices will set MISO to 3-state and stop communicating. The device currently sending will finish it’s current message and stop.

The Switch procedure contain a programmatic delay intended for the sending device to detect and abort it’s sending. Once that times out the new device will assume the MISO is available and start sending.

MISO Switch Response

MISO Switch Response is sent after a delay needed to secure that the sending device stops. This is sent from the new device and indicate the current queue length. The next message is the first message in the queue.

Message Repeat Request

A repeat request is issued to repeat 1-2 missing messages. The response will either be messages repeated or a Message Repeat Reject if the sender is unable to repeat the messages.

Message Repeat Reject

Sent in response to a Message Repeat Request if one side is unable to repeat the messages. Can happen if the gap in sequence is to large.

Link Reset

Issued by both sides to reset sequence numbering. Used as a response to errors.

See documentation page for an updated Version of this post…

Universal Motor Controller

I designed this universal motor controller capable on driving DC-, Stepper-, BLDC- and even AC – motors earlier. The design parameters was 12-24V at 15A. This is quite a capable controller, but I did a mistake that limit the controller to 12-20V since I connected the Gate Drivers to the Motor PSU directly. To compensate for this I need to modify the design and implement a separate 12V PSU. As I correct this I also want to consider some additional changes.

I am considering is to replace the RS485 with an isolated RS485 due to the amount of energy involved. The 3rd change is Ethernet on a separate adapter board. Basically I want to copy the modules I use on the Universal Adapter as soon as I have tested them.

I am not sure about Ethernet. Ethernet sound nice due to the functionality, but it is a clumsy, 4-wire 1:1 solution. RS485 is slower, but it is a 2-wire network. It actually makes more sense having dual RS485 to be honest. CAN & Ethernet is easier to deal with using an adapter board- RS485 is considered a lower level of communication than CAN because CAN have protocols like CANopen, J1939 etc. The reality is that if we use RS-X that changes.

What I probably should do at some point is to create a “Ethernet” on top of RS-X by using a dual RS-X connection. But, that is fun for later…

So the modified design will be

  • STM32F405RG MCU, 168Mhz, 32bit M4, 1MbFlash, 192KbSRAM
  • 4 x separate half bridge drivers, 30V @15A
  • Current sensors on all
  • BEMF sensors
  • PSU Voltage Sensor
  • Separate 3.3V supercap to sustain MCU in power dips.
  • 3 x hall sensors
  • 2 x temperature sensors.
  • 1 x resolver
  • 2 x end sensors
  • 1-2 x RS485
  • Adapter board for battery/caps
  • Adapter board for CAN/Ethernet/Wifi


  • Solenoid driver
  • DC Motor driver
  • Stepper Motor Driver
  • Brushless 3-Phase motor driver

PLC Modular System

I have worked far to long with 19″ cabinets and things you mount from front, so what I am thinking is a micro-version of a rack system. We box each electronic module with a backbone plug and custom front connectors. We then plug them in, wire using standard wiring (that we probably have to create) in front – no wiring in the back.

These boxes are simple and can easily be printed on a 3D printer. They will also allow us to mount more electronics tighter to address the total size.

A classic PLC uses 2 wires for a 24V pulse signal – we can typically standardize these so that we apply standard, plug & play cables and avoid as much custom wiring as possible. The top front is after all for wiring to equipment, not for internal wiring that is already done in the back-plane. I think this can work, but I need to talk it through with professional automation engineers – luckily I have access to them in numbers.

One drawback I can see straight away is vibration. I was planning to make this so small that it could fit mobile Equipment, but mobile Equipment vibrate a lot. We will need an outer box and holding mechanism that tolerate very high vibration – or more correctly reduce vibration.

Plain – Distributed Processing Part 4

A lot of Plain assembly syntax is experimental and will be reviewed as we move forward. I think it is important to get concept ideas out in the open for discussions – we can always optimize keywords and syntax later.

In Distributed Systems we need to synchronizing data between multiple modules and this  creates a need for a distributed database system. The transaction mechanism we created earlier fit straight into this, but I need to review the concept to cover a few loose ends.

use System
Module LedHat
            Object LedGroup
                        Bit Led1
                        Bit Led2
                        Bit Led3

            Interface C LedGroup leds[1..6]

My previous example shows how I can call a function located on a different device. In this New example I want to set the leds directly from 32xIO by sharing data.

use System
use LedHat
Module 32xIO
            Transaction LedHat.leds[1]

The “leds” array is declared as interface allowing other modules to access it, so we can as well just access the array from 32xIO inside a Transaction statement. What happens is that we use DRA to connect between LedHat and 32xIO as previously explained, but we now need to (1) send a message to lock access, (2) make the changes, (3) commit changes. We get two extra messages, but less code this way. This was the easy part!

The system illustrated above is two systems wired as one just to complicate things. 32xIO #1 need to connect to LedHat #1 and 32xIO #2 need to connect to LedHat #2. This creates ambiguity as we by default will connect at random – first request will get first LedHat in list etc.

One way of solving this would be to use different module names – this is possible – but you will end up maintaining separate code for multiple devices depending on how they are used. Let’s try to avoid that as much as possible! In this case I have two “domains”, each with an array of 3 x 6 leds using the same name. And as I don’t want to hard-code the domain name I need something else.

A classic solution would be a complicated configuration, but I do not want that either – I have spent to many hours configuring complex communication systems to walk into that trap.

The concept I want to test out is a “System Diagram” – some kind off high level description of our system with modules, devices and how they connect. With this in place I would only need to tell my module what role it play in that system – lets give it a try:

use LedHat
use 32xIO
System SpiderRobot
            Domain green owner LedHat
                        LedHat greenLedGroup
                        32xIO greenIO
            Domain blue owner LedHat
                        Ledhat blueLedGroup
                        32xIO blueIO

The example above create a system “SpiderRobot” with two domain’s – “green” and “blue”.

I did consider using xml for this, but decided that this actually is part of our code and should use Plain syntax. I like xml because it is an excellent data storage format that can be edited manually if we need to – but, as xml syntax also can be very cryptic – difficult to read logic – this should not be part of any programming language – IMO!

pd 32xIO SpiderRobot -d blue

This is a proposed pd (program download) command. I will review the utility command line later, so this is just a quick & dirty proposal – 32xIO and SpiderRobot are plain assembly (*.pln files). -d blueIO tell the pd that the module can see domain “blue” in addition to global domain.

As the 32xIO now request a LedHat it will only be given access to the LedHat in the same domain. As we start LedHat and 32xIO we also report what domain we are, or that we are unassigned – in the later case we need to be assigned domain visibility & roles by an utility later.

use LedHat
use 32xIO
System SpiderRobot
            Domain green owner LedHat
                        LedHat greenLedGroup
                        32xIO greenIO
            Domain blue owner LedHat
                        Ledhat blueLedGroup1
                        Ledhat blueLedGroup2
                        32xIO blueIO1
                        32xIO blueIO2
	     Wire blueIO1 to blueLedGroup1
	     Wire blueIO2 to blueLedGroup2

This example complicate our story a bit because I decided to add a 2nd LedHat and 32xIO to domain “blue”. In this case I still do not what LedHat to connect to so we need to “wire” the system manually since auto-wiring will not work anymore.

The added “wire” statement solves this, but I just decided that having two LedHat’s was a bit much, so I want to use only one and let the two 32xIO Hat’s access different led Groups.

use LedHat
use 32xIO
System SpiderRobot
            LedHat greenLedGroup
            32xIO greenIO
            32xIO blueIO
            wire greenIO to leds[1]
            wire blueIO to leds[2] as leds[1]

In this case I actually don’t need domain grouping so I just specify my 3 Hat’s and how they are wired together. The wire statement only specify visibility and how we view content. The code does in this case program leds[1] so as I wire blueIO to use leds[2] I also need to specify that this is seen as leds[1].

My concern here is that we introduce too many error scenarios, and as this is a highly experimental concept we need to be open minded for better solutions or loose ends.

Plain – Distributed Processing Part 3

The system I described in part 2 needs to send a message from a module in device #2 to a module in device #5.

This tree is basically the physical address of a resource as seen from RPI1 and RPI2. But, as this address might change with wirings we need a more generic way to program this. The key in this case is that we use the module names are a “resource”.

32xIO and LedHat are both reported as resources in the system during startup. The 32xIO module will due to the “use LedHat” statement request a “LedHat” resource and be sent an address in return. This is part of Dynamic Resource Allocation in easyIPC – a topic we have yet to cover. With an address we need to map a message routing from device#2 to device#5 – this is called a stream in easyIPC. A stream is always 2-ways.

1 The VM “32xIO” (Not the device) will initiate a DRA request. And as part of the request we assign a Stream ID on the device.
2 RPI1 decide to forward the request to RPI2 since this own a request of this type.
3 RPI2 will forward the request to the LedHat device using a managing stream id
4 The LedHat will allocate the resources and send a DRA Responce back with a selected stream ID.
5 RPI2 will set up it’s own Routing between this Stream ID’s and RPI1 and forward the response to RPI1
6 RPI1 will set up its own Routing between the stream ID’s and forward the response to 32xIO.

We have now set up a stream. Any message sent from 32xIO on that stream will be forwarded to the LedHat and wise versa.

DRA will also deal with re-allocating of resources and it is more details to it, but this illustrates how we will  (1) report the modules as resources and (2) connect resource streams in easyIPC.

to be continued in part 4 …

Plain – Distributed Processing Part 2

Our concept of distributed processing is going to need some attention to details in the Assembler/VM design, but it will work. We  now have two mechanisms involved:

  • We have an easy way to synchronize data between several modules
  • We can make on module execute logic on a different module.

The principles of how we do this through easyIPC is easy, but we need to dig into the detailson some some loose ends in our design. One such issue is module addressing in a larger network.

The block diagram above consist 7 devices in a system. We have two RPI’s one for controlling the actuator/sensor sub systems, and one for HMI. The HMI contains a Led Hat where I want to blink Leds from the Servo and stepper controllers.

 LedHat example

use System
Module LedHat
            Object LedGroup
                        Bit Led1
                        Bit Led2
                        Bit Led3
            interface C LedGroup leds[1..6];
            Interface Func SetLedStatus(uint32 group, Bit l1, Bit l2, Bit l3)
                        Transaction leds[group]
                                    leds[group].Led1 = l1
                                    leds[group].Led2 = l2
                                   leds[group].Led3 = l3

32xIO example

use System
use LedHat
Module 32xIO

These two code examples are the Plain code I expect to write.

to be continued in part 3…

VM Test Ground

I decided to use the 32 x IO (Servo, Analogue, Digital) as my test ground for the VM – the firmware will in this case include easyIPC (SPI in this case) and a 32 channel programmable IO controller. Each of the channels have capabilities like:

  • Servo with a 14 bit pulse resolution.
  • PWM out with 14 bit resolution. This is a bit-banged PWM that can be used on all channels.
  • Digital Signal Input
  • Digital Signal Output

 Some of the channels will have the following:

  • High resolution/frequency PWM signals
  • Analogue Input
  • Analogue output.

This firmware is an excellent test-ground because it includes highly programmable logic and a hard real-time core on the bit-banging part.

Lets draft some PLAIN Assembly code:

Enum uint32 Mode

Object Channel 
            Mode chMode = Mode.Servo
            uint32 position=0
            uint32 frequency = 0
            uint32 duty = 0
            uint32 analogueOut = 0
            uint32 analogueIn = 0

Channel Ch1
Channel Ch2
Channel Ch3
Channel Ch4

Bit digitalIn[32]
Bit digitalOut[32]

This is a draft of how I want PLAIN Assembly to see the easyIPC objects. Ch1.Mode will be located at register 0x8000, but we can also locate data on selected registers as follows

Channel Ch1 at R(0x8010)

In this example I force Ch1 to be located at Register 0x8010.

The more tricky part is the integration with C/C++ code. The challenge is that the module and data we transfer must match what the C/C++ firmware expects. This last mapping is done by the real-time linker in the firmware that receive the above as a “PLAIN Module Specification”. If it fail it will need to reject the module. In theory it should never fail as the assembler should stop us, but it is always the possibility of firmware version mismatch. This part will need to be strict or we will just dig into loads of debug problems.

Map Channel to C(Channel)
Map digitalIn to C(DigIn)
Map digitalOut to C(DigOut)

Assign Ch1.chMode = Mode.Servo
Assign Ch2.chMode = Mode.DigitalIn
Assign Ch3.chMode = Mode.DigitalIn

Event digitalIn[2]
            Assign Ch1.position = 0

Event digitalIn[3]
            Assign Ch1.position = 100

This example configure Ch1 as a Servo and Ch2, Ch3 as digital input pins. The Map statements link the objects to associated C/C++ code. The Assembler (and real-time linker) will check these exact names and parameters – parameters must match on name and data type.

The Event statement “digitalIn[2]” declare that any change to bit 2 in the digitalIn will cause a call to this bit of logic. This will be called regardless if it is C/C++ or PLAIN assembly that makes the change.

 I think this will work, but I need to let it mature to catch up missing bits and see if I can optimize this. Notice that while this example is ca 40 lines in assembly we would be talking about ca 7 instructions in the resulting code (+ initialization). The initialization will in this case be nothing since 0 is the default value on all registers. The VM will automatically reset this before execution to avoid that we have random, default values. “Event digitalIn[2]” will generate 2 instructions – an Assign and a Return.

But, keep in mind that this draft is work in progress. I will implement this next to see how it actually works out in real life.