Bar graph

Hi
This program displays two bars 8 pixels high, how to change the high to 1 pixel ?

/* 
* Simple 2-channel VU-meter with peak detect - by mira308sw - 2013
* a crazy sketch for 16x2 lcd display
*/

#include <LiquidCrystal.h>

/* Modify the pin number below to meet your board
*/
#define IN_LEFT    4  // analog input for left channel
#define IN_RIGHT   5  // analog input for right channel

LiquidCrystal lcd( 8,  // RS
                   9,  // E
                   4,  // DB4
                   5,  // DB5
                   6,  // DB6
                   7   // DB7
                   );

/* Other minor configurable value
*/
#define T_REFRESH    100            // msec bar refresh rate
#define T_PEAKHOLD   3*T_REFRESH    // msec peak hold time before return

/* local variable
*/
byte  fill[6]={ 0x20,0x00,0x01,0x02,0x03,0xFF };      // character used to fill (0=empty  5=full)
byte  peak[7]={ 0x20,0x00,0x04,0x05,0x06,0x07,0x20 }; // character used to peak indicator
int   lmax[2];                                        // level max memory
int   dly[2];                                         // delay & speed for peak return

void  bar  ( int row,int lev )
{
  lcd.setCursor( 0,row );
  lcd.write( row ? 'R' : 'L' );
  for( int i=1 ; i<16 ; i++ )
  {
    int f=constrain( lev      -i*5,0,5 );
    int p=constrain( lmax[row]-i*5,0,6 );
    if( f )
      lcd.write( fill[ f ] );
    else
      lcd.write( peak[ p ] );
  }
  if( lev>lmax[row] )
  {
    lmax[row] = lev;
    dly[row]  = -(T_PEAKHOLD)/T_REFRESH;                // Starting delay value. Negative=peak don't move
  }
  else
  {
    if( dly[row]>0 )
      lmax[row] -= dly[row]; 

    if( lmax[row]<0 )
      lmax[row]=0;
    else
      dly[row]++;
  }
}

byte block[8][8]=
{
  { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 },  // define character for fill the bar
  { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 },
  { 0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C },
  { 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E },

  { 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 },  // define character for peak level
  { 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 },
  { 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02 },
  { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },
};

void  setup  ( void )
{
  lcd.begin( 16,2 );
  for( int i=0 ; i<8 ; i++ )
    lcd.createChar( i,block[i] );
}

long  lastT=0;

void  loop  ( void )
{
  if( millis()<lastT )
    return;
  lastT += T_REFRESH;    
  int anL = map( sqrt( analogRead( IN_LEFT  )*16 ),0,128,0,80 );  // sqrt to have non linear scale (better was log)
  int anR = map( sqrt( analogRead( IN_RIGHT )*16 ),0,128,0,80 );
  bar( 0,anL );
  bar( 1,anR );
}

Depending on whether you want the top or bottom single pixel, you will have to alter the definitions of "block" by zeroing all but either the first or last byte (depending on whether you want the top or bottom pixel, which will be the same for both channels) in each row of the definition.

Do you mean like this ?

 { 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  // define character for fill the bar
  { 0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
{ 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  // define character for peak level
  { 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },

It is not working properly, some random additional pixels are showing up.

The problem could be in this lines, but I don't know how to work with them

byte  fill[6]={ 0x20,0x00,0x01,0x02,0x03,0xFF };      // character used to fill (0=empty  5=full)
byte  peak[7]={ 0x20,0x00,0x04,0x05,0x06,0x07,0x20 }; // character used to peak indicator

with this modification

/*


    https://forum.arduino.cc/index.php?topic=163354.0


  Simple 2-channel VU-meter with peak detect - by mira308sw - 2013


  a crazy sketch for 16x2 lcd display


*/





#include <LiquidCrystal.h>





/* Modify the pin number below to meet your board


*/


#define IN_LEFT   A0  // analog input for left channel


#define IN_RIGHT   A1  // analog input for right channel


[color=#222222][/color]
[color=#222222]LiquidCrystal 
lcd( 8,  // RS[/color][color=#222222][/color]
[color=#222222]  
                 9,  // E[/color][color=#222222][/color]
[color=#222222]  
                 4,  // DB4[/color][color=#222222][/color]
[color=#222222]  
                 5,  // DB5[/color][color=#222222][/color]
[color=#222222]  
                 6,  // DB6[/color][color=#222222][/color]
[color=#222222]  
                 7   // DB7[/color][color=#222222][/color]
[color=#222222]  
                 );[/color]


/* Other minor configurable value


*/


#define T_REFRESH    100            // msec bar refresh rate


#define T_PEAKHOLD   3*T_REFRESH    // msec peak hold time before 
return





/* local variable


*/


//byte  fill[6] = { 0x20, 0x00, 0x01, 0x02, 0x03, 0xFF }; // character used 
to fill (0=empty  5=full)


//byte  peak[7] = { 0x20, 0x00, 0x04, 0x05, 0x06, 0x07, 0x20 }; // 
character used to peak indicator


////////////////////


byte  fill[6] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}; // character used to 
fill (0=empty  5=full)


byte  peak[7] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // character 
used to peak indicator


////////////////////


int   lmax[2];                                        // level max 
memory


int   dly[2];                                         // delay & speed 
for peak return





void  bar  ( int row, int lev )


{


  lcd.setCursor( 0, row );


  lcd.write( row ? 'R' : 'L' );


  for ( int i = 1 ; i < 16 ; i++ )


  {


    int f = constrain( lev      - i * 5, 0, 5 );


    int p = constrain( lmax[row] - i * 5, 0, 6 );


    if ( f )


      lcd.write( fill[ f ] );


    else


      lcd.write( peak[ p ] );


  }


  if ( lev > lmax[row] )


  {


    lmax[row] = lev;


    dly[row]  = -(T_PEAKHOLD) / T_REFRESH;              // Starting delay 
value. Negative=peak don't move


  }


  else


  {


    if ( dly[row] > 0 )


      lmax[row] -= dly[row];





    if ( lmax[row] < 0 )


      lmax[row] = 0;


    else


      dly[row]++;


  }


}





byte block[8][8] =


{


  /*


  { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, // define character 
for fill the bar


  { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },


  { 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C },


  { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E },


  */


  ///////////////


  { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // define character 
for fill the bar


  { 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },


  { 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },


  { 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },


  //////////////


  /*


    { 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 },  // define character for 
peak level


    { 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 },


    { 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02 },


    { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },


  */


  /////////////////


{ 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  // define character for peak 
level


  { 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },


  { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },


  { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },


  ////////////////


};





void  setup  ( void )


{


  lcd.begin( 16, 2 );


  for ( int i = 0 ; i < 8 ; i++ )


    lcd.createChar( i, block[i] );


}





long  lastT = 0;





void  loop  ( void )


{


  if ( millis() < lastT )


    return;


  lastT += T_REFRESH;


  //int anL = map( sqrt( analogRead( IN_LEFT  )*16 ),0,128,0,80 );  // sqrt 
to have non linear scale (better was log)


  int anL = map( sqrt( analogRead( IN_LEFT  ) * 5.5 ), 0, 128, 0, 80 
);


  int anR = map( sqrt( analogRead( IN_RIGHT ) * 16 ), 0, 128, 0, 80 
);


  bar( 0, anL );


  bar( 1, anR );


}

I have like this lines.

bar a.jpg

they should be like that



bar a.jpg

post #3 code correction

/*
    https://forum.arduino.cc/index.php?topic=163354.0
  Simple 2-channel VU-meter with peak detect - by mira308sw - 2013
  a crazy sketch for 16x2 lcd display
*/


#include <LiquidCrystal.h>


/* Modify the pin number below to meet your board
*/
#define IN_LEFT   A0  // analog input for left channel
#define IN_RIGHT   A1  // analog input for right channel

LiquidCrystal lcd( 8,  // RS
                   9,  // E
                   4,  // DB4
                   5,  // DB5
                   6,  // DB6
                   7   // DB7
                   );
/* Other minor configurable value
*/
#define T_REFRESH    100            // msec bar refresh rate
#define T_PEAKHOLD   3*T_REFRESH    // msec peak hold time before return


/* local variable
*/
//byte  fill[6] = { 0x20, 0x00, 0x01, 0x02, 0x03, 0xFF }; // character used to fill (0=empty  5=full)
//byte  peak[7] = { 0x20, 0x00, 0x04, 0x05, 0x06, 0x07, 0x20 }; // character used to peak indicator
////////////////////
byte  fill[6] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}; // character used to fill (0=empty  5=full)
byte  peak[7] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // character used to peak indicator
////////////////////
int   lmax[2];                                        // level max memory
int   dly[2];                                         // delay & speed for peak return


void  bar  ( int row, int lev )
{
  lcd.setCursor( 0, row );
  lcd.write( row ? 'R' : 'L' );
  for ( int i = 1 ; i < 16 ; i++ )
  {
    int f = constrain( lev      - i * 5, 0, 5 );
    int p = constrain( lmax[row] - i * 5, 0, 6 );
    if ( f )
      lcd.write( fill[ f ] );
    else
      lcd.write( peak[ p ] );
  }
  if ( lev > lmax[row] )
  {
    lmax[row] = lev;
    dly[row]  = -(T_PEAKHOLD) / T_REFRESH;              // Starting delay value. Negative=peak don't move
  }
  else
  {
    if ( dly[row] > 0 )
      lmax[row] -= dly[row];


    if ( lmax[row] < 0 )
      lmax[row] = 0;
    else
      dly[row]++;
  }
}


byte block[8][8] =
{
  /*
  { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, // define character for fill the bar
  { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },
  { 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C },
  { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E },
  */
  ///////////////
  { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // define character for fill the bar
  { 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  { 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  { 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  //////////////
  /*
    { 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 },  // define character for peak level
    { 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 },
    { 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02 },
    { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },
  */
  /////////////////
{ 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  // define character for peak level
  { 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  ////////////////
};


void  setup  ( void )
{
  lcd.begin( 16, 2 );
  for ( int i = 0 ; i < 8 ; i++ )
    lcd.createChar( i, block[i] );
}


long  lastT = 0;


void  loop  ( void )
{
  if ( millis() < lastT )
    return;
  lastT += T_REFRESH;
  //int anL = map( sqrt( analogRead( IN_LEFT  )*16 ),0,128,0,80 );  // sqrt to have non linear scale (better was log)
  int anL = map( sqrt( analogRead( IN_LEFT  ) * 5.5 ), 0, 128, 0, 80 );
  int anR = map( sqrt( analogRead( IN_RIGHT ) * 16 ), 0, 128, 0, 80 );
  bar( 0, anL );
  bar( 1, anR );
}

try

byte  fill[6] = { 0b11111, 0x00, 0x00, 0x00, 0x00, 0x00}; // character used to fill (0=empty  5=full)
byte  peak[7] = { 0b11111, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // character used to peak indicator

if it is wrong, show a picture of the LCD and describe what you want do get instead.

No changes, screen the same as in post #3
This what I need = one row for numbers and second for bars

2 bars 2.jpg

This I get from one row and one input, I need 2 inputs.

2 bars 2.jpg

this would need a major work, if you want to display both baragraphs IN ONE LINE.
a 5 + 5 pixel combination would request to prepare 10 custom chars, but you only can use 5 custom chars.
So one way would be to define the last char during runtime and change it according to the remainder of the two values.

define 3 custom chars with
line top
line bottom
line both

and try show it according to your values.
If this works, let's do the final step to make the end of the line / the last character dynamic

I have them = 3 custom chars, but first I want to display correctly just 2 top lines.

any way to adapt to lcd 20x4?

and set the bar graphs to (2,3 rows) otherwise that (0,1 rows)??
thanks

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