Software-Entprellen eines FRM_IN Eingangs

Begonnen von limats, 12 Januar 2014, 12:19:29

Vorheriges Thema - Nächstes Thema

limats

Hallo zusammen,

ich hab an meinem Arduino über ca. 8m Kabel diverse Relaisausgänge meiner Heizung angeschlossen.
Leider prellen die Relais sehr stark. Außerdem hab ich durch die lange Leitung im Kabelkanal neben diversen Starkstromleitungen jede Menge Störungen.
HW-Debouncing ist aufwendig und außerdem hab ich die Störungen damit auch nicht ganz weg bekommen.
Gibt es irgend eine Möglichkeit, das SW-mäßig mit der Firmata und dem FRM_IN Modul zu realisieren?
Also entweder in der Firmata selbst oder im Observer des FRM_IN Moduls?

Gruß
Leo
Fhem auf BBB:
HM-CFG-USB für div. HM-Sensoren, CUL+WMBUS für EnergyCam, Nanocul für IT, Arduino Mega 2560 als 1-wire-Gateway und für div. digitale Ein-/Ausgänge, Volkszähler-USB-IR-Lesekopf mit SMLUSB, Solarsteuerung über VBUS

ntruchsess

das ist bislang noch nicht drin. Perlseitig wäre es leichter einzubauen. Firmataseitig wäre es sinnvoller, weil es sinnlose Kommunikation vermeiden würde.

Gruß,
Norbert
while (!asleep()) {sheep++};

limats

Hallo Norbert,

wär es für dich machbar, so etwas einzubauen? Würde mich auch gerne als Tester zur Verfügung stellen.
Oder hättest du einen Tipp für mich, wie man das in deinen Perl-Code einbauen könnte? Dann könnte ich mich selbst daran versuchen. Meine erste Idee mit einem Sleep in der Observer-Methode (ähnlich der Debounce-Funktionalität in RPI_GPIO) funktioniert hier glaub nicht, weil die Nachrichten von der Firmata ja auch während der Wartezeit auflaufen und vermutlich danach abgearbeitet werden.

Gruß
Leo
Fhem auf BBB:
HM-CFG-USB für div. HM-Sensoren, CUL+WMBUS für EnergyCam, Nanocul für IT, Arduino Mega 2560 als 1-wire-Gateway und für div. digitale Ein-/Ausgänge, Volkszähler-USB-IR-Lesekopf mit SMLUSB, Solarsteuerung über VBUS

justme1968

das auf firmata seite zu machen hatte ich auch schon mal vorgeschlagen :)

es ist recht einfach das bis dahin hard codiert selber zu machen. ich hatte das auf die schnelle mit der arduino Bounce lib gemacht. so lange du nicht die pins dynamisch konfigurieren willst kannst du einfach in DigitalInputFirmata.cpp die Bounce.h includen, für jeden pin den du enprellen wllst ein bounce objekt anlegen und dann in report() statt readPort(...) zu verwenden die rückgabe aus den einzelnen bounce.read() zu verknüpfen.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

pula

@justme: hast du dazu evtl ein beispiel bzw fertiges ino?
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

justme1968

nein. sorry. ich hatte das nicht weiter verfolgt.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

limats

#6
Hallo,

hab das bei mir mittlerweile sehr lange so am laufen:


/*
  DigitalInputFirmata.h - Firmata library
  Copyright (C) 2006-2008 Hans-Christoph Steiner.  All rights reserved.
  Copyright (C) 2010-2011 Paul Stoffregen.  All rights reserved.
  Copyright (C) 2009 Shigeru Kobayashi.  All rights reserved.
  Copyright (C) 2009-2011 Jeff Hoefs.  All rights reserved.
  Copyright (C) 2013 Norbert Truchsess. All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  See file LICENSE.txt for further informations on licensing terms.
*/

#ifndef DigitalInputFirmata_h
#define DigitalInputFirmata_h

#include <Firmata.h>
#include <utility/FirmataFeature.h>
#include Bounce2.h

void reportDigitalInputCallback(byte port, int value);

class DigitalInputFirmata:public FirmataFeature
{
public:
  DigitalInputFirmata();
  void reportDigital(byte port, int value);
  void report(void);
  void handleCapability(byte pin);
  boolean handleSysex(byte command, byte argc, byte* argv);
  boolean handlePinMode(byte pin, int mode);
  void reset();

private:
  /* digital input ports */
  byte reportPINs[TOTAL_PORTS];       // 1 = report this port, 0 = silence
  byte previousPINs[TOTAL_PORTS];     // previous 8 bits sent

  /* pins configuration */
  byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
  void outputPort(byte portNumber, byte portValue, byte forceSend);

  /* debounce */
  Bounce bouncePINs[TOTAL_PORTS];
};

#endif



/*
  DigitalInputFirmata.cpp - Firmata library
  Copyright (C) 2006-2008 Hans-Christoph Steiner.  All rights reserved.
  Copyright (C) 2010-2011 Paul Stoffregen.  All rights reserved.
  Copyright (C) 2009 Shigeru Kobayashi.  All rights reserved.
  Copyright (C) 2009-2011 Jeff Hoefs.  All rights reserved.
  Copyright (C) 2013 Norbert Truchsess. All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  See file LICENSE.txt for further informations on licensing terms.
*/

#include <Firmata.h>
#include <DigitalInputFirmata.h>
#include Bounce2.h

DigitalInputFirmata *DigitalInputFirmataInstance;

void reportDigitalInputCallback(byte port, int value)
{
  DigitalInputFirmataInstance->reportDigital(port,value);
}

DigitalInputFirmata::DigitalInputFirmata()
{
  DigitalInputFirmataInstance = this;
  Firmata.attach(REPORT_DIGITAL, reportDigitalInputCallback);
  for (byte i=0; i < TOTAL_PORTS; i++) {
    bouncePINs[i] = Bounce();
    if (i >= 2 && i <= 4) {
      bouncePINs[i].attach(i);
      bouncePINs[i].interval(100);
      bouncePINs[i].update();
    }
  } 
}

boolean DigitalInputFirmata::handleSysex(byte command, byte argc, byte* argv)
{
  return false;
}

void DigitalInputFirmata::outputPort(byte portNumber, byte portValue, byte forceSend)
{
  // pins not configured as INPUT are cleared to zeros
  portValue = portValue & portConfigInputs[portNumber];
  // only send if the value is different than previously sent
  if(forceSend || previousPINs[portNumber] != portValue) {
    Firmata.sendDigitalPort(portNumber, portValue);
    previousPINs[portNumber] = portValue;
  }
}

/* -----------------------------------------------------------------------------
* check all the active digital inputs for change of state, then add any events
* to the Serial output queue using Serial.print() */
void DigitalInputFirmata::report(void)
{
  /* Using non-looping code allows constants to be given to readPort().
   * The compiler will apply substantial optimizations if the inputs
   * to readPort() are compile-time constants. */
  if (TOTAL_PORTS > 0 && reportPINs[0]) {
        byte bitmask = portConfigInputs[0];
unsigned char out=0, pin=port*8;
if (IS_PIN_DIGITAL(pin+0) && (bitmask & 0x01) && digitalRead(PIN_TO_DIGITAL(pin+0))) out |= 0x01;
if (IS_PIN_DIGITAL(pin+1) && (bitmask & 0x02) && digitalRead(PIN_TO_DIGITAL(pin+1))) out |= 0x02;
if (IS_PIN_DIGITAL(pin+2) && (bitmask & 0x04) {
          bouncePINs[2].update();
          if (bouncePINs[2].read()) out |= 0x04;
        }
if (IS_PIN_DIGITAL(pin+3) && (bitmask & 0x08) {
          bouncePINs[3].update();
          if (bouncePINs[3].read()) out |= 0x08;
        }
if (IS_PIN_DIGITAL(pin+4) && (bitmask & 0x10) {
          bouncePINs[4].update();
          if (bouncePINs[4].read()) out |= 0x10;
        }
if (IS_PIN_DIGITAL(pin+5) && (bitmask & 0x20) && digitalRead(PIN_TO_DIGITAL(pin+5))) out |= 0x20;
if (IS_PIN_DIGITAL(pin+6) && (bitmask & 0x40) && digitalRead(PIN_TO_DIGITAL(pin+6))) out |= 0x40;
if (IS_PIN_DIGITAL(pin+7) && (bitmask & 0x80) && digitalRead(PIN_TO_DIGITAL(pin+7))) out |= 0x80;
outputPort(0, out, false);
  if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
  if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
  if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
  if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
  if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
  if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
  if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
  if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
  if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
  if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
  if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
  if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
  if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
  if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}

void DigitalInputFirmata::reportDigital(byte port, int value)
{
  if (port < TOTAL_PORTS) {
    reportPINs[port] = (byte)value;

    if (value) outputPort(port, readPort(port, portConfigInputs[port], true);
  }
  // do not disable analog reporting on these 8 pins, to allow some
  // pins used for digital, others analog.  Instead, allow both types
  // of reporting to be enabled, but check if the pin is configured
  // as analog when sampling the analog inputs.  Likewise, while
  // scanning digital pins, portConfigInputs will mask off values from any
  // pins configured as analog
}

boolean DigitalInputFirmata::handlePinMode(byte pin, int mode)
{
  if (IS_PIN_DIGITAL(pin)) {
    if (mode == INPUT) {
      portConfigInputs[pin/8] |= (1 << (pin & 7));
      pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
      digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
      return true;
    } else {
      portConfigInputs[pin/8] &= ~(1 << (pin & 7));
    }
  }
  return false;
}

void DigitalInputFirmata::handleCapability(byte pin)
{
  if (IS_PIN_DIGITAL(pin)) {
    Firmata.write((byte)INPUT);
    Firmata.write(1);
  }
}

void DigitalInputFirmata::reset()
{
  for (byte i=0; i < TOTAL_PORTS; i++) {
    reportPINs[i] = false;      // by default, reporting off
    portConfigInputs[i] = 0;    // until activated
    previousPINs[i] = 0;
  }
}


Ist aber natürlich alles hart codiert. Wäre super, wenn man das irgendwie sauber in die Firmata einbauen könnte. Aber dazu bin ich zuwenig drin.

Gruß
Leo
Fhem auf BBB:
HM-CFG-USB für div. HM-Sensoren, CUL+WMBUS für EnergyCam, Nanocul für IT, Arduino Mega 2560 als 1-wire-Gateway und für div. digitale Ein-/Ausgänge, Volkszähler-USB-IR-Lesekopf mit SMLUSB, Solarsteuerung über VBUS

pula

#7
Hi,

super, vielen Dank, das klingt sehr vielversprechend.
Leider bekomme ich folgende Fehler beim compilieren:
DigitalInputFirmata.cpp:68:27: error: 'port' was not declared in this scope
  unsigned char out=0, pin=port*8;
DigitalInputFirmata.cpp:71:48: error: expected ')' before '{' token
  if (IS_PIN_DIGITAL(pin+2) && (bitmask & 0x04) {
                                                ^
DigitalInputFirmata.cpp:105:1: error: a function-definition is not allowed here before '{' token
{
^
DigitalInputFirmata.cpp:149:1: error: expected '}' at end of input
}


Ich habe das gegen die aktuelle Bounce2 gebaut. Kann das sein, daß Du noch eine ältere Version hast und sich was geändert hat?
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

pula

#8
Hi,

ich versuche, die Frage anders zu formulieren.
Kann mir bitte jemand sagen, was hier
unsigned char out=0, pin=port*8;
port zu bedeuten hat bzw. wo das herkommt?

Hier wird ja port definiert:
void DigitalInputFirmata::reportDigital(byte port, int value)

allerdings nicht hier, was dann den Fehler verursacht:
void DigitalInputFirmata::report(void)

Ich würde den code gerne verstehen, um das dann irgendwie zum Laufen zu bringen, da ich das Teil wirklich dringend brauche...

Danke im voraus!
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

pula

#9
Niemand? Soweit ich das gesehen habe, hat es irgendwann 2012 oder so hier Änderungen in der firmata gegeben?
@limats: Wärst Du möglicherweise so nett und würdest die entsprechenden Files, die bei dir compilieren, zur Verfügung stellen?

Ach ja: sorry, wenn ich ein wenig nervig sein sollte, aber das ist für mich echt wichtig (Abschluß vom Umbau)....
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

pula

Ich antworte mir mal selbst - habe ein wenig weitergemacht und meine sehr verstaubten C-Kenntnisse hervorgekramt.
So bekomme ich zumindest mal keinen error beim builden mehr:

/*
  DigitalInputFirmata.cpp - Firmata library
  Copyright (C) 2006-2008 Hans-Christoph Steiner.  All rights reserved.
  Copyright (C) 2010-2011 Paul Stoffregen.  All rights reserved.
  Copyright (C) 2009 Shigeru Kobayashi.  All rights reserved.
  Copyright (C) 2009-2011 Jeff Hoefs.  All rights reserved.
  Copyright (C) 2013 Norbert Truchsess. All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  See file LICENSE.txt for further informations on licensing terms.
*/

#include <Firmata.h>
#include "DigitalInputFirmata.h"
#include <Bounce2.h>

DigitalInputFirmata *DigitalInputFirmataInstance;

void reportDigitalInputCallback(byte port, int value)
{
  DigitalInputFirmataInstance->reportDigital(port,value);
}

DigitalInputFirmata::DigitalInputFirmata()
{
  DigitalInputFirmataInstance = this;
  Firmata.attach(REPORT_DIGITAL, reportDigitalInputCallback);
  for (byte i=0; i < TOTAL_PORTS; i++) {
    bouncePINs[i] = Bounce();
    if (i >= 2 && i <= 4) {
      bouncePINs[i].attach(i);
      bouncePINs[i].interval(100);
      bouncePINs[i].update();
    }
  }
}

boolean DigitalInputFirmata::handleSysex(byte command, byte argc, byte* argv)
{
  return false;
}

void DigitalInputFirmata::outputPort(byte portNumber, byte portValue, byte forceSend)
{
  // pins not configured as INPUT are cleared to zeros
  portValue = portValue & portConfigInputs[portNumber];
  // only send if the value is different than previously sent
  if(forceSend || previousPINs[portNumber] != portValue) {
    Firmata.sendDigitalPort(portNumber, portValue);
    previousPINs[portNumber] = portValue;
  }
}

/* -----------------------------------------------------------------------------
* check all the active digital inputs for change of state, then add any events
* to the Serial output queue using Serial.print() */
void DigitalInputFirmata::report(void)
{
  /* Using non-looping code allows constants to be given to readPort().
   * The compiler will apply substantial optimizations if the inputs
   * to readPort() are compile-time constants. */
  byte bitmask = portConfigInputs[0];
  unsigned char out=0;
  if ((IS_PIN_DIGITAL(0)) && (bitmask & 0x01)) {
          bouncePINs[0].update();
          if (bouncePINs[0].read()) out |= 0x01;
        }
  if ((IS_PIN_DIGITAL(1)) && (bitmask & 0x02)) {
          bouncePINs[0].update();
          if (bouncePINs[1].read()) out |= 0x02;
        }
  if ((IS_PIN_DIGITAL(2)) && (bitmask & 0x04)) {
          bouncePINs[2].update();
          if (bouncePINs[2].read()) out |= 0x04;
        }
  if ((IS_PIN_DIGITAL(3)) && (bitmask & 0x08)) {
          bouncePINs[3].update();
          if (bouncePINs[3].read()) out |= 0x08;
        }
  if ((IS_PIN_DIGITAL(4)) && (bitmask & 0x10)) {
          bouncePINs[4].update();
          if (bouncePINs[4].read()) out |= 0x10;
        }
  if ((IS_PIN_DIGITAL(5)) && (bitmask & 0x20)) {
          bouncePINs[5].update();
          if (bouncePINs[5].read()) out |= 0x20;
        }
  if ((IS_PIN_DIGITAL(6)) && (bitmask & 0x40)) {
          bouncePINs[6].update();
          if (bouncePINs[6].read()) out |= 0x40;
        }
  if ((IS_PIN_DIGITAL(7)) && (bitmask & 0x80)) {
          bouncePINs[7].update();
          if (bouncePINs[7].read()) out |= 0x80;
        }
  outputPort(0, out, false);
  Serial.println(out);
  if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
  if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
  if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
  if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
  if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
  if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
  if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
  if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
  if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
  if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
  if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
  if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
  if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
  if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
  if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}

void DigitalInputFirmata::reportDigital(byte port, int value)
{
  if (port < TOTAL_PORTS) {
    reportPINs[port] = (byte)value;
    if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
  }
  // do not disable analog reporting on these 8 pins, to allow some
  // pins used for digital, others analog.  Instead, allow both types
  // of reporting to be enabled, but check if the pin is configured
  // as analog when sampling the analog inputs.  Likewise, while
  // scanning digital pins, portConfigInputs will mask off values from any
  // pins configured as analog
}

boolean DigitalInputFirmata::handlePinMode(byte pin, int mode)
{
  if (IS_PIN_DIGITAL(pin)) {
    if (mode == INPUT) {
      portConfigInputs[pin/8] |= (1 << (pin & 7));
      pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
      digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
      return true;
    } else {
      portConfigInputs[pin/8] &= ~(1 << (pin & 7));
    }
  }
  return false;
}

void DigitalInputFirmata::handleCapability(byte pin)
{
  if (IS_PIN_DIGITAL(pin)) {
    Firmata.write((byte)INPUT);
    Firmata.write(1);
  }
}

void DigitalInputFirmata::reset()
{
  for (byte i=0; i < TOTAL_PORTS; i++) {
    reportPINs[i] = false;      // by default, reporting off
    portConfigInputs[i] = 0;    // until activated
    previousPINs[i] = 0;
  }
}


Funktionieren tut es leider trotzdem noch nicht...
In meinem Verständnis sollten doch so die PINs 0-7 debounced werden, oder?
Kann mir jemand verraten, wie hier die Zählweise der PINs ist bitte????
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

pula

#11
Ich schreib mal wieder in der Hoffnung, daß mir vielleicht doch jemand weiterhelfen kann...  :o

mit diesem Code funktioniert zumindest Pin 2 - die anderen allerdings nicht. Firmata ist irgendwie auch schwer zu debuggen *grmpf*
Um irgendwelche Fehler in den Prüfungen der Konfiguration auszuschließen, habe ich bei Pin 3 einmal die Prüfung herausgenommen, ob er als DigitalOut definiert ist, hat leider auch nichts gebracht.... Habe zum testen auch mal den Pin3 vor Pin2 in den Code gegeben, um hier ebenfalls Fehler auszuschließen. Leider auch ein Schuß in den Ofen....
An der Hardware kanns auch nicht liegen, mit den Original-Files tut alles (aber prellt halt)....

Außer Pin2 meldet kein Pin richtig an fhem zurück. Der aktuelle Code-Schnipsel:
void DigitalInputFirmata::report(void)
{
  /* Using non-looping code allows constants to be given to readPort().
   * The compiler will apply substantial optimizations if the inputs
   * to readPort() are compile-time constants. */
  if (TOTAL_PORTS > 0 && reportPINs[0]) {
byte bitmask = portConfigInputs[0];
unsigned char out=0;
if (IS_PIN_DIGITAL(0) && (bitmask & 0x01) && digitalRead(PIN_TO_DIGITAL(0))) out |= 0x01;
if (IS_PIN_DIGITAL(1) && (bitmask & 0x02) && digitalRead(PIN_TO_DIGITAL(1))) out |= 0x02;
//        if (IS_PIN_DIGITAL(3)) {
          bouncePINs[3].update();
//   if (bouncePINs[3].update() && (bouncePINs[3].read() == HIGH)) bitSet(out,3);
          if (bouncePINs[3].read()) bitSet(out,3);
//        }
        if (IS_PIN_DIGITAL(2)) {
          bouncePINs[2].update();
          if (bouncePINs[2].read()) bitSet(out,2);
        }
if (IS_PIN_DIGITAL(5)) {
          bouncePINs[5].update();
          if (bouncePINs[5].read()) bitSet(out,5);
        }
if (IS_PIN_DIGITAL(6)) {
          bouncePINs[6].update();
          if (bouncePINs[6].read()) bitSet(out,6);
        }
if (IS_PIN_DIGITAL(7) && (bitmask & 0x80) && digitalRead(PIN_TO_DIGITAL(7))) out |= 0x80;
outputPort(0, out, false);
  }
  if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
  if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
  if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
  if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
  if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
  if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
  if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
  if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
  if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
  if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
  if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
  if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
  if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

limats

Hallo,

Sorry, bin über Weihnachten nicht wirklich zum Lesen vom Forum gekommen.
Im Code von mir wird der Debounce-Mechanismus für die Pins 2 bis 4 eingeschaltet.
Ich verwende derzeit nur diese Pins am Arduino Mega als Digitale Eingänge. Die anderen Pins sind entweder Ausgänge oder 1-wire Ports.
Kann gut sein, dass das so nur in meiner Konstellation funktioniert.
Hab leider gerade keinen Zugriff auf meinen Rechner. Wenn ich wieder rankomme, werd ich versuchen, mal den gesamten Sketch rauszusuchen.
Ist alles schon ganz schön lang her...

Leo
Fhem auf BBB:
HM-CFG-USB für div. HM-Sensoren, CUL+WMBUS für EnergyCam, Nanocul für IT, Arduino Mega 2560 als 1-wire-Gateway und für div. digitale Ein-/Ausgänge, Volkszähler-USB-IR-Lesekopf mit SMLUSB, Solarsteuerung über VBUS

pula

Hi,

das wäre super, wenn Du Dir das mal ansehen könntest.

Habe eigentlich auch die Initialisierung auch angepasst, von daher denke ich, daß das Debouncing auch für alle Pins eingeschaltet sein sollte:

DigitalInputFirmata::DigitalInputFirmata()
{
  DigitalInputFirmataInstance = this;
  Firmata.attach(REPORT_DIGITAL, reportDigitalInputCallback);
  for (byte i=2; i < 7; i++) {
    bouncePINs[i] = Bounce();
    bouncePINs[i].attach(i);
    bouncePINs[i].interval(100);
    }
}


An dem UNO soll eigentlich momentan eh nichts dranhängen außer vier entprellte Taster. Der einen, der funktioniert (Pin2) tut auch wirklich prächtig, kein Prellen und vor allem keine "Fehlzündungen" - bei den anderen ist das leider nicht so und so geht immer mal wieder ein Licht an, das eigentlich aus bleiben sollte....

lg

Pula
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

pula

Hi,

ein Freund hat mich auf die Idee gebracht (und mir ein entsprechendes Code-Beispiel geschickt), den Taster "per Hand" zu entprellen.
Es scheint jetzt zu funktionieren (ohne Bounce2).
Danke auch an limats, der dafür die Grundlage geliefert hat :-)

Hier die entsprechenden Code-Teile, falls die mal jemand brauchen kann:

DigitalInput.cpp:
DigitalInputFirmata::DigitalInputFirmata()
{
  DigitalInputFirmataInstance = this;
  Firmata.attach(REPORT_DIGITAL, reportDigitalInputCallback);
  for (byte i=2; i < 7; i++) {
    oldPIN[i] = LOW;
    lastMillis[i] = 0;
    }
}

und
void DigitalInputFirmata::report(void)
{
  /* Using non-looping code allows constants to be given to readPort().
   * The compiler will apply substantial optimizations if the inputs
   * to readPort() are compile-time constants. */
  uint32_t minDelay = 100;
  uint32_t currMillis;
  bool currPIN;
  byte out;
  out =readPort(0, portConfigInputs[0]);
  if (TOTAL_PORTS > 0 && reportPINs[0]) {
byte bitmask = portConfigInputs[0];
        currMillis = millis();
if (IS_PIN_DIGITAL(0) && (bitmask & 0x01) && digitalRead(PIN_TO_DIGITAL(0))) out |= 0x01;
if (IS_PIN_DIGITAL(1) && (bitmask & 0x02) && digitalRead(PIN_TO_DIGITAL(1))) out |= 0x02;
       
        if (IS_PIN_DIGITAL(2)) {       
  currPIN = digitalRead(PIN_TO_DIGITAL(2));
        if (currMillis - lastMillis[2] > minDelay) {
             lastMillis[2] = currMillis;
     if ((currPIN != oldPIN[2])) {
        // zustandaenderung
if bitRead(out,2) {
      bitSet(out,2);
}
else {
  bitClear(out,2);
}
             }
         oldPIN[2] = currPIN;
          }
        }
        if (IS_PIN_DIGITAL(3)) {       
  currPIN = digitalRead(PIN_TO_DIGITAL(3));
        if ( currMillis - lastMillis[3] > minDelay) {
             lastMillis[3] = currMillis;
     if ((currPIN != oldPIN[3])) {
        // zustandaenderung
if bitRead(out,3) {
      bitSet(out,3);
}
else {
  bitClear(out,3);
}
             }
         oldPIN[3] = currPIN;
          }
        }
        if (IS_PIN_DIGITAL(6)) {       
  currPIN = digitalRead(PIN_TO_DIGITAL(6));
        if ( currMillis - lastMillis[6] > minDelay) {
             lastMillis[6] = currMillis;
     if ((currPIN != oldPIN[6])) {
        // zustandaenderung
if bitRead(out,6) {
      bitSet(out,6);
}
else {
  bitClear(out,6);
}
             }
         oldPIN[6] = currPIN;
          }
        }
        if (IS_PIN_DIGITAL(7)) {       
  currPIN = digitalRead(PIN_TO_DIGITAL(7));
        if ( currMillis - lastMillis[7] > minDelay) {
             lastMillis[7] = currMillis;
     if ((currPIN != oldPIN[7])) {
        // zustandaenderung
if bitRead(out,7) {
      bitSet(out,7);
}
else {
  bitClear(out,7);
}
             }
         oldPIN[7] = currPIN;
          }
        }
outputPort(0, out, false);
  }
  if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
  if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
  if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
  if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
  if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
  if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
  if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
  if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
  if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
  if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
  if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
  if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
  if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}


Und die entsprechende Definition in DigitalInput.h:
  /* debounce */
  uint32_t lastMillis[TOTAL_PORTS];
  bool oldPIN[TOTAL_PORTS];


Aus einem Grund, den ich noch nicht herausgefunden habe, funktioniert das bei mir mit Pin 5 nicht, daher habe ich den außen vor gelassen...

fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram