Will man in rauer Umgebung mit einem Raspi kommunizieren, ist der Einsatz eines industriellen Touchpanels eine gute Idee. Ich setze hierfür gerne die Geräte von Proface ein. Die Geräte gibt es in vielen Größen und Ausführungen .Mittels eines Softwaretools (GP ProEX) lassen sich leicht und schnell ansprechende Oberflächen erstellen. Hier will ich in einem kurzen Beispiel zeigen, wie man mir Hilfe eines ProFace-Touchpanels mit dem Raspberry Pi kommuniziert und die GPIOs des Raspis schaltet sowie den Zustand seiner Eingänge anzeigt.Schnittstellen
Schnittstellen
Die Proface Panels verfügen über eine unglaubliche Anzahl von Treibern für nahezu alle am Markt verfügbaren Steuerungen und einer Vielzahl weiterer Geräte wie z.B. Frequenzumricher (Inverter) oder auch Temperaturregler. Für unsere Anwendung bietet es sich an, den Modbus als Protokoll zum Informationsaustausch zwischen Raspi und Panel zu nutzen. Als physikalisches Übertragungsmedium soll hierbei das Ethernet genutzt werden, sowohl der Pi als auch die ProFace-Panels bieten entsprechende Schnittstellen hierfür.
Qelltext für die Modbus-Kommunikation mit den ProFace – Panels
#!/usr/bin/env python
'''
Pymodbus Server With Updating Thread
--------------------------------------------------------------------------
This is an example of having a background thread updating the
context while the server is operating. This can also be done with
a python thread::
from threading import Thread
thread = Thread(target=updating_writer, args=(context,))
thread.start()
'''
#---------------------------------------------------------------------------#
# import the modbus libraries we need
#---------------------------------------------------------------------------#
from pymodbus.server.async import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer
import RPi.GPIO as GPIO
#---------------------------------------------------------------------------#
# import the twisted libraries we need
#---------------------------------------------------------------------------#
from twisted.internet.task import LoopingCall
#---------------------------------------------------------------------------#
# configure the service logging
#---------------------------------------------------------------------------#
import logging
logging.basicConfig()
log = logging.getLogger()
#log.setLevel(logging.DEBUG)
# RPi.GPIO Layout verwenden (wie Pin-Nummern)
GPIO.setmode(GPIO.BOARD)
# Pin 13 (GPIO 27) auf Output setzen
GPIO.setup(37, GPIO.OUT)
GPIO.setup(35, GPIO.OUT)
GPIO.setup(33, GPIO.OUT)
GPIO.setup(31, GPIO.OUT)
GPIO.setup(29, GPIO.OUT)
#Pins auf Input setzen
GPIO.setup(40, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(38, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(36, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(32, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(22, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
#---------------------------------------------------------------------------#
# define your callback process
#---------------------------------------------------------------------------#
def updating_writer(a):
''' A worker process that runs every so often and
updates live values of the context. It should be noted
that there is a race condition for the update.
:param arguments: The input arguments to the call
'''
log.debug("updating the context")
context = a[0]
register = 1
slave_id = 0x00
address = 0x00
#Wert aus Register 000001 von Button auslesen
values = context[slave_id].getValues(register, address)
if values[0] == False:
gpio_off(37)
elif values[0] == True:
gpio_on(37)
address = 0x01
#Wert aus Register 000002 von Button auslesen
values = context[slave_id].getValues(register, address)
if values[0] == False:
gpio_off(35)
elif values[0] == True:
gpio_on(35)
address = 0x02
#Wert aus Register 000003 von Button auslesen
values = context[slave_id].getValues(register, address)
if values[0] == False:
gpio_off(33)
elif values[0] == True:
gpio_on(33)
address = 0x03
#Wert aus Register 000004 von Button auslesen
values = context[slave_id].getValues(register, address)
if values[0] == False:
gpio_off(31)
elif values[0] == True:
gpio_on(31)
address = 0x04
#Wert aus Register 000005 von Button auslesen
values = context[slave_id].getValues(register, address)
if values[0] == False:
gpio_off(29)
elif values[0] == True:
gpio_on(29)
# Eingang lesen
register = 1
address = 0x05
if GPIO.input(40) == GPIO.HIGH:
values = [1]
#setzt den Datenanzeiger auf den Wert
context[slave_id].setValues(register, address, values)
elif GPIO.input(40) == GPIO.LOW:
values = [0]
context[slave_id].setValues(register, address, values)
# Eingang lesen
register = 1
address = 0x06
if GPIO.input(38) == GPIO.HIGH:
values = [1]
#setzt den Datenanzeiger auf den Wert
context[slave_id].setValues(register, address, values)
elif GPIO.input(38) == GPIO.LOW:
values = [0]
context[slave_id].setValues(register, address, values)
# Eingang lesen
register = 1
address = 0x07
if GPIO.input(36) == GPIO.HIGH:
values = [1]
#setzt den Datenanzeiger auf den Wert
context[slave_id].setValues(register, address, values)
elif GPIO.input(36) == GPIO.LOW:
values = [0]
context[slave_id].setValues(register, address, values)
# Eingang lesen
register = 1
address = 0x08
if GPIO.input(32) == GPIO.HIGH:
values = [1]
#setzt den Datenanzeiger auf den Wert
context[slave_id].setValues(register, address, values)
elif GPIO.input(32) == GPIO.LOW:
values = [0]
context[slave_id].setValues(register, address, values)
# Eingang lesen
register = 1
address = 0x09
if GPIO.input(22) == GPIO.HIGH:
values = [1]
#setzt den Datenanzeiger auf den Wert
context[slave_id].setValues(register, address, values)
elif GPIO.input(22) == GPIO.LOW:
values = [0]
context[slave_id].setValues(register, address, values)
def request_data(a):
log.debug("reading the context")
context = a[0]
register = 2
slave_id = 0x00
address = 0x00
values = context[slave_id].getValues(register, address, count=15)
print values
def gpio_on(pin):
# LED immer ausmachen
GPIO.output(pin, GPIO.LOW)
# LED an
GPIO.output(pin, GPIO.HIGH)
def gpio_off(pin):
# LED aus
GPIO.output(pin, GPIO.LOW)
#---------------------------------------------------------------------------#
# initialize your data store
#---------------------------------------------------------------------------#
store = ModbusSlaveContext(
di = ModbusSequentialDataBlock(0, [0]*100),
co = ModbusSequentialDataBlock(0, [0]*100),
hr = ModbusSequentialDataBlock(0, [2]*100),
ir = ModbusSequentialDataBlock(0, [0]*100))
context = ModbusServerContext(slaves=store, single=True)
#---------------------------------------------------------------------------#
# initialize the server information
#---------------------------------------------------------------------------#
identity = ModbusDeviceIdentification()
identity.VendorName = 'pymodbus'
#---------------------------------------------------------------------------#
# initialize the server information
#---------------------------------------------------------------------------#
identity = ModbusDeviceIdentification()
identity.VendorName = 'pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'
#---------------------------------------------------------------------------#
# run the server you want
#---------------------------------------------------------------------------#
time = 0.2 # 5 seconds delay
time2 = 1
print context[0]
loop = LoopingCall(f=updating_writer, a=(context,))
loop2 = LoopingCall(f=request_data, a=(context,))
loop.start(time, now=False) # initially delay by time
#loop2.start(time2, now=False) # initially delay by time
StartTcpServer(context, identity=identity, address=("192.168.10.38", 502))