FHEM Forum

FHEM => Sonstiges => Thema gestartet von: limats am 12 Januar 2014, 12:19:29

Titel: Software-Entprellen eines FRM_IN Eingangs
Beitrag von: limats am 12 Januar 2014, 12:19:29
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
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: ntruchsess am 12 Januar 2014, 14:55:08
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
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: limats am 12 Januar 2014, 23:39:07
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
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: justme1968 am 13 Januar 2014, 00:04:55
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
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 23 Dezember 2015, 21:44:17
@justme: hast du dazu evtl ein beispiel bzw fertiges ino?
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: justme1968 am 23 Dezember 2015, 22:07:11
nein. sorry. ich hatte das nicht weiter verfolgt.

gruss
  andre
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: limats am 23 Dezember 2015, 22:47:43
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
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 24 Dezember 2015, 16:24:08
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?
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 28 Dezember 2015, 08:51:36
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!
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 28 Dezember 2015, 18:04:08
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)....
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 28 Dezember 2015, 20:54:56
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????
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 30 Dezember 2015, 16:37:19
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);
}
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: limats am 30 Dezember 2015, 22:27:52
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
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 31 Dezember 2015, 14:53:25
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
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 31 Dezember 2015, 17:49:10
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...

Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: pula am 07 Januar 2016, 19:20:56
Hallo,

falls es jemanden interessieren sollte (bzw. mal irgendwann jemand das gleiche Problem wie ich haben sollte).
Da mit der Lösung aus dem letzten Posting leider die "Phantom-Auslösungen" noch immer nicht behoben waren (mit der bounce2 aber schon), bin ich gemeinsam mit einem Freund der Sache auf den Grund gegangen und wir haben herausgefunden, warum ein Arduino überfordert war.

Durch den Code
Bounce bouncePIN[TOTAL_PORTS] in DigitalInputFirmata.h
wird für jeden Pin des Arduino ein Bounce-Objekt instanziert, was das Ding offenbar überfordert (mit einem Mega hingegen funktioniert die Sache).

Wie haben den Code nun folgendermaßen angepasst:
Bounce bouncePIN[8]

Und in der DigitalFirmata.cpp entsprechend:
DigitalInputFirmata::DigitalInputFirmata()
{

  DigitalInputFirmataInstance = this;
  Firmata.attach(REPORT_DIGITAL, reportDigitalInputCallback);
  for (byte i=0; i < 8 /*TOTAL_PORTS*/; i++) {
    if (i >= 2 && i <= 7) {
      //bouncePIN[i] = Bounce();
      bouncePIN[i].attach(i);
      bouncePIN[i].interval(100);
      bouncePIN[i].update();
    }
  }
}
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)) {
          bouncePIN[3].update();
  if (bouncePIN[3].update() && (bouncePIN[3].read() == HIGH)) bitSet(out,3);
          if (bouncePIN[3].read()) bitSet(out,3);
        }
        if (IS_PIN_DIGITAL(2)) {
          bouncePIN[2].update();
          if (bouncePIN[2].read()) bitSet(out,2);
        }
if (IS_PIN_DIGITAL(5)) {
          bouncePIN[5].update();
          if (bouncePIN[5].read()) bitSet(out,5);
        }
if (IS_PIN_DIGITAL(6)) {
          bouncePIN[6].update();
          if (bouncePIN[6].read()) bitSet(out,6);
        }
if (IS_PIN_DIGITAL(7)) {
          bouncePIN[7].update();
          if (bouncePIN[7].read()) bitSet(out,7);
        }
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);
}


Damit ist seit gestern Ruhe, ich hatte an momentan zwei angeschlossenen Tastern keine einzige "Phantom-Auslösung" und die Taster sind sauber entprellt. War mir lieber als das in Hardware zu machen ;-)

Cheers,

Pula
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: tresa am 21 Januar 2016, 22:49:42
Hallo,
ich würde deinen Code gerne verwenden aber leider funktioniert das bei mir nicht so richtig. Ich habe die Eingänge an einem Arduino Mega an den PINs 22 bis 32 angeschlossen. Muss ich da an deinem Code noch was anpassen? Hier?


  for (byte i=0; i < 8 /*TOTAL_PORTS*/; i++) {
    if (i >= 2 && i <= 7) {


Danke für deine Hilfe.
Grüße
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: ckreuzer am 27 April 2016, 18:20:16
Hallo,
ich habe einen Arduino Mega als reines Input Device, d.h. sämmtliche Ports von 2 bis 69 sollen als DigitalInput verwendet werden.
Derzeit behelfe ich mir mit attr <TASTER> event-min-interval reading:0.1
Das funktioniert eigentlich relativ gut.
Allerdings ist man da von "Geistereffekten" nicht gefeilt.
Mit der Bounc2 Library habe ich nun versucht sämmtliche Ports mittels Bounce zu entprellen.
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;
    for (byte i=2; i < TOTAL_PORTS; i++)
{
      bouncePINs[i].update();
      if (bouncePINs[i].read()) bitSet(out,i);
}
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);
}

Das funktioniert allerdings anscheinend nur für die ersten Pins.
Andere Pins werden nicht entprellt bzw. derDigitalInput funktioniert gar nicht mehr (z.B. Pin 16-19)
Ich würde hier dringend Hilfe benötigen, da meine Programmierkenntnisse nicht wirklich die besten sind und ich da nicht mehr weiterkomme.
(Ich verstehe die Funktionsweise des Arduino auch zu wenig)

Danke &lg
Christian
Titel: Antw:Software-Entprellen eines FRM_IN Eingangs
Beitrag von: ckreuzer am 18 Mai 2016, 12:55:33
 HAllo,
ein kurzes Update:
Zum Glück habe ich eine kleine Schwester die programmieren kann.
Bei mir sind die Geistereffekte nun schon ein paar Tage weg.
(ca. 60 Taster wurden auf einem Arduino Mega entprellt)
Die dazugehörigen Änderungen (falls es jemand brauchen kann):
/*
  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
#define TIMES_TO_WAIT 5
#include <Firmata.h>
#include "FirmataFeature.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
  byte timePINs[TOTAL_PORTS];     // Timing Pins

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

#endif

Und:
/*
  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"

DigitalInputFirmata *DigitalInputFirmataInstance;

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

DigitalInputFirmata::DigitalInputFirmata()
{
  DigitalInputFirmataInstance = this;
  Firmata.attach(REPORT_DIGITAL, reportDigitalInputCallback);
}

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];
 
  if(!forceSend)
  {
  if(previousPINs[portNumber] != portValue)
  {
//Änderung des Signals

if(timePINs[portNumber] == (TIMES_TO_WAIT + 1))
{
//vorheriges Signal wurde gesendet -->
//dieses Signal eventuell auch senden
timePINs[portNumber] = 1;
}
else
{
//vorheriges Signal wurde nicht gesendet -->
//dieses Signal als gesendet setzen
timePINs[portNumber] = TIMES_TO_WAIT + 1;
}
previousPINs[portNumber] = portValue;
  }
  else
  {
if (timePINs[portNumber] < TIMES_TO_WAIT)
timePINs[portNumber] = timePINs[portNumber] + 1;
  }
  }
 
  if(forceSend || timePINs[portNumber] == TIMES_TO_WAIT)
  {
    //Signal senden
    Firmata.sendDigitalPort(portNumber, portValue);
    //Zeichen, dass Signal gesendet wurde
    timePINs[portNumber] = TIMES_TO_WAIT +1;
  }
}

/* -----------------------------------------------------------------------------
* 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. */
   /*for (byte i=0; i < TOTAL_PORTS; i++) {
   if (reportPINs[i]) outputPort(i, readPort(i, portConfigInputs[i]), false);
   }*/
  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;
timePINs[i] = TIMES_TO_WAIT + 1;
  }
}



Viele Grüße

Christian