Go Down

Topic: Bounce (and Bounce 2) Library Official Question Forum (Read 48129 times) previous topic - next topic

tof

Well, the code in red is inside another if statement.
If I remember correctly, the first if checks for stability. It does not change the actual state (HIGH/LOW).
The third if resets the conter and sets the actual state (HIGH/LOW).
Thomas Ouellet Fredericks

windy1023

#76
Jul 25, 2018, 03:34 pm Last Edit: Jul 25, 2018, 04:24 pm by windy1023
The first if checks if the actual reading is different from the last reading, if it is different due to noise or pressing or releasing, the code will reset the counter and toggle the value of the last reading for the next comparison, so it won't change the actual state --> correct

If the actual reading is equal to the last reading and if the stability duration is longer than the threshold time, then the third if will check if the actual reading is different from the actual state, if so, it will reset the counter and toggle the actual state

The question is, I don't find the impact if we don't reset the counter in the third if. Because if we want to change the actual state, we need:
 - actual reading = last reading
 - the duration >= threshold time
 - actual reading != actual state

and we will have this as result:
 - actual reading = last reading = new state

So if there is any new change in the next reading, we can't bypass the first if, therefore the third if won't be an issue if we don't reset the counter inside

tlipinski

#77
Sep 11, 2018, 09:50 pm Last Edit: Sep 11, 2018, 10:48 pm by tlipinski
Hi! Does anyone have example of extending readCurrentState() and setPinMode() methods? I need to debounce buttons connected through PCF8574 expander however I have trouble with all this inheritance stuff in c++.

I tried to extend Bounce class with ExpanderBounce having constructor with additional parameter representing expander which I need to use in readCurrentState() and setPinMode() methods:

Code: [Select]

#include <Wire.h>
#include <PCF8574.h>
#include <Bounce2.h>
#include "ExpanderBounce.h"

PCF8574 expander;

ExpanderBounce debouncer1 = ExpanderBounce(expander);

void setup() {
  Serial.begin(9600);
  expander.begin(0x20);

  Serial.println("before attach");
  debouncer1.attach(0, INPUT_PULLUP); //0 is expander's data pin
  Serial.println("after attach");

  debouncer1.interval(5);
}

void loop() {
  debouncer1.update();
  if (debouncer1.fell()) {
    Serial.println("Button pressed");
  }
}


Code: [Select]

#include <Bounce2.h>
#include <PCF8574.h>

class ExpanderBounce : public Bounce {
  public:
    ExpanderBounce(PCF8574 e);

  protected:
    PCF8574 expander;
    virtual bool readCurrentState();
    virtual void setPinMode(int pin, int mode);
};


Code: [Select]

#include "ExpanderBounce.h"

ExpanderBounce::ExpanderBounce(PCF8574 e) : Bounce() {
  expander = e;
}

bool ExpanderBounce::readCurrentState() {
  Serial.println("readCurrentState");
  return expander.digitalRead(pin);
}

void ExpanderBounce::setPinMode(int pin, int mode) {
  Serial.println("setPinMode");
  expander.pinMode(pin, mode);
}


It compiles but after program starts it hangs in setup() and doesn't start loop(). On serial monitor I see only:
Code: [Select]

before attach
setPinMode
readCurrentState

and that's it. It won't print "after attach" line. Nothing else happens. No errors.



The expander is correctly set up. This is regular code for handling button presses through expander. It works perfectly fine with the same bread board set up, except button debouncing obviously:)
Code: [Select]

#include <Wire.h>
#include <PCF8574.h>

PCF8574 expander;

void setup() {
  Serial.begin(9600);
  expander.begin(0x20);
  expander.pinMode(0, INPUT_PULLUP); // pin 0 is expander's data pin
}

void loop() {
  if (expander.digitalRead(0) == LOW) {
    Serial.println("0 pressed");
  }
}


Any ideas?:)

Edit:
Arduino UNO R3
Bounce2 2.52.0

tlipinski

After debugging depper in libraries I finally solved this. My rusty C++ skills were the problem:) I think I now understand what was wrong.

C++ passes params by value so ExpanderBounce actually had copy of the expander instead of the instance I created line earlier. The line "expander.begin(0x20)" was simply initializing unused instance and the code was hanging somewhere in PCF8574 library trying to work with uninitialized expander... Fix was to pass it by reference.

Here's the correct code in a single file in case someone had similar issue:
Code: [Select]

#include <Wire.h>
#include <PCF8574.h>
#include <Bounce2.h>

class ExpanderBounce : public Bounce {
  public:
    ExpanderBounce(PCF8574 &e) {
      expander = &e;
    }

  protected:
    PCF8574 *expander;
    bool readCurrentState() {
      return expander->digitalRead(pin);
    }
    void setPinMode(int pin, int mode) {
      expander->pinMode(pin, mode);
    }
};

PCF8574 expander;
ExpanderBounce debouncer1 = ExpanderBounce(expander);


void setup() {
  Serial.begin(9600);
  expander.begin(0x20);

  Serial.println("before attach");
  debouncer1.attach(0, INPUT_PULLUP); //expander's pin 0
  Serial.println("after attach");

  debouncer1.interval(5);
}

void loop() {
  debouncer1.update();
  if (debouncer1.fell()) {
    Serial.println("Button pressed");
  }
}


tof

Hi, thanks for contributing. Mind if I had it in the examples for Bounce2?
Thomas Ouellet Fredericks

tlipinski


dfitterman

I have an application which controls a motor which opens and closes a mask, much like a pair of doors. The loop portion of the sketch has several phases of operation, so it is not reentered for as much as a few minutes. The individual phases of motor running are usually for a few seconds.

Control of the motor requires reading an encoder to determine the position of the mask and  limit switches to prevent physical damage to the apparatus. A generalization of the sketch is a follows:

Code: [Select]
#include "Bounce2.h"

// create debounced switch object
const int tSwitchPin = 7;
const uint16_t dbTime = 10;
Bounce tSwitch = Bounce();

// create encoder object
const int pinA = 1;
const int pinB = 2;
int posZero = 0;
MotorEncoder encoder(pinA, pinB, posZero);

int targetPos = 500;

setup() {
  //  setup tSwich line
  pinMode(tSwitchPin, INPUT_PULLUP);
  tSwitch.attach(tSwitchPin);
  tSwitch.interval(dbTime);
}

loop() {
  //  STUFF BEFORE MASK MOTION HERE { . . . }

  //  START MOTOR HERE

  //  update encoder
  encoder.update()

  //  update limit switch
  tSwitch.update(); //  <== THIS UPDATE IS OFTEN UNRELIABLE

  //  run motor until enocder position is reached or limit switch goes LOW
  while ( encoder.pos() < targetPos && tSwitch.read() == HIGH ) {
    // update encoder and switch
    encoder.update();
    tSwitch.update();
  }

  //  STOP MOTOR HERE

  //  STUFF AFTER MASK MOTION HERE { . . . }

}

The update of tSwitch before the while loop is often unreliable, with the state of the switch being reported incorrectly. This results in the motion being stopped almost immediately after it starts.

My work around was to add the following code for the first update to insure that enough time has elapsed for the switch to settle.
Code: [Select]
  uint16_t tStart;
  tStart = millis();
  while ( millis() - tStart  < dbTime ) {
    //  update tSwitch
    tSwitch.update();
  }

Can this sort of behavior be obtained with a feature already in Bounce2?

tof

Bounce needs to be updated as fast as possible. As a general rule, you should never delay or hold the execution of loop. Use variables as states inside loop() instead of using while loops or delays.
Thomas Ouellet Fredericks

mu234

Hello guys!

Is it possible to use attach on a veriable? For example, I am using the ledState, which changes very fast, but I want it under control, hence I am thinking to use the debouncer... namely rose and fall, anyway, will it workon veriable and no pin?

Best.

tof

No. It must be attached to a pin.

If you want to know if a variable "fell" or "rose" simply compare the new value to the previous value.

Without context it is hard to give you a better answer.

Thomas Ouellet Fredericks

jonatan_allan

Hello how can I use this library with the firm? I have 17 buttons, however they are of the momentary type and need to be on / off. In the example below we have a basic code where pin 13 receives a change in its state whenever there is an action of type fell (). My question is: How can I submit this change using the Firmata library?

Code: [Select]

// This example toggles the debug LED (pin 13) on or off
// when a button on pin 2 is pressed.
// Include the Bounce2 library found here :
// https://github.com/thomasfredericks/Bounce2
#include <Bounce2.h>
#define BUTTON_PIN 2
#define LED_PIN 13
int ledState = LOW;
Bounce debouncer = Bounce(); // Instantiate a Bounce object
void setup() {
  debouncer.attach(BUTTON_PIN,INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
  debouncer.interval(25); // Use a debounce interval of 25 milliseconds
  pinMode(LED_PIN,OUTPUT); // Setup the LED
  digitalWrite(LED_PIN,ledState);
}
void loop() {
   debouncer.update(); // Update the Bounce instance
   if ( debouncer.fell() ) {  // Call code if button transitions from HIGH to LOW
     ledState = !ledState; // Toggle LED state
     digitalWrite(LED_PIN,ledState); // Apply new LED state
   }
}

tof

Firmata is basically a closed system. AsciiMassage (can be downloaded from Arduino) is more flexible and includes examples of integration with Max, TouchDesigner and Processing in the extras\applications folder.
Thomas Ouellet Fredericks

Go Up