flashing custom number help on a lcd i2c

Hi,
i am trying to make a large custom number flash with the press of a button, i can do it with an led or text on lcd but cant make it happen with the number function.
any help would be great

/*
 * customChars
 *
 * This sketch displays double-height digits
 * the bigDigit arrays were inspired by Arduino forum member dcb
 */
//#include <LiquidCrystal.h>
#include <Wire.h>

// 2. for the LCD functions
#include <LiquidCrystal_I2C.h>
int button = 4;
int count = 0;
int upLastTime, downLastTime, upNow, downNow;

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
byte glyphs[5][8] = {
  { B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000  } ,
  { B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111  } ,
  { B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111  } ,
  { B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111  } ,
  { B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110  } };
const int digitWidth = 3; // the width in characters of a big digit (excludes space between characters)
//arrays  to index into custom characters that will comprise the big numbers
// digits 0 - 4                             0      1       2      3      4
const char bigDigitsTop[10][digitWidth]={ 3,0,3, 0,3,32, 2,2,3, 0,2,3, 3,1,3,
// digits 5-9                               5      6      7        8      9
                                          3,2,2, 3,2,2, 0,0,3,   3,2,3, 3,2,3};
const char bigDigitsBot[10][ digitWidth]={ 3,1,3, 1,3,1,  3,1,1, 1,1,3, 32,32,3,
                                           1,1,3, 3,1,3, 32,32,3, 3,1,3, 1,1,3};
char buffer[12]; // used to convert a number into a string
void setup ()
{
  pinMode (button,INPUT_PULLUP);
  lcd.begin(16,2);
  lcd.setCursor(3, 0); // top left
  lcd.print("ENIGMA ver1");
  // create the custom glyphs
 for(int i=0; i < 5; i++)
   lcd.createChar(i, glyphs[i]);   // create the 5 custom glyphs
  // show a countdown timer
 // for(int digit = 9; digit >= 0; digit--)
  //{
    //showDigit(digit, 2);  // show the digit
    //delay(1000);
 // }
  lcd.clear();
}


void loop ()
{
  upNow = digitalRead(button); 
 if (upNow == HIGH && upLastTime == LOW) { 
  //lcd.setCursor(0,0);
  //lcd.print(count++);
   showNumber( count++, 0);
   


    delay(20); // bit of debounce delay
 }  
 upLastTime= upNow;  
  
if(count > 99) count = 0;
  }

void showDigit(int digit, int position)
{
  lcd.setCursor(position * (digitWidth + 1), 0);
   for(int i=0; i < digitWidth; i++)
      lcd.print(bigDigitsTop[digit][i]);
   lcd.setCursor(position * (digitWidth + 1), 1);
   for(int i=0; i < digitWidth; i++)
      lcd.print(bigDigitsBot[digit][i]);
}
void showNumber(int value, int position)
{
 int index; // index to the digit being printed, 0 is the leftmost digit
    itoa(value, buffer, 10); // see Recipe 2.8 for more on using itoa
    // dislay each digit in sequence
    for(index = 0; index < 10; index++) // display up to ten digits
    {
      char c = buffer[index];
      if( c == 0)  // check for null (not the same as '0')
         return; // the end of string character is a null, see Chapter 2
      c = c - 48; // convert ascii value to a numeric value  (see Recipe 2.9)
      showDigit(c, position + index);
    }
}

What isn't working the way you expect?
It seems to work for me as designed.
The big number on the LCD increments each time the button is released.

There is some debouncing issues which can cause more than one increment, but other than that it seems to be working.
--- bill

Thanks for your reply.
What i want to do is press the button and the number flashes on and off repeatedly, till the button is pressed again.

Managed to get it to flash with a while loop however cant manage to break out of it when the button is pressed again

/*
 * customChars
 *
 * This sketch displays double-height digits
 * the bigDigit arrays were inspired by Arduino forum member dcb
 */
//#include <LiquidCrystal.h>
#include <Wire.h>

// 2. for the LCD functions
#include <LiquidCrystal_I2C.h>
int button = 4;
int count = 0;
int upLastTime, downLastTime, upNow, downNow;
int stoploop = false;

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
byte glyphs[5][8] = {
  { B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000  } ,
  { B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111  } ,
  { B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111  } ,
  { B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111  } ,
  { B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110  } };
const int digitWidth = 3; // the width in characters of a big digit (excludes space between characters)
//arrays  to index into custom characters that will comprise the big numbers
// digits 0 - 4                             0      1       2      3      4
const char bigDigitsTop[10][digitWidth]={ 3,0,3, 0,3,32, 2,2,3, 0,2,3, 3,1,3,
// digits 5-9                               5      6      7        8      9
                                          3,2,2, 3,2,2, 0,0,3,   3,2,3, 3,2,3};
const char bigDigitsBot[10][ digitWidth]={ 3,1,3, 1,3,1,  3,1,1, 1,1,3, 32,32,3,
                                           1,1,3, 3,1,3, 32,32,3, 3,1,3, 1,1,3};
char buffer[12]; // used to convert a number into a string
void setup ()
{
  pinMode (button,INPUT_PULLUP);
  lcd.begin(16,2);
  lcd.setCursor(3, 0); // top left
  lcd.print("ENIGMA ver1");
  // create the custom glyphs
 for(int i=0; i < 5; i++)
   lcd.createChar(i, glyphs[i]);   // create the 5 custom glyphs
  // show a countdown timer
 // for(int digit = 9; digit >= 0; digit--)
  //{
    //showDigit(digit, 2);  // show the digit
    //delay(1000);
 // }
  lcd.clear();
}


void loop ()
{
  upNow = digitalRead(button);
 if (upNow == HIGH && upLastTime == LOW) {
  //lcd.setCursor(0,0);
  //lcd.print(count++);
   showNumber( count++, 0);
while(stoploop = true) {
   
  showNumber(count,0);
  delay(1000);
   lcd.clear();
  delay(1000);
  showNumber(count,0);
  
 }
   


    delay(20); // bit of debounce delay
 } 
 upLastTime= upNow; 
 
if(count > 99) count = 0;
  }

void showDigit(int digit, int position)
{
  lcd.setCursor(position * (digitWidth + 1), 0);
   for(int i=0; i < digitWidth; i++)
      lcd.print(bigDigitsTop[digit][i]);
   lcd.setCursor(position * (digitWidth + 1), 1);
   for(int i=0; i < digitWidth; i++)
      lcd.print(bigDigitsBot[digit][i]);
}
void showNumber(int value, int position)
{
 int index; // index to the digit being printed, 0 is the leftmost digit
    itoa(value, buffer, 10); // see Recipe 2.8 for more on using itoa
    // dislay each digit in sequence
    for(index = 0; index < 10; index++) // display up to ten digits
    {
      char c = buffer[index];
      if( c == 0)  // check for null (not the same as '0')
         return; // the end of string character is a null, see Chapter 2
      c = c - 48; // convert ascii value to a numeric value  (see Recipe 2.9)
      showDigit(c, position + index);
    }
}

To do that kind of stuff, you need some state information to keep track of what state you are in.
(i.e. blinking vs not blinking, vs increment)
And no matter what state you are in you still have to look at the button.
The state will determine if you flash or not flash, or increment the value.

You may want to take a look at using a button library to read the button.
It can simplify things as it does the debouncing and tracking state information of the button.
You can even to things like long presses.
Here is one that I like to use: GitHub - JChristensen/JC_Button: Arduino library to debounce button switches, detect presses, releases, and long presses
It isn't available in the library manager but you can download it and install it from a zip file using the library manager.

It won't solve the state issue for your flashing/not-flashing state but it could make testing the button status simpler.

--- bill

i can do it(flash) with an led or text on lcd but cant make it happen with the number function.

How did you achieve the flashing in these cases?

You will need to separate the button press for the increment from the flashing display of the number. Now, the display function is buried inside of the increment function.

Decide what number you want to display. Then you can flash it. You will need to turn the number on an off with non blocking techniques in order to stay responsive to a button press.

You know, if you are always going to flash the entire display, it would be easier to use
lcd.noDisplay() and lcd.display() to turn off all the pixels and back on again.
That way you don't have to do all the lookups and re-draw the screen or even know what is on the display.
Just turn off all the pixels wait a bit, then turn them back on.

--- bill

Thanks for the reply's

have it nearly working, however it will only flash on every second number or button press is there a way to get around this?

/*
 * customChars
 *
 * This sketch displays double-height digits
 * the bigDigit arrays were inspired by Arduino forum member dcb
 */
//#include <LiquidCrystal.h>
#include <Wire.h>

// 2. for the LCD functions
#include <LiquidCrystal_I2C.h>
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50; 
int button = 4;
int button2 = 5;
int count = 0;
int upLastTime, downLastTime, downNow;
int upNow = HIGH;
int downpin = 3;
int buttonHoldTime = 0;
const byte buttonPin = 6;
const byte ledPin = 13;
const byte buttonpin2 = 5;
int buttonstate2 = 0;
boolean flashing = false;
byte currentButtonState = HIGH;
byte currentButtonState1 = HIGH;
byte previousButtonState = HIGH;
byte previousButtonState1 = HIGH;
unsigned long currentTime;
unsigned long onoffStarted;
long flashPeriod = 1000;
bool lcdstate = true;
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
byte glyphs[5][8] = {
  { B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000  } ,
  { B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111  } ,
  { B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111  } ,
  { B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111  } ,
  { B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110  } };
const int digitWidth = 3; // the width in characters of a big digit (excludes space between characters)
//arrays  to index into custom characters that will comprise the big numbers
// digits 0 - 4                             0      1       2      3      4
const char bigDigitsTop[10][digitWidth]={ 3,0,3, 0,3,32, 2,2,3, 0,2,3, 3,1,3,
// digits 5-9                               5      6      7        8      9
                                          3,2,2, 3,2,2, 0,0,3,   3,2,3, 3,2,3};
const char bigDigitsBot[10][ digitWidth]={ 3,1,3, 1,3,1,  3,1,1, 1,1,3, 32,32,3,
                                           1,1,3, 3,1,3, 32,32,3, 3,1,3, 1,1,3};
char buffer[12]; // used to convert a number into a string
void setup ()
{
  pinMode (buttonPin,INPUT_PULLUP);
  pinMode (buttonpin2,INPUT_PULLUP);
  pinMode(downpin,INPUT_PULLUP);
  lcd.begin(16,2);
  lcd.setCursor(3, 0); // top left
  lcd.print("ENIGMA ver1");
  // create the custom glyphs
 for(int i=0; i < 5; i++)
   lcd.createChar(i, glyphs[i]);   // create the 5 custom glyphs
  // show a countdown timer
 // for(int digit = 9; digit >= 0; digit--)
  //{
    //showDigit(digit, 2);  // show the digit
    //delay(1000);
 // }
  lcd.clear();
}


void loop ()
{
 currentButtonState = digitalRead(buttonPin);
 
 
 // If the switch changed, due to noise or pressing:
 if (currentButtonState != previousButtonState ) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > 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 (currentButtonState != previousButtonState && currentButtonState == LOW)  //button has become pressed
  {
    
    showNumber(count+=4,0);
    
    flashing = !flashing;
  }
  
  
  previousButtonState = currentButtonState;          //save the button state for the next check
  
  if (flashing)
  {
    currentTime = millis();
    if (currentTime - onoffStarted > flashPeriod)  //if the flash period ended ?
    {
      if (lcdstate == true) {     //check to see state of lcd
          lcdstate = false;         //flip state of lcd
        }
        else if (lcdstate == false) {
          lcdstate = true;
        }

    

        if ( lcdstate == true) {        //the bool argument for lcdstate (true/false)
          lcd.display();
          lcd.setCursor(0,0);
         
        }
        else if ( lcdstate == false) {
          lcd.noDisplay();
     
        } //flip the state of the Lcd
      onoffStarted = currentTime;                  //save the time when it occured
    }
  }
  
 
  
  //buttonstate2 = digitalRead(buttonpin2);

  if(digitalRead (buttonpin2) == LOW){
    flashing = false;
    digitalWrite(ledPin,LOW); 
    
  
    }


currentButtonState1 = digitalRead(downpin);
  if (currentButtonState1 != previousButtonState1 && currentButtonState1 == LOW)  //button has become pressed
  {
    showNumber(count-=4,0);
    
    flashing = !flashing;
   
  }
  previousButtonState1 = currentButtonState1;          //save the button state for the next check
 
  if (flashing)
  {
    currentTime = millis();
    if (currentTime - onoffStarted > flashPeriod)  //if the flash period ended ?
    {
      if (lcdstate == true) {     //check to see state of lcd
          lcdstate = false;         //flip state of lcd
        }
        else if (lcdstate == false) {
          lcdstate = true;
        }



        if ( lcdstate == true) {        //the bool argument for lcd state (true/false)
          lcd.display();
          lcd.setCursor(0,0);
          
        }
        else if ( lcdstate == false) {
          lcd.noDisplay();
          
 
        } //flip the state of the LED
      onoffStarted = currentTime;      
                 //save the time when it occured
    }
  }
  else
  {
    
    
  }
if(count < 4) count = 0;
  


   }

void showDigit(int digit, int position)
{
  lcd.setCursor(position * (digitWidth + 1), 0);
   for(int i=0; i < digitWidth; i++)
      lcd.print(bigDigitsTop[digit][i]);
   lcd.setCursor(position * (digitWidth + 1), 1);
   for(int i=0; i < digitWidth; i++)
      lcd.print(bigDigitsBot[digit][i]);
}
void showNumber(int value, int position)
{
 int index; // index to the digit being printed, 0 is the leftmost digit
    itoa(value, buffer, 10); // see Recipe 2.8 for more on using itoa
    // dislay each digit in sequence
    for(index = 0; index < 10; index++) // display up to ten digits
    {
      char c = buffer[index];
      if( c == 0)  // check for null (not the same as '0')
         return; // the end of string character is a null, see Chapter 2
      c = c - 48; // convert ascii value to a numeric value  (see Recipe 2.9)
      showDigit(c, position + index);
    }
}

it will only flash on every second number or button press

It looks like you are alternating between flashing an not flashing with each buttonPin or downPin press.

I think you are using buttonPin2 to control the flash/no flash.

If that's the case, the other pin presses should just increment/decrement and set the mode to flashing.

Hi,

yes Button 2 is for switching off, i need the other button to perform the 2 functions of incrementing the number and start the flashing.

yes Button 2 is for switching off, i need the other button to perform the 2 functions of incrementing the number and start the flashing.

I think I understand. Why when you respond to an increment/decrement button press to you have

 flashing = !flashing;

This toggles the state of flashing. What happens if you replace that line with

flashing = true;

Brilliant!!!!

thank you that works!!