B4R Tutorial LCD Bar Graph

Discussion in 'B4R Tutorials' started by Johan Schoeman, Jun 1, 2019.

  1. Johan Schoeman

    Johan Schoeman Expert Licensed User

    The attached project mimics this posting. Have added the basic functionality with inline C. It uses the rCore and rLiquidCrystal libraries.

    Wiring diagram:
    lcdbargraph_bb.png

    Result:
    20190601_164030.jpg


    Sample code (change it to your licking):
    Code:
    'LCD Display - LCD 1602
    'See attached wiring diagram


    #Region Project Attributes
        
    #AutoFlushLogs: True
        
    #CheckArrayBounds: True
        
    #StackBufferSize: 300
    #End Region

    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'Public variables can be accessed from all modules.
        Public Serial1 As Serial
        
    Dim lcd As LiquidCrystal
        
    Dim t As Timer
        
    Dim maxvalue As Byte = 100
        
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
        
        t.Initialize(
    "t_Tick"500)
        lcd.Initialize(
    8,255,9Array As Byte(4,5,6,7))
        Delay(
    10)
        lcd.Begin(
    162)
        lcd.Clear
        
        RunNative(
    "createOne",Null)
        RunNative(
    "createTwo",Null)
        RunNative(
    "createThree",Null)
        RunNative(
    "createFour",Null)
        RunNative(
    "createFive",Null)
        
        lcd.SetCursor(
    0,0)
        
        lcd.Write(
    "B4R - LCD Graph")
        Delay(
    3000)
        lcd.SetCursor(
    0,1)
        Delay(
    10)
        RunNative(
    "writeCharAlarm"0)
        
        t.Enabled = 
    True

    End Sub

    Sub t_Tick
        
        
    Dim i As Byte = Rnd(0, maxvalue + 1)
        lcd.Clear
        lcd.SetCursor(
    0,0)
        lcd.Write(
    "VALUE = ")
        lcd.SetCursor(
    8,0)
        lcd.Write(i)
        
        lcd.SetCursor(
    0,1)

        
    Dim full As Float = 16 * (i/maxvalue)
        
    Dim ff As Int = full
        
        
    Dim fraction As Int = Round(10 * (full - ff))
        fraction = 
    Round((fraction * 5 / 10))
        
        
    For j = 1 To full
            RunNative(
    "writeCharAlarm"4)
        
    Next
        
        
    If fraction = 1 Then
            RunNative(
    "writeCharAlarm"0)
        
    Else if fraction = 2 Then
            RunNative(
    "writeCharAlarm"1)
        
    Else if fraction = 3 Then
            RunNative(
    "writeCharAlarm"2)
        
    Else if fraction = 4 Then
            RunNative(
    "writeCharAlarm"3)
                
        
    End If

    End Sub

    #if C                         

        Byte One[8] = {
        B10000,
        B10000,
        B10000,
        B10000,
        B10000,
        B10000,
        B10000,
        B10000
    };

        byte Two[8] = {
        B11000,
        B11000,
        B11000,
        B11000,
        B11000,
        B11000,
        B11000,
        B11000
    };

        Byte Three[8] = {
        B11100,
        B11100,
        B11100,
        B11100,
        B11100,
        B11100,
        B11100,
        B11100
    };

        Byte Four[8] = {
        B11110,
        B11110,
        B11110,
        B11110,
        B11110,
        B11110,
        B11110,
        B11110
    };

        Byte Five[8] = {
        B11111,
        B11111,
        B11111,
        B11111,
        B11111,
        B11111,
        B11111,
        B11111
    };

        void createOne(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(0, One);
        }
        
        void createTwo(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(1, Two);
        }   
        
        void createThree(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(2, Three);
        }   
        
        void createFour(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(3, Four);
        }   
        
        void createFive(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(4, Five);
        }               

        void writeCharAlarm(B4R::Object* o) {
           b4r_main::_lcd->lc->write((Byte)o->toULong());
        }

    #end if
    There are most probably better ways to do this - but the lcd bar graph in the above/attached is working.
     

    Attached Files:

    Erel, Mashiane and MarkusR like this.
  2. Johan Schoeman

    Johan Schoeman Expert Licensed User

    Same wiring diagram as in post #1 above - it just takes away some of the unwanted flickering of the display while changing values. The below code will draw a bar graph in row 2 of the LCD display, starting at zero and going up to "maxvalue", and then down from maxvalue to zero (see comments added to the code) - actual value is displayed in Row 0 of the LCD display.

    Change the value of "maxvalue" for a different "range"
    Code:
    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'Public variables can be accessed from all modules.
        ....
        ....
        ....
        
    Dim maxvalue As Int = 100                        'set the maximum value to display
        ....
        ....
       
    End Sub


    Code:
    #Region Project Attributes
        
    #AutoFlushLogs: True
        
    #CheckArrayBounds: True
        
    #StackBufferSize: 300
    #End Region

    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'Public variables can be accessed from all modules.
        Public Serial1 As Serial
        
    Dim lcd As LiquidCrystal
        
    Dim t As Timer                                   'create a timer
        Dim maxvalue As Int = 100                        'set the maximum value to display
        Dim i As Byte
        
    Dim countupwards As Boolean = True               'are we counting up of down....
      
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
      
        t.Initialize(
    "t_Tick"200)                             'initialize the timer
        lcd.Initialize(8,255,9Array As Byte(4,5,6,7))         'using pins 4, 5, 6, 7 for data, pin 8 = RS, pin 9 = Enable
        Delay(10)
        lcd.Begin(
    162)                                        'set LCD display for 16 columns and 2 rows
        lcd.Clear
      
        RunNative(
    "createOne",Null)                             'create the character that displays one column of 8 pixels (on LCD 1602 there are 16 * 5 = 80 columns)
        RunNative("createTwo",Null)                             'create the character that displays two columns of 8 pixels
        RunNative("createThree",Null)                           'create the character that displays three columns of 8 pixels
        RunNative("createFour",Null)                            'create the character that displays four columns of 8 pixels
        RunNative("createFive",Null)                            'create the character that displays five columns of 8 pixels
      
        lcd.SetCursor(
    0,0)                                      'set the cursor to column 0, row 0
      
        lcd.Write(
    "B4R - LCD Graph")                            'display initial message
        Delay(1500)                                             'show initial message for 1.5 seconds
        lcd.Clear                                               'clear the display
        lcd.SetCursor(0,1)                                      'set the cursor to column 0, row 1
      
        t.Enabled = 
    True                                        'enable the time

    End Sub

    Sub t_Tick
      
        lcd.SetCursor(
    0,0)                                      'set cursor to column 0, row 0
        lcd.Write("VALUE = ")                                   'display "VALUE = "
        For k = 8 To 15                                         'write a space (" ") to the remainder colums of row 0
            lcd.SetCursor(k,0)
            lcd.Write(
    " ")                                      'write the space
        Next
        lcd.SetCursor(
    8,0)                                      'set the cursor to column 8, row 0 (rows and coluns start at 0)
        lcd.Write(i)                                            'write the value of i to the LCD - it will display for eg  "VALUE = 73"
      
        lcd.SetCursor(
    0,1)                                      'put the cursor at column 0, row 1 (preparing for the bar graph)

        
    Log("i = ", i)
        
    Dim full As Float = 16 * (i/maxvalue)                   'calculate how many chars of 5x8 are needed to draw the bar graph (eg if maxvalue = 100, then if value to display = 73, then 16 * 73/100 is the number of "chars"on the LCD display to switch on")
        Dim ff As Int = full                                    'get the INT number of full 5x8 chars to switch on
        Log("ff = ", ff)

      
        
    Dim fraction As Int = Round(10 * (full - ff))           'calculate the fraction of a "char" that must be switched on
        fraction = Round((fraction * 5 / 10))                   'eg if calue to display = 73 and maxvalue = 100, 73/100 = 0.73 * 16 = 11 full chars and 0.68 of a char
        Log("fraction = ", fraction)                            '0.68 of a char  = 0.68 * 5 = 3.4 (then rounding 3.4 to the nearest int)
        Log(" ")
      
        lcd.SetCursor(
    0,1)                                      'first, fill the number of full chars with 5*8 all switched on
        For j = 0 To ff - 1
            RunNative(
    "writeCharAlarm"4)                      'write the nuber of full chars
        Next
      
        
    If fraction = 1 Then                                    'now write the fractions
            RunNative("writeCharAlarm"0)                      'it can be 1 up to 4 rows of 8 (column) pixels - on a 16 * x display there 80 pixel columns
        Else if fraction = 2 Then
            RunNative(
    "writeCharAlarm"1)
        
    Else if fraction = 3 Then
            RunNative(
    "writeCharAlarm"2)
        
    Else if fraction = 4 Then
            RunNative(
    "writeCharAlarm"3)
        
    Else if fraction = 5 Then
            RunNative(
    "writeCharAlarm"4)
        
    Else if fraction = 0 Then
        
    End If

        
    Dim dummy As Int = 0                                   'want to determine where to clear the bar graph from without having to call lcd.Clear - it makes the display less flickering
        If fraction > 0 Then
            dummy = 
    1
        
    Else
            dummy = 
    0 
        
    End If

        
    Dim total_on As Int = ff + dummy                       'how many chars to clear in the bargraph after new bar graph has been written to the display

        
    For k = total_on To 15                                 'clear the excess "chars" in the bar graph
            If total_on < 16 Then
                lcd.SetCursor(k, 
    1)
                lcd.Write(
    " "
            
    End If
        
    Next
      
        
    If countupwards = True Then                         
            count_up                                           
    'count up from 0 to maxvalue and switch direction when getting to maxvalue - bar graph will follow suite
        Else
            count_down                                           
    'count down from maxvalue to 0 and switch direction when getting to maxvalue - bar graph will follow suite
        End If
      
      
    End Sub

    Sub count_up                                             'when counting up
      
        i = i + 
    1
        
    If i = maxvalue Then
            Delay(
    100)
            countupwards = 
    Not(countupwards)                 'switch counting direction
        End If
      
    End Sub

    Sub count_down                                            'when counting down
      
        i = i - 
    1
        
    If i = 0 Then
            Delay(
    100)
            countupwards = 
    Not(countupwards)                  'switch counting direction
        End If
      
    End Sub


    'the C code below creates the custom chars and displays them
    #if C                       

        Byte One[8] = {
        B10000,
        B10000,
        B10000,
        B10000,
        B10000,
        B10000,
        B10000,
        B10000
    };

        byte Two[8] = {
        B11000,
        B11000,
        B11000,
        B11000,
        B11000,
        B11000,
        B11000,
        B11000
    };

        Byte Three[8] = {
        B11100,
        B11100,
        B11100,
        B11100,
        B11100,
        B11100,
        B11100,
        B11100
    };

        Byte Four[8] = {
        B11110,
        B11110,
        B11110,
        B11110,
        B11110,
        B11110,
        B11110,
        B11110
    };

        Byte Five[8] = {
        B11111,
        B11111,
        B11111,
        B11111,
        B11111,
        B11111,
        B11111,
        B11111
    };

        //create ONE = one column ON (out of 80 columns on a 16*2 LCD display with 5 rows x 8 pixels per LCD char)
        void createOne(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(0, One);
        }
      
        //create TWO = two columns ON (out of 80 columns on a 16*2 LCD display with 5 rows x 8 pixels per LCD char)
        void createTwo(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(1, Two);
        } 
      
        //create THREE = three columns ON (out of 80 columns on a 16*2 LCD display with 5 rows x 8 pixels per LCD char) 
        void createThree(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(2, Three);
        } 
      
        //create FOUR = four columns ON (out of 80 columns on a 16*2 LCD display with 5 rows x 8 pixels per LCD char) 
        void createFour(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(3, Four);
        } 
      
        //create FIVE = five columns ON (out of 80 columns on a 16*2 LCD display with 5 rows x 8 pixels per LCD char) 
        void createFive(B4R::Object* o) {
           b4r_main::_lcd->lc->createChar(4, Five);
        }             

        //dispaly the char (0 to 4) that has been created and stored in the LCD Display
        void writeCharAlarm(B4R::Object* o) {
           b4r_main::_lcd->lc->write((Byte)o->toULong());
        }

    #end if
     
    Mostez likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice