Resolving mraa Python 3 Support on Siemens IOT2000 I/O Modules

David Krause9 min read
I/O ModulesSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Overview

Engineers integrating the Siemens SIMATIC IOT2000 family (IOT2040 / IOT2050) with the Input/Output Module 6ES7 647-0KA01-0AA2 frequently hit an ImportError: No module named 'mraa' when their application logic is written in Python 3. The shipped Example Image (for example example-v2.2.0.wic dated 27 March 2018) exposes the C library libmraa but does not bundle the corresponding python3-mraa binding. Because the maintenance cadence of these prebuilt images is governed by an OSS Clearing workflow, an updated WIC image with Python 3 mraa support may not be available for many release cycles. This article documents the root cause, a reproducible build path on the host PC and on-device, and the verification procedure that confirms the shield pins are reachable from Python 3.

Field-proven caveat: Siemens cannot ship a prebuilt WIC image that includes new open-source packages until they pass through OSS Clearing. Treat any "is there an updated image" request as a build-it-yourself task and freeze your Yocto recipe in version control so production fleets remain reproducible.

Affected Hardware and Software

Component Identifier / Version Notes
SIMATIC IOT2040 6ES7 647-0AA00-0BA2 / 6ES7 647-0BA00-0BA2 Intel Quark x86 SoC, 1 GB RAM
SIMATIC IOT2050 6ES7 647-0BA10-0YA2 (basic) / 6ES7 647-0BA10-0XA2 (advanced) ARM TI AM6528, 1–2 GB RAM, replaces IOT2040
Input/Output Module (Shield) 6ES7 647-0KA01-0AA2 Arduino-form-factor shield, exposes DI / DO / AI via mraa pin numbers
Example Image example-v2.2.0.wic (2018-03-27) and later V2.x releases Based on Yocto / Angstrom, ships Python 2 only by default
mraa library libmraa ≥ 1.x (C library present, Python 3 binding missing) Available as libmraa2, libmraa-dev, mraa-tools
Python interpreter Python 2.7.14 (default), Python 3.5 / 3.7 (optional) Python 3 must be added manually

Root Cause Analysis

Three independent gaps converge to produce the error:

  1. Image release policy. Siemens publishes the WIC image as an example rather than a product-grade firmware. Every binary that lands in the image must clear the OSS license review pipeline. The result is an update cadence measured in quarters, not days, which means newly available upstream packages (such as Python 3 mraa wheels) lag behind what an integrator can compile locally.
  2. Python 3 binding not packaged. The image provides the libmraa.so C library and the mraa-gpio CLI utility, but the SWIG-generated Python 3 module (_mraa.so + mraa.py) is not installed under /usr/lib/python3.x/site-packages/. A bare import mraa therefore raises ModuleNotFoundError (Python 3) or ImportError (Python 2.7) on the same image.
  3. Hardware pin-map assumption. The I/O shield 6ES7 647-0KA01-0AA2 uses a fixed mraa board definition file (/etc/mraa/iot2000.bm or /usr/share/mraa/platform/iot2000.json) that maps shield connectors to logical pin numbers. Even after the Python binding is installed, mraa.getVersion() and the pin look-ups must succeed; a mismatched board file will produce "No pins" output from mraa-gpio list even when the library is correctly loaded.

Prerequisites

  • PC host (Linux recommended; Ubuntu 18.04 / 20.04 LTS validated) with git, cmake > 3.5, build-essential, swig > 3.0, python3-dev, python3-setuptools.
  • SSH access to the IOT2000 with root privileges (default user root, no password on the example image with a serial console).
  • Network connectivity from the IOT2000 to a local APT/OPKG feed or to the host PC via SCP.
  • Optional: cross-compilation toolchain if you want to avoid native compilation on the device (recommended for IOT2040 Quark due to slow CPU).
Cross-compile tip: The Quark CPU in the IOT2040 will spend 25–40 minutes compiling swig and mraa from source. Use the Yocto SDK (iot2040-sdk-*.sh) provided by Siemens Support to cut build time to under two minutes.

Building mraa with Python 3 Bindings

The reference upstream is the Eclipse mraa project (formerly Intel). Clone, configure, build, and install on the host first; the same recipe runs natively on the device.

Step 1 — Fetch source

git clone https://github.com/eclipse/mraa.git
cd mraa
git checkout v2.2.0          # pin to a known-good tag for IOT2000

Step 2 — Configure build with Python 3

mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_INSTALL_PREFIX=/usr \
      -DBUILD_PYTHON3=ON \
      -DPYTHON3_EXECUTABLE=$(which python3) \
      -DBUILD_EXAMPLES=OFF \
      -DBUILD_TESTING=OFF \
      ..

Verify the configure summary contains Python3 support: ON and the correct interpreter path. If swig is missing, install swig3.0 (Debian/Ubuntu) or rebuild the host toolchain.

Step 3 — Compile and install

make -j$(nproc)
sudo make install
sudo ldconfig

The SWIG output src/python/mraa.py and the compiled extension src/python/_mraa.cpython-3Xm-x86_64-linux-gnu.so are copied to /usr/lib/python3/dist-packages/.

Step 4 — Quick smoke test on host

python3 -c "import mraa; print(mraa.getVersion())"

Expected output (mraa 2.2.0):

v2.2.0

Deploying to the IOT2000

  1. Identify the running image. Connect via SSH and run cat /etc/os-release; confirm the version and whether libmraa2 is already installed via the package manager (opkg info libmraa2).
  2. Install prerequisites on the device.
    opkg update
    opkg install python3 python3-pip libmraa2 libmraa-dev mraa-tools swig
    
  3. Stage built artefacts. SCP the compiled modules from the host:
    scp /usr/lib/python3/dist-packages/mraa.py \
        root@<iot2000-ip>:/usr/lib/python3.7/site-packages/
    scp /usr/lib/python3/dist-packages/_mraa*.so \
        root@<iot2000-ip>:/usr/lib/python3.7/site-packages/
    scp /usr/lib/libmraa.so.2* \
        root@<iot2000-ip>:/usr/lib/
    
    On the device run ldconfig.
  4. Verify board file. The shield relies on /etc/mraa/mraa-platform-iot2000.bm. If mraa-gpio list reports No pins, copy the file from /usr/local/share/mraa/platform/iot2000.json to /etc/mraa/ and reboot.

Hardware Configuration for 6ES7 647-0KA01-0AA2

The Input/Output Module is an Arduino-shield form-factor board that piggy-backs onto the IOT2040/IOT2050. The following mapping is used by mraa-gpio and the Python binding:

mraa pin Shield marking Direction Voltage domain
0 DIG IN 1 Input 24 V DC (IEC 61131-2 type 1)
1 DIG IN 2 Input 24 V DC
2 DIG IN 3 Input 24 V DC
3 DIG IN 4 Input 24 V DC
4 DIG OUT 1 Output (sink) 24 V DC, 0.5 A per channel
5 DIG OUT 2 Output (sink) 24 V DC, 0.5 A per channel
6 AIN 1 Analog input 0–10 V, 12-bit
7 AIN 2 Analog input 0–10 V, 12-bit
8 AOUT 1 Analog output 0–10 V, 12-bit
9 AOUT 2 Analog output 0–10 V, 12-bit
10 Relay K1 Output (dry contact) 30 V DC / 1 A
11 Relay K2 Output (dry contact) 30 V DC / 1 A
14 STATUS LED Output 3.3 V

Always confirm the silk-screen on your specific hardware revision against the schematic in the Siemens Equipment Manual for the Input/Output Module (download via Siemens Industry Online Support, article ID 109769760).

Python 3 Sample Application

The following minimal script toggles digital output 1 in response to digital input 1 and logs the analog value on AIN 1:

#!/usr/bin/env python3
import mraa
import time

print("mraa version:", mraa.getVersion())
print("platform    :", mraa.getPlatformName())

DI1  = mraa.Gpio(0)          # shield terminal X1 / DIG IN 1
DO1  = mraa.Gpio(4)          # shield terminal X2 / DIG OUT 1
AIN1 = mraa.Aio(6)           # shield terminal X3 / AIN 1

DI1.dir(mraa.DIR_IN)
DO1.dir(mraa.DIR_OUT)

while True:
    state = DI1.read()
    DO1.write(state)
    raw   = AIN1.read()              # 0..1023 from mraa, 12-bit
    volts = raw * 10.0 / 1023.0      # convert to 0..10 V
    print(f"DI1={state}  AIN1={volts:0.2f} V")
    time.sleep(0.25)

Save as /opt/iot2000/io_demo.py, mark executable (chmod +x), and launch with python3 /opt/iot2000/io_demo.py.

Verification Procedures

  1. Library import. python3 -c "import mraa; print(mraa.getVersion())" — expect the previously installed version string.
  2. Board detection. mraa-gpio list — should display the pin table for the IOT2000 platform, not "No pins".
  3. Loopback test. Wire a wire from shield terminal X1 (DIG IN 1) to X2 (DIG OUT 1). Run the sample script. Apply 24 V to X1 and confirm the script reports DI1=1; remove the 24 V and confirm DI1=0. A multimeter on X2 pin 1 should mirror the input.
  4. Analog test. Apply 0 V, 5 V, and 10 V from a calibrated source to AIN 1. Readback should be within ±0.05 V of the input.
  5. Reboot persistence. Reboot the device and confirm systemctl restart io_demo (or the equivalent SysV init script) starts the Python 3 process cleanly with mraa available.

Troubleshooting Matrix

Symptom Likely Cause Resolution
ImportError: No module named 'mraa' in Python 3 python3-mraa not installed Build from source (this article) or add to Yocto recipe IMAGE_INSTALL_append = " python3-mraa"
mraa-gpio list shows No pins Board definition file missing or wrong path Copy correct iot2000.bm to /etc/mraa/ and reboot
ImportError: libmraa.so.2: cannot open shared object file LD_LIBRARY_PATH not set or ldconfig not run Run ldconfig, verify /usr/lib/libmraa.so.2 exists
Pin reads random values on shield input Shield not seated; no 24 V common reference Re-seat shield; verify terminal X4 (24 V supply) is powered
SWIG errors during build swig < 3.0 installed Install swig3.0 or newer
ModuleNotFoundError for _mraa only (not mraa) Architecture mismatch between .so and Python interpreter Rebuild on device or with the matching Yocto SDK
Process killed with SIGSEGV on first DI1.read() Pin number out of range for the platform Confirm mraa.getPinCount() and use only valid indices
Updates break after opkg upgrade libmraa replaced without re-installing binding Re-install python3-mraa after every libmraa upgrade

Integrating into a Yocto Build (Recommended for Production)

For fleet deployments, build a custom image rather than patching a running WIC:

  1. Clone the Siemens-provided BSP layer meta-iot2000 matching your hardware (git clone https://github.com/siemens/meta-iot2000).
  2. Add meta-openembedded/meta-python and meta-openembedded/meta-oe to bblayers.conf.
  3. Append the install list in your recipe:
    IMAGE_INSTALL_append = " python3 python3-pip libmraa python3-mraa mraa-tools"
    
  4. Build with bitbake iot2000-example-image and flash the resulting *.wic with dd or bmaptool.

This approach bypasses the OSS-clearing delay entirely because the artefacts are produced inside your own build pipeline.

Safety and Wiring Considerations

Electrical safety: The shield inputs are 24 V DC type-1 per IEC 61131-2. Always de-energise the field wiring before inserting or removing the shield. Outputs are sink-only; do not source voltage into DIG OUT terminals without verifying polarity. The relay contacts (K1, K2) are rated 30 V DC / 1 A resistive — exceeding this rating voids the module's UL listing.

Route analog signals in twisted pair with the shield grounded at the panel entry only. Keep the IOT2000 at least 100 mm away from VFD power conductors to avoid conducted EMI on the analog inputs.

Performance Notes

On the IOT2040 (Quark @ 400 MHz) a Python 3 mraa digital I/O loop achieves approximately 1.5 kHz read rate before GIL contention becomes visible. The IOT2050 (ARM Cortex-A53 @ 1.0 GHz) reaches 8–10 kHz. For control loops faster than 1 ms, consider writing the deterministic portion in C and exposing it through a thin Python wrapper.

Frequently Asked Questions

Why does the official Siemens Example Image still ship Python 2 only?

Each WIC image must pass through OSS Clearing before public release, which is why update cadence is measured in quarters. Python 2 remains the default interpreter on releases built before the Python 2 end-of-life project concluded; you can layer Python 3 manually as described above, or build your own image with the meta-iot2000 BSP.

Is the Input/Output Module 6ES7 647-0KA01-0AA2 compatible with both IOT2040 and IOT2050?

Yes. The shield uses the Arduino Uno R3 pin-out and the mraa board definition iot2000.bm. On the IOT2050 you must enable the Arduino-shield interface in the BIOS and update to the latest firmware so the I2C and GPIO multiplexers route correctly to the shield header.

Can I install python3-mraa via pip instead of compiling from source?

No reliable pip wheel exists for the IOT2000 platform because PyPI only publishes x86_64 / aarch64 manylinux wheels. Compiling from the Eclipse mraa sources against the on-device Python interpreter guarantees ABI compatibility.

What is the difference between mraa-gpio showing "No pins" and a missing Python binding?

mraa-gpio list interrogates only the C library and the board map; it will work even when the Python 3 binding is absent. If the tool returns "No pins" but the library is present, the board file is missing or pointed at the wrong path. If the tool returns pins but import mraa still fails, install the Python 3 binding.

Do I need a license to use mraa commercially on the IOT2000?

mraa is licensed under the MIT License (source files) with select components under BSD-3-Clause. Both are permissive and compatible with commercial use, but you must still satisfy the OSS attribution obligations that come with shipping a Linux-based Siemens image to end customers.

Back to blog