Repurposing a PLC clone for use with Arduino

7 minute read

It is fairly common to find in online shopping pages, advertising like this: “Industrial control board compatible with FX1N, FX2N, FX3U and programmable with GX software”. The price is attractive, however, the documentation is non-existent, and there is no mention of how to program it with other tools like Arduino in other operating systems different from Windows. This article will introduce a few key concepts to help solve this problem.

Industrial control board compatible with PLC programming software of a specific manufacturer

Key component: Industrial control board compatible with FX1N

Attack of the clones

These boards mention compatibility with GX software, which is manufactured by a Japanese company that makes PLC and also cars. At first sight, the compatibility is not official, as no trademark is printed. Their origin is unknown, maybe they were simplified copies based on original schematics and source code, or somehow the native binary format of the PLC was reverse engineered and an interpreter was built and runs in the microcontroller translating the code. Most of the cards are based on STM32 microcontrollers, and according to some articles and videos, the original programming software actually recognizes them as an original PLC!

Plastic enclosure, DIN rail installation

Due to their low cost (around $25 USD), and for their relay isolated outputs, optically isolated inputs, RS232 serial port and regulated power supply, are great candidates for small projects as long as they can be programmed with a free multi-platform tool like Arduino or STM suite. In addition, a schematic diagram is needed to find out which I/O of the microcontroller goes to which peripheral in the board!

Bill of materials
Parts used
Component Buy link Datasheet
Industrial control board compatible with FX1N buy it industrial-control-board-fx1n.pdf
24 V 15 W DIN rail mount power supply buy it 24v-din-rail-power-supply.pdf
USB to RS232 converter buy it usb-rs232-converter.pdf
DB9 solderless terminal connector buy it db9-solderless-terminal-connector.pdf
30 AWG UL1423 type PVDF wire buy it UL1423.pdf
Dupont cable jumper buy it dupont-jumper-cables.pdf
Single line male header 2.54mm buy it FHA3-S1XX.pdf
Pinout for industrial control boards repository
Industrial control boards based on STM32 stm32-industrial-control-boards
Optional component Buy link Datasheet
Magnifying double eye for jewelry buy it magnifying-double-eye.pdf
USB digital microscope camera buy it microscope-camera-digital-usb.pdf
Digital multimeter powered by AA batteries buy it digital-multimeter-powered-aa-batteries-ut139c.pdf

The aforementioned board, sports a STM32F103 microcontroller, so instinctively a footprint for a SWD programming header should be looked for.

Possible programming header footprint at lower right

After following the tracks of this header, one pin was found connected to 3.3 V, another one to GND, but the other two pins were not connected to SWD pins on the microcontroller but to PC10 and PC11 pins. Starting the search from the microcontroller, there are no tracks from SWD or USB pins, so the only alternative available for reprogramming is through UART1 using the bootloader stored in ROM

Serial port related components

Following the tracks leaving from the DB9 connector, they end in an unmarked chip, however, due to the nearby capacitors it is probably a MAX232 or equivalent. Following the tracks leaving from this chip they end in PA9 and PA10 pins of the microcontroller which are the UART1 pins.

Luckily in this board, the resistor which is connected to the BOOT0 pin is clearly marked on the silkscreen. To start in bootloader mode, a male header was soldered to the 3.3 V pad, and using a Dupont wire jumper, a temporary connection between BOOT0 and 3.3 V is made while the board is powered up

Method used for bootloader activation

Once the bootloader was running, STM32CubeProg was launched and communication with the microcontroller was verified. The chip was in read protect mode, so no way to backup the firmware to reverse the board to its original state. All FLASH memory has been erased.

Using Arduino IDE, it was proceeded to the installation STM32duino core and to make a small test application that sends data through the serial port to the PC. The app was downloaded and the incoming data verified. Now the adventure starts!

USB to RS232 converter and connectors used for communication check between PC and board
Identifying I/O pins

Because of the lack of a schematic diagram, or marks in the silkscreen showing which microcontroller I/O pins goes to which peripheral, this work must be done manually, with a lot of patience to follow the tracks. Fortunately the board has only 2 layers, so it is possible to start with only a double-eye magnifier for jewelry and a multimeter.

LED and switch

The board has two LED indicators, one labeled as RUN an the other labeled as ERR. Additionally, there is a switch that was used by the old PLC firmware to stop program execution. Due to these peripherals have a few elements between them and the microcontroller, they are very easy to start with.

Microcontroller I/O pins connected to LED indicators and switch identified

The pins were found mapped as follows:

Digital inputs

Digital inputs were relatively easy to find, because the tracks leaving the optocuplers went directly to the microcontroller. Only a few ones were tricky because they jumped to the opposite layer or traveled under a big component.

Following input tracks

The pins were found mapped as follows:

X0 PA0
X1 PA1
X2 PB9
X3 PA6
X4 PA7
X5 PB5
X6 PB4
X7 PD2
Digital outputs

The digital outputs took the most effort, because the tracks went first to an UL2003 chip, and from there to each relay, traveling under components or jumping to the opposite layer. Multimeter was crucial to follow the tracks.

Following output tracks

The pins were found mapped as follows:

Y0 PB8
Y1 PB1
Y2 PB10
Y3 PB0
Y4 PC5
Y5 PC4
Analog inputs

The analog inputs were relatively easy to find, because they are only 3 and they are connected only to a voltage resistor divider (15 K/30 K) between them and the microcontroller.

Following analog input tracks

The pins were found mapped as follows:

Final touches

At this point, all peripherals are mapped to the microcontroller I/O pins, however, whenever the board needs to be reprogrammed, BOOT0 needs to be set to 3.3 V using a temporal wire jumper, which implies opening the enclosure. A quick fix will be to connect a wire from the BOOT0 pin to the RUN/STOP switch used by the old PLC firmware, in this way the ROM bootloader could be initiated externally without opening the case for reprogramming

External switch now wired to BOOT0 pin

At this stage, you have a low cost board with enough peripherals for small experiments without requiring additional hardware and can be programmed using Arduino IDE or STM suite. To replicate this experiment with a different board (as long as the CPU has been identified) follow the steps below:

  • Look for SWD header footprint on the PCB (4 pads) and follow the tracks to the microcontroller to make sure the pins are the right ones.
  • If the previous step fails, follow the tracks from the UART1 pins of the microcontroller and add the additional hardware (level converter, connectors) for PC communication
  • Look for BOOT0 pin, it is usually connected to the ground through a resistor, it will serve as a “test point”
  • Using STM32CubeProg erase the microcontroller FLASH memory, If UART1 was used as a connection means, the ROM bootloader must be launched, setting BOOT0 to 3.3 V while powering on the board.
  • Using the Arduino IDE or the STM suite, make a little test application, which sends characters to the serial port, to know if the board could be programmed
  • Follow the tracks from the peripherals to the microcontroller, to make the I/O pin mapping
  • Make a wire connection from BOOT0 to the RUN/STOP switch to easily program the board
Possible improvements

Create a skeleton application as a boiler plate for each program for the board, this application should have some kind of mechanism that checks the condition of the RUN/STOP switch to decide whether to go to ROM bootloader or start executing the program stored in the FLASH, This eliminates the need for an electrical connection between BOOT0 and the switch.

Another option, if a skeleton app is not desired, is to make a bootloader stored in the FLASH that uses UART1 for communication, similar to the one stored in ROM, but this one checks the condition of the RUN/STOP switch to decide whether to download a new program or executing the program stored in the FLASH