OpenPLC with Python FB
In this article, you will learn how to use Python FB in OpenPLC Editor and send the PLC data to the ThingsBOard's Cloud Dashboard.
OpenPLC with Python FB- Sending PLC Data to the Cloud
What This Project Does
In this project, we use OpenPLC Runtime v4 running on a laptop (or edge device) to:
Generate a simulated sine wave temperature value using the built-in OpenPLC simulator
Read it inside a Python Function Block via shared memory
Send live telemetry to ThingsBoard Cloud via HTTP — using only Python's standard library
Write a connection status back to the PLC so the ST program knows if the cloud is reachable
No hardware required. No third-party packages. No cost.
Watch Full Walkthrough with LIVE Demo
System Architecture
What is a Python Function Block?
Python Function Blocks let you write automation logic in Python while integrating seamlessly with your IEC 61131-3 program. They are ideal for tasks that are difficult or verbose in Structured Text:
HTTP / REST API calls
JSON formatting and parsing
Statistical calculations
Cloud and IoT communication
Execution
Runs inside the PLC scan cycle
Runs as a separate process
Timing
Synchronized with scan cycle
Asynchronous ~100ms loop
State
Managed by the runtime
Managed by the Python process
Language
ST, LD, FBD, IL
Python 3
Libraries
IEC standard functions only
Python standard library
Python FBs are NOT synchronized with the PLC scan cycle. Use standard IEC languages for real-time, time-critical control logic. Use Python for non-time-critical tasks like cloud communication.
The Two Required Functions
Every Python Function Block defines exactly two functions called automatically by the runtime:
block_init() - Called once when the Python process starts. Use it for:
Initializing global variables
Setting up timers and data structures
Printing startup messages
block_loop() - Called every ~100ms for the lifetime of the process. Use it for:
Reading inputs from
shm_inProcessing data
Writing outputs to
shm_out
How Variables Work in Python FBs
Variables declared in the Variables Table in the OpenPLC Editor are accessible directly by name inside your Python code.
Example 1: Console Print (shm_in Only)
This example introduces shm_in and struct.unpack, reading a value from the PLC into Python and printing it to the PLC Logs.
Main ST Program: Example 1
Variable Table
Main ST Program
Understanding the Sine Wave Generator
The SIN() function uses radians. One full circle = 2π = 6.283 radians. Resetting angle After 6.283, the wave repeats cleanly.
Each scan adds 0.05 radians — completing a full cycle in approximately 125 scans (~2.5 seconds at 20ms scan time).
The formula 50.0 + (30.0 * SIN(angle)) produces:
+1 (peak)
80°C
0 (midpoint)
50°C
-1 (trough)
20°C
Python FB Code: Example_1
Variable Table
Python Code
PLC Logs Output
Example 2: ThingsBoard Cloud Integration
This example extends Example 1 with two additions:
Sends the temperature to ThingsBoard Cloud via HTTP every 5 seconds
Write a connection status back to the PLC via
shm_out-1for connected,0for disconnected
Variable Table
ThingsBoard Cloud Setup
Sign up for free at thingsboard.cloud
Create a new device e.g.
OpenPLCCopy the url with the Access Token from the device credentials
Replace
YOUR_TOKENin the code below
The ThingsBoard HTTP telemetry API endpoint is:
Python FB Code
Main ST Program
Variable Table
Main ST Program
Key Gotchas: Lessons Learned
Building this project revealed several non-obvious behaviors worth knowing before you start:
1. Use time.time() for intervals — not loop counters
Using loop_counter % 50 == 0 seems logical, but fires immediately on loop 0, before the runtime has stabilized. An HTTP call at that moment can stall the process. Use time.time() instead — it waits a true interval from a stable starting point.
2. Always import time
The OpenPLC runtime uses the time module internally to manage block_loop() timing. Even if your code does not use time directly — always include it, or you will get a NameError that crashes the process.
3. Declare ALL persistent variables as global in BOTH functions
Without global in block_loop() Python creates a silent local copy of the variable that is destroyed at the end of each call. Always declare in both block_init() and block_loop():
4. Avoid special characters in comments
Em dashes —, curly quotes ', and other Unicode characters cause C compiler errors when OpenPLC embeds your Python code. Use plain ASCII only — hyphens - and straight quotes '.
5. ThingsBoard Cloud requires HTTPS
Local ThingsBoard uses http:// on port 8080. ThingsBoard Cloud requires https:// on port 443.
When to Use Python vs ST vs C++
Cloud communication, HTTP, REST APIs
Python FB
JSON formatting, string processing
Python FB
Real-time control, timing, interlocks
Structured Text
Scan-cycle-critical logic
Structured Text
Direct hardware access, byte manipulation
C++ FB
Hardware and Software Used
PLC Runtime
OpenPLC Runtime v4
Editor
Autonomy Edge IDE (edge.autonomylogic.com)
Hardware
Any laptop or edge device
Cloud Dashboard
ThingsBoard Cloud (free tier)
Protocol
HTTP REST API via Python urllib
Languages
IEC 61131-3 Structured Text + Python 3
Keynotes
🔗 Resources
🌐 Open PLC editor and Runtime: autonomylogic.com
🧑💻 Code Compile
♥️ Work With Me
I regularly test industrial automation and IIoT devices. If you’d like me to review your product or showcase it in my courses and YouTube channel:
📧 Email: rajvir@codeandcompile.com or drop me a message on LinkedIn
Last updated
Was this helpful?