# Push button controlling optocoupler weird behavior

**URL:** <https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367>\
**Category:** Programming\
**Created:** [August 29, 2023, 8:53pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367 "2023-08-29T20:53:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [August 29, 2023, 8:53pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/1 "2023-08-29T20:53:30Z")

</div>

Hi,  
this is my first time here.  
I'd like to know if somebody could give me a hand with the following.

I'm using a Arduino Uno board with two push-buttons (digital pins 3 & 4) to control 2 pairs of relays (a 4 module relay) (digital pins 10-13).

In addition I'm sending the button state, though Firmata to PD.

Sometimes it works Ok. But sometime not. It's too unstable. It suddenly begins to change the button state even if I'm not pushing any button.

Below I include a drawing of the schematic and the code.

Any hint will be really helpful.

Thanks in advance,

Alexis

* * *

 ![opto-2b](https://europe1.discourse-cdn.com/arduino/original/4X/8/2/1/821d997a8604d44124b09c26b54d774f05537623.jpeg)

* * *

```arduino

//#include <Firmata.h>
//#include "utility/SerialFirmata.h"

const int buttonPin1 = 3; // Botón para optoacopladores 1 y 2
const int buttonPin2 = 4; // Botón para optoacopladores 3 y 4

const int opto1Pin = 10; // Pin del primer optoacoplador
const int opto2Pin = 11; // Pin del segundo optoacoplador
const int opto3Pin = 12; // Pin del tercer optoacoplador
const int opto4Pin = 13; // Pin del cuarto optoacoplador

byte optoStates[4] = {LOW, LOW, LOW, LOW}; // Estados de los optoacopladores
byte prevButtonState1 = LOW; // Estado previo del botón 1
byte prevButtonState2 = LOW; // Estado previo del botón 2

byte myArray[6]; // Array para almacenar los estados de los optoacopladores

void setup() {
 pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  
 pinMode(opto1Pin, OUTPUT);
  pinMode(opto2Pin, OUTPUT);
  pinMode(opto3Pin, OUTPUT);
  pinMode(opto4Pin, OUTPUT);

  Serial.begin(9600);
 // Firmata.begin(57600);
}

void loop() {
 // Firmata.update(); // Actualizar la comunicación Firmata
  
  byte buttonState1 = digitalRead(buttonPin1);
  byte buttonState2 = digitalRead(buttonPin2);

  // Cambiar estado de optoacopladores 1 y 2 con el botón 1
  if (buttonState1 != prevButtonState1) {
    if (buttonState1 == HIGH) {
      optoStates[0] = !optoStates[0];
      optoStates[1] = !optoStates[1];
    }
    prevButtonState1 = buttonState1;
  }

  // Cambiar estado de optoacopladores 3 y 4 con el botón 2
  if (buttonState2 != prevButtonState2) {
    if (buttonState2 == HIGH) {
      optoStates[2] = !optoStates[2];
      optoStates[3] = !optoStates[3];
    }
    prevButtonState2 = buttonState2;
  }

  digitalWrite(opto1Pin, optoStates[0]);
  digitalWrite(opto2Pin, optoStates[1]);
  digitalWrite(opto3Pin, optoStates[2]);
  digitalWrite(opto4Pin, optoStates[3]);

  // Almacenar estados de optoacopladores en el array
  for (int i = 0; i < 4; i++) {
    myArray[i] = optoStates[i];
  }

  // Enviar array a través de Serial.write
  Serial.write(myArray, sizeof(myArray));

  delay(100); // Pequeña pausa para evitar rebotes de los botones
}

```

---

<div class="post-metadata">

**Author:** ![UKHeliBob](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ukhelibob/32/215663_2.png) [@UKHeliBob](https://forum.arduino.cc/u/UKHeliBob)\
**Post date:** [August 29, 2023, 9:01pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/2 "2023-08-29T21:01:32Z")

</div>

Your buttons are wired in a very strange way. Why do you have a resistor in series with the left hand one ?

This diagram may be helpful

 ![image](https://europe1.discourse-cdn.com/arduino/original/4X/1/b/9/1b90318fdcef285817828b630668b6fb9df222f9.png)

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [August 29, 2023, 11:42pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/3 "2023-08-29T23:42:34Z")

</div>

Dear @UKHeliBob  
I'm not sure why do I have a resistor in series there. Have I tried to avoid a short circuit actually causing it?  
I'll try what you've suggested and let you know how does it goes.  
Thanks for your help.

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 1, 2023, 3:46am UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/4 "2023-09-01T03:46:21Z")

</div>

Dear @UKHeliBob I've just tried all the possibilities offered by your diagram with similar results.  
S3 and S2 behave in a slightly more stable manner.  
However it still does some random weird actions.  
The board might actually be failing. Tomorrow I'll try another board.

Thanks again.

Best,

Alexis

---

<div class="post-metadata">

**Author:** ![xfpd](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/xfpd/32/1120236_2.png) [@xfpd](https://forum.arduino.cc/u/xfpd)\
**Post date:** [September 1, 2023, 5:30am UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/5 "2023-09-01T05:30:32Z")

</div>

Is the button on Pin 3 using a pull-down resistor, or a voltage divider?

If both buttons are to use a pull-down, try wiring the buttons like this:

```arduino
PIN3--+--resistor----GND (Pin3 is pulled low if button is open/not pressed)
      |
     / button (normally open)
      |
      + --------------VCC (Pin3 senses HIGH when button is pressed)

```

---

<div class="post-metadata">

**Author:** ![gcjr](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gcjr/32/314015_2.png) [@gcjr](https://forum.arduino.cc/u/gcjr)\
**Post date:** [September 1, 2023, 10:38am UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/6 "2023-09-01T10:38:28Z")

</div>

buttons are typically connected between the pin and ground, the pin configured as INPUT\_PULLUP to use the internal pullup resistor which pulls the pin HIGH and when pressed, the button pulls the pin LOW.

---

<div class="post-metadata">

**Author:** ![evanmars](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/evanmars/32/217678_2.png) [@evanmars](https://forum.arduino.cc/u/evanmars)\
**Post date:** [September 1, 2023, 12:57pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/7 "2023-09-01T12:57:55Z")

</div>

> [@alexis\_perepelycia](#):
>
> S3 and S2 behave in a slightly more stable manner.

When wired as S3, did you change the pinMode to INPUT\_PULLUP?

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 8, 2023, 10:26pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/8 "2023-09-08T22:26:35Z")

</div>

> [@gcjr](#):
>
> INPUT\_PULLUP

Dear @xfpd  
thanks for your help!  
Tried what you've suggested with same luck to prior attemps thou.  
Best,  
Alexis

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 8, 2023, 10:28pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/9 "2023-09-08T22:28:39Z")

</div>

Dear @gcjr  
thanks for your time  
I did that on the code  
Got a more reliable behavior but with an uncontrolled overall result  
Best  
Alexis

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 8, 2023, 10:29pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/10 "2023-09-08T22:29:47Z")

</div>

Dear @evanmars

thanks for your help  
Did that as well with similar luck

Best

Alexis

---

<div class="post-metadata">

**Author:** ![gcjr](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gcjr/32/314015_2.png) [@gcjr](https://forum.arduino.cc/u/gcjr)\
**Post date:** [September 8, 2023, 10:40pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/11 "2023-09-08T22:40:12Z")

</div>

> [@alexis\_perepelycia](#):
>
> ```arduino
> if (buttonState1 != prevButtonState1) {
> if (buttonState1 == HIGH) {
> optoStates[0] = !optoStates[0];
> optoStates[1] = !optoStates[1];
> }
> prevButtonState1 = buttonState1;
> }
> 
> ```

how are you handling debouncing ??

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 9, 2023, 2:09am UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/12 "2023-09-09T02:09:30Z")

</div>

dear @gcjr

what you mean by 'debouning'?

I'm using that part of the code to change (alternate between) the state of the relay according to its actual state

---

<div class="post-metadata">

**Author:** ![paulpaulson](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/paulpaulson/32/363643_2.png) [@paulpaulson](https://forum.arduino.cc/u/paulpaulson)\
**Post date:** [September 9, 2023, 4:06am UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/13 "2023-09-09T04:06:06Z")

</div>

Hello [alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)

Due to their mechanical and physical construction, push-buttons often generate multiple transitions when opening/closing: These transitions can be read as several actuations in a very short time and deceive the sketch.

---

<div class="post-metadata">

**Author:** ![gcjr](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gcjr/32/314015_2.png) [@gcjr](https://forum.arduino.cc/u/gcjr)\
**Post date:** [September 9, 2023, 7:21am UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/14 "2023-09-09T07:21:44Z")

</div>

> [@alexis\_perepelycia](#):
>
> what you mean by 'debouning'?

looks like it's processing a button press  
what if you did

```arduino
  if (buttonState1 != prevButtonState1) {
    if (buttonState1 == HIGH) {
      optoStates[0] = !optoStates[0];
      optoStates[1] = !optoStates[1];
    }
    prevButtonState1 = buttonState1;
    delay (20);
  }

```

---

<div class="post-metadata">

**Author:** ![camsysca](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/camsysca/32/1015228_2.png) [@camsysca](https://forum.arduino.cc/u/camsysca)\
**Post date:** [September 9, 2023, 11:28am UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/15 "2023-09-09T11:28:22Z")

</div>

> [@alexis\_perepelycia](#):
>
> what you mean by 'debouning'?

Due to mechanical factors, when you first press a button, the metallic contact often will make contact, bounce open, make contact, etc. several times. If your code is scanning quickly, these bounces may be recorded as individual button presses. Consequently, your software may see 1, 2, 3, 4, or more button close/open series, while you believe you pushed the button once. Generally, a first order fix for this is to insert a delay as others have suggested, so that your software should see the initial closure, then sense again that it is closed(therefore no change).  
HTH

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 9, 2023, 12:09pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/16 "2023-09-09T12:09:57Z")

</div>

Dear @paulpaulson

thanks for your help.  
I'm implementing a delal at the very bottom of the code : ```  
delay(100);

```arduino
Best,

Alexis
```

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 9, 2023, 12:11pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/17 "2023-09-09T12:11:35Z")

</div>

Dear @gcjr

thanks again.  
I'll try that.  
So far I've been using a delay at the end of the code : ```  
delay(100);

```arduino

Best,

Alexis
```

---

<div class="post-metadata">

**Author:** ![alexis\_perepelycia](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/alexis_perepelycia/32/1044979_2.png) [@alexis\_perepelycia](https://forum.arduino.cc/u/alexis_perepelycia)\
**Post date:** [September 9, 2023, 12:13pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/18 "2023-09-09T12:13:51Z")

</div>

Dear @camsysca ,

thanks for your help.  
I'm indeed using a delay at the end of the code : ```  
delay(100);

```arduino
Perhaps I should move that isntance to a different section of the code.

Best,

Alexis
```

---

<div class="post-metadata">

**Author:** ![StefanL38](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/stefanl38/32/713548_2.png) [@StefanL38](https://forum.arduino.cc/u/StefanL38)\
**Post date:** [September 9, 2023, 12:17pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/19 "2023-09-09T12:17:00Z")

</div>

> [@alexis\_perepelycia](#):
>
> what you mean by 'debouning'?

This is a picture of a digital storage oscilloscope that can record voltage over time very very fast.  
Fast enough to make visible that within 0,01 seconds the contact of a mechanical button opens / closes **multiple** times.

microcontroller can execute code so fast that this open/closing within 0,01 seconds is detected as multiple button-presses.

This is called bouncing.  
And debouncing means write code tat takes care of this effect to filter it out to avoid "false alarms"

 ![image](https://europe1.discourse-cdn.com/arduino/original/4X/8/5/1/851be284f565bda0f653afdb326beb9ed36c5da5.jpeg)

> **[Arduino: De-Bounce a Button with micros() or millis() - Bald Engineer](https://www.baldengineer.com/arduino-de-bounce-a-button-with-micros.html)**
>
> The Arduino is fast, humans are slow. When you push down a button, what seems like a single change to slow humans is really multiple presses to an Arduino.  This is known as “bouncing.”  Figure 1 is an oscilloscope screenshot showing what...

---

<div class="post-metadata">

**Author:** ![StefanL38](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/stefanl38/32/713548_2.png) [@StefanL38](https://forum.arduino.cc/u/StefanL38)\
**Post date:** [September 9, 2023, 12:36pm UTC](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367/20 "2023-09-09T12:36:06Z")

</div>

Here is your code with additional serial printing to make visible what is going on in your code.

This is done by a tricky so called "macro" which enables to write a single line of code that has a functionality of

- printing the value only in case the value has CHANGED
- printing an ID-Text
- printing the **name** of the variable
- printing the **value** of the variable

There are two modifications:

it used baudrate 115200 instead of 9600.  
This means you have to adjust the baudrate in the serial monitor  
it has a **#define** for the configuration as INPUT or INPUT\_PULLUP  
and does print the actual configuration to the serial monitor

```arduino
#define inputConfiguration INPUT_PULLUP
//#define inputConfiguration INPUT

```

as a variant you can de-comment this line of code

```arduino
//printIO_PinStates();

```

If you de-comment this line  
it will print the IO-pins states onces EVERY second regardless if the value has changed or not

```arduino
// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " " #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " " #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

//#include <Firmata.h>
//#include "utility/SerialFirmata.h"

const int buttonPin1 = 3; // Botón para optoacopladores 1 y 2
const int buttonPin2 = 4; // Botón para optoacopladores 3 y 4

const int opto1Pin = 10; // Pin del primer optoacoplador
const int opto2Pin = 11; // Pin del segundo optoacoplador
const int opto3Pin = 12; // Pin del tercer optoacoplador
const int opto4Pin = 13; // Pin del cuarto optoacoplador

byte optoStates[4] = {LOW, LOW, LOW, LOW}; // Estados de los optoacopladores
byte prevButtonState1 = LOW; // Estado previo del botón 1
byte prevButtonState2 = LOW; // Estado previo del botón 2

byte myArray[6]; // Array para almacenar los estados de los optoacopladores

#define inputConfiguration INPUT_PULLUP
//#define inputConfiguration INPUT

void setup() {
  Serial.begin(115200);
  Serial.print("io-pins defined as ");
  Serial.println(inputConfiguration);
  
  pinMode(buttonPin1, inputConfiguration);
  pinMode(buttonPin2, inputConfiguration);

  pinMode(opto1Pin, OUTPUT);
  pinMode(opto2Pin, OUTPUT);
  pinMode(opto3Pin, OUTPUT);
  pinMode(opto4Pin, OUTPUT);

  //Serial.begin(9600);
  // Firmata.begin(57600);
}

void loop() {
  // Firmata.update(); // Actualizar la comunicación Firmata

  //printIO_PinStates();
  
  byte buttonState1 = digitalRead(buttonPin1);
  // only in case the value of variable "buttonState1" has CHANGED print ONCE
  dbgc("0A", buttonState1);

  byte buttonState2 = digitalRead(buttonPin2);
  // only in case the value of variable "buttonState2" has CHANGED print ONCE
  dbgc("0B", buttonState2);

  // Cambiar estado de optoacopladores 1 y 2 con el botón 1
  if (buttonState1 != prevButtonState1) {
    dbgc("0C", prevButtonState1);
    if (buttonState1 == HIGH) {
      optoStates[0] = !optoStates[0];
      dbgc("0D", optoStates[0]);

      optoStates[1] = !optoStates[1];
      dbgc("0E", optoStates[1]);
    }
    prevButtonState1 = buttonState1;
  }

  // Cambiar estado de optoacopladores 3 y 4 con el botón 2
  if (buttonState2 != prevButtonState2) {
    dbgc("2C", prevButtonState2);
    if (buttonState2 == HIGH) {
      optoStates[2] = !optoStates[2];
      dbgc("2D", optoStates[2]);
      optoStates[3] = !optoStates[3];
      dbgc("2E", optoStates[3]);
    }
    prevButtonState2 = buttonState2;
  }

  digitalWrite(opto1Pin, optoStates[0]);
  digitalWrite(opto2Pin, optoStates[1]);
  digitalWrite(opto3Pin, optoStates[2]);
  digitalWrite(opto4Pin, optoStates[3]);

  // Almacenar estados de optoacopladores en el array
  for (int i = 0; i < 4; i++) {
    myArray[i] = optoStates[i];
  }

  // Enviar array a través de Serial.write
  //Serial.write(myArray, sizeof(myArray));

  //delay(100); // Pequeña pausa para evitar rebotes de los botones
}

void printIO_PinStates() {
  // print value of digitalRead(buttonPin1) only ONCE per second
  dbgi("IO1",digitalRead(buttonPin1),1000);
  dbgi("IO2",digitalRead(buttonPin2),1000);
}

```

best regards Stefan

[Next page](https://forum.arduino.cc/t/push-button-controlling-optocoupler-weird-behavior/1163367.md?page=2)
