So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By edsaib
#81984 Hello everyone,

so I've been working on this project for a while now and stumbled upon a problem which I haven't been able to solve so far. For this project I'm using an ESP8266 NodeMCU 1.0 with industrial buttons connected to the PCF8574 port expander (I also integrated ws2812 smd's into the buttons). For the buttons I use a modified header file (input_pcf.h) which was initially written by a friend of mine and for the ws2812 I am also using a header file (neo.h) written by the same friend (both of them are working fine). As for the port expander, I use the PCF8574 library written by xreef on github . To sum everything up, I connected the buttons to (GND and) the PCF8574, which is connected to the Microcontroller via I2C. The data bus of the smd's are also connected to the ESP.

(Almost) everything has been working fine so far, until I modified the input.h file and connected the buttons to the port expander. You initialize the input object with a pin, which is connected to a button. You can connect the industrial button two ways: on the closing side and on the opening side, I am using the opening side against GND. As I cannot just initialize the input object with a pin from the port expander, I just modified the input.h to input_pcf.h where I also have to pass a reference of the PCF8574 object to it, so I can directly read the pin state in my input_pcf.h. Unfortunately, this is not working at all. The button presses are not detected at all and nothing is reacting to it. Now I am trying to resolve the problem...

...did I do something wrong when passing the object by reference? there a fallacy in my logic to it?

I have checked all connections many times, so I am pretty sure the connections are fine. When examining the button press with the esp, everything is working fine, and the smd's light up as intended. I tested the port expander as well with a simple code where I light up an LED and there were no problems with it. I hope some of you could help me to solve this problem! The code of all relevant files used are below. Thank you in advance!

Code: Select all
#include "PCF8574.h"
#include "input_pcf.h"
#include "neo.h"

// neopixel
const int neo_data = D3;
const int btn = 0;
neo neo(2, neo_data);

//input button(btn);
PCF8574 pcf(0x20, D2, D1);
input_pcf button(btn, pcf);

bool pressed = false;
bool debug_once = true;
unsigned long timer = 0;

void setup() {
  // put your setup code here, to run once:
  // put your setup code here, to run once:
  Serial.println("\nSerial Init OK");

  pcf.pinMode(btn, INPUT);
  pcf.digitalWrite(btn, HIGH);
  Serial.println("PCF Init OK");

  pinMode(neo_data, OUTPUT);
  digitalWrite(neo_data, LOW);

  Serial.println("Init OK\n");


void loop() {
  // put your main code here, to run repeatedly:
    Serial.println("Entering Loop\n");
  timer = millis();

    Serial.println("Button pressed");
      neo.led.setPixelColor(0, BLACK);
      neo.led.setPixelColor(1, BLACK);
      pressed = false;
    } else {
      neo.led.setPixelColor(0, PURPLE);
      neo.led.setPixelColor(1, WHITE);
      pressed = true;


  //if(millis() - timer >= 3) Serial.println(millis() - timer);

  debug_once = false;


Code: Select all
//@(#) input_pcf.h

#ifndef INPUT_PCF_H
#define INPUT_PCF_H

#include "PCF8574.h"

class input_pcf

    PCF8574& pcf;
    const uint16_t pin;
    unsigned long timer = 0;
    boolean state = false;
    boolean state_long = false;

    boolean pressed_long = false;
    boolean pressed = false;

    input_pcf(const uint16_t pin, PCF8574& pcf_ref) : pin(pin), pcf(pcf_ref){
    void Update(){ //button input debouncing and press duration detection
      pressed = false;
      pressed_long = false;

      //button pressed
      if(!pcf.digitalRead(pin) && !state && millis() - timer >= 50){
        state = true;
        timer = millis();
      //button pressed long
      else if(!pcf.digitalRead(pin) && state && !state_long && millis() - timer >= 1000){
        state_long = true;
        pressed_long = true;
      //button pressed short
      else if(pcf.digitalRead(pin) && state && millis() - timer >= 50){
        if(millis() - timer < 1000) pressed = true;
        state_long = false;
        state = false;
        timer = millis();


Code: Select all
//@(#) neo.h

#ifndef NEO_H
#define NEO_H

#include <Adafruit_NeoPixel.h>          //WS2812 library
#include "WS2812_Definitions.h"

class neo

    unsigned long neo_show_timer = 0;
    const uint16_t neo_show_delay = 75;

    const uint16_t led_count;
    const uint16_t led_pin;


    Adafruit_NeoPixel led;

    neo(const uint16_t &count,const uint16_t &pin) : led_count(count), led_pin(pin), led(Adafruit_NeoPixel(this->led_count, this->led_pin, NEO_GRB + NEO_KHZ800)){
      //this->led = new Adafruit_NeoPixel(this->led_count, this->led_pin, NEO_GRB + NEO_KHZ800);

    //Sets all LEDs to off, but DOES NOT update the display;
    void clearLEDs(){
      for (uint16_t i=0; i<led.numPixels(); i++){
        led.setPixelColor(i, 0);

    void Setup(){
    void Loop(){
      //update rgb LED ring
      if(millis() - neo_show_timer >= neo_show_delay){  ;
        neo_show_timer = millis();

//leds.setPixelColor(i, color);
//leds.setPixelColor(i, red, green, blue);


NOTE: I know the code needs some refactoring and the names of some functions might be somewhat ambiguous (like setup() or loop() in neo.h). Please try to ignore these issues when answering :roll: