Programming a progress bar to a lcd and led ring

Hello!
So I´m using a Uno Rev3 wifi board and I got the LCD to work using the I2C method. I have the progress bar coded out

 // progress bar kood
  byte bar1[8] = {
    B10000,
    B10000,
    B10000,
    B10000,
    B10000,
    B10000,
    B10000,
    B10000,
  };
  byte bar2[8] = {
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
  };
  byte bar3[8] = {
    B11100,
    B11100,
    B11100,
    B11100,
    B11100,
    B11100,
    B11100,
    B11100,
  };
  byte bar4[8] = {
    B11110,
    B11110,
    B11110,
    B11110,
    B11110,
    B11110,
    B11110,
    B11110,
  };
  byte bar5[8] = {
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
  };
  byte up[8] = {
    B00000,
    B00100,
    B01110,
    B11111,
    B11111,
    B00000,
    B00000,
  };

  byte down[8] = {
    B00000,
    B00000,
    B11111,
    B11111,
    B01110,
    B00100,
    B00000,
  };
  lcd.createChar(0, bar1);
  lcd.createChar(1, bar2);
  lcd.createChar(2, bar3);
  lcd.createChar(3, bar4);
  lcd.createChar(4, bar5);
  lcd.createChar(5, up);
  lcd.createChar(6, down);
}

Now my question is, how would I go about implementing the ring RGB led to activate and work with the created lcd.createChar value at the same time.

Using the Ws2812 LED with arduino Neopixel.

Thanks in advance -Kaimar

The LCD character value is between 0 and 6 so if you divide the number of LEDs in the ring by that value the result will be the number of LEDs to illuminate

Not sure what you mean here?

All binary numbers must be 8 digits long, yours are not.

Binary values are read from the right hand most bit, being the least significant bit, and the further you go left the more significance the bit has .

For more readability use hex in the form of a 0x prefix, so for example the number 3 could be encoded as 0x3.

this in the binary representation would be B00000011

Or more conventionally 0b00000011

Maybe I didn´t really explain myself well. That code that I but, works for the LCD, when a action is called the code starts and I get a progress bar, now I´ve never really worked with RGB led coding by neopixel before so I´m not entirely sure how I would merge similar call for the ring led. What I want is that while the progress bar on the LCD is moving the rgb ring would also be active going from 4 leds in red first, then 4 yellow and then 4 green. My idea is that I will but the led around the button that activates the progress bar, so if the player can not see the lcd they can follow the progress with the leds around the button.

void drawPorcent(byte porcent){
  //Vaja:kood on brute force, improve
  int aDibujar=(8*porcent)/10;
  lcd.setCursor(0,1);

  if(aDibujar<5)
  {
    switch(aDibujar){
    case 0:
      break;
    case 1:
      lcd.write((uint8_t)0);
      break;
    case 2:
      lcd.write(1);
      break;
    case 3:
      lcd.write(2);
      break;
    case 4:
      lcd.write(3);
      break;
    }
  }
  while(aDibujar>=5){
    if(aDibujar>=5)
    {
      lcd.write(4);
      aDibujar-=5;
    }
    if(aDibujar<5)
    {
      switch(aDibujar){
      case 0:
        break;
      case 1:
        lcd.write((uint8_t)0);
        break;
      case 2:
        lcd.write(1);
        break;
      case 3:
        lcd.write(2);
        break;
      case 4:
        lcd.write(3);
        break;
      }
    }
  }
}

This is basically a brute force version for making the progress bar active while the button is pressed.

You do not need this one, there is already such a character pre-defined. It is code 255. You could save one user-defined character for some other use.

Actually, that's not true, Mike. Using either the Bxxx or 0bxxx format, you can give any number of digits. For the Bxxx format, the maximum is 8 bits/digits. For the 0bxxx format, you can go to 64 bits (unsigned long long) to my knowledge.

Since the bits represent a pattern of pixels which are on or off, I think binary format is more readable in this case.

Im very new to coding with arduino, what exactly do you mean by pre-defined code 255. How would I go about improving it, so instead of calling for lcd.write(5)

void checkArrows(byte i,byte maxx ){

  if(i==0){
    lcd.setCursor(15,1);
    lcd.write(6); 
  }
  if(i==maxx){  
    lcd.setCursor(15,0);
    lcd.write(5);
  }
  if(i>0 && i<maxx){
    lcd.setCursor(15,1);
    lcd.write(6);
    lcd.setCursor(15,0);
    lcd.write(5);  
  }
}
lcd.write(255);

But since you have not used up all 8 available user-defined characters, I only mentioned it for interest.

1 Like

Thats good to know, I thank you for the advice, might come useful in the future when expanding the code and gamemodes.

Do you have a stand-alone code for the led ring?

With the LCD, using only spaces and the full block character, you can only represent 16 values with your bar graph. But by defining those user-defined characters, you have increased that to 80 values.

In a similar way, if your led ring has, say, 12 LEDs, you could only represent 12 values with the LEDs either on or off. But since you can also control the brightness of each led, you could increase that number by having one of the LEDs show 1/4, 1/2, 3/4 brightness, for example.

Actually, you only need to use 1 user-defined character for your bar graph. Instead of pre-defining characters with 1, 2, 3 or 4 pixels width, you could define only the one you actually need, just before you update the LCD, each time you update it.

Not sure that will work

If you define a character, print it then change the definition ready for the next required shape the one that you just printed will change as well

I did say

In fact, if the bar graph value to be displayed had changed only a little, you may only need to re-define the user-defined character, and not need to print anything to the LCD.

Please explain what you mean in more detail, bearing in mind that you said

The bar-graph will be made up of block characters (code 255) and spaces (code 32) except, if necessary, one character which will need to be 1, 2, 3 or 4 pixels wide.

You could dedicate 1 of the 8 user-defined characters for this purpose. Each time you update the bar-graph, you also update the definition of that character to show the required pixels.

I am already digging an LCD, breadboard and Nano out of my parts boxes...

OK. I think that I see what you are getting at

Define a character as 1 pixel wide and print it where you need it. When you need a character 2 pixels wide in the same position redefine the same character as 2 pixels wide and it will change immediately. There is no need to even print it again

Is that what you mean ?

This can give you a start point:

https://wokwi.com/projects/416702310621449217

#include <Wire.h>
#include <hd44780.h> // include hd44780 library header file
#include <hd44780ioClass/hd44780_I2Cexp.h> // i/o expander/backpack class
hd44780_I2Cexp lcd; // auto detect backpack and pin mappings

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

void setup()
{
  int status;

  status = lcd.begin(LCD_COLS, LCD_ROWS);
  if (status) // non zero status means it was unsuccesful
  {
    // begin() failed so blink error code using the onboard LED if possible
    hd44780::fatalError(status); // does not return
  }

}

void loop(void)
{
  static int lastFullBlocks = -1;
  static int lastPartialBlock = -1;
  static int lastValue = -1;

  int value = map(analogRead(A0), 0, 1023, 0, 79);

  if (value != lastValue) {

    lcd.setCursor(0, 0);
    if (value < 10) lcd.print("0");
    lcd.print(value);
  
    int fullBlocks = value / 5;
    int partialBlock = value % 5;
  
    if (lastFullBlocks != fullBlocks) {
      lcd.setCursor(0, 1);
      for (int i = 0; i < fullBlocks; i++) lcd.write(255);
      lcd.write(0);
      for (int i = fullBlocks + 1; i < 16; i++) lcd.write(32);
      lastFullBlocks = fullBlocks;
    }
  
    if (lastPartialBlock != partialBlock) {
      uint8_t pattern[5] = {0b00000, 0b10000, 0b11000, 0b11100, 0b11110};
      uint8_t p = pattern[partialBlock];
      uint8_t udc[8]  = {p, p, p, p, p, p, p, p};
      lcd.createChar(0, udc);
      lastPartialBlock = partialBlock;
    }

   lastValue = value;
  }

  delay(200);
}



(excuse my damaged LCD!)

1 Like

Are going to pull the plastic off, or am I?