1. Schritte mit HS485

Hallo alle zusammen.

ich hoffe ich darf diesen Beitrag hier Posten.

Ich habe ein kleines perl-script gechrieben, um die HS485-Funktionen zu testen.
Das ist wirklich nur ein proof of concept, aber vielleicht hilft es hier ja jemandem:

#Testscript für HS485PCI
my @bytes = (0xFE, 0x04, 0x01, 0xBE, 0xD2);
my $hexstr = pack('C*',@bytes);

my @on_bytes = (0xFD, 0x00, 0x00, 0x0E, 0x30, 0x98, 0x00, 0x00, 0x00, 0x00, 0x06, 0x73, 0x00, 0x03, 0x01, 0x14, 0x86);
my @off_bytes = (0xFD, 0x00, 0x00, 0x0E, 0x30, 0x98, 0x00, 0x00, 0x00, 0x00, 0x06, 0x73, 0x00, 0x03, 0x00, 0x04, 0x84);

my $on_hexstr = pack('C*',@on_bytes);
my $off_hexstr = pack('C*',@off_bytes);



if ($Startup or $Reload) {

	my $send_data = unpack ('H*',$hexstr);

	print_log "$send_data";

}



$hs485pci1 = new hs485pci_interface($hexstr, 'Check','HS485PCI');
$hs485pci1 -> add ($on_hexstr, 'ON');
$hs485pci1 -> add ($off_hexstr, 'OFF');



if (my $data = said $hs485pci1) {
	$data= unpack ('H*',$hexstr);
	print_log "Data from interface: $data ";
 }

Wichtig ist eigentlich nu das die Schnittstelle richtig initialisiert wird, sonst gehts nicht:

Parameter : Baudrate=19200, Daten= 8bit, Stopp=1bit, parity=even, Handshake=cts

Gesendet werden Hex als Ascii daten:
Beispiel: 0xFE 0x04 0x01 0xBE 0xD2 ->ANfrage Software version HS485PCI
0xFE -> Startbyte kommando an HS485PCI, 0XFD Kommando an bus
0x04, 0x01 ->Anfrage Software
0xBE, 0xD2 ->CRC16-Checksumme , lt.protokoll nach polynom 0x1002

Bei mir haperts an der Checksumme…

ich bekomme die nicht selber berechnet. Hat jemand sowas schonmal gemacht?

Hier der link zur Protokollbeschreibung: http://www.elv-downloads.de/downloads/programme/HS485/HS485_Protokoll.pdf

Da hakts echt bei mir. ich habe schon diverse Tools Probiert (jacksum) komme ber nie auf die im Beispiel erzeugte CRC…
Es gibt ja auch die C++ Demo als quellcode:
http://www.elv-downloads.de/downloads/programme/HS485/hs485_demo_software_v1_60.zip
aber mit c++ hab ichs nicht so. Ich verstehe da nicht wie die CRC berechnet wird.
Kann jemand helfen?

Hallo Thorsten,

diese Funktion GetCRC16(…) sollte die Checksumme korrekt berechnen:

$strToSend = "\xfe\x04\x01";
$CRC16 = GetCRC16($strToSend. "\x00\x00"); // ergibt "BED2"
echo "Checksum 1: ". sprintf("%X", $CRC16). "
";


$strReceived = "\xfe\x04\x01\xbe\xd2";
$CRC16 = GetCRC16($strReceived); // ergibt 0
echo "Checksum 2: ". sprintf("%X", $CRC16). "
";


function GetCRC16($s)
{
 $CRCreg = 0xffff00;
 for ($cp=0; $cp<strlen($s); $cp++)
 {
  $CRCreg |= ord($s[$cp]);
  for ($bp=0; $bp<8; $bp++)
  {
   $CRCreg <<= 1;
   if ($CRCreg & 0x1000000) $CRCreg ^= 0x100200; // hier ist das Polynom 0x1002 enthalten
   $CRCreg &= 0xffffff;
  }
 }
 return $CRCreg >> 8;
}

Beim Senden ist zu beachten, dass für die Berechnung der Checksumme an den String noch zwei Null-Bytes ("\x00\x00") anzuhängen sind. Die berechnete Checksumme wird dann anstelle dieser beiden Null-Bytes gesendet.

Bei einem korrekt empfangenen String muss die berechnete Checksumme immer Null ergeben.

Gruß
HJH

Suuper klasse!! Vielen dank.

Jetzt kann es endlich weitergehen.

Ich schreibe mal ein kleines programm und poste den quellcode hier.

Ich denke den perl-code auf php umzustzen ist dann das kleinere problem.

soo hier mal mein kleines testscript in perl:

es kann prüfen ob HS485PCI vorhanden ist,
un man kann 2 Ausgänge schalten.

Leider habe ich die umsetzung der CRC-berechnung nicht hinbekommen…
in php funzt es aber in perl komme ich auf andere ergebnisse.

#!/bin/perl -w 
#Testprogramm für HS485 PCI 
#Schaltet Aktor 2+3 an Adresse 0x00000e30 Ein und Aus 
#Switch Port 2+3 on adress 0x00000e30 on and off 
# call with : perl test_hs485 /dev/ttyUSBx 



use strict; 
use Device::SerialPort; 
use bigint; 

#--------------------------------Variablendeklaration------------------------------------------------- 
my $send_cmd; 
my $strToSend; 
my $strReceived; 
my $CRC16; 
my $CRCreg; 
my $cp; 
my $bp; 
my @s; 
my $s; 


#---------------------------------Datenübergabe vom Programmaufruf 
#----------------------------------Get parameter on program start 
my ($port, $hex_cmd); 

$port = shift; 
$hex_cmd = shift; 

#---------------------------------Erstellen der Seriellen Schnittstelle 
#---------------------------------Open new serial port 
my $device = Device::SerialPort->new ($port) or die " Konnte $port nicht öffnen!
"; 

        $device->error_msg(1);	# use built-in error messages 
        $device->user_msg(0); 
        $device->databits(8); 
        $device->baudrate(19200); 
        $device->parity("even");	 
        $device->stopbits(1); 
        $device->dtr_active(0); 
        $device->handshake("rts"); 
        $device->write_settings || die "Konnte Einstellungen für $port nicht setzen
"; 
        $device->read_char_time(0);     # don't wait for each character 
        $device->read_const_time(1000); # 1 second per unfulfilled "read" call 

#---------------------------------Prüfen ob HS485 vorhanden 
#---------------------------------Test if HS485PCI present 
my @bytes = (0xFE, 0x04, 0x01, 0xBE, 0xD2);    	#command for get software version from HS485PCI 
my $cmd = pack('C*',@bytes);			#convert Databytes into datastream 
$device->write($cmd);				#send cmd 

my ($cnt,$data)=$device->read(255); 		#read 255 Chars max. 
        if ($cnt > 0) {               		#process received data and check if interface is present 
 		$data= unpack 'H*', $data; 
                        if ($data eq 'fe00980005810115f6dc'){ 
                                print "HS485 vorhanden : $data 
"; 
                        } 
                        else{ 
                                die "Kein HS485 vorhanden
"; 
                                }						 
        } 
         
#----------------------------------Menüfunktionen------------------------ 
MENUE: 
system 'clear'; 
print <<HERE_MENUE; 
********************HS485PCI Testprogramm************************* 

Port 2 ON				[1] 
Port 2 OFF				[2] 
Port 3 ON				[3] 
Port 3 OFF				[4] 
Read data from bus  (10sek)			[5] 
Test CRC-calculation			[6] 
End					[7] 

HERE_MENUE 


my $eingabe = 0; 
chomp ($eingabe= <STDIN>); 

SWITCH: { 
        $eingabe eq 1 && do {SwitchOnOff(1); 
                                        last SWITCH; }; 
         
        $eingabe eq 2 && do {SwitchOnOff(2); 
                                        last SWITCH; }; 

        $eingabe eq 3 && do {SwitchOnOff(3); 
                                        last SWITCH; }; 
                                         
        $eingabe eq 4 && do {SwitchOnOff(4); 
                                        last SWITCH; }; 
                                         
        $eingabe eq 5 && do {ReadBus(); 
                                        last SWITCH; }; 
                                         
        $eingabe eq 6 && do {testcrc(); 
                                        last SWITCH; };				 
                                         
        $eingabe eq 7 && do {print "Beendet
"; 
                                        exit;}; 
                                         				 
} 
         
sub SwitchOnOff { 
        my $parm = shift; 
        if ($parm eq 1){ 
                 @bytes = (0xFD, 0x00, 0x00, 0x0E, 0x30, 0x98, 0x00, 0x00, 0x00, 0x00, 0x06, 0x73, 0x00, 0x03, 0x01, 0x14, 0x86);    #Sende Aktor 3 ON /send port3 ON 
                 $cmd= pack('C*',@bytes); 
                 $send_cmd = unpack ('H*',$cmd); 
                print"Sende: $send_cmd
"; 
                $device->write($cmd); 
        } 
        if ($parm eq 2){ 
                @bytes = (0xFD, 0x00, 0x00, 0x0E, 0x30, 0x98, 0x00, 0x00, 0x00, 0x00, 0x06, 0x73, 0x00, 0x03, 0x00, 0x04, 0x84);    #Sende Aktor 3 OFF /send port3 OFF 
                 $cmd= pack('C*',@bytes); 
                 $send_cmd = unpack ('H*',$cmd); 
                print"Sende: $send_cmd
"; 
                $device->write($cmd); 
        } 
        if ($parm eq 3){ 
                 @bytes = (0xFD, 0x00, 0x00, 0x0E, 0x30, 0x98, 0x00, 0x00, 0x00, 0x00, 0x06, 0x73, 0x00, 0x02, 0x01, 0x06, 0xA4);    #Sende Aktor 2 ON /send port2 ON 
                 $cmd= pack('C*',@bytes); 
                 $send_cmd = unpack ('H*',$cmd); 
                print"Sende: $send_cmd
"; 
                $device->write($cmd); 
        } 
        if ($parm eq 4){ 
                 @bytes = (0xFD, 0x00, 0x00, 0x0E, 0x30, 0x98, 0x00, 0x00, 0x00, 0x00, 0x06, 0x73, 0x00, 0x02, 0x00, 0x16, 0xA6);    #Sende Aktor 2 OFF /send port2 OFF 
                 $cmd= pack('C*',@bytes); 
                 $send_cmd = unpack ('H*',$cmd); 
                print"Sende: $send_cmd
"; 
                $device->write($cmd); 
        } 
goto MENUE;	 
} 
         
sub ReadBus { 
        print "warte auf Daten..."; 
        my $STALL_DEFAULT=10; # how many seconds to wait for new input 
        my $timeout=$STALL_DEFAULT; 
        my $chars=0; 
        my $buffer=""; 
        while ($timeout>0) {		 
                my ($count,$saw)=$device->read(255); # will read _up to_ 255 chars 
                if ($count > 0) { 
                        $chars+=$count; 
                        $buffer.=$saw; 
                        $buffer= unpack 'H*', $buffer; 
                        print "Empfangene Daten: $buffer 
"; 
                        # Check here to see if what we want is in the $buffer 
                        # say "last" if we find it 
                } 
                else { 
                        $timeout--; 
                } 
        } 

                if ($timeout==0) { 
                        print "Seit $STALL_DEFAULT sekunden keine Daten Emfangen - gehe  zurück  
"; 
        		goto MENUE; 
 } 
 } 
  
sub testcrc { 
#Beim Senden ist zu beachten, dass für die Berechnung der Checksumme  
#an den String noch zwei Null-Bytes ("\x00\x00") anzuhängen sind.  
#Die berechnete Checksumme wird dann anstelle dieser beiden Null-Bytes gesendet. 
# 
#For calculating the checksum you have  to add 2 null bytes ("\x00\x00") 
$strToSend = "\0xfe\0x04\0x01"; 
$CRC16 = GetCRC16($strToSend. 0x0000); # ergibt / gives "BED2" 
print "Checksum 1: ". sprintf("%X", $CRC16). "
"; 

$strReceived = "\0xfe\0x04\0x01\0xBE\0xD2"; 
$CRC16 = GetCRC16($strReceived); # ergibt  / gives "0" 
print "Checksum 2: ". sprintf("%X", $CRC16). "
"; 
goto MENUE; 
} 
  
sub GetCRC16{ 
         
$CRCreg = 0xffff00; 
$s = $_[0]; 

@s=split(//,$s); 
for ($cp=0; $cp<length($s); $cp++){	 
        $CRCreg |= ord($s[$cp]); 
                for ($bp=0; $bp<8; $bp++){ 
                        $CRCreg <<= 1; 
                        if ($CRCreg & 0x1000000){ 
                                $CRCreg ^= 0x100200; # hier ist das Polynom 0x1002 enthalten 
                                $CRCreg &= 0xffffff; 
                                } 
                        } 
} 
return $CRCreg >> 8; 

}  

Hallo Thorsten,

ich kenne PEARL nicht.

Aber ich frage mich wie der Funktion „sub GetCRC16{…}“ das Argument übergeben wird. Mit anderen Worten: woher weiß sie, welcher String verwendet werden soll?

Gruß
HJH

durch: $s = $_[0];

Hallo Olli, hallo Thorsten,

$_[n] ist offensichtlich ein Array für die Übergabe-Parameter.
Jetzt wüsste ich noch gern was diese Zeile bewirkt:
@s=split(//,$s);

Hier der Algorithmus für die Checksummenberechnung in einfache Worte gefasst:

Der String wird bitweise (shift left) durch das Checksummenregister geschoben.
Jedesmal, wenn dabei ein 1-Bit oben herausfällt, wird das Checksummenregister mit dem Plynom XOR-verknüpft. Bei einem 0-Bit wird nichts unternommen. Der Vorgang wiederholt sich solange, bis der String vollständig durchgeschoben ist.

Die XOR-Verknüpfung bewirkt dort, wo das Polynom ein 1-Bit enthält, eine Invertierung des zugehörigen CRC-Bits.

Ich habe der Einfachheit halber das Checksummenregister und das gerade anstehende String-Byte zu einem einzigen Register (3 Byte) zusammengefasst. Diese werden also gemeinsam geschoben. Das ganze funktioniert nur, wenn ein PERL-Integer, so wie in PHP auch, mindestens 32bit lang ist. Das ist auch der Grund, warum der Rückgabewert um 8 Stellen nach rechts geschoben werden muss, damit das String-Byte eliminiert wird.

Zu überprüfen wäre auch, ob die Bitwise Operatoren in PERL und PHP identisch sind.

Ich hoffe das hilft bei der Fehlersuche.

Gruß
HJH

Mit dem split wird der string in ein array gesplittet. Der erste Parameter von split ist ein regulärer Ausdruck und matched hier die \0 in dem String. In etwas vergleichbar mit explode().

Denk ich mir jetzt mal so… ist schon ein paar Jahre her mit Perl.

Hallo Olli,

in PHP (und auch in C-Sprachen) ist es nicht nötig einen String in ein Array zu konvertieren. Jeder String kann auch so als Array adressiert werden.

Ich fürchte, dass Perl die binäre 0 (0x00) als String-Ende interpretiert, was zur Folge hat, dass ein Perl-String niemals eine 0 enthalten kann, zumindest nicht ohne Escape-Zeichen. Perl wäre dann für diese Zwecke nicht die beste Wahl.

In PHP geht das so wunderschön einfach.

Gruß
HJH

jungs macht euch keinen Stress mehr…

Ich habe die lösung:

#!/bin/perl

use strict;
use warnings;

my $strToSend = "\xfe\x04\x01";
my $CRC16 = GetCRC16($strToSend. "\x00\x00"); # ergibt "BED2"
print "Checksum 1: ". sprintf("%X", $CRC16). "
";


my $strReceived = "\xfe\x04\x01\xbe\xd2";
$CRC16 = GetCRC16($strReceived); # ergibt 0
print "Checksum 2: ". sprintf("%X", $CRC16). "
";

sub GetCRC16 {
    my $s = shift;
    
    my $CRCreg = 0xffff00;
    
    for (my $cp=0; $cp<length($s); $cp++) {
    $CRCreg |= ord( substr($s,$cp,1) );
    
    for (my $bp=0; $bp<8; $bp++) {
        $CRCreg <<= 1;
        if ($CRCreg & 0x1000000) { 
        $CRCreg ^= 0x100200; # hier ist das Polynom 0x1002 enthalten
        }
        $CRCreg &= 0xffffff;
    }
    }
    return $CRCreg >> 8;
} 

1;

eigentlich ganz einfach, ich hatte bei der parameterübergabe an die sub-routine wohl einen fehler.

Hallo,

eventuell kann ja jemand weiterhelfen.
Ich probiere jetzt schon 2 Tage das I/O-Modul zuüberzeugen das es mal schaltet, macht es aber nicht.

Die Kommunikation mit dem Interface geht und gibt auch Rückantwort.

$Interface = "\xFE\x04\x01\xBE\xD2";
COMPort_SendText(51003, $Interface);

Antwort, xFE x00 x98 x00 x05 x81 x01 x15 xF6 xDC. was auch immer das heissen mag,(außer das das Interface vorhanden ist) stimmt mit obigen aber überein. Die Doku schweigt sich dazu aus.

Hier die Befehle für das I/O Modul.

$Ausgang1 = "\xFD\x00\x00\x18\xEA\x98\x00\x00\x00\x00\x06\x73\x00\x03\xFF\x21\x74";
COMPort_SendText(51003, $Ausgang1);
IPS_LogMessage($IPS_SELF, "HS485_Ausgang:  ". $Ausgang1);

auch hier gibt es eine Antwort vom Modul.
xFD x00 x00 x00 x00 x19 x00 x00 x18 xEA x02 xA2 x82. das war es auch schon.

FD = Startzeichen
000018EA = Moduladresse
98 = Kontrollzeichen
00000000 = Absender
06 = Framelänge(Anzahldatenbytes + 2 Byte Checksumme
73 = Befehl(s, Aktor setzen)
00 = Dummy
03 = Aktornummer
FF = Event(toggle)
2174 = Checksumme(berechnet nach Code von HJH)

Hier noch mal der Code aus dem Beispiel.

// Setzt den Zustand eines Ausgangs an einem Module
void SetActor(Com *p_cCom)
{	
	unsigned long  ulAddress  = 0;
	unsigned int uiAktor=0;
	unsigned int uiAuswahl=0;
	struct stData pFrame;
	// Adresse angeben
	printf("
Adresse(Hex): ");
   scanf("%x",&ulAddress);
   // Aktor
   while(true){
	   printf("
Aktor(-1: Ende) : ");
	   scanf("%d",&uiAktor);
	 	if(uiAktor==-1)
		 	break;  
		printf("Zustand:	An: 	0x01
		Aus:	0x00
		Toggle:	0xFF
Auswahl: ");
		scanf("%x",&uiAuswahl);
		// Buffer leeren, damit evtl. empfangene Nachrichten gelöscht werden
		while(ReadFrame(p_cCom));
	   // Senden
		pFrame.ucStartByte=FRAME_START_LONG;
		pFrame.ucControlByte=0x98;
		pFrame.ucDataLength=4;
		AddressHexToChar(pFrame.ucSenderAddress,0x00000000);
    	AddressHexToChar(pFrame.ucReceiverAddress,ulAddress);
		pFrame.ucFrameData[0]='s';
		pFrame.ucFrameData[1]=0x00;					// Sensor; hier nur Dummy, da nicht erforderlich
		pFrame.ucFrameData[2]=((unsigned char)uiAktor)&0xFF;		// Zielaktor
		pFrame.ucFrameData[3]=((unsigned char)uiAuswahl)&0xFF;		// Wert
		Send(p_cCom,&pFrame);
	}
}

Eigentlich müsste es so funktionieren aber nur eigentlich. Einkommende Daten werden noch nicht ausgewertet. Sehe ich aber im obigen Beispiel auch nicht oder sollte es daran liegen.

Hi

Habe auch so ein IO-Modul hier,damit kann ich meins schalten.
COMPort_SendText(65093,chr(0xFD).chr(0x00).chr(0x00).chr(0x10).chr(0xFA).chr(0x98).chr(0x00).chr(0x00).chr(0x00).chr(0x00).chr(0x06).chr(0x73).chr(00).chr(01).chr(01).chr(0x74).chr(0x08));
//$Startzeichen = „FD“
//$Adresse = „000010FA“;
//$Kontroolzeichen =„98“;
//$Absenderadresse = „00000000“;
//$Laenge =„06“
//$Aktorsetzen =„73“;
//$xxx =„00“;
//$Kanal =„01“;
//$Zustandan =„01“;
//$Hex =„0x“;
//$Checksumme =„7408“;

Hallo,

bliebe nur noch die Frage nach der Softwareversion des Moduls.

Bei mir ist aktuell 1.01, welche ist denn bei euch auf dem Modul.

Hallo RWN,

xFE ist das Startzeichen für einen „Discovery-Frame“.

Mit Hilfe der Befehlsfolge \xFE\x04\x01\xBE\xD2 kann der HS485-Bus nach angeschlossenen Modulen „abgesucht“ werden. Diese Funktion nutzt z.B. die Konfigurationssoftware für das HS485-System.

Bei der Befehlsfolge xFD x00 x00 x00 x00 x19 x00 x00 x18 xEA x02 xA2 x82 handelt es sich um einen „ACK-Frame“. Hiermit bestätigt das angesprochene Modul den Empfang deines Toggle-Befehls.

  • Um welchen Modultyp handelt es sich?
  • Ist der Port 03 des Moduls aus Ausgang konfiguriert?
  • Lässt der Ausgang sich „manuell“ mit Hilfe eines Sensor-Eingangs eines Moduls ansprechen?

Hallo Ernst,

xFE ist das Startzeichen für einen „Discovery-Frame“.

Mit Hilfe der Befehlsfolge \xFE\x04\x01\xBE\xD2 kann der HS485-Bus nach angeschlossenen Modulen „abgesucht“ werden. Diese Funktion nutzt z.B. die Konfigurationssoftware für das HS485-System

das war mir klar.

Bei der Befehlsfolge xFD x00 x00 x00 x00 x19 x00 x00 x18 xEA x02 xA2 x82 handelt es sich um einen „ACK-Frame“. Hiermit bestätigt das angesprochene Modul den Empfang deines Toggle-Befehls.

das habe ich mittlerweile auch verstanden.

  • Um welchen Modultyp handelt es sich?

Ich kenne nur ein I/O Modul das heisst 127, das anders wären Schalter/Dimmer.

  • Ist der Port 03 des Moduls aus Ausgang konfiguriert?

egal ob gesetzt oder nicht, es tut sich nichts. Zumal es vom Programm so gehem muss.

x73\x00\x03\xFF

hier wird ja der Aktor und Ausgang gesetzt, ob toogle/ein oder aus.

  • Lässt der Ausgang sich „manuell“ mit Hilfe eines Sensor-Eingangs eines Moduls ansprechen?

ja, wenn er über die Soft konfiguriert wurde.

Habe noch einen Luxsensor, dieser schaltet auch einwandfrei das Modul.

Wenn der Sendebefehl falsch wäre, dürfte eigentlich kein ACK zurückkommen. Sozumindest sehe ich es wenn ich probiere und die Sendefolge nicht stimmt.

Ich habe mir jetzt nochmal den HS485 S bestellt und werde diesen mal testen.
Was mir in der Demo aufgefallen ist, ist dieses hier.

// Setzt den Zustand eines Ausgangs an einem Module
void SetOutput(Com *p_cCom)
{	
	struct stData pFrame;
	unsigned long ulAddress;
	unsigned int uiActor;
	unsigned int uiValue;
	// Buffer leeren, damit evtl. empfangene Nachrichten gelöscht werden
	while(ReadFrame(p_cCom));
	// Adresse angeben
	printf("
Adresse(Hex): ");
   scanf("%x",&ulAddress);
   // Aktor
   printf("Aktor(Hex): ");
   scanf("%x",&uiActor);
   // Zustand; je nach Modultype unterschiedlich-> siehe Protokollbeschreibung
   printf("HS485S  0x00 Aus
	0x01 An
	0xFF Toggeln
");
   printf("HS485D  0-0x10 Helligkeit
	0x11 runterdimmen
	0x12 hochdimmen
	0x13 hoch-/runterdimmen
	0x14 an/aus
	0x15 alte Helligkeit
");
   printf("Wert(Hex): ");
   scanf("%x",&uiValue);
   // Senden
	pFrame.ucStartByte=FRAME_START_LONG;
	pFrame.ucControlByte=0x98;
	pFrame.ucDataLength=4;
	AddressHexToChar(pFrame.ucSenderAddress,0x00000000);
	AddressHexToChar(pFrame.ucReceiverAddress,ulAddress);
	pFrame.ucFrameData[0]='s';
	pFrame.ucFrameData[1]=0x00;				// Sensor; hier nur Dummy, da nicht erforderlich
	pFrame.ucFrameData[2]=uiActor&0xFF;		// Zielaktor
	pFrame.ucFrameData[3]=uiValue&0xFF;		// Wert
	Send(p_cCom,&pFrame);
	printf("
");
}

im Gegensatz zu hier

// Setzt den Zustand eines Ausgangs an einem Module
void SetActor(Com *p_cCom)
{	
	unsigned long  ulAddress  = 0;
	unsigned int uiAktor=0;
	unsigned int uiAuswahl=0;
	struct stData pFrame;
	// Adresse angeben
	printf("
Adresse(Hex): ");
   scanf("%x",&ulAddress);
   // Aktor
   while(true){
	   printf("
Aktor(-1: Ende) : ");
	   scanf("%d",&uiAktor);
	 	if(uiAktor==-1)
		 	break;  
		printf("Zustand:	An: 	0x01
		Aus:	0x00
		Toggle:	0xFF
Auswahl: ");
		scanf("%x",&uiAuswahl);
		// Buffer leeren, damit evtl. empfangene Nachrichten gelöscht werden
		while(ReadFrame(p_cCom));
	   // Senden
		pFrame.ucStartByte=FRAME_START_LONG;
		pFrame.ucControlByte=0x98;
		pFrame.ucDataLength=4;
		AddressHexToChar(pFrame.ucSenderAddress,0x00000000);
    	AddressHexToChar(pFrame.ucReceiverAddress,ulAddress);
		pFrame.ucFrameData[0]='s';
		pFrame.ucFrameData[1]=0x00;					// Sensor; hier nur Dummy, da nicht erforderlich
		pFrame.ucFrameData[2]=((unsigned char)uiAktor)&0xFF;		// Zielaktor
		pFrame.ucFrameData[3]=((unsigned char)uiAuswahl)&0xFF;		// Wert
		Send(p_cCom,&pFrame);
	}
}

Hier liegt wohl der Hund begraben:confused:

Hallo Rainer,

das Problem dürfte an der Zählweise des 127 IO liegen.

Probier mal bitte „0E“ statt „03“ zu senden.

Habe durch Austesten folgende Belegung festgestellt:

00 --> Sensor 1
.
.
.
0B --> Sensor 12

0C --> Aktor 1
.
0E --> Aktor 3
.
.
12 --> Aktor 7

Hallo Ernst,

SUPER es geht.

Erstmal Vielen Dank.

Wie hast Du das jetzt so schnell rausbekommen.

Vorallem sollte ELV mal die Anleitungen auf den neusten Stand bringen.

Angeschrieben habe ich sie ja schon, Antwort bis jetzt Fehlanzeige,

Sowie es den anschein hat, hast Du das System ja auch in Gebrauch. Wenn Du einen Tester suchst, ich stehe zur Verfügung :smiley:

Hallo Ernst, hallo Rainer,

jedes Telegramm muss ja mit einer korrekten Checksumme versehen sein.

Wie berechnet ihr denn diese Checksumme?

Das von ELV genannte Polynom 0x1002 führt bei mir zu völlig anderen Ergebnissen.
Auch ist nicht ganz klar, welche Zeichen in die Checksumm einzubeziehen sind.

Die Protokollbeschreibung von ELV ist meiner Ansicht nach sogar fehlerhaft, zumindest aber höchst missverständlich.

Gruß
HJH

Hallo Rainer,

„schnell“ rausbekommen ?

Hab an dem gleichen Problem ziemlich lange rumgesucht.

Die Doku von ELV ist recht Mager, und nicht auf dem neusten Stand!

Einzelne Befehle senden, geht wie Du ja festgestellt hast recht „einfach“.

Frames empfangen, und die empfangenen Werte Variablen zuweisen ist nicht ganz so einfach.

Ich habe zur zeit 13 HS485-Module im Einsatz. Da geht auf dem Bus einiges ab!

Sobald ich eine halbwegs funktionsfähige Version am laufen habe, werde ich sie hier vorstellen.

Aber das kann noch dauern!

Hallo Hans-Jörg,

ich berechne die Checksumme nach deinen Vorgaben(Script) hier im Thread. Das passt auch alles, bis jetzt zumindest.

Ich füge diese allerdings im Moment noch manuell ein, also Sendebefehl ausrechnen lassen und Checksumme an Sendebefehl anhängen. Ich weiß, umständlich ohne Ende aber zum testen ist mir das lang gut. Hauptsache es geht erst mal.

Edit: Der Empfang genauso.