Olimex MODIO Debounce 4 inputs

Hello,

I am pretty new to arduino programing, and I stack at the very basic issue. So I have olimex modio plate with 4 digital inputs which are communicate with arduino threw I2C.
I manage to read the status of digital inputs, but I can not implement debounce function correctly.
If I use debounce like its written on arduino official function its work correctly, but as soon as I want to implement like functino and call it from loop i have problem because millis() and lastDebounce time are all the time the same.

Could you please give me guidance what I do wrong, because its very enoying I know where is problem, but I dont know how to fix it.

delay 2000 is just for debugging

Thank you for your help guys.

My code:

//The example turns on and off all relays of MOD-IO.
//It also reads and prints all digital inputs and all 
//analog inputs over the serial monitor

// Globalne knjiznice
#include <Wire.h>
#include <MOD_IO.h>



//////////////////////////////////////
/*int buttonState;
int lastButtonState = LOW;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
int Q1;
*/
//////////////////////////////////////



// Control MOD-IO at address 0x2C (the 7-bit address), 
// shifted 1-bit left the address is 0x58.
// Be sure to enter the correct I2C address of your module

MOD_IO modio(0x58);

//Variables
 uint8_t val; // Digital IN value read all
 uint8_t val1; // DI1
 uint8_t val2; // DI2
 uint8_t val3; // DI3
 uint8_t val4; // DI4



void setup () {
  Serial.begin(9600);
  modio.begin();

  

/////////////////////////////////////////////////


////////////////////////////////////////////////

}

void loop () { 




//Reads and prints the digital inputs 

  val = modio.digitalReadAll();
 
// Reads digital inputs status one by one number means digital input number of bit neds to be convert from binary to dec digital in4=8=1000b
  
  val1 = modio.digitalRead(1); //DI1
  val2 = modio.digitalRead(2); //DI2
  val3 = modio.digitalRead(4); //DI3
  val4 = modio.digitalRead(8); //DI4

  //Serial print just for control states

  Serial.print("digital Inputs: ");
  Serial.println(val,BIN);
  Serial.print("digital Input 1: ");
  Serial.println(val1);
  Serial.print("digital Input 2: ");
  Serial.println(val2);
  Serial.print("digital Input 3: ");
  Serial.println(val3);
  Serial.print("digital Input 4: ");
  Serial.println(val4);

 //////////////////////////////////////////////////
/*
int In1 = val1;
Serial.print("In 1: ");
Serial.println(In1);

if (In1 != lastButtonState) {
  lastDebounceTime = millis();
}

if ((millis()-lastDebounceTime) > debounceDelay) {
  Serial.println("IF1");
  Serial.print("time: ");
  Serial.println(millis()-lastDebounceTime);
  Serial.print("In1");
  Serial.println(In1);
  Serial.print("Button state");
  Serial.println(buttonState);

if(In1 != buttonState) {
  buttonState = In1;
  Serial.println("IF2");
  
  if (buttonState == HIGH){
    Serial.println("IF3");
    Q1 = !Q1;
  }
}

}

lastButtonState = In1;

 modio.setRelay(RELAY1,Q1);
*/

 ///////////////////////////////////////////////////





///////////////////////////////////////////////////
 
//Relays turning on and off. Note that the relays require external power supply
//provided to the PWR_J of the MOD-IO board

 /* modio.setRelay(RELAY1, 1);
  delay(PERIOD);
  modio.setRelay(RELAY1, 0);
  
  modio.setRelay(RELAY2, 1);
  delay(PERIOD);
  modio.setRelay(RELAY2, 0);
  
  modio.setRelay(RELAY3, 1);
  delay(PERIOD);
  modio.setRelay(RELAY3, 0);
  
  modio.setRelay(RELAY4, 1);
  delay(PERIOD);
  modio.setRelay(RELAY4, 0);
  
  
*/






int Q1;
Q1= debounce(val1);
Serial.print("Q output: ");
Serial.println(Q1);

 modio.setRelay(RELAY1,Q1);
   
  delay(2000);
  
}

///////////////////////////////////////////////////////////////////
              //Functions://
///////////////////////////////////////////////////////////////////

int debounce (int In){

int buttonState;
int lastButtonState = LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
int Q1;

if (In != lastButtonState) {
  lastDebounceTime = millis();
}

if ((millis()-lastDebounceTime) > debounceDelay) {
  Serial.println("State IF1");
  Serial.print("time: ");
  Serial.println(millis()-lastDebounceTime);
  Serial.print("In");
  Serial.println(In);
  Serial.print("Button state");
  Serial.println(buttonState);

if(In != buttonState) {
  buttonState = In;
  Serial.println("State: IF2");
  
  if (buttonState == HIGH){
    Serial.println("State: IF3");
    Q1 = !Q1;
    return Q1;
  }
}

}

lastButtonState = In;




}

Your topic has been moved to a section where it will get the attention that it deserves.

Can you please edit your post, select all code and click the image button and next save the post again.

Hello, I did like you say, thank you for your help and guides that I post correct topics.

Thanks for editing your post.

  int lastButtonState = LOW;
  unsigned long lastDebounceTime = 0;

The most obvious mistake is that the above two variables need to be static. As it’s now, they will loose their values when the debounce function ends.

  static int lastButtonState = LOW;
  static unsigned long lastDebounceTime = 0;

Based on the fact that debounce takes an argument, it looks like you might want to reuse the function for different inputs. In that case, the current approach will not work because you can not use the above variables at the same time for different inputs.

Hi,

Thank you, for your help, now I understand a little more how functions works. And also, when I make it static like you suggest now my function works.
For me would be the best to use library, but all libraries uses direct PIN for input debounce, in my case I have problem because I get input value from I2C. And also my problem is because I am not completely understand library background and I am not familiar to change it.

If you have any suggestions regarding library I would be very glad.

Thank you very much,

Best regards
Andrej

Do you know what structs are and how to use them?

I know what are structs when you programing PLC (siemens), its structure of the variables inside, but with arduino I need to learn what are and how to use them.

Thank you for your suggestions

It’s the same in C/C++.

You will need to put the two static variables and maybe something more in there; it’s a while ago that I wrote my own version. Create an array of those structs for your pins and pass e.g the index to the debounce function which will use the indexed element of the struct array.

SO if I understant right, I expend my debounce funtion with indexed elemnts, and when I call functin I call it with index.

Hope I understant your suggestion right.

Hello
I guess the job of debouncing has been done inside the olimex modio modul already.
Do you looking for a state change detection of a input signal instead?

Hello,

I dont check the code which is on MODIO board, but when I make test with wire and I made some bad connections I receive disturbances on the output ( it start going from on to off), and because of this I have an idea that I need to use debounce function in my program. The problem is that I have now working code only for one switch but I will need 4 switches.
But my end project will have 20 switches so 5 plates in row.

But this is next step. At first i need to solve basics.

Thank you best regards

Hello
Understood. I´ve make a quick and dirty mods inside your code. The inputs were scanned with a given update rate specified in the constant scanInputDuration. Try and check it. The sketch is completely untestet .

const unsigned long scanInputDuration {20} // 20msec = 50Hz 


//The example turns on and off all relays of MOD-IO.
//It also reads and prints all digital inputs and all
//analog inputs over the serial monitor
// Globalne knjiznice
#include <Wire.h>
#include <MOD_IO.h>
//////////////////////////////////////
/*int buttonState;
  int lastButtonState = LOW;
  unsigned long lastDebounceTime = 0;
  unsigned long debounceDelay = 50;
  int Q1;
*/
//////////////////////////////////////
// Control MOD-IO at address 0x2C (the 7-bit address),
// shifted 1-bit left the address is 0x58.
// Be sure to enter the correct I2C address of your module
MOD_IO modio(0x58);
//Variables
uint8_t val; // Digital IN value read all
uint8_t val1; // DI1
uint8_t val2; // DI2
uint8_t val3; // DI3
uint8_t val4; // DI4
void setup () {
  Serial.begin(9600);
  modio.begin();

  /////////////////////////////////////////////////
  ////////////////////////////////////////////////
}
void loop () {
  //Reads and prints the digital inputs
  val = modio.digitalReadAll();

  // Reads digital inputs status one by one number means digital input number of bit neds to be convert from binary to dec digital in4=8=1000b

  scanInput(); // scan input for given scanInputDuration time 

  //Serial print just for control states
  Serial.print("digital Inputs: ");
  Serial.println(val, BIN);
  Serial.print("digital Input 1: ");
  Serial.println(val1);
  Serial.print("digital Input 2: ");
  Serial.println(val2);
  Serial.print("digital Input 3: ");
  Serial.println(val3);
  Serial.print("digital Input 4: ");
  Serial.println(val4);
  //////////////////////////////////////////////////
  /*
    int In1 = val1;
    Serial.print("In 1: ");
    Serial.println(In1);
    if (In1 != lastButtonState) {
    lastDebounceTime = millis();
    }
    if ((millis()-lastDebounceTime) > debounceDelay) {
    Serial.println("IF1");
    Serial.print("time: ");
    Serial.println(millis()-lastDebounceTime);
    Serial.print("In1");
    Serial.println(In1);
    Serial.print("Button state");
    Serial.println(buttonState);
    if(In1 != buttonState) {
    buttonState = In1;
    Serial.println("IF2");

    if (buttonState == HIGH){
      Serial.println("IF3");
      Q1 = !Q1;
    }
    }
    }
    lastButtonState = In1;
    modio.setRelay(RELAY1,Q1);
  */
  ///////////////////////////////////////////////////
  ///////////////////////////////////////////////////

  //Relays turning on and off. Note that the relays require external power supply
  //provided to the PWR_J of the MOD-IO board
  /* modio.setRelay(RELAY1, 1);
    delay(PERIOD);
    modio.setRelay(RELAY1, 0);

    modio.setRelay(RELAY2, 1);
    delay(PERIOD);
    modio.setRelay(RELAY2, 0);

    modio.setRelay(RELAY3, 1);
    delay(PERIOD);
    modio.setRelay(RELAY3, 0);

    modio.setRelay(RELAY4, 1);
    delay(PERIOD);
    modio.setRelay(RELAY4, 0);


  */
  int Q1;
  Q1 = debounce(val1);
  Serial.print("Q output: ");
  Serial.println(Q1);
  modio.setRelay(RELAY1, Q1);

  delay(2000);

}
void scanInput() {
  static unsigned long scanInputMillis = 0;
  if (millis() - scanInputMillis >= scanInputDuration) {
    scanInputMillis = millis();
    val1 = modio.digitalRead(1); //DI1
    val2 = modio.digitalRead(2); //DI2
    val3 = modio.digitalRead(4); //DI3
    val4 = modio.digitalRead(8); //DI4
  }
}

///////////////////////////////////////////////////////////////////
//Functions://
///////////////////////////////////////////////////////////////////
int debounce (int In) {
  int buttonState;
  int lastButtonState = LOW;
  unsigned long lastDebounceTime = 0;
  unsigned long debounceDelay = 50;
  int Q1;
  if (In != lastButtonState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    Serial.println("State IF1");
    Serial.print("time: ");
    Serial.println(millis() - lastDebounceTime);
    Serial.print("In");
    Serial.println(In);
    Serial.print("Button state");
    Serial.println(buttonState);
    if (In != buttonState) {
      buttonState = In;
      Serial.println("State: IF2");

      if (buttonState == HIGH) {
        Serial.println("State: IF3");
        Q1 = !Q1;
        return Q1;
      }
    }
  }
  lastButtonState = In;
}

I think this should give you the idea. It uses normal Arduino pins and loop() only processes a single button for a state change example

/*
  Debounce_1: Original code, modified to use INPUT_PULLUP and longer 'delay'
  Debounce_2: Using a function instead of loop; added serial prints
  Debounce_3: Added state change detection in loop, moved led functionality to loop
  Debounce_4: Adding struct for button to store the relevant debounce info
  Debounce_5: added #defines
*/

#define NUMELEMENTS(x) sizeof(x) / sizeof(x[0])

const byte ISPRESSED = LOW;
const byte IDX_STARTBTN = 0;
const byte IDX_STOPBTN = 1;

struct BUTTON
{
  const uint8_t pin;              // the button pin
  uint8_t debouncedState;         // debounced button state
  uint8_t lastButtonState;        // internal use
  uint32_t lastDebounceTime;      // internal use
  const uint32_t debounceDelay;   // delay, internal use
};

BUTTON buttons[] =
{
  {2, !ISPRESSED, !ISPRESSED, 0, 50},
  {3, !ISPRESSED, !ISPRESSED, 0, 50},
};

const int ledPin = LED_BUILTIN; // the number of the LED pin
int ledState = HIGH;            // the current state of the output pin

void setup()
{
  // loop through input pins and enable internal pullup
  for (uint8_t btnCnt = 0; btnCnt < NUMELEMENTS(buttons); btnCnt++)
  {
    pinMode(buttons[btnCnt].pin, INPUT_PULLUP);
  }
  // led pin as output
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);

  // setup serial comms
  Serial.begin(57600);
}

void loop()
{
  static uint8_t btnIndex = IDX_STARTBTN;

  // last read value; init with not ispressed
  static uint8_t lastRead = !ISPRESSED;

  // debouce button
  uint8_t currentRead = debounceButton(btnIndex);

  // on change
  if (currentRead != lastRead)
  {
    lastRead = currentRead;
    Serial.print(millis());
    // if button is pressed
    if (currentRead == ISPRESSED)
    {
      Serial.print(F(": buttons["));
      Serial.print(btnIndex);
      Serial.println(F("] pressed"));
      // toggle the ;ed
      ledState = !ledState;
      digitalWrite(ledPin, ledState);
    }
    else
    {
      Serial.print(F(": buttons["));
      Serial.print(btnIndex);
      Serial.println(F("] released"));
    }
  }
}


/*
  debounce the button
  In
    index into buttons array
  Returns:
    debounced button state
*/
byte debounceButton(uint8_t index)
{
  // read the state of the switch into a local variable:
  byte reading = digitalRead(buttons[index].pin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != buttons[index].lastButtonState)
  {
    // reset the debouncing timer
    buttons[index].lastDebounceTime = millis();
  }

  if ((millis() - buttons[index].lastDebounceTime) > buttons[index].debounceDelay)
  {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttons[index].debouncedState)
    {
      buttons[index].debouncedState = reading;
    }
  }

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  buttons[index].lastButtonState = reading;

  // return the debounced state
  return buttons[index].debouncedState;
}

Thank you guys for your help.

Now I manage to make more user friendly code, but the problem is when I put the power on the EPS32 which comunicate with my ModIO olimex board sometimes I get just like all inputs are 1, but realy are 0. And I need to hard reset booty plates that things go to right working conditions.
So I am wondering if there is issue with I2C communication is there and command that executed wire.h, when the line is ready or there is some other software peoblem, because MODIO from olimex has its own microcontroller and source code is written in microchip studio.
Is there any posibility that I can programm AT Mega 16 with arduino.
So my idea is to change the progamm on mod IO plate, that the things will start to work, and after use I2C only for data communication.
Because I am afraid if I dont change the data on MOD IO there will be all the time same problem.
Or my knowledge is not enough to solve the problem with communicatino with ESP32.

Thank you for your help
Best regards
Andrej

Code for debouce with wich help me Mr. paulpaulson, also I would like to thank Mr. sterretje:

#include <Wire.h>
#include <MOD_IO.h>



  

//////////////////////////////////////

//////////////////////////////////////



// Control MOD-IO at address 0x2C (the 7-bit address), 
// shifted 1-bit left the address is 0x58.
// Be sure to enter the correct I2C address of your module

MOD_IO modio(0x58);

//Variables
const unsigned long scanInputDuration {20}; // 20msec = 50Hz 

 uint8_t dIn1; // Digital input 1
 uint8_t dIn2; // Digital input 2
 uint8_t dIn3; // Digital input 3
 uint8_t dIn4; // Digital input 4

 


void setup () {
  Serial.begin(9600);
  modio.begin();


}

void loop () { 

scanInput(); // scan input for given scanInputDuration time 

  
       
  modio.setRelay(RELAY1, dIn1);
  modio.setRelay(RELAY2, dIn2);
  modio.setRelay(RELAY3, dIn3);
  modio.setRelay(RELAY4, dIn4);


  
  Serial.print("digital Input 1: ");
    Serial.println(dIn1);
    Serial.print("digital Input 2: ");
    Serial.println(dIn2);
    Serial.print("digital Input 3: ");
    Serial.println(dIn3);
    Serial.print("digital Input 4: ");
    Serial.println(dIn4);
   
 
  delay(2000);
} 
//Relays turning on and off. Note that the relays require external power supply


 /* modio.setRelay(RELAY1, 1);
  delay(PERIOD);
  modio.setRelay(RELAY1, 0);
  
  modio.setRelay(RELAY2, 1);
  delay(PERIOD);
  modio.setRelay(RELAY2, 0);
  
  modio.setRelay(RELAY3, 1);
  delay(PERIOD);
  modio.setRelay(RELAY3, 0);
  
  modio.setRelay(RELAY4, 1);
  delay(PERIOD);
  modio.setRelay(RELAY4, 0);
  */
  


void scanInput() {
 
  static unsigned long scanInputMillis = 0;
  
  if (millis() - scanInputMillis >= scanInputDuration){
    scanInputMillis = millis();
    dIn1 = modio.digitalRead(1); //DI1
    dIn2 = modio.digitalRead(2); //DI2
    dIn3 = modio.digitalRead(4); //DI3
    dIn4 = modio.digitalRead(8); //DI4
  int writeState = 1;
  
    //Just for monitor after working comment this
   
  }
  
    //if (_print){
    Serial.print("millis: ");
    Serial.println(millis());
    Serial.print("ScanInputMillis: ");
    Serial.println(scanInputMillis);
    Serial.print("pushTime: ");
    Serial.println(millis() - scanInputMillis);
    Serial.print("digital Input 1: ");
    Serial.println(dIn1);
    Serial.print("digital Input 2: ");
    Serial.println(dIn2);
    Serial.print("digital Input 3: ");
    Serial.println(dIn3);
    Serial.print("digital Input 4: ");
    Serial.println(dIn4);

}

Project_MicrocipStudio7.zip (19.7 KB)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.