XPortHub2 w/Ethernet

3D model of XPortHub2. This contains an 10/100Mbps Ethernet with a standard RJ45 socket that replace TF Card, I2C and SPI on XPortHub1.

  • New style SWD port.
  • Raspberry PI Backbone with SPI and CAN.
  • RTC with Battery holder on back.
  • 8 x user leds.
  • 2 x CAN ports. CAN1 is connected on Raspberry PI Connector so that CAN connect as you stack board together. Just like SPI.
  • 2 x RS485 ports.
  • 2 x RS232 ports.
  • 1 x USB port.
  • 1 x 10/100Mpbs Ethernet port.
  • 1 x TTL UART.
  • SPI Flash.

I fancied having a STM32 based board with Ethernet thought I already have an ESP32 based one. This board is attractive as a stand-alone adapter board as well.

Starting now we will also offer boards for sale. This is only limited number of prototype boards that can be purchased through www.basicpi.com.

This last image show the back of the board where you can see the CR1220 battery holder. One big upgrade is that KiCad show the ground plane correctly and even detect icelands. This groundplane worked out nicely.

SWD

J4 at right is the SWD connector. This can be reduced to 3 pins (SWCLK, SWDIO and GND), but it is wise to include Boot0, nRESET and 3.3V. I have painted SWCLK and SWDIO lanes in light red – those are the important ones that needs to be kept as short as possible. The only reason I use a 2×5 pin connector here is because they are easily available and give a stable connection base as I add a 1.27 pitch to 2.54 pitch adapter on top. It also gives the advantage that I actually can program the boards using a male adapter and just putting it down the holes. I recommend a proper connector if you work with the board, but this is a neat production trick to avoid mounting connectors on all boards.

This is my latest SWD format that I know apply on all boards, but I have so far used the same adapter board on everything and it have worked very well. I usually have a few ST-Link/v2 with adapters and it’s very easy to connect to board – which is how it should be.

I will however make a new adapter targeting boards inside a stack. I can manage with my existing ones, but I need to dissassemble the stack to mount/remove adapters. I want a new adapter where the PCB take me outside the board so I can mount/remove SWD’s while they are part of a stack.

Ethernet W5500 on XPortHub2 PCB

 

This pic is from the new XPortHub2 with Ethernet via W5500. The routing is close to being a single layer. The total number of passive components makes this occupy 1/3 of the board.

The only challenge here is that HR911105A is a bit to tall for the next board in the stack – this is not critical, but I will look for a lower profile RJ45. It is also easy to forget that silkprint takes as much space as the components on 0603 packages.

Fiber Modules

Fiber modules have been around for some years. The picture below show a 14.- USD 8 x Ethernet/2 x Fiber Mux/Switch that can be found on AliExpress etc. I have also seen smaller modules and 16 x Ethernet modules in the same price range – also boxed versions.

The interesting thing about these is that the Fibre links in theory can stretch a cable up to 100km. As I mentioned this has been around for decades, but it impresses me to see these modules down below 20.- USD in cost.

My own PLC uses high speed SPI as backbone and I already have Ethernet through Raspberry PI or ESP32 Board, but I fancied drawing a dual ethernet solution based on Wiznet W5500 as well. I have used this chip before. Ethernet and Fiber will extend the backbone to cover kilometers of wired net then needed. I am also a bit interested in using Ethernet as backbone all over, but space is a bit limited on the current Hat format. If I am to upgrade to Ethernet as backbone I will need to increase size, so having an Ethernet adapter is a compromize.

The ESP32 Ethernet module contains Ethernet and Wifi, but the SPI on it reduces backbone speed to ca 9Mhz as Slave. I can live with that, but I would prefer a higher speed. It is however challenges involved in using SPI the way I do, and a pure Ethernet backbone have a lot of advantages. But, is has one disadvantage – added space need on my boards + you need the switch in the backplane. And don’t forget that we also have CAN that can stretch over 1km.

Another option is to upgrade XPortHub and replace the SPI/I2C ports with an Ethernet port. I could just use magnets and a different, smalle connector etc. I have a bit of space problem here, but it can be done if I either sacrifice TF card or move TF card and/or battery to back side of card.

C#/.Net Dark Theme

Working on HMI in C#/.NET is fun, but it is a large task to get dark themes right. Below is a list of components that I want to complete:

clEditCtrl Simple text edit control.
clHScrollBar Horizontal Scroll Bar.
clObjectEditor Advanced grid alike editor to edit an “object” with a tree of items.
clPopUpMenu Classic pop-up menu.
clShapeLabel Label with titled corner options.
clSmallButton Small, flat button with image symbols.
clTabBottonCtrl Advanced button with sub-buttons.
clTabStrip A list of buttons located on an edge.
clVScrollBar Vertical Scroll Bar.
clMenu Classic Horizontal Menu
clCaption Dialog title caption
clToolBar Horizontal bar for various sub tools

Other components will be added as needed, but I want to complete the list above so I can move on with other things for now. I decided to not do a drop in replacement of all components, many of the components above also add advanced functionality to be able to quickly create an advanced HMI.

I have tried various schemes, but I ended up sub-classing from UserControl and re-create things from scratch on most components. Luckily I could use the edit control with a few tricks, because that alone is a lot of work. To make this work I had to add color properties as follows on all components.

BackColor Most components have this
ForeColor Most have this as well.
BorderStyle Need to override BorderStyle
BorderColor Very few components could control border color from the application.
BackColorHover Background color if mouse hover over the component.
BackColorShape Used only on shape controls where I need to “normal” background colors.
BackColorSelected Used on controls like push-buttons to signal state.

I started doing this on Qt as well earlier, but I concluded that C# was so much easier to work with and as performance issues I had earlier are gone I moved back to C#/.NET. I might go back and re-visit Qt at some point.

CANopen/SIIS2 – Part 4, PDO Map

A PDO differ from a SDO in the sence that the COB ID is the message ID. In a single system you have 8 x 127 messages that can be PDO and only needs to be know by consumer and producer. A simple PDO Map can map directly to memory variables, but a more proper implementation will do so indirectly through SDO Index Map.

In a Static PDO Map this is assigned by Firmware at start-up, while in a dynamic PDO Map this can be configured with separate messages.

In terminology you have PDO, MPDO, RPDO, TPDO, but to keep it simple only use PDO. RPDO and TPDO are separate groups as you have 4  x RPDO and 4 x TPDO groups – how they are used is up to the device profile. MPDO (Multiplexed PDO) is something I have never used, so my knowledge about that is a bit thin (yet).

CANopen/SIIS2 – Part 3, SDO Index Map

SDO is the simplest part of CANopen that can be compared to Modbus. A SDO message is addressed to a node and consist of Index, Sub-index and 1-4 byte variable. A common implementation is to have indexes in an array with pointers to the actual variable and use bsearch to find index/sub-index. How you implement this is not part of the standard, so you could just implement a very large switch etc, but a table is recommended.

In fact, most stacks have a Design Tool that will allow you to generate this table in source code and the associated EDS file.

CANopen/SIIS2 – part 2, stack UML diagram

I am considering using CANopenNode to create a full SIIS2 stack, but before I jump into someone elses work I like to think through how and why I want CANopen build. Below is a simple UML diagram.

This diagram lack Bootloader and Object Dictionary, but I simply created classes for each bulk of work that needs to be done.

CANbus. I need a driver outside the stack. This will integrate to various HW as well as adapters for Windows etc.

CANopen. We definitely need a CANopen with all main interface functions. A simple class to be used to create a stack and then add CANModules to this as needed. We can createa a CANopenSlave and CANopenMaster, but also provide a custom implementation.

The rest of the CANopen stack is easily divided into groups of work using CANModule as base. CANModule can carry common functions while each of the SDO, PDO, LSS, NMT etc carry their respective messages with Processing, Encoding and Decoding. Some of the blocks like SDO, PDO, LSS and NMT should be sub-classed because Client/Server, Producer/Consumer, Master/Slave have different implementations of the same messages. So can EMCY, SYNC and Time, but as these are smaller I am not sure I bother.

Creating a C++ layer like this also allows for the user to sub-class and easily modify the stack without changing the base code or dealing with nasty #ifdef code.

Heartbeat is actually part of NMT with separate schemes for Master and Slave.

This is how I would like to divide code up in C++ and if you look at CANopenNode you notice that these building blocks more or less exist in C code – this was accidentally.

CANopen Bootloader will need to be created from scratch.

Object Dictionary will need to be re-done. The onle used in CANopenNode is not sufficient for what I want to do.

That said – I am not convinced I will jum onto this train – just toying with the idea for now. Wherever I write my own from scratch or use CANopenNode is of no consequence as I can easily write a C++ wrapper on top of CANopenNode.

CANopen/SIIS2 – Part 1

The industry around me is a heavy user of CANopen (SIIS2) which is the “Subsea” version of a CAN protocol. CANopen is similar to Modbus, but it offer more functionality. It is also a more complicated protocol stack that tend to cost from 5-15K USD depending on content.

I have written CANopen protocols in the past so I am toying with the idea to write one in C++ for embedded systems, while I am also happy to see that CANopenNode have changed license from GPL to Apache 2.0. CANopenNode looks like a nice implementation that cover ca 50% of a full stack.

The modbus standard is available while CANopen standard is close to 300 cryptic docs that you have to pay for. The later makes it difficult for people to write open source or promote the standard.

The main functionality is very similar between Modbus and CANopen – in modbus you read/write registers, while in CANopen you read/write objects which for most parts are 32 bit variables.

Both CAN and RS485 (that often is used for Modbus) uses a twisted, differential wire. The main difference is that CANbus is more difficult since it uses arbitration.

On Modbus you have a request/response protocol meaning Master send and wait for a Slave to respond.

On CAN all devices can send whenever they want using Arbitration. The 11 first bits in the header is arbitration field and basically the message with the lowest number “win”. This requires good timing and an aligned bus to work. The drawback is that the payload on classic CAN is 8 bytes. More modern bus systems like CAN FD and FlexRay that also uses arbitration have bigger payloads, but few MCU’s support these yet.

Modbus is a few messages and job done – it is a very simple protocol to wrap up.

Modbus have high latency, while CANbus support burst – a technique to just send messages as fast as you can. The Burst technique more than compensate for the header and low payload – CANopen is far more efficient in data transfer than your would expect.

Modbus based on RS485 can support 2Mbps or 10Mbps serial lines, CANbus is max 1Mbps.

CANbus have a High Speed and Low Speed/Fault Tolerant version. The FT version means the transceiver can drop to half-duplex and continue to work with only one of the twisted pair wires as long as it also have Ground. The FT version is to my knowledge only used in SIIS2.

CANopen is a large job consisting of several components:

Bootlolader. This do not exist in Modbus, but CANopen have it’s own bootloader with a defined boot sequence where a device ask a Network Master (NMT) if it should start or download new firmware.

SDO is the main protocol to send generic data up/down. It support single variables and blocks of data both ways.

PDO allows you to send proprietary messages from node to node using all 8 bytes for data. SDO can only use 4 bytes, while PDO messages can be packed.

NMT (Network Master) perform start up sequence and monitor the network.

LSS (Layered Service Settings) consist of some 33 message sequences that control the node and its services.

And you also have the smaller components like Heartbeat, EMCY, SYNC and TIME.

The main part of a CANopen is however the object dictionary – which is similar to modbus registers. This is the list of objects and a huge portion of the CANopen standard is dedicated to describe how various devices should look like – what interface they should have.

CiA402 define a motor controller, while CiA443 define several standard Subsea components as examples.

The standards for CANopen have an extremely low quality – errors and inconsistent, little description to help understand usage etc – I have worked close to two decades with telecom protocols – actually writing protocols like ISDN and SS7 – and CANopen is the worst standard I have ever seen – it is a mess of a standard.

CANopen is NOT difficult as such, but understanding the so called standard in an uniform way and making sure devices integrate properly have turned out to be a lot of work.

Terminology like Master and Slave stack is used. CANopen have a few Master components, but it is actually a distributed network where some of the nodes takes on resposibilities. The work “Master” do however also means you have a device that is capable to track other devices – it need tables over the other devices etc, while a “Slave” or a “Device Stack” only need to know about itself.

For those new to CANopen I will recommend starting out with CANopenNode – this is open source C code under Apache 2.0 license. The stack is still work in progress, but I had no problem following some message sequences and noticing what was working correct/incorrect – which at the end means the code is mantainable.