HBWired Modul aus dem Tutorial mit 16 Aus- und 16 Eingängen erweitern

Begonnen von grogo, 18 August 2018, 13:30:22

Vorheriges Thema - Nächstes Thema

grogo

Hallo zusammen,

ich eröffne mal ein neues Thema. Gerne möchte ich das HBW Modul mit 4 Ausgängen und 2 Eingängen aus dem Tutorial auf 16 Aus- und 16 Eingänge erweitern.

Es klappt auch alles bis auf die Funktion des langen Tastendrucks.

Ich habe das 4/2 Modul im Netz betrieben. Hier die Daten auf dem BUS. 2mal kurz gedrückt und 2mal lang gedrückt.


R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:2E:3E:18
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:32:EE:22
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:37:BE:28
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:37:BE:28
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:3B:7E:30
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:3B:7E:30
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:3B:7E:30


Man kann sehen, dass die Daten vom Modul 42:FF:FF:02  gesendet werden. ( 4B=#K key Info / 05 Kanal 5)

Bei einem langen Tastendruck wird der Befehl öfter gesendet. (denke laut HBWKey.cpp alle 300ms) Ich geh mal davon aus, dass die letzten 6 Byte eine Art Zeitstempel sind.

Somit kann die Zentrale scheinbar erkennen, dass der Taster öfter gedrückt worden ist.

Jetzt mache ich das gleiche mit dem 16/16 Modul:

R: FD:FF:FF:FF:FF:F8:42:DA:80:82:06:4B:13:00:0A:EB:DA
R: FD:FF:FF:FF:FF:F8:42:DA:80:82:06:4B:13:00:0E:AB:D2
R: FD:FF:FF:FF:FF:F8:42:DA:80:82:06:4B:13:00:12:7B:E8
R: FD:FF:FF:FF:FF:F8:42:DA:80:82:06:4B:13:00:16:3B:E0


Man kann wieder sehen, dass das Modul 42:DA:80:82 einen Tastendruck auf den Bus legt. Leider wird hier der Befehl auch beim langen Tastendruck nur einmal gesendet. (die letzten beiden Protokolle).

Hier die beiden Sketchs für das 4/2 Modul


// Gibt den Typen des HBWired Moduls an
// 0xAB Device HBW-TER-MOD42 Modul für 4 Relais und 2 Taster (TEST)
// 0xAC Device HBW-TER-MOD1616
#define HMW_DEVICETYPE 0xAB

// Gibt GeräteAdresse des HBWired Moduls an
// #define HMW_ADDRESS 0x42FFFF01

#define HARDWARE_VERSION 0x01
#define FIRMWARE_VERSION 0x0100

//#include "HBWSoftwareSerial.h"
#include "HBWired.h"
#include "HBWSwitch.h" 
#include "HBWKey.h"
#include "EEPROM.h"



#define RS485_RXD 14   // Receive-Pin
#define RS485_TXD 15   // Transmit-Pin
#define RS485_TXEN 3  // Transmit-Enable

struct hbw_config {
  uint8_t  logging_time;     // 0x0001
  uint32_t central_address;  // 0x0002 - 0x0005
  // vier relais (switches) je 2 Byte
  hbw_config_switch switchcfg[4];  // 0x0006 - 0x000D
  // zwei Taster (keys)  je 2 Byte
  hbw_config_key keycfg[2];        // 0x000E - 0x0011
} config;

// uint32_t ownaddress = HMW_ADDRESS;

//HBWSoftwareSerial rs485(RS485_RXD, RS485_TXD);
HBWDevice* device = NULL;

//NEU (6 Kanaele statt 2) 4 Relais und 2 Taster
HBWChannel* channels[6];

void setup()
{
  Serial.begin(19200);
  Serial3.begin(19200,SERIAL_8E1);
 
  //rs485.begin();

  // NEU: Definition mehrerer Kanaele pro Typ
  //      (das geht natuerlich auch eleganter)
  channels[0] = new HBWSwitch(13,&(config.switchcfg[0]));
  channels[1] = new HBWSwitch(9,&(config.switchcfg[1]));
  channels[2] = new HBWSwitch(10,&(config.switchcfg[2]));
  channels[3] = new HBWSwitch(11,&(config.switchcfg[3]));
  channels[4] = new HBWKey(7,&(config.keycfg[0]));
  channels[5] = new HBWKey(8,&(config.keycfg[1]));

  //Eigene Adresse in die obersten Bytes vom EEPROM schreiben
  //setOwnAddress(ownaddress);

  EEPROM.write(E2END - 3, 0x42);
  EEPROM.write(E2END - 2, 0xFF);
  EEPROM.write(E2END - 1, 0xFF);
  EEPROM.write(E2END, 0x02);
 
  device = new HBWDevice(HMW_DEVICETYPE, HARDWARE_VERSION, FIRMWARE_VERSION,
                         &Serial3,RS485_TXEN,sizeof(config),&config,
                         // NEU (6 statt 2 Kanaele)
                         6,channels,
                         &Serial,
                         NULL, NULL);
  hbwdebug(F("B: HBW-TER-MOD42 Version 2A\n"));
}


void loop()
{
  // call the HBW loop
  device->loop();
};


und für das 16/16 Modul


// Gibt den Typen des HBWired Moduls an
// 0xAB Device HBW-TER-MOD42 Modul für 4 Relais und 2 Taster (TEST)
// 0xAC Device HBW-TER-MOD1616
#define HMW_DEVICETYPE 0xAC

// Gibt GeräteAdresse des HBWired Moduls an
// #define HMW_ADDRESS 0x42FFFF01

#define HARDWARE_VERSION 0x01
#define FIRMWARE_VERSION 0x0100

#include "HBWired.h"
#include "HBWSwitch.h" 
#include "HBWKey.h"
#include "EEPROM.h"

#define RS485_TXEN 3  // Transmit-Enable

struct hbw_config {
  uint8_t  logging_time;     // 0x0001
  uint32_t central_address;  // 0x0002 - 0x0005
  // 16 relais (switches) je 2 Byte
  hbw_config_switch switchcfg[16];  // 0x0006 - 0x0025
  // 16 Taster (keys)  je 2 Byte
  hbw_config_key keycfg[16];        // 0x0026 - 0x0045
} config;

// uint32_t ownaddress = HMW_ADDRESS;

HBWDevice* device = NULL;

//NEU (32 Kanaele = 16 SWITCH (RELAIS) 16 KEY (TASTER))
HBWChannel* channels[32];

void setup()
{
  Serial.begin(19200);
  Serial3.begin(19200,SERIAL_8E1);

  // Definition mehrerer Kanaele pro Typ
  // Relais Port A
  channels[0] = new HBWSwitch(36,&(config.switchcfg[0]));
  channels[1] = new HBWSwitch(37,&(config.switchcfg[1]));
  channels[2] = new HBWSwitch(34,&(config.switchcfg[2]));
  channels[3] = new HBWSwitch(35,&(config.switchcfg[3]));
  channels[4] = new HBWSwitch(32,&(config.switchcfg[4]));
  channels[5] = new HBWSwitch(33,&(config.switchcfg[5]));
  channels[6] = new HBWSwitch(30,&(config.switchcfg[6]));
  channels[7] = new HBWSwitch(31,&(config.switchcfg[7]));
  // Relais Port B
  channels[8] = new HBWSwitch(28,&(config.switchcfg[8]));
  channels[9] = new HBWSwitch(26,&(config.switchcfg[9]));
  channels[10] = new HBWSwitch(27,&(config.switchcfg[10]));
  channels[11] = new HBWSwitch(29,&(config.switchcfg[11]));
  channels[12] = new HBWSwitch(24,&(config.switchcfg[12]));
  channels[13] = new HBWSwitch(22,&(config.switchcfg[13]));
  channels[14] = new HBWSwitch(23,&(config.switchcfg[14]));
  channels[15] = new HBWSwitch(25,&(config.switchcfg[15]));
  // Taster Port A
  channels[16] = new HBWKey(43,&(config.keycfg[0]));
  channels[17] = new HBWKey(48,&(config.keycfg[1]));
  channels[18] = new HBWKey(51,&(config.keycfg[2]));
  channels[19] = new HBWKey(47,&(config.keycfg[3]));
  channels[20] = new HBWKey(39,&(config.keycfg[4]));
  channels[21] = new HBWKey(49,&(config.keycfg[5]));
  channels[22] = new HBWKey(53,&(config.keycfg[6]));
  channels[23] = new HBWKey(52,&(config.keycfg[7]));
  // Taster Port B
  channels[24] = new HBWKey(46,&(config.keycfg[8]));
  channels[25] = new HBWKey(50,&(config.keycfg[9]));
  channels[26] = new HBWKey(45,&(config.keycfg[10]));
  channels[27] = new HBWKey(42,&(config.keycfg[11]));
  channels[28] = new HBWKey(44,&(config.keycfg[12]));
  channels[29] = new HBWKey(41,&(config.keycfg[13]));
  channels[30] = new HBWKey(38,&(config.keycfg[14]));
  channels[31] = new HBWKey(40,&(config.keycfg[15]));


  //Eigene Adresse in die obersten Bytes vom EEPROM schreiben
  //setOwnAddress(ownaddress);

  EEPROM.write(E2END - 3, 0x42);
  EEPROM.write(E2END - 2, 0xDA);
  EEPROM.write(E2END - 1, 0x80);
  EEPROM.write(E2END, 0x82);

 
  device = new HBWDevice(HMW_DEVICETYPE, HARDWARE_VERSION, FIRMWARE_VERSION,
                         &Serial3,RS485_TXEN,sizeof(config),&config,
                         // NEU (32 Kanaele)
                         32,channels,
                         &Serial,
                         NULL, NULL);
  hbwdebug(F("B: HBW-TER-MOD1616 Version 2B\n"));
}

void loop()
{
  // call the HBW loop
  device->loop();
};



Mit dem Code der HBWKey.cpp hätte ich eigentlich gedacht, dass es auch noch ein Bit für den langen Tastendruck gibt, aber dies kann ich im RS485 BUS weder beim 4/2 Modul (das funktioniert) noch beim 16/16 Modul sehen.

Scheinbar wird der lange Tastendruck wie oben zu sehen nur über wiederholenden Datensatz mit gleichem Zeitstempel auf dem BUS erkannt.


#include "HBWKey.h"

// Class HBWKey
HBWKey::HBWKey(uint8_t _pin, hbw_config_key* _config) {
keyPressedMillis = 0;
keyPressNum = 0;
pin = _pin;
config = _config;
pinMode(pin,INPUT_PULLUP);
}


void HBWKey::loop(HBWDevice* device, uint8_t channel) {
uint32_t now = millis();
if(digitalRead(pin)){
// d.h. Taste nicht gedrueckt
// "Taste war auch vorher nicht gedrueckt" kann ignoriert werden
    // Taste war vorher gedrueckt?
if(keyPressedMillis){
// entprellen, nur senden, wenn laenger als 50ms gedrueckt
// aber noch kein "long" gesendet
if(now - keyPressedMillis >= 50 && !lastSentLong){
keyPressNum++;
            device->sendKeyEvent(channel,keyPressNum, false);
};
keyPressedMillis = 0;
};
}else{
// Taste gedrueckt
// Taste war vorher schon gedrueckt
if(keyPressedMillis){
// muessen wir ein "long" senden?
if(lastSentLong) {   // schon ein LONG gesendet
if(now - lastSentLong >= 300){  // alle 300ms wiederholen
// keyPressNum nicht erhoehen
lastSentLong = now ? now : 1; // der Teufel ist ein Eichhoernchen
                    device->sendKeyEvent(channel,keyPressNum, true);  // long press
};
}else if(now - keyPressedMillis >= long(config->long_press_time) * 100) {
// erstes LONG
keyPressNum++;
lastSentLong = now ? now : 1;
                device->sendKeyEvent(channel,keyPressNum, true);  // long press
};
}else{
// Taste war vorher nicht gedrueckt
keyPressedMillis = now ? now : 1; // der Teufel ist ein Eichhoernchen
lastSentLong = 0;
}
}
}


Habe ich irgendwo einen Programmierfehler? Oder liegt es daran, dass ich die Anzahl der Aus-/Eingänge nicht größer machen kann, weil es einen Überlauf gibt oder die Feldgrößen nicht ausreichen?

Hat jmd eine Idee?

Herzlichen Dank,

Stephan

grogo

Hab noch ein wenig probiert und doch festgestellt, dass der Zustand long/short.press an die Zentrale übergeben wird.

aus HBWired.cpp  txFrameData[3] = (longPress ? 3 : 2) + (keyPressNum << 2);

Damit wird short/long im 15 Feld mit Bit 0 übergeben.

In den Bits 2-7 wird die Anzahl des Drückens des Kanals hochgezählt. Dann ist das Feld 15 im Datensatz auf dem Bus also doch kein Zeitstempel.

Hier dann das Beispiel vom 4/2 Modul. 4mal kurz gedrückt ein mal lang


R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:06:9E:4C
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:0A:5E:54
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:0E:1E:5C
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:12:CE:66
R: FD:FF:FF:FF:FF:F8:42:FF:FF:02:06:4B:05:00:17:9E:6C


Feld 15:
0x06 = 0001 10b (erste Mal gedrückt / kurz)
0x0A = 0010 10b (zweite Mal gedrückt / kurz)
0x0E = 0011 10b (dritte Mal gedrückt / kurz)
0x12 = 0100 10b (vierte Mal gedrückt / kurz)
0x17 = 0101 11b (zweite Mal gedrückt /lang)

Leider ist dies nicht bei dem 16/16 Modul so. Das Programm springt in die If-Abfrage in der HBWKey.cpp nicht in den Zweig für Long.press. Nur warum klappt es bei dem 4/2 Modul. An der HBWKey.cpp habe ich nichts verändert.




Thorsten Pferdekaemper

Hi,
wie schon vorher gesagt vermute ich, dass es an der long_press_time liegt. Probleme hier liegen meistens daran, dass die Gerätebeschreibungsdatei nicht mit der Definition der struct hbw_config zusammenpasst.
Das solltest Du mal überprüfen und dann in FHEM nachsehen, auf welchem Wert long_press_time sitzt.
Gruß,
   Thorsten
FUIP

grogo

Hi Thorsten,

danke für die Info.

Es lag wirklich an der Einstellung der long_press_time in der Zentrale. Dieser stand laut default aus der XML auf dem Wert 1.0. Im 4/2 Modul stand der Wert von Kanal 5 auf 1.0 und von Kanal 6 auf 0.5. Jetzt habe ich in den Einstellungen des 16/16 Moduls die Werte alle auf 0.5 genommen und jetzt klappt es mit long_press key.

Bei dem 4/2 Modul habe ich dann glücklicherweise den Kanal probiert, der auf 0.5 stand. Der Kanal 5 mit 1.0 geht bei mir auch nicht beim 4/2 Modul. Umgestellt auf 0.5 und es klappt.

Auszug aus der xml

...<!-- NEU: 16 Keys statt 1, Kanal 17-32, Adresse groesser, address_step korrigiert -->

<channel index="17" type="KEY" count="16" physical_index_offset="-1">
<paramset id="hmw_input_ch_master" type="MASTER" address_step="2" address_start="0x26">
<parameter id="LONG_PRESS_TIME">
<logical type="float" unit="s" default="0.5" max="5.0" min="0.4"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+1"/>
</physical>
<conversion type="float_integer_scale" factor="10"/>
<conversion type="integer_integer_map">
<value_map to_device="false" from_device="true" parameter_value="10" device_value="0xff"/>
</conversion>
</parameter>
</paramset>
...

Thorsten Pferdekaemper

Hi,
ich denke, dass es bei 1.0 gar nicht klappt liegt an folgendem: Die 1.0 sind im XML als Default eingestellt. (0xFF markiert ein "leeres" EEPROM. Das wird als 10 interpretiert, mit Faktor 10 ergibt das 1.0.) Im Sketch werden aber 0xFF nicht besonders behandelt, wodurch man wahrscheinlich 25.5 Sekunden lang drücken muss, bis das als langer Tastendruck erkannt wird.
Man muss also entweder mindestens einmal die Konfiguration von FHEM auf's Device schieben (durch eine Änderung, z.B. die 1.0 auf 0.5 ändern). ...oder man macht was im Sketch. Das geht wahrscheinlich am einfachsten, indem man nach dem new HBWDevice die Defaultwerte entsprechend setzt.
Alternativ kann man auch eine der afterReadConfig-Methoden redefinieren.
Gruß,
   Thorsten
FUIP