Problems with counter and push button

Good day,
I'm new to the forum, but enjoy reading and scrolling through other posts to learn more on programming. I'm currently working on a project with a seven segment display counter that increases when a pushbutton is pressed. I've managed to get the counter to add 1 each time you press and release the button. What I'm struggling to do is that when I push and hold the button for longer than 1 second (and keep it pushed) the counter must increase continuously by 1 until the button is released. I've found coding on the forum that do exactly that, but I do not know you to implement and incorporate it in my current code. If someone can help me, I will be eternal gratefull.

Here are my code:

// Assign Shift Register Pins for Data, latch and Clock
  int Target_dataPin = 2; //Target Shift Registers
  int Target_latchPin = 3;
  int Target_clkPin = 4;

// Assign pins for buttons
  int Target_ButtonUp = A0;
  int Target_ButtonDown = A1;

// Variable for reading the button status
  int Target_ButtonUpV = 0;
  int Target_ButtonDownV = 0;

// Previous state of each button declaration
  int Target_ButtonUpV_LastButtonState = 0;
  int Target_ButtonDownV_LastButtonState = 0;

// Initialize what will be displayed / variables
  int Target_Display1 = 0, Target_Display2 = 0, Target_Display3 = 0;

// Set counters to zero for displays / set variables for the score
  int Target_Count = 0;


void setup()
{
// Declare pins as outputs

  pinMode(Target_latchPin, OUTPUT);
  pinMode(Target_clkPin, OUTPUT);
  pinMode(Target_dataPin, OUTPUT);

// Declare buttons as inputs
  pinMode(Target_ButtonUp, INPUT_PULLUP);
  pinMode(Target_ButtonDown, INPUT_PULLUP);

  }
      // End of setup()


void loop() 
{
//Read the Button Pins to see if one of them has been pressed
  Target_ButtonUpV = digitalRead (Target_ButtonUp);
  Target_ButtonDownV = digitalRead (Target_ButtonDown);
 
//Read the Button Pins to see if one of them has been pressed
 if (Target_ButtonUpV != Target_ButtonUpV_LastButtonState) {
// if the state has changed, increment the counter     
    if (Target_ButtonUpV == HIGH){
      if (Target_Count != 999) Target_Count+=1;
      }
 }

 if (Target_ButtonDownV != Target_ButtonDownV_LastButtonState) {
// if the state has changed, decrement the counter     
    if (Target_ButtonDownV == HIGH){
      if (Target_Count != 0) Target_Count-=1;
    }
  }


// Save the current state as the last state for next time through the loop
  Target_ButtonUpV_LastButtonState = Target_ButtonUpV;
  Target_ButtonDownV_LastButtonState = Target_ButtonDownV;

  delay(50);

  UpdateDisplay();
}
  // End of loop()


//*******************************


// Shift 8 bits out MSB first

void ShiftBits(byte DataOut) 
{
 
  int i = 0;
  int pinState;
  
  digitalWrite(Target_dataPin, 0);
  digitalWrite(Target_clkPin, 0);
  
   for (i = 7; i >= 0; i--)  
    {
    digitalWrite(Target_clkPin, 0);
    
    if (DataOut & (1 << i)) 
      {
      pinState = 1;
      }
    else 
      {  
      pinState = 0;
      }
 
    digitalWrite(Target_dataPin, pinState);                 // Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(Target_clkPin, 1);                       // Register shifts bits on upstroke of clock pin  
    digitalWrite(Target_dataPin, 0);                        // Zero the data pin after shift to prevent bleed through
    }

  digitalWrite(Target_clkPin, 0);                         // Stop shifting
    
}   // End of ShiftBits()

//*******************************

void UpdateDisplay()
{
  
  int aDecValues[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 64 };    //103
  unsigned long temp1;
  boolean leadingZero;
    
  temp1 = Target_Count;
    
  int hundreds1 = temp1 / 100;
  temp1 -= (hundreds1 * 100);

  int tens1 = temp1 / 10;
  temp1 -= (tens1 * 10);

  int units1 = temp1;

if (leadingZero==false) // removing leading zeros
  {
    if (hundreds1==0 && tens1>0)      {
      hundreds1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1>0)          {
      hundreds1 = 64; 
      tens1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1==0)          {
      hundreds1 = 64; 
      tens1 = 64;
      units1 = 64;
    }
  }
  
  digitalWrite(Target_latchPin, 0);
  ShiftBits(aDecValues[hundreds1]);
  ShiftBits(aDecValues[tens1]);                       // Update tens digit
  ShiftBits(aDecValues[units1]);                      // Update units digit 
  digitalWrite(Target_latchPin, 1);
  delay(100);                                        // Adjust this delay to vary the count time
 
}   // End of UpdateDisplay()

You must try to combine the two codes yourself. Without this, there is nothing to discuss.

Did you try to add the code with button hold to your scketch? Show your efforts

That's quite amusing, because most beginners have the opposite problem! Their counters increase while the button is pressed and they want it to increase only once each time the button is pressed. That's because they haven't realised that they need their code to detect when the button changes from not being pressed to being pressed - a "state change" of the button.

So if you remove your code that checks for the button state change, you will get what you want. The only thing you may not have thought of is how fast you want the count to increase while the button is pressed. That's easy to do with delay(), unless there is a problem with using delay() in your sketch, such as needing to multiplex a display.

Did you know that there is a standard Arduino function that could replace the ShiftBits() function in your code?

Dear b707
Thank you for the reply. Wherewith the combined code:

// Assign Shift Register Pins for Data, latch and Clock
  int Target_dataPin = 2; //Target Shift Registers
  int Target_latchPin = 3;
  int Target_clkPin = 4;

// Assign pins for buttons
  //int Reset_Button = ;
  int Target_ButtonUp = A0;
  int Target_ButtonDown = A1;

// Variable for reading the button status
  int Target_ButtonUpV = 0;
  int Target_ButtonDownV = 0;

// Previous state of each button declaration
  int Target_ButtonUpV_LastButtonState = 0;
  int Target_ButtonDownV_LastButtonState = 0;

// Initialize what will be displayed / variables
  int Target_Display1 = 0, Target_Display2 = 0, Target_Display3 = 0;

// Set counters to zero for displays / set variables for the score
  int Target_Count = 0;

// Interval time for long and short press
  float value = 0;

  unsigned long interval_1 = 30;
  unsigned long interval_2 = 1000;

  unsigned long previousMillis1 = 0;
  unsigned long previousMillis2 = 0;
  
void setup()
{
// Declare pins as outputs

  pinMode(Target_latchPin, OUTPUT);
  pinMode(Target_clkPin, OUTPUT);
  pinMode(Target_dataPin, OUTPUT);

// Declare buttons as inputs
  pinMode(Target_ButtonUp, INPUT_PULLUP);
  pinMode(Target_ButtonDown, INPUT_PULLUP);

  }
      // End of setup()


void loop() {
// Set currentMillies = millis
   unsigned long currentMillis = millis();

   if (currentMillis - previousMillis2 >= interval_2) {
       //timer2 is done
       interval_1 = 30;//this is for timer1
     } else {
       //timer2 not done
       interval_1 = 500;//this is for timer1
     }
//Read the Button Pins to see if one of them has been pressed
  Target_ButtonUpV = digitalRead (Target_ButtonUp);
  Target_ButtonDownV = digitalRead (Target_ButtonDown);
 
//Read the Button Pins to see if one of them has been pressed
 if (Target_ButtonUpV != Target_ButtonUpV_LastButtonState) {
// if the state has changed, increment the counter     
    if (Target_ButtonUpV == HIGH){
      if (Target_Count != 999) Target_Count+=1;
      }
 }

 if (Target_ButtonDownV != Target_ButtonDownV_LastButtonState) {
// if the state has changed, decrement the counter     
    if (Target_ButtonDownV == HIGH){
      if (Target_Count != 0) Target_Count-=1;
    }
  }


// Save the current state as the last state for next time through the loop
  Target_ButtonUpV_LastButtonState = Target_ButtonUpV;
  Target_ButtonDownV_LastButtonState = Target_ButtonDownV;

  delay(50);

  UpdateDisplay();
}
  // End of loop()


//*******************************


// Shift 8 bits out MSB first

void ShiftBits(byte DataOut) 
{
 
  int i = 0;
  int pinState;
  
  digitalWrite(Target_dataPin, 0);
  digitalWrite(Target_clkPin, 0);
  
   for (i = 7; i >= 0; i--)  
    {
    digitalWrite(Target_clkPin, 0);
    
    if (DataOut & (1 << i)) 
      {
      pinState = 1;
      }
    else 
      {  
      pinState = 0;
      }
 
    digitalWrite(Target_dataPin, pinState);                 // Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(Target_clkPin, 1);                       // Register shifts bits on upstroke of clock pin  
    digitalWrite(Target_dataPin, 0);                        // Zero the data pin after shift to prevent bleed through
    }

  digitalWrite(Target_clkPin, 0);                         // Stop shifting
   
}   // End of ShiftBits()

//*******************************

void UpdateDisplay()
{
  
  int aDecValues[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 64 };    //103
  unsigned long temp1;
  boolean leadingZero;
    
  temp1 = Target_Count;
    
  int hundreds1 = temp1 / 100;
  temp1 -= (hundreds1 * 100);

  int tens1 = temp1 / 10;
  temp1 -= (tens1 * 10);

  int units1 = temp1;

if (leadingZero==false) // removing leading zeros
  {
    if (hundreds1==0 && tens1>0)      {
      hundreds1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1>0)          {
      hundreds1 = 64; 
      tens1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1==0)          {
      hundreds1 = 64; 
      tens1 = 64;
      units1 = 64;
    }
  }
  
  digitalWrite(Target_latchPin, 0);
  ShiftBits(aDecValues[hundreds1]);
  ShiftBits(aDecValues[tens1]);                       // Update tens digit
  ShiftBits(aDecValues[units1]);                      // Update units digit 
  digitalWrite(Target_latchPin, 1);
  delay(100);                                        // Adjust this delay to vary the count time
 
}   // End of UpdateDisplay()

Is it compiled? Is it works?
If no - what is the problem, in detail.

Dear PaulRB
Thank you for the reply. I guess I was lucky to get the counter to work as it is. I did not know about the shiftOut() function and will surely have a look at it for future reference. In the meantime I'm happy with the counter as long as it works. Maybe in a updated version of my project I will try to use shiftOut() instead of shiftBits().

Regards

Yes, the code is compiled and does upload. But when I push the button nothing happen. The counter does nothing.

But it still updating when you release the button, as in your initial code?

No, it does absolutely nothing. I now see that I have omitted a piece of code from the above pasted code. The code uploaded to the arduino is the correct one. The piece omitted is:

if (Target_ButtonUpV != Target_ButtonUpV_LastButtonState) {
// if the state has changed, increment the counter     
    if (Target_ButtonUpV == HIGH){
        if (currentMillis - previousMillis1 >= interval_1) {
        if (Target_Count != 999) Target_Count+=1;
        previousMillis1 = currentMillis;
    }
  } else {//button is low, not pressed
    previousMillis2 = currentMillis;
      
      }

Here is the full code:

// Assign Shift Register Pins for Data, latch and Clock
  int Target_dataPin = 2; //Target Shift Registers
  int Target_latchPin = 3;
  int Target_clkPin = 4;

// Assign pins for buttons
  //int Reset_Button = ;
  int Target_ButtonUp = A0;
  int Target_ButtonDown = A1;

// Variable for reading the button status
  int Target_ButtonUpV = 0;
  int Target_ButtonDownV = 0;

// Previous state of each button declaration
  int Target_ButtonUpV_LastButtonState = 0;
  int Target_ButtonDownV_LastButtonState = 0;

// Initialize what will be displayed / variables
  int Target_Display1 = 0, Target_Display2 = 0, Target_Display3 = 0;

// Set counters to zero for displays / set variables for the score
  int Target_Count = 0;

// Interval time for long and short press
  float value = 0;

  unsigned long interval_1 = 30;
  unsigned long interval_2 = 1000;

  unsigned long previousMillis1 = 0;
  unsigned long previousMillis2 = 0;
  
void setup()
{
// Declare pins as outputs

  pinMode(Target_latchPin, OUTPUT);
  pinMode(Target_clkPin, OUTPUT);
  pinMode(Target_dataPin, OUTPUT);

// Declare buttons as inputs
  pinMode(Target_ButtonUp, INPUT_PULLUP);
  pinMode(Target_ButtonDown, INPUT_PULLUP);

  }
      // End of setup()


void loop() {
// Set currentMillies = millis
   unsigned long currentMillis = millis();

   if (currentMillis - previousMillis2 >= interval_2) {
       //timer2 is done
       interval_1 = 30;//this is for timer1
     } else {
       //timer2 not done
       interval_1 = 500;//this is for timer1
     }
//Read the Button Pins to see if one of them has been pressed
  Target_ButtonUpV = digitalRead (Target_ButtonUp);
  Target_ButtonDownV = digitalRead (Target_ButtonDown);
 
//Read the Button Pins to see if one of them has been pressed
 if (Target_ButtonUpV != Target_ButtonUpV_LastButtonState) {
// if the state has changed, increment the counter     
    if (Target_ButtonUpV == HIGH){
        if (currentMillis - previousMillis1 >= interval_1) {
        if (Target_Count != 999) Target_Count+=1;
        previousMillis1 = currentMillis;
    }
  } else {//button is high, not pressed
    previousMillis2 = currentMillis;
      
      }
 }

 if (Target_ButtonDownV != Target_ButtonDownV_LastButtonState) {
// if the state has changed, decrement the counter     
    if (Target_ButtonDownV == HIGH){
      if (Target_Count != 0) Target_Count-=1;
    }
  }


// Save the current state as the last state for next time through the loop
  Target_ButtonUpV_LastButtonState = Target_ButtonUpV;
  Target_ButtonDownV_LastButtonState = Target_ButtonDownV;

  delay(50);

  UpdateDisplay();
}
  // End of loop()


//*******************************


// Shift 8 bits out MSB first

void ShiftBits(byte DataOut) 
{
 
  int i = 0;
  int pinState;
  
  digitalWrite(Target_dataPin, 0);
  digitalWrite(Target_clkPin, 0);
  
   for (i = 7; i >= 0; i--)  
    {
    digitalWrite(Target_clkPin, 0);
    
    if (DataOut & (1 << i)) 
      {
      pinState = 1;
      }
    else 
      {  
      pinState = 0;
      }
 
    digitalWrite(Target_dataPin, pinState);                 // Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(Target_clkPin, 1);                       // Register shifts bits on upstroke of clock pin  
    digitalWrite(Target_dataPin, 0);                        // Zero the data pin after shift to prevent bleed through
    }

  digitalWrite(Target_clkPin, 0);                         // Stop shifting
   
}   // End of ShiftBits()

//*******************************

void UpdateDisplay()
{
  
  int aDecValues[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 64 };    //103
  unsigned long temp1;
  boolean leadingZero;
    
  temp1 = Target_Count;
    
  int hundreds1 = temp1 / 100;
  temp1 -= (hundreds1 * 100);

  int tens1 = temp1 / 10;
  temp1 -= (tens1 * 10);

  int units1 = temp1;

if (leadingZero==false) // removing leading zeros
  {
    if (hundreds1==0 && tens1>0)      {
      hundreds1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1>0)          {
      hundreds1 = 64; 
      tens1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1==0)          {
      hundreds1 = 64; 
      tens1 = 64;
      units1 = 64;
    }
  }
  
  digitalWrite(Target_latchPin, 0);
  ShiftBits(aDecValues[hundreds1]);
  ShiftBits(aDecValues[tens1]);                       // Update tens digit
  ShiftBits(aDecValues[units1]);                      // Update units digit 
  digitalWrite(Target_latchPin, 1);
  delay(100);                                        // Adjust this delay to vary the count time
 
}   // End of UpdateDisplay()

Sorry, but I don't see any significant difference between the last code and initial one. You said that you have a code example with button hold down. Where is it in the code?

// Assign Shift Register Pins for Data, latch and Clock
  int Target_dataPin = 2; //Target Shift Registers
  int Target_latchPin = 3;
  int Target_clkPin = 4;

// Assign pins for buttons
  //int Reset_Button = ;
  int Target_ButtonUp = A0;
  int Target_ButtonDown = A1;

// Variable for reading the button status
  int Target_ButtonUpV = 0;
  int Target_ButtonDownV = 0;

// Previous state of each button declaration
  int Target_ButtonUpV_LastButtonState = 0;
  int Target_ButtonDownV_LastButtonState = 0;

// Initialize what will be displayed / variables
  int Target_Display1 = 0, Target_Display2 = 0, Target_Display3 = 0;

// Set counters to zero for displays / set variables for the score
  int Target_Count = 0;

**// Interval time for long and short press**
**  float value = 0;**

**  unsigned long interval_1 = 30;**
**  unsigned long interval_2 = 1000;**

**  unsigned long previousMillis1 = 0;**
**  unsigned long previousMillis2 = 0;**
  
void setup()
{
// Declare pins as outputs

  pinMode(Target_latchPin, OUTPUT);
  pinMode(Target_clkPin, OUTPUT);
  pinMode(Target_dataPin, OUTPUT);

// Declare buttons as inputs
  pinMode(Target_ButtonUp, INPUT_PULLUP);
  pinMode(Target_ButtonDown, INPUT_PULLUP);

  }
      // End of setup()


void loop() {
**// Set currentMillies = millis**
**   unsigned long currentMillis = millis();**

**   if (currentMillis - previousMillis2 >= interval_2) {**
**       //timer2 is done**
**       interval_1 = 30;//this is for timer1**
**     } else {**
**       //timer2 not done**
**       interval_1 = 500;//this is for timer1**
**     }**
//Read the Button Pins to see if one of them has been pressed
  Target_ButtonUpV = digitalRead (Target_ButtonUp);
  Target_ButtonDownV = digitalRead (Target_ButtonDown);
 
//Read the Button Pins to see if one of them has been pressed
 if (Target_ButtonUpV != Target_ButtonUpV_LastButtonState) {
// if the state has changed, increment the counter     
    if (Target_ButtonUpV == HIGH){
        **if (currentMillis - previousMillis1 >= interval_1) {**
**        if (Target_Count != 999) Target_Count+=1;**
**        previousMillis1 = currentMillis;**
**    }**
**  } else {//button is high, not pressed**
**    previousMillis2 = currentMillis;**
**      **
**      }**
** }**

 if (Target_ButtonDownV != Target_ButtonDownV_LastButtonState) {
// if the state has changed, decrement the counter     
    if (Target_ButtonDownV == HIGH){
      if (Target_Count != 0) Target_Count-=1;
    }
  }


// Save the current state as the last state for next time through the loop
  Target_ButtonUpV_LastButtonState = Target_ButtonUpV;
  Target_ButtonDownV_LastButtonState = Target_ButtonDownV;

  delay(50);

  UpdateDisplay();
}
  // End of loop()


//*******************************


// Shift 8 bits out MSB first

void ShiftBits(byte DataOut) 
{
 
  int i = 0;
  int pinState;
  
  digitalWrite(Target_dataPin, 0);
  digitalWrite(Target_clkPin, 0);
  
   for (i = 7; i >= 0; i--)  
    {
    digitalWrite(Target_clkPin, 0);
    
    if (DataOut & (1 << i)) 
      {
      pinState = 1;
      }
    else 
      {  
      pinState = 0;
      }
 
    digitalWrite(Target_dataPin, pinState);                 // Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(Target_clkPin, 1);                       // Register shifts bits on upstroke of clock pin  
    digitalWrite(Target_dataPin, 0);                        // Zero the data pin after shift to prevent bleed through
    }

  digitalWrite(Target_clkPin, 0);                         // Stop shifting
   
}   // End of ShiftBits()

//*******************************

void UpdateDisplay()
{
  
  int aDecValues[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 64 };    //103
  unsigned long temp1;
  boolean leadingZero;
    
  temp1 = Target_Count;
    
  int hundreds1 = temp1 / 100;
  temp1 -= (hundreds1 * 100);

  int tens1 = temp1 / 10;
  temp1 -= (tens1 * 10);

  int units1 = temp1;

if (leadingZero==false) // removing leading zeros
  {
    if (hundreds1==0 && tens1>0)      {
      hundreds1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1>0)          {
      hundreds1 = 64; 
      tens1 = 64;
    } 
    if (hundreds1==0 && tens1==0 && units1==0)          {
      hundreds1 = 64; 
      tens1 = 64;
      units1 = 64;
    }
  }
  
  digitalWrite(Target_latchPin, 0);
  ShiftBits(aDecValues[hundreds1]);
  ShiftBits(aDecValues[tens1]);                       // Update tens digit
  ShiftBits(aDecValues[units1]);                      // Update units digit 
  digitalWrite(Target_latchPin, 1);
  delay(100);                                        // Adjust this delay to vary the count time
 
}   // End of UpdateDisplay()

To do so, you should update the counter during the button hold. But the line below allows the code to access the counter on release event only:

Thanks
I'll change that

Thank you very much for your help. Appreciate. It works 100%.

Regards

So mark the thread as solved

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