Autor Thema: Raspberry Pi + Easy  (Gelesen 58320 mal)

Offline heicar

  • Newbie
  • *
  • Beiträge: 14
Re:Raspberry Pi + Easy
« Antwort #30 am: September 03, 2014, 18:58:40 Nachmittag »
Ich hab zu danken Peter,

also erstes Ergebnis mit .01, zweites mit 0.1, drittes mit 1 ist jeweils immer

>>> scan_baudrates()
Trying to connect /dev/ttyUSB0 at 9600 baud
Error 8
Trying to connect /dev/ttyUSB0 at 19200 baud
Error 8
Trying to connect /dev/ttyUSB0 at 38400 baud
Error 8
Trying to connect /dev/ttyUSB0 at 57600 baud
Error 8
1022


?

Gruß Heicar

Offline Peter_Pig

  • Jr. Member
  • **
  • Beiträge: 48
Re:Raspberry Pi + Easy
« Antwort #31 am: September 03, 2014, 21:19:23 Nachmittag »
Da kommt scheinbar überhaupt nichts rüber von der Easy.

Kaum zu glauben, dass die Kommunikation in Richtung Easy klappt aber nichts von dort zurück kommt.

Hast Du in deinem Easy Programm zufälligerweise irgend ein SP Baustein eingebaut (Serielles Protokoll)? Ich glaube damit schon mal Probleme gehabt...

Ansonsten fällt mir nichts mehr ein (bin auch nicht unbedingt ein Experte).

Hast Du dein USB Kabel mal unter Windows an Easy-Soft oder der EasyCom DLL getestet?

Ich werde versuchen ein Abgespecktes Script zu schreiben, das es uns leichter macht das Problem einzugrenzen.

Gruß,

Peter

Offline Peter_Pig

  • Jr. Member
  • **
  • Beiträge: 48
Re:Raspberry Pi + Easy
« Antwort #32 am: September 03, 2014, 21:33:02 Nachmittag »
Versuche mal das hier, bitte:

#

import serial
import time

s =serial.Serial('/dev/ttyUSB0', baudrate = 9600, timeout = 0)

d = '\x45\x08\x20\x00\x04\x08\x00\x01\xCF\x92'

res=s.write(d)

print res

time.sleep(1)

res=s.read(10)

print res.encode('hex')


Das versucht M9 auf "1" zu setzen, und versucht dann die Rückmeldung von Easy zu lesen.

Die richtige Antwort wäre 650500000000cc (65=header, 05=länge ab hier, 00 00 00 = kein Fehler, 00 CC = CRC16 hash)

Danke nochmal!

Gruß,

Peter
« Letzte Änderung: September 03, 2014, 22:12:21 Nachmittag von Peter_Pig »

Offline heicar

  • Newbie
  • *
  • Beiträge: 14
Re:Raspberry Pi + Easy
« Antwort #33 am: September 04, 2014, 20:03:57 Nachmittag »
tja,

das kommt als Ausgabe

10
00

...
Mit Windows und der Easy Soft klappte die Kommunikation bestens

Ich werde wohl in ein neues Kabel investieren müssen...


Danke für deine Hilfe Peter

Gruß Heicar

Offline Peter_Pig

  • Jr. Member
  • **
  • Beiträge: 48
Re:Raspberry Pi + Easy
« Antwort #34 am: September 04, 2014, 23:26:50 Nachmittag »
Hi Heicar,

Wenn dein Kabel unter Easy Soft gut funzt, dann muss ich davon ausgehen, dass es nicht am Kabel liegt, wenn es mit meinem armseligen Skript nicht tut...

Trotzdem ...  ::)

Also die 10 die als erstes erscheint ist kein Wunder, das ist nur die Anzahl an Byte die auf das Port geschrieben worden ist.

Ob diese 10 Byte irgend ein Gerät gelesen hat, das weiss man zu diesem Zeitpunkt noch nicht.

Als Bestätigung für den gelungenen Empfang, würde die Easy aber netterweise eine Antwort auf das (den?) Port schreiben, entweder eine Fehlermeldung, oder eine Erfolgsmeldung.

Sogar bei Passwort geschützter Schnittstelle, würde die Easy zumindest eine komplette Antwort schicken (komplett ist, nach meinem Wissensstand : ein header Byte, noch ein Byte mit der Anzahl an darauf folgenden bytes, zwei oder mehr weitere Bytes mit information und zwei abschließende Bytes mit dem CRC16 hash)

Wenn dein M9 tatsächlich auf der Easy gesetzt wurde, dann gehe ich davon aus, dass die Easy die Botschaft empfangen, verstanden und ausgeführt hat, und dementsprechend eine Erfolgsmeldung zurückschickt, die zumindest eine Handvoll Bytes beinhaltet.

Unter bestimmten Umständen (Port wird aderseitig benutzt, Einstellungen stimmen nicht, hash stimmt nicht, timeout, etc...) gibt s.read() - auf meinem Windows Rechner und auf dem Raspy - einen Null-Byte zurück ... sozusagen gar nichts, dargestellt auf der Konsole durch eine leere Zeile.

00 ist jedoch 'etwas', auch wenn es sich nicht danach anhört, ganze 8 bit.

Die beste Nachricht die Du mir geben könntest ist, dass M9 NICHT gesetzt wurde...

Leider fehlt hier Feedback von weiteren, geduldigen, tapferen "Beta-Testern". Das macht die Sache viel schwerer.

Also, danke nochmal, Heicar.

Gruß,

Peter

Offline heicar

  • Newbie
  • *
  • Beiträge: 14
Re:Raspberry Pi + Easy
« Antwort #35 am: September 05, 2014, 06:32:09 Vormittag »
Im Grunde funktioniert das Kabel. Es ist aber ja eins mit serieller also SubD9 Buchse. Ich habe diese dann über ein RS232-RJ45 Wandler ins Netz gehängt, damit ich nicht direkt am Schaltschrank sitzen muss wenn ich die Easy programmieren will.
Jetzt habe ich eine USB-Seriell Adapter an dem Raspi angeschlossen und diesen dann direkt mit der Easy verbunden. Ich hatte auch einen zweiten USB-Seriell Adapter getestet - ging auch nicht.

Wenn du mit den HEX Code bitte mit dem Merker 75 umschreiben könntest kann ich direkt sehen ob er gesetzt wird.

Gruß Heicar

Offline Peter_Pig

  • Jr. Member
  • **
  • Beiträge: 48
Re:Raspberry Pi + Easy
« Antwort #36 am: September 05, 2014, 19:48:45 Nachmittag »
Anbei die codierten strings:

M75 Net ID 0 auf 1 setzen : '\x45\x08\x20\x00\x04\x4a\x00\x01\x6f\x86'
M75 Net ID 0 auf 0 setzen : '\x45\x08\x20\x00\x04\x4a\x00\x00\xae\x46'

M75 Net ID 0 lesen : '\x45\x07\x00\x00\x0a\x09\x00\x27\xe5'

(Das gibt zwar nicht nur M75 zurück, ist aber die verwendete Anfrage)

Viel Glück!!!!  :)

Und schönes Wochenende.

Peter
« Letzte Änderung: September 05, 2014, 19:57:26 Nachmittag von Peter_Pig »

Offline heicar

  • Newbie
  • *
  • Beiträge: 14
Re:Raspberry Pi + Easy
« Antwort #37 am: September 08, 2014, 19:29:49 Nachmittag »
Danke Peter,

so ich kann dich beruhigen. Dein Script funktioniert. Ich habe mir ein EASY USB Kabel geordert. Und siehe da - Es geht damit. Ich kann also Merker setzen und diese dann auch abfragen. Ausgänge abfragen geht auch.
Erste Sahne  :)

Gerad eben hab ich mich ans Logging von ca. 20 Merkern - Problem dann wenn das Logging über dein Script läuft kann ich nichts mehr über das Script schalten.
Ich muss ja immer aktiv die Merker auf den aktuellen Zustand abfragen. Da dauert es ziemlich lange bis wieder der 1. Merker abgefragt wird.  So ist wohl auch keine Zeit "zwischendurch" noch irgendeinen Merker zu setzen. Es müsste also eine zweite unabhängige Instanz auf den USB Port schreiben. Geht sowas? Sonst wird die Latenz von druck auf den Webbutton bis zum Auslösen einer Aktion zu lange - und die Frau schreit das es defekt ist....
Jetzt habe ich ca. eine Latenz von einer Sekunde. Ist das i.O??? Oder kann man was optimieren.

Danke Heicar


Offline Peter_Pig

  • Jr. Member
  • **
  • Beiträge: 48
Re:Raspberry Pi + Easy
« Antwort #38 am: September 09, 2014, 00:56:41 Vormittag »
Hi Heicar,

ich bin spät drann, nach einem 18 Stunden Tag.

Es freut mich, dass es mit dem USB-CAB doch funktioniert  :D

Der Preis dieses Kabels ist aber m.E. unverhältnissmässig hoch, deshalb hätte ich mich gefreut, wenn sich andere Wege finden ließen.

Das bleibt wohl für später offen...

So, nun zu deinen Fragen (ganz kurz, weil müde):

Ich rate Dir davon ab, einzelne Merker(-Bit) abzufragen. Versuche in deinem Easy Programm alle Merker so dicht wie möglich zusammenzuführen (d.h. benachbarte Merker verwenden).

Z.B. kannst Du dann M1 bis M32 mit nur einem Aufruf von MD1.get_value() auslesen. Der 32 bit Integer den du bekommst, braucht dann ein bisschen Dekodierung, um die einzelnen Bits auszulesen, das geht aber relativ einfach.

Am besten ist wenn man solche Aufgaben dem Fernrechner überlässt (z.B. mittels JavaScript), das spart dem Raspy Arbeit, vor allen dingen wenn mehrere Clients auf einmal etwas von ihm wollen.

Dann gibt es noch die Methode get_values() - anstatt get_value() - die gibt dir, mit einer einzigen Abfrage, gleich 32 byte aus dem Speicherbereich zurück...

Es sind noch andere Funktionen verfügbar, die die Sache erleichtern könnten:

Jede plc_item Instanz kann Ihren Wert selbstständig ins Netzwerk schicken, so dass alle Rechner - die auf diesen Port hören - sie empfangen (broadcasting).

Dafür sind die Übergabeparameter bc_port und bias da:

Wenn der vorherige Wert des plc_items sich um mindestens den Wert bias ändert, schickt er automatisch seinen neuen Wert ins Netz, über bc_port.

Der Haken ist: plc_item tut sich erst "updaten" wenn get_value() aufgerufen wird...

Ich habe da einen Socket-Server Script, der auf meinem Raspi als Dienst läuft. Das Skript benutzt die com_lib.py um mit der Easy zu kommunizieren (also com_lib.py in den selben Ordner werfen), und sockets um mit anderen (lokalen oder fernen) Prozessen zu kommunizieren:

#!/usr/bin/env python

# IPC_TO_SERIAL.py  #140416 -------------------------------------------
#
# socketserver for com_lib.py
#----------------------------------------------------------------------

import com_lib as com_lib

import os
import socket
import select
import struct
import serial
import sys
import time
import atexit

time.sleep(10)

res = com_lib.set_device_baudrate(57600)

if res == 0:
    
    print com_lib.o_serial
    com_lib.close_port()


# ------------------------------------------ default plc_items ---------------------------------------

for index in range(1,97):

    exec('M'+str(index)+'=com_lib.plc_item(0,\"M\",'+str(index)+')')
    exec('MB'+str(index)+'=com_lib.plc_item(0,\"MB\",'+str(index)+')')
    exec('MW'+str(index)+'=com_lib.plc_item(0,\"MW\",'+str(index)+')')
    exec('MD'+str(index)+'=com_lib.plc_item(0,\"MD\",'+str(index)+')')
    
for index in range(1,13):

    exec('I'+str(index)+'=com_lib.plc_item(0,\"I\",'+str(index)+')')

for index in range(1,9):

    exec('Q'+str(index)+'=com_lib.plc_item(0,\"Q\",'+str(index)+')')

for index in range(1,5):

    exec('IA'+str(index)+'=com_lib.plc_item(0,\"IA\",'+str(index)+')')

QA = com_lib.plc_item(0,'QA',1)

# -------- subscriptions --------

subscribed_items = []


def subscribe_item(_item,_port,_max_age=1,_bias=0):

    _item.port = _port
    _item.max_age = _max_age
    _item.bias = _bias

    subscribed_items.append(_item)
    
def unsubscribe_item(_item):

    _item.port = None
    
    subscribed_items.remove(_item)

subscribe_item(Q1,54000,.1)
subscribe_item(IA1,54000,1.5,10)
subscribe_item(MD1,54000,2)
subscribe_item(MD89,54000,3)

def get_interfaces():
    
    resp =[]
    
    for item in subscribed_items:

        tmp_item = (item.item_type+str(item.index+1),item.port,item.max_age,item.bias)
        resp.append(tmp_item)

    return resp

        
# ------------------ serial ----

s_name='/dev/ttyUSB0'
s_baudrate=9600
s_timeout=1

def set_serial(_name,_baudrate,_timeout):

    global s_name,s_baudrate,s_timeout
    
    s_name = _name
    s_baudrate = _baudrate
    s_timeout = _timeout
    
# ------------------------- raw socket to serial com -----------------

def write_port(outData):

    try:

        if com_lib.o_serial.inWaiting() > 0:
            
            com_lib.urb.append(com_lib.o_serial.read(com_lib.o_serial.inWaiting())) # --- flush unrequested data to urb
            
        com_lib.o_serial.write(outData)
  
        return listen_port()                                # --- go wait for data

    except:

        return 4                                            # --- no port?

def listen_port():

    try:

        cnt = 0
        
        while cnt < 500 :

            data_len=com_lib.o_serial.inWaiting()

            if data_len > 6: #( ----  smallest message 'e'/len/err_1/err_2/crc_1/crc_2
            
                in_packet = com_lib.o_serial.read(2)

                tupl = struct.unpack('<sB',in_packet)

                if tupl[0] == 'e':
                    
                    pl_len = int(tupl[1])
                    in_packet = in_packet+com_lib.o_serial.read(pl_len)
                    
                    return in_packet

                else:

                    in_packet = in_packet+com_lib.o_serial.read(com_lib.o_serial.inWaiting())
                    return in_packet
                
            else:
                cnt=cnt+1

        return 8                                    # ---- function timed out

    except:

        return 9                                    # ---- tty port is closed or does not exist
    

# ----------------- sockets --------------------------------------
# ----------------------------------------------------------------

# ----------------- socket server --------------------------------

client_objects = []
size = 1024

# setup variables and server sockets (UNIX and INET)

unix_sock = '/tmp/raspy_com'

# clean up for nix

if os.path.exists(unix_sock):

    os.remove(unix_sock)

# server sockets

unix_backlog = 5

tcp_host = None


# ------ get LAN address ----------------------------------

if tcp_host == None:
    
    if os.name != "nt":

        import fcntl

        def get_interface_ip(ifname):

            ts = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            return socket.inet_ntoa(fcntl.ioctl(ts.fileno(), 0x8915, struct.pack('256s',ifname[:15]))[20:24])
            
        
    tcp_host = socket.gethostbyname(socket.gethostname())

    if tcp_host.startswith('127.'):

        interfaces = ['eth0','eth1','eth2','wlan0','wlan1','wifi0','ath0','ath1','ppp0',]

        for ifname in interfaces:

            try:

                tcp_host = get_interface_ip(ifname)
                
                break
            
            except IOError:

                tcp_host = 'localhost'            
                pass
        
# ---------------------------------------------------------

def close_sockets():

    print 'closing sockets'
    
    for socket in client_objects:

        socket.close()

atexit.register(close_sockets)

tcp_port = 50000
tcp_backlog = 5

got_nix_server = False
server_count = 0

try :
    
    unix_server = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
    unix_server.setblocking(0)
    unix_server.bind(unix_sock)
    unix_server.listen(unix_backlog)

    client_objects.append(unix_server)
    server_count = 1
    got_nix_server = True
    print 'Unix Socket Server listening at '+unix_sock

except:

    print str(os.name)+' seems not to implement the AF_UNIX family.'

tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server.setblocking(0)
tcp_server.bind((tcp_host,tcp_port))
tcp_server.listen(tcp_backlog)

client_objects.append(tcp_server)
server_count = server_count + 1
print 'TCP Socket Server listening at '+str(tcp_host)+':'+str(tcp_port)

com_lib.open_port()

# ------------------------ main -----------------------------

running = 1

while running:

    if len(client_objects) > server_count:
        
        startTime = time.time()

        for item in subscribed_items:

            if item.timestamp  < startTime - item.max_age:
                #print 'updating item '+item.item_type+str(item.index+1)
                res = item.get_value()

    input_ready,output_ready,in_error = select.select(client_objects,[],client_objects,.01)

    for rc in input_ready:

        if rc == unix_server:

            client,address = unix_server.accept()
            client_objects.append(client)
            
            if com_lib.o_serial == None:

                res = com_lib.open_port()

            client.send(str(len(client_objects)-2))
            print 'new NIX client '+str(len(client_objects)-2)+' connected to socket '+unix_sock
            
        elif rc == tcp_server:
            
            client,address = tcp_server.accept()
            client_objects.append(client)

            if com_lib.o_serial == None:

                res = com_lib.open_port()
                
            client.send(str(len(client_objects)-2))
            print 'new TCP client #'+str(len(client_objects)-2)+' connected by '+str(address)
            
        else:

            try:
                
                sock_type = rc.family
                sock_address = rc.getpeername()
                
                data = rc.recv(size)

            except:

                data = False

            if data:

                if data[0] == 'E':
                    
                    res = write_port(data)
                    rc.send(str(res))

                else:
                    
                    try:
                        
                        exec('res='+data)
                        rc.send(str(res))

                    except:
                        
                        rc.send('?')
                        
            else:

                rc.close()
                client_objects.remove(rc)
                
                if len(client_objects) <= server_count:
                    
                       print 'nobody connected... closing serial port'
                       com_lib.close_port()


    for rc in in_error:                    

        rc.close()
        client_objects.remove(rc)


Dieses Skript Instanziert am Anfang alle M, MB, MD, Q, A die auf einer 822er zur Verfügung stehen.

Später werden, nmittels subscribe_item() einige davon mit einem Port, einem bias und einem max_age (maximales alter) versehen, so dass sie automatisch geupdated werden (fürchterliches wort).

Es ist heute zu spät um das zu erklären ... (gääähhn...) aber vielleicht kannst Du reinschauen, es anpassen und mit rumspielen.

Ich verspreche mehr information demnächst...  ;)

Ach so, ein einfacher Client für die broadcast Pakete:


# -------- udp broadcast receiver ------

MY_PORT = 54000

import sys
from socket import *

s = socket(AF_INET,SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR,1)
s.bind(('',MY_PORT))

while 1:

    data,wherefrom = s.recvfrom(1500,0)
    print data,wherefrom


Gute Nacht + und vielen Dank für deine Geduld!

Gruß,

Peter
« Letzte Änderung: September 09, 2014, 01:17:48 Vormittag von Peter_Pig »

Offline jopebe

  • Jr. Member
  • **
  • Beiträge: 42
Antw:Raspberry Pi + Easy
« Antwort #39 am: August 02, 2016, 19:25:42 Nachmittag »
Lang lang ist es her!
Gibt es ein Happy-End?
Oder ist die Sache im Sande verlaufen?
Es wäre schön, wenn EasyNet Anschluss an andere Systeme fände; der Pi wäre ein guter Anfang.
jopebe