BV4512 Code Examples

(NOTE the BV4219 has been superseded by the BV4512 which is functionally compatible for the I2C version).

The example presented here is for the BV513, physical connection to the BV513 must include pull up resistors, the details for which can be found in the Connection section. The source code including the volt meter example is in the downloads section.

Voltage meter example

The following is by no means complete but will provide some basic understanding of how to use the device. The initialisation section uses i2ctest and will report if the device is not connected properly. There are a couple of text and a couple of graphics functions but it may actually be easier to simply send the commands directly via the i2write statement.

// Example of using the BV4512 formally the BV4219
// with PIC32 Basic
//
constant LCDGADR 0x42

// initialise and check address
function lcdg_init
    i2copen 400000
    if i2ctest(LCDGADR) = 0 then
        print "Device not connected at address ";hex$(LCDGADR)
    endif
endf

// ----------- Text functions ----------------------
//
// put character to display at current location
// use: lcd20_putc('a')
// lcd20_putc(97)
function lcdg_putc(c)
    i2cwrite LCDGADR 0x20 c
endf

// prints a string to display at current position
function lcdg_puts(s$)
dim j
    for j = 1 to len(s$)
        lcdg_putc(asc(s$,j))
    next
endf

// set line and current position, line is 0 or 7 snd
// postion is 0 to 20
// use: lcd20_lp(1,5)
function lcdg_lp(line,pos)
    i2cwrite LCDGADR 0x25 line pos // set line & pos
endf

// clear screen and home cursor
function lcdg_cls
    i2cwrite LCDGADR 0x05
endf

// -------------- Graphic Functions ----------------
//
// Draw horizontal and vertical lines atarting at given
// co-ordimates where
// x: horixontal 0-127
// y: vertical 0-63
function lcdg_Hline(x,y, length)
    i2cwrite LCDGADR 0x12 x y length
endf
function lcdg_Vline(x,y, length)
    i2cwrite LCDGADR 0x14 x y length
endf
//
// Draws a box N no fill F filled
// x,y are the top left hand corner of the box and
// xl, yl are the lengths of the sides
function lcdg_Nbox(x,y,xl,yl)
    i2cwrite LCDGADR 0x16 x y xl yl
endf
function lcdg_Fbox(x,y,xl,yl)
    i2cwrite LCDGADR 0x18 x y xl yl
endf

Volt Meter

volt meter lcd display

Just to take the example a little further, here is a very simple volt meter that obtains the voltage form ADC channel 0 (RB0, JP3-16) and presents it as text and a moving arrow made up of three vertical lines.

The initialise routine opens the ADC channel 0 that will be used later, after initialising and clearing the screen the word 'Volts' is written. The graticule consists of 4 vertical lines, the numbers 0-3 and a rectangle. The positioning of the vertical lines has been chosen to correspond with the voltage displayed. To get the text to be exactly under the graticule lines the 'x' position command has been used before placing the text. The last instruction simply draws the rectangle.

The function that draws the bar representing the voltage 'v_bar' uses a very simple method to clear the last bar (room for much improvement here) it simply overwrites anything that was there with text 'space' after first setting the correct starting position with lcdg_lp(). The voltage is presented as the actual voltage so the value can range between 0 and 3.3. This is converted by v_bar() to give a suitable horizontal position. In fact this was done before the graticule, that's where the graticule values came from:

0 >> (0 * 25)+10    = 10
1 >> (1 * 35)+10    = 45
2 >> (2 * 35)+10    = 80
3 >> (3 * 35)+10    = 115

The actual voltage is obtained from 'v_volts#' and this assumes that the actual reference voltage is 3.3V, this can of course be adjusted. On the BV513 it is actually slightly less as it is smoothed via a 100R resistor. Ideally the input to the ADC needs a filter circuit to smooth out the variations, this can be done in software by taking several samples and then averaging which is what has been done here.

The last function 'go' puts all of this together in a continuous loop, to exit the loop press any key at the keyboard. This example has been kept as simple as possible and so there is a lot of room for improvement.

// ---------- Sample voltage indicator ----------------
//
// Initialise ADC and set up a clean display with
// graticule
function v_init
    openadc 30 0
    lcdg_init
    lcdg_cls
    lcdg_puts("Volts")
    // graticule on line 2
    lcdg_Vline(10,24,7) // 0v
    lcdg_Vline(45,24,7) // 1v
    lcdg_Vline(80,24,7) // 2v
    lcdg_Vline(115,24,7) // 3v
    // numbers on line 4 in pixel positions
    lcdg_lp(4,0) // correct line
    i2cwrite LCDGADR 7 8
    lcdg_putc('0')
    i2cwrite LCDGADR 7 43
    lcdg_putc('1')
    i2cwrite LCDGADR 7 78
    lcdg_putc('2')
    i2cwrite LCDGADR 7 113
    lcdg_putc('3')
    // box to put line in
    lcdg_Nbox(6,15,119,10)
endf

function v_bar(volts#)
dim v#=(volts#*35)+10
    lcdg_lp(2,1)
    lcdg_puts("                   ") // clear
    lcdg_Vline(v#,16,6)
    lcdg_Vline(v#+1,16,8)
    lcdg_Vline(v#+2,16,6)
endf

// prints voltahe next to 'Volts'
function v_vdisp(v#)
dim j
// clear last reading
    lcdg_lp(0,6)
    for j = 1 to 5
        lcdg_putc(' ')
    next
    lcdg_lp(0,6)
    lcdg_puts(format$("#.###",v#))
endf

// gets software smoothed out voltage
// voltage is represented by 1023=3.3V so
// voltage constant is 3.3/1023 = 0.0032258
function v_volts#
dim av=0, j, v#
    for j=1 to 300
        av=av+adc(0)
    next
    av=av/300
    v#=av*0.0032258
    result v#
endf

function go
dim k=5, v#
    v_init
    while key?(2) = 0
        v#=v_volts#
        v_vdisp(v#)
        v_bar(v#)
    wend
endf