Designing a Bar Meter for my audio conceptions

AntiLoop

Well-known member
Hi all,

I've been searching all over the net to find how to code such a level meter on a TFT (ILI9341_t3),wich have those colors:

bar meter.png


I don't really need the segments,but who knows who can do that...
I'm taking this exerpt from scratch:

Code:
float leftNumber = peak1.read();
      float rightNumber = peak2.read();
      Serial.print(leftNumber);
      Serial.print(", ");
      Serial.print(rightNumber);
      Serial.println();

      // draw the verticle bars
      int height = leftNumber * 200;
      tft.fillRect(20, 280 - height, 40, height, ILI9341_GREEN);
      tft.fillRect(20, 280 - 200, 40, 200 - height, ILI9341_BLACK);
      height = rightNumber * 200;
      tft.fillRect(65, 280 - height, 40, height, ILI9341_GREEN);
      tft.fillRect(65, 280 - 200, 40, 200 - height, ILI9341_BLACK);
      // a smarter approach would redraw only the changed portion...

I woud like to make the green color first show up to a certain level,then followed by orange and then followed by red in the same bar
and in this principe of level growing up.
All suggestions are welcome;)
 
Create an array of uint32_t bar_colors[30] (30, or however many bars you want to draw). Fill/initialize that array with the colors that you want (bar_colors[0] thru bar_colors[19] all set to ILI9341_GREEN, bar_colors[20] thru bar_colors[24] set to ILI9341_YELLOW, bar_colors[25] thru bar_colors[29] set to ILI9341_RED). As you use an index variable to step thru drawing the bars, use that bar_colors[] array (indexed by the bar number) to pass the desired color to your tft.fillRect() function call. Changing the color scaling (if you want more bars, more colors, etc.) is then as simple as changing the initialization values for the bar_colors[] array.

Mark J Culross
KD5RXT
 
Thanks! kd5rxt-mark
That is a good panoramic vision to begin this project,i never thought about arrays,i was also blocked with the redraw stuff,
but later i will see after that...
 
Finally i will keep your arrays idea to build later a peak meter with little segments,i'm sure it will be very nice

For the mixing colors,i make a selection with map for every color and then, some if conditions to accurate the bar meter:

Code:
if (msecs > 30) {
    if (peak1.available() && peak2.available()) {
      msecs = 0;
      
      float leftNumber = peak1.read();
      float rightNumber = peak2.read();     

      int leftValue = (int)(leftNumber * 100);//better use int values           
      int rightValue = (int)(rightNumber * 100);
    
      int leftGreen = map(leftValue,0,40,0,10);//all the colors mappings
      int rightGreen = map(leftValue,0,40,0,10);

      int leftOrange = map(leftValue,40,50,10,20);
      int rightOrange = map(leftValue,40,50,10,20);

      int leftYellow = map(leftValue,50,70,20,25);
      int rightYellow = map(leftValue,50,70,20,25);

      int leftRed = map(leftValue,70,100,25,30);
      int rightRed = map(leftValue,70,100,25,30);
      
                        

      // draw the verticle bars LEFT
      int height = leftNumber * 200;
      if(leftValue > 0 && leftValue < 55){
      tft.fillRect(20, 280 - leftGreen * 5, 20, leftGreen * 5, ILI9341_GREEN);
      tft.fillRect(20, 280 - 200, 20, 200 - leftGreen * 5 , ILI9341_BLACK);}

      if(leftValue > 50 && leftValue < 70){
      tft.fillRect(20, 280 - leftOrange * 5, 20, leftOrange * 5, ILI9341_ORANGE);
      tft.fillRect(20, 280 - 200, 20, 200 - leftOrange * 5 , ILI9341_BLACK);}
      
      if(leftValue > 65 && leftValue < 75){
      tft.fillRect(20, 250 - leftYellow * 5, 20, leftYellow * 5, ILI9341_YELLOW);
      tft.fillRect(20, 250 - 200, 20, 200 - leftYellow * 5, ILI9341_BLACK);}
      
      if(leftValue > 70 && leftValue < 100){
      tft.fillRect(20, 230 - leftRed * 5, 20, leftRed * 5, ILI9341_RED);
      tft.fillRect(20, 230 - 200, 20, 200 - leftRed * 5, ILI9341_BLACK);}



      // draw the verticle bars RIGHT
      
      if(rightValue > 0 && rightValue < 55){
      tft.fillRect(65, 280 - rightGreen * 5, 20, rightGreen * 5, ILI9341_GREEN);
      tft.fillRect(65, 280 - 200, 20, 200 - rightGreen * 5 , ILI9341_BLACK);}

      if(rightValue > 50 && rightValue < 70){
      tft.fillRect(65, 280 - rightOrange * 5, 20, rightOrange * 5, ILI9341_ORANGE);
      tft.fillRect(65, 280 - 200, 20, 200 - rightOrange * 5 , ILI9341_BLACK);}
      
      if(rightValue > 65 && rightValue < 75){
      tft.fillRect(65, 250 - rightYellow * 5, 20, rightYellow * 5, ILI9341_YELLOW);
      tft.fillRect(65, 250 - 200, 20, 200 - rightYellow * 5, ILI9341_BLACK);}
      
      if(rightValue > 70 && rightValue < 100){
      tft.fillRect(65, 230 - rightRed * 5, 20, rightRed * 5, ILI9341_RED);
      tft.fillRect(65, 230 - 200, 20, 200 - rightRed * 5, ILI9341_BLACK);}

30 max for the map output came from your array suggestion,i think it's not so bad :)
 
I've made an color array version,but all the colors seem to mix together,much of blue=green+yellow
certainly due to the display latency when the colors are falling down.

Code:
uint32_t bar_colors[30];
int leftValue = 0;
int rightValue = 0;
.
.
.
void setup():

for(leftValue = 0;leftValue <10;leftValue ++)
  {bar_colors[leftValue] = {ILI9341_GREEN};}
  for(leftValue = 10;leftValue <15;leftValue ++)
  {bar_colors[leftValue] = {ILI9341_YELLOW};}
  for(leftValue = 15;leftValue <25;leftValue ++)
  {bar_colors[leftValue] = {ILI9341_ORANGE};}
  for(leftValue = 25;leftValue <30;leftValue ++)
  {bar_colors[leftValue] = {ILI9341_RED};}
.
.
.
void loop():


if (msecs > 15) {
    if (peak1.available() && peak2.available()) {
      msecs = 0;
      
      float leftNumber = peak1.read();
      float rightNumber = peak2.read();     

       leftValue = (int)(leftNumber * 70);           
       rightValue = (int)(rightNumber * 70);
                                      

      // draw the verticle bars LEFT     
      
      tft.fillRect(20, 280 - leftValue * 3, 20, leftValue * 3, bar_colors[leftValue]);
      tft.fillRect(20, 280 - 200, 20, 200 - leftValue * 3 , ILI9341_BLACK);}
      

      // draw the verticle bars RIGHT     
      
      tft.fillRect(65, 280 - rightValue * 3, 20, rightValue * 3, bar_colors[rightValue]);
      tft.fillRect(65, 280 - 200, 20, 200 - rightValue * 3 , ILI9341_BLACK);
 
I have done something similar and displaying bar data on an ILI9341.

See this vid at the 10 sec mark (7:00 as well)

Code is here, but the display portion is at line 357

Mine is segment based but can be more "solid bar", change WIDTH - 1 to WIDTH - 0 (first instance is at line 368, but there are several lines that need changing)

Hope this helps.
 
Have a look at the decibel scale, i.e. 20*log10(linear_level), where the linear level is a float from 0.0 to 1.0. This gets you a value in dbFS (dB full scale) from -inf to 0. Take a range which makes sense for your application, e.g. -60 to 0.
 
Hi,kriskasprzak,
looks fine,i think it's a spectrum based bar level,was it really more important than a simple bar level?
but it looks close of what i would like to build,a level meter for my TDM project,i would like to monitor
for example,12 inputs and 16 outputs on a RA8875 7inch.-->teensy 4.1 + 2XCS42448 in TDM mode,
i'm sure it will be very nice to look at.
there are very impressive examples,like a spectral simulation in the RA8875 library from teensy.

Hi,TomChiron,
I don't know to whom you are talking?
kriskasprzak and his audio control or my bar level,wich is only a simple tentative but maybe later more accurate
for audio measuring or recording.But what you said about decibel scale is taken under the wood for later.
 
Hi,TomChiron,
I don't know to whom you are talking?
kriskasprzak and his audio control or my bar level,wich is only a simple tentative but maybe later more accurate
for audio measuring or recording.But what you said about decibel scale is taken under the wood for later.
You asked

....
I woud like to make the green color first show up to a certain level,then followed by orange and then followed by red in the same bar
and in this principe of level growing up.
All suggestions are welcome;)

and I offered my answer.
 
Ok Tom,sorry for my misunderstanding :oops:

You said "Have a look at the decibel scale, i.e. 20*log10(linear_level)"
But is the peak level reading from the teensy editor module sure enough to build db meter?
 
Last edited:
Back
Top