Need help with code for the OneButton.h library

Hello people. I am a novice with Arduino and would need some help with the following code using the OneButton.h library.

I've been using the Arduino code below created with the help from this forum on my ebike to control the 2 LED bars used as headlights for a while and it is working great.

I would like to add a new function using the attachMultiClick command to have the LEDs flash as follow:

Flash the white LED 3 times with 70ms between flash then pause 100ms then flash the yellow LED 3 times with 70ms between flash, then pause 100ms and loop back to flash the white LED 3 times and so on...

(Similar to a police car flashing light)

How can I make the code for button.attachMultiClick below to loop or is there a better code to make this flash function?

Here is the code for the OneButton.h library:

#include <OneButton.h>

const uint8_t whiteLed_pin  = 12;
const uint8_t yellowLed_pin = 11;
const uint8_t button_pin    = 10;

OneButton button( button_pin, true, true );


void setLeds( const bool white, const bool yellow )
{
  Serial.print( "White " );
  Serial.print( white == true ? "ON" : "OFF" );
  Serial.print( ", Yellow " );
  Serial.println( yellow == true ? "ON" : "OFF" );

  digitalWrite( whiteLed_pin, white == true ? HIGH : LOW );
  delay(10);
  digitalWrite( yellowLed_pin, yellow == true ? HIGH : LOW );
}


void setup()
{
  Serial.begin( 115200 );

  pinMode( whiteLed_pin, OUTPUT );
  pinMode( yellowLed_pin, OUTPUT );
  setLeds( true, false );

  button.setDebounceTicks( 25 );
  button.setClickTicks( 130 );
  button.setPressTicks( 300 );

  static bool state = false;

  button.attachClick( []()
    {
      setLeds( state, !state );
      state = !state;
    }
  );
    
  button.attachDoubleClick( []()
    {
      setLeds( true, true );
      state = true;
    }
  );

  button.attachLongPressStart( []()
    {
      setLeds( false, false );
      state = true;
    }
  );

  
} 
  

void loop()
{
  button.tick();

  button.attachMultiClick( []()
  {
      digitalWrite(11,HIGH);
      delay(70);
      digitalWrite(11,LOW);
      delay(70);
      digitalWrite(11,HIGH);
      delay(70);
      digitalWrite(11,LOW);
      delay(70);
      digitalWrite(11,HIGH);
      delay(70);
      digitalWrite(11,LOW);
      delay(100);
      digitalWrite(12,HIGH);
      delay(70);
      digitalWrite(12,LOW);
      delay(70);
      digitalWrite(12,HIGH);
      delay(70);
      digitalWrite(12,LOW);
      delay(70);
      digitalWrite(12,HIGH);
      delay(70);
      digitalWrite(12,LOW);
      delay(70);
    
  }
  );
}

Here is the link for my current working code on wokwi simulator without the button.attachMultiClick section:
https://wokwi.com/projects/329108148327547474

Any help would be appreciated.

Cheers

Why would be put the code for the multiClick function inside loop() when all the other buttons have their code defined within setup(). You don't need to define it multiple times.

As for how to do this, do NOT put the entire sequence inside your multiClick() function or your buttons will not be responsive while you are running that code that contains many delay() calls.

It is much better to simply set a mode variable to indicate you want this mode and then react to that inside loop. You will also need to get rid of all those delays. Look at the Blink Without Delay example in the IDE to learn how (File->exampes->02.digital->BlinkWithoutDelay)

as already mentioned activate your blinking with a "mode" variable and get rid of all your delays.

proposal:

//https://forum.arduino.cc/t/need-help-with-code-for-the-onebutton-h-library/1037089
// to be deleted 2022-11

#include <OneButton.h>

const uint8_t whiteLed_pin  = 12;
const uint8_t yellowLed_pin = 11;
const uint8_t button_pin    = 10;

const uint8_t no_pin = 255;  // this is no GPIO

OneButton button( button_pin, true, true );

enum class Mode {IDLE, FLASH} mode;

void setLeds( const bool white, const bool yellow )
{
  Serial.print( "White " );
  Serial.print( white == true ? "ON" : "OFF" );
  Serial.print( ", Yellow " );
  Serial.println( yellow == true ? "ON" : "OFF" );

  digitalWrite( whiteLed_pin, white == true ? HIGH : LOW );
  delay(10);
  digitalWrite( yellowLed_pin, yellow == true ? HIGH : LOW );
}


void setup()
{
  Serial.begin( 115200 );

  pinMode( whiteLed_pin, OUTPUT );
  pinMode( yellowLed_pin, OUTPUT );
  setLeds( true, false );

  button.setDebounceTicks( 25 );
  button.setClickTicks( 130 );
  button.setPressTicks( 300 );

  static bool state = false;

  button.attachClick( []()
  {
    Serial.println(F("click"));
    setLeds( state, !state );
    state = !state;
  }
                    );

  button.attachDoubleClick( []()
  {
    Serial.println(F("double click"));
    setLeds( true, true );
    state = true;
  }
                          );

  button.attachLongPressStart( []()
  {
    Serial.println(F("long press"));
    setLeds( false, false );
    state = true;
  }
                             );

  button.attachMultiClick( []()
  {
    Serial.println(F("Multi Click"));
    digitalWrite(yellowLed_pin, LOW);
    digitalWrite(whiteLed_pin, LOW);
    if (mode != Mode::FLASH) mode = Mode::FLASH;
    else  mode = Mode::IDLE;
  }
                         );
}

struct Flashpattern
{
  uint8_t pin;
  uint8_t interval;
};

Flashpattern flashpattern[] {
  {yellowLed_pin, 70},
  {no_pin, 70},
  {yellowLed_pin, 70},
  {no_pin, 70},
  {yellowLed_pin, 70},
  {no_pin, 70},
  {whiteLed_pin, 70},
  {no_pin, 70},
  {whiteLed_pin, 70},
  {no_pin, 70},
  {whiteLed_pin, 70},
  {no_pin, 70}
};

constexpr size_t noOfFlashpattern = sizeof(flashpattern) / sizeof(flashpattern[0]);

void flash()
{
  static byte state = 0;
  static uint32_t previousMillis = 0;
  uint32_t currentMillis = millis();
  if (currentMillis - previousMillis >= flashpattern[state].interval)
  {
    previousMillis = currentMillis;
    if (flashpattern[state].pin != no_pin) digitalWrite(flashpattern[state].pin, LOW);
    state++;
    if (state >= noOfFlashpattern) state = 0;
    if (flashpattern[state].pin != no_pin) digitalWrite(flashpattern[state].pin, HIGH);
  }
}

// not used in sketch
void flashSpoiledWithDelay()
{
  digitalWrite(11, HIGH);
  delay(70);
  digitalWrite(11, LOW);
  delay(70);
  digitalWrite(11, HIGH);
  delay(70);
  digitalWrite(11, LOW);
  delay(70);
  digitalWrite(11, HIGH);
  delay(70);
  digitalWrite(11, LOW);
  delay(100);
  digitalWrite(12, HIGH);
  delay(70);
  digitalWrite(12, LOW);
  delay(70);
  digitalWrite(12, HIGH);
  delay(70);
  digitalWrite(12, LOW);
  delay(70);
  digitalWrite(12, HIGH);
  delay(70);
  digitalWrite(12, LOW);
  delay(70);
}

void loop()
{
  button.tick();
  switch (mode)
  {
    case Mode::FLASH :
      flash();
      break;
  }
}

P.S.: your description doesn't fit to your code. You only had 70ms delays - no 100ms delay at the end of the pattern sequence...

1 Like

Thank you so much noiasca, that works beautifully...

I am very good at many things, but Arduino coding is not one of em..

Cheers

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