Firmata and debouncing

Hi all!

I am using fhem as controller and am using arduinos with firmata (ethernet) for controlling relays and check for button presses for my home automation.

Unfortunately I am having bouncing issues which I would like to resolve using Bounce2 - but my knowledge seems to be too weak for that :-( I am just trying to connect some buttons to pins 2-6 of an UNO.... In my understanding the following code (adapted from DigitalInput.cpp) should work, but unfortunately it does not :-( - this means, it does not report anything to fhem.... Maybe some of the chiefs have some hints for me?

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];
    byte 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(2) && (bitmask & 0x04)) {
          if (bouncePINs[2].update()) {
          if (bouncePINs[2].read() == HIGH) {
            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) && 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);
}

(Experimenting with pin 2).... Thanks in advance for any helpful hint!!!!!

Unfortunately I am having bouncing issues which I would like to resolve using Bounce2 - but my knowledge seems to be too weak for that :-(

You can't use libraries that require the Arduino to be more than a moron when you have loaded the moron (aka Firmata) sketch. Any debouncing has to be done by the program that is driving the moronic Arduino.

Hi,

thanks. But I dont need servo and so on. All this particular arduino should do is serve some inputs using firmata and debounce them. This should not be a problem for an UNO? Firmata is my choice because it is pretty well supported by fhem....

All this particular arduino should do is serve some inputs using firmata and debounce them.

It can't. Debouncing in software requires some intelligence. You've effectively lobotomized the Arduino by installing Firmata, so the other end of the serial connection needs to have the smarts to debounce the switches.

The alternative is to debounce with hardware.

Or, ditch Firmata and implement your own protocol.

Thank you!

Unfortunately it is not an option to implement my own protocol as I would also need to write the fhem part then.

I already have done some code with firmata and bounce2 which is working, unfortunately only for pin 2?! which I do not understand.

Maybe you would be so kind to have a closer look at it, maybe you can see what is wrong?

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);
    } 
}
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);
}

I just would need 4 debounced pins in this special case…
I am afraid, that hardware debouncing is a little bit above my horizon tough… :frowning:
@PaulS: it seems that you are not the biggest fan of firmata?

or even better: debouncing is not THE problem. the problem is that there are moreless random peaks and firmata sends button presses then (seems to be a problem of nearby power supplies or something.... those are the real problems as my home automation reacts and switches on lights or radiators.... I want the sketch to filter out peaks which are less then (for example) 50ms.... do you maybe know a solution for this?

Otto001,

When I need to debounce, I use the following very simple technique.

First, declare a variable at the global level. In setup(), set it to 0.

Asuuming you have a button attached to buttonPin, which drives that pin low when pushed, use the code shown below.

unsigned log later;

void setup() { ...

later = 0; }

void loop() { int data; ...

data = digitalRead(buttonPin);

if (data == LOW) and (millis() > later)) {

... //service the button push

later = millis() + 250; }

}

You can adjust the 250 ms. as needed for your equipment.

otto001: or even better: debouncing is not THE problem. the problem is that there are moreless random peaks and firmata sends button presses then (seems to be a problem of nearby power supplies or something.... those are the real problems as my home automation reacts and switches on lights or radiators.... I want the sketch to filter out peaks which are less then (for example) 50ms.... do you maybe know a solution for this?

Great. I'm glad you see that debouncing is not the problem - it is interference. So let's see if we can help you figure that one out. It is almost unheard of for simple switches to pick up interference so badly. So how about sharing some details of your hardware - schematics, photos and so on.

It's so much better than hobbling your input interface. It will be very sluggish and awkward with the filtering included.

When I need to debounce, I use the following very simple technique.

Nice idea, IF you control the sketch on the Arduino. Using Firmata, you do not.

OP: What is controlling the switches? You imply that some other application is sending messages to the Firmata sketch to make things happen. That does NOT involve humans pressing switches, which are the cause of bouncing.

I have a debounce library at github. You might be able to use the lower layer of that library - DebounceFilter - to accomplish what you want.

See DebounceFilter.