LCD/OLED analogue bargraph

nick12ab

Senior Member
Due to this thread, I wrote my own version of the bargraph code. However as it had already been done at least twice before I've also produced some variants to not make this thread just a waste of space with nothing new.

Improved versions of all three bargraph styles shown here are now available, but currently only for parallel LCDs/OLEDs.
The new improved versions use a convenient gosub for the bargraph and attributes of the bargraph such as length and position can be conveniently set via variables - this makes it easy to have multiple bargraphs on the display at once. On the originals it is hard to change some of these properties due to all the values (except for the value) being constants. If you want to use a serial LCD then you are stuck with the originals. The parallel LCD versions are much more 'responsive' than the serial LCD versions because of not having a slow serial interface, therefore even if I do eventually do serial LCD versions they will still be quite sluggish i.e. if the value of the bar is set using a potentiometer then turning the knob quickly from one end to the other will cause the bargraph to increment smoothly whilst it is being turned when using the parallel interface but when using the serial interface the bar will jump up in big steps.

Remember, AXE133 users can simply plug their programming cable into the AXE133 and reprogram the built-in PICAXE-18M2 to benefit immediately from the parallel LCD/OLED interface, and if for some reason you want to go back to using this as a serial display then program the 18M2 with the serial firmware available on the PICAXE website.

The already-done one



Click here for the NEW parallel LCD/OLED version

Outdated AXE033/AXE133 serial version:
Code:
#picaxe 28x2
#no_data
symbol lcdpin = C.3
symbol adcpin = C.2
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol lcdsize = 16
main:
	pause 200
	serout lcdpin, N2400_8, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32)
	serout lcdpin, N2400_8, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48)
	serout lcdpin, N2400_8, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56)
	serout lcdpin, N2400_8, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60)
	serout lcdpin, N2400_8, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62)
	serout lcdpin, N2400_8, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63)
	do
		readadc adcpin,readvar
		length = lcdsize * 5 - 1 * readvar / 255 + 1
		serout lcdpin,N2400_8,(254,128,#length," ",254,192)
		charactercounter = lcdsize
		do
			if length => 5 then
				serout lcdpin,N2400_8,(13)
				length = length - 5
				dec charactercounter
			else
				exit
			end if
		loop
		readvar = length + 8
		serout lcdpin,N2400_8,(readvar)
		for loopcounter = 0 to charactercounter
			serout lcdpin,N2400_8,(32)
		next
	loop
True linear bar

The gap between each character space, which is exactly one pixel wide on OLEDs and around one pixel wide on LCDs means that the relationship between bar length and input value is not perfectly linear. This example treats this gap as just being inactive pixels so that the relationship is perfectly linear, but of course it is not possible to actually make the gaps light up.



Click here for the NEW parallel LCD/OLED version

Outdated AXE033/AXE133 serial version:
Code:
#picaxe 28x2
#no_data
symbol lcdpin = C.3
symbol adcpin = C.2
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol lcdsize = 16
main:
	pause 10
	serout lcdpin, N2400_8, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32)
	serout lcdpin, N2400_8, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48)
	serout lcdpin, N2400_8, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56)
	serout lcdpin, N2400_8, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60)
	serout lcdpin, N2400_8, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62)
	serout lcdpin, N2400_8, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63)
	do
		readadc adcpin,readvar
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		serout lcdpin,N2400_8,(254,128,#length," ",254,192)
		charactercounter = lcdsize
		do
			if length => 6 then
				serout lcdpin,N2400_8,(13)
				length = length - 6
			elseif length = 5 then
				serout lcdpin,N2400_8,(13)
				length = length - 5
			else
				exit
			end if
			dec charactercounter
		loop
		readvar = length + 8
		serout lcdpin,N2400_8,(readvar)
		for loopcounter = 0 to charactercounter
			serout lcdpin,N2400_8,(32)
		next
	loop
Something more unique

This version only uses alternate columns on the LCD/OLED so that the gap between characters goes unnoticed. There are also down/up indicators at the ends of the bargraph so the lcdsize constant must be set to the desired size of the bargraph bit not the length of the LCD for the original version. For the new parallel LCD/OLED version, the length set by using the barlength variable does include the arrows on the end.



Click here for the NEW parallel LCD/OLED version

Outdated AXE033/AXE133 serial example:
Code:
#picaxe 18m2
#no_data
symbol lcdpin = C.3
symbol adcpin = C.2
symbol readvar = b4
symbol length = b5
symbol loopcounter = b6
symbol charactercounter = b7
symbol endposition = b8

symbol lcdsize = 14

	setfreq m8
	pause 200
	serout lcdpin, N2400_8, (254, 64, 32, 32, 32, 53, 32, 32, 32, 32)
	serout lcdpin, N2400_8, (254, 72, 32, 48, 48, 53, 48, 48, 32, 32)
	serout lcdpin, N2400_8, (254, 80, 32, 52, 52, 53, 52, 52, 32, 32)
	serout lcdpin, N2400_8, (254, 88, 32, 53, 53, 53, 53, 53, 32, 32)
	serout lcdpin, N2400_8, (254, 96, 34, 39, 47, 49, 47, 39, 34, 32)
	serout lcdpin, N2400_8, (254, 104, 40, 60, 58, 49, 58, 60, 40, 32)
	endposition = lcdsize + 193
main:
	do
		readadc adcpin,readvar
		length = lcdsize * 3 - 1 * readvar / 255 + 1
		serout lcdpin,N2400_8,(254,128,#length," ",254,endposition,13,254,192,12)
		charactercounter = lcdsize
		do
			dec charactercounter
			if length > 3 then
				serout lcdpin,N2400_8,(11)
				length = length - 3
			else
				exit
			end if
		loop
		readvar = length + 8
		serout lcdpin,N2400_8,(readvar)
looplabel:
		if charactercounter > 0 then
			serout lcdpin,N2400_8,(8)
			dec charactercounter
		else
			goto main
		end if
		goto looplabel
	loop
Comments appreciated.
 
Last edited:

Jeremy Harris

Senior Member
There's a slight problem if you try this on an OLED, in that the OLED needs initialising with an extra line in order to set the cursor direction correctly:
Code:
lcddata = %00000110 : pulsout enable,100
The code works as is for an LCD, so I'm assuming there is a difference in the OLED default initialisation.

Other than that it's a neat bit of code, thanks. I may well use it to replace the rather crude full block "fuel gauge" bar graph Ah meter I made for my electric bike, perhaps with some tweaks to the custom characters.
 

nick12ab

Senior Member
There's a slight problem if you try this on an OLED, in that the OLED needs initialising with an extra line in order to set the cursor direction correctly:
Blast! My fault for using the wrong example code I had saved to get the initialization sequence from which I forgot was incompatible with OLEDs. I should really update my old example code!
 
0 <> a.0 <> s.a0 <> adc0???

I've been toying with your code for the "Something more unique" bar graph and found what seems to me to be an oddity with the readadc command on my AXE401 shield (firmware B.3).

I simplified your code removing everything except the part I had trouble with. This code works:
Code:
#picaxe 28x2
symbol adcin = [COLOR="#FF0000"]0[/COLOR]  ; Leg2  =  A.0  =  S.A0  = ADC0
pause 100
serout C.0, N2400_8, (254,1) ;clear OLED
pause 100
do
	readadc adcin,b4
	serout C.0,N2400_8,(254,128,#b4,"  ")
	pause 100
	toggle c.3
loop
But this code doesn't work:
Code:
#picaxe 28x2
symbol adcin = [COLOR="#FF0000"]A.0[/COLOR]  ; Leg2  =  A.0  =  S.A0  = ADC0
pause 100
serout C.0, N2400_8, (254,1) ;clear OLED
pause 100
do
	readadc adcin,b4
	serout C.0,N2400_8,(254,128,#b4,"  ")
	pause 100
	toggle c.3
loop
The value for b4 is stuck on 255. Your posted code for the AXE133 contained:
Code:
symbol adcpin = C.2
which did not work for me.
When I moved the wire to A.0 and changed C.2 in your code to A.0 instead, that still didn't work. (I tried several other pins as well.)
But when I use "0" instead of A.0 it worked fine (see my first two code versions above, the first uses "0" and the second, which failed for me, uses "A.0").

I thought A.0 was the same as 0 in this case. Any suggestions on what I'm missing?

Once I got it working, I love the display, thanks! I'll be trying to code a left/right centering display to go with it.
 

hamtech

Member
Nick, excellent work. i have tried both parallel and serial versions and both work but i agree parallel is much better.

i am trying to compare and display the output of three peak detectors (audio) and the choose the best.

I have would like to display the three bargraphs at the same time. Using a 28x2 i have managed to combine two displays. But lose the third line somewhere, something wrong with the way i have modified your code . Furthermore i do not get the correct display ie miss the end arrow of the second line of the version i am trying to use. It is perfect for what, i want using three adc onthe 28x2. It should be fast enough, but i cant work out to get three displays at once. As. I say i get two showing but not a third. What i did was to copy the code twice and have main,main1.main2. And call the second two as sub routines but when i set the third line to 212 it goes off the display.

I would be grateful for a steer on how to use the code to display the three analogue bargraphs simultaneously.

many thanks.

hamtech
 

nick12ab

Senior Member
Nick, excellent work. i have tried both parallel and serial versions and both work but i agree parallel is much better.

i am trying to compare and display the output of three peak detectors (audio) and the choose the best.

I have would like to display the three bargraphs at the same time. Using a 28x2 i have managed to combine two displays. But lose the third line somewhere, something wrong with the way i have modified your code . Furthermore i do not get the correct display ie miss the end arrow of the second line of the version i am trying to use. It is perfect for what, i want using three adc onthe 28x2. It should be fast enough, but i cant work out to get three displays at once. As. I say i get two showing but not a third. What i did was to copy the code twice and have main,main1.main2. And call the second two as sub routines but when i set the third line to 212 it goes off the display.

I would be grateful for a steer on how to use the code to display the three analogue bargraphs simultaneously.
By your reference to the 'end arrows', I take it you're referring to this bargraph display:



Each bargraph you want to display will need its own 'endposition' constant. The value of the constant is lcdsize + start of bargraph address where lcdsize is the size of the bargraph part (normally 18 for a 20 character display) and start of bargraph address is where you want the bargraph part to start so that is normally the address of the start of the line + 1.

Since there are many things that can go wrong with this code, I really need to see what cc=ode you have done in order to help more.
 

hamtech

Member
Nick

Thanks for your reply. It is indeed the code sample that I am using. However I have been able to track where I went wrong. I needed to substitute a return command for each of the goto main at the bottom each block of code (your code block repeated three times with two gosubs at the bottom of the first block before the goto main command.)

It works well with three bargraphs and i have the length displayed for each as the ascii adc value on line one. Feeding in the output from the 28X2 ADCs the bargraphs look good, although may need to change the charging times but the 4 line LCD works well. Thank you for sharing the code !

So you know what I am at : I am comparing signals from three satellite receivers and trying to select the best (least noise - highest level) signal for my PC to decode based on the peak level of the signal. I have built three peak detectors which feed a varying dc level to the ADCs on the 28X2.

I now have to compare each of the values to select one enabling output for 1 of four switches contained in a CD4066 switching chip. I can do that, but would like to come up with some sort of algorthym in that it switches it only when it is better than the last selected by 10%. At the moment it is OK when the signals improve and the levels go up, but I haven't worked out what to do when the overall levels are falling. Each level represents a signal which starts rough, low dc level from detector then as the satellite goes overhead improves to a good signal level and not much difference between any detector output and then as the sat disappeasr over the horizon the signals drop off. My challenge is to continuosuly select the best signal from the adc. In general more signal level = better quality. So you can see that the lcd display adds a visual quality to my project and i am grateful to you for the code.
 

hamtech

Member
Nick


My code and (mainly) yours is attached. See what you think.


I haven't got the output select working right. My logic doesn't seem to work with regard to selecting the best output. Output C indicates and causes C.2 to go high but the others don't follow the varying inputs??????
Code:
'Something more unique
'8-bit parallel example:

'This version only uses alternate columns on the LCD/OLED so that the gap between characters goes unnoticed. There are also down/up indicators at the ends of the bargraph so the lcdsize constant must be set to the desired size of the bargraph bit not the length of the LCD.



#picaxe 28X2
#no_data
#no_end


DirsA=%00000000
DirsB=%11111111
Dirsa=%00000000
Dirsc=%10111111
let adcsetup = %0000000000001111 ; set ADC0,1,2,3

symbol enable = C.4
symbol rs = C.6
symbol outA= C.0
symbol outB= C.1
symbol outC= C.2
symbol outD= C.3

symbol readvarA= b4
symbol readvarB= b5
symbol readvarC= b6
symbol length = b10
symbol loopcounter = b11
symbol charactercounter = b12
symbol endposition = b13
symbol lcddata = pinsB
symbol lcdsize = 18
table 50, ("Voted Output = ")
symbol index =b15


'Initialise LCD Display

pause 100   ' wait for LCD to reset

low rs     							' set command mode

lcddata = %00110000: pulsout enable, 100	 ' Function  8 bit, 2 line, 5 x 8
pause 15				
lcddata = %00110000: pulsout enable, 100   ' Function  (data transfers by pulsing enable output)
pause 15
lcddata = %00110000: pulsout enable, 100   ' Function  8 bit, 2 line, 5 x 8
pause 5
setfreq m16


lcddata= %00111000 : pulsout enable,10  	' Function again
lcddata= %00000001 : pulsout enable,10	' clear display
pause 10						' wait 10ms
lcddata =%00000010 : pulsout enable,10	' return home to position
lcddata= %00000110 : pulsout enable,10	' set entry mode
pause 10						' wait 10ms
lcddata =%00001100 : pulsout enable,10	; display on, no cursor

' next two lines from bargraph routine 
lcddata = %00111000 : pulsout enable,10	' output 16 = Move cursor left


lcddata = 64	  : pulsout enable,1	' set Graphics address		'
high rs						' set data mode

for loopcounter = 0 to 47
lookup loopcounter,(32,32,32,53,32,32,32,32,32,48,48,53,48,48,32,32,32,52,52,53,52,52,32,32,32,53,53,53,53,53,32,32,34,39,47,49,47,39,34,32,40,60,58,49,58,60,40,32),lcddata
pulsout enable,1   '  sets up user defined grapics 

next

'Voter message 
low rs
lcddata =128: pulsout enable, 10  ' (128-147) line 1 position ($80 + 1-19)
high rs

For index = 50 to 64
READTABLE index, lcddata: pulsout enable,10  ' sending characters to line 1
next index



endposition = lcdsize + 193

'*********************** start of main routine **************************************************

main:
setfreq m16
do

readadc A.0, readvarA   ' read ADC 1 input voltage and convert to a decimal value
readadc A.1, readvarB   ' read ADC 2 input voltage and convert to a decimal value
readadc A.2, readvarC	' read ADC 3 input voltage and convert to a decimal value


gosub voting



length = lcdsize * 3 - 1 * readvarA / 255 + 1

' print bargraph lenth on line 1
'low rs					' set command mode
'lcddata = 128 : pulsout enable,1   	' position on line for count
'bintoascii length,b25,b26,b27

'high rs					' set data mode
'lcddata = b26 : pulsout enable,1
'lcddata = b27 : pulsout enable,1


low rs					' set command mode
lcddata = endposition : pulsout enable,1
high rs					' set data mode
lcddata = 13 : pulsout enable,1
low rs					' set command mode
lcddata = 192 : pulsout enable,1 	' set line bargraph is on
high rs					' set data mode


lcddata = 12 : pulsout enable,1	
charactercounter = lcdsize
do
dec charactercounter
if length > 3 then
lcddata = 11 : pulsout enable,1
length = length - 3
else
exit
end if
loop
lcddata = length + 8 : pulsout enable,1

looplabel:
if charactercounter > 0 then
lcddata = 8 : pulsout enable,1
dec charactercounter
else

gosub main2
gosub main3


goto main

end if
goto looplabel


loop





main2:

endposition = lcdsize + 149


length = lcdsize * 3 - 1 * readvarB / 255 + 1
'low rs						' set command mode			
'lcddata = 136 : pulsout enable,1   	   	' position on line for count
'bintoascii length,b25,b26,b27
'high rs		

'lcddata = b26 : pulsout enable,1
'lcddata = b27 : pulsout enable,1

low rs						' set command mode
lcddata = endposition : pulsout enable,1
high rs						' set data mode
lcddata = 13 : pulsout enable,1
low rs						'set command mode
lcddata = 148 : pulsout enable,1   		' set Line  bargraph is on
high rs					'	set data mode
lcddata = 12 : pulsout enable,1
charactercounter = lcdsize
do
dec charactercounter
if length > 3 then
lcddata = 11 : pulsout enable,1
length = length - 3
else
exit
end if
loop
lcddata = length + 8 : pulsout enable,1

looplabel1:
if charactercounter > 0 then
lcddata = 8 : pulsout enable,1
dec charactercounter

else

return


end if
goto looplabel1


return


main3:
endposition = lcdsize + 213



length = lcdsize * 3 - 1 * readvarC / 255 + 1
'low rs
'lcddata = 142 : pulsout enable,1  ' position on line for count
'bintoascii length,b25,b26,b27
'high rs
'lcddata = b26 : pulsout enable,1
'lcddata = b27 : pulsout enable,1


low rs
lcddata = endposition : pulsout enable,1
high rs
lcddata = 13 : pulsout enable,1
low rs
lcddata = 212 : pulsout enable,1   ' Line  bargraph is on
high rs
lcddata = 12 : pulsout enable,1
charactercounter = lcdsize
do
dec charactercounter
if length > 3 then
lcddata = 11 : pulsout enable,1
length = length - 3
else
exit
end if
loop
lcddata = length + 8 : pulsout enable,1

looplabel2:
if charactercounter > 0 then
lcddata = 8 : pulsout enable,1
dec charactercounter
else
return

end if
goto looplabel2
return



  
  
  
  
voting:   ' to select highest ADC output and enable corrct channel


'A v C select higher of the two

if readvarA >= readvarB then 	

		goto AvC  		'  A is greater or the same as B

		else    goto BvC   '  B is greater than A

end if


AvC:


if readvarA >=  readvarC then ' A is greater or the same as C and is selected
		debug: pause 1000
		high outA 
		low rs
		lcddata =143:pulsout enable,10  ' set cursor position
		high rs
		lcddata ="A":pulsout enable,10  ' send voted character
	
		low outb:low outc: low outd     ' reset others
		
		
		else 
		
 		high outC      ' C is greater than A
		low rs
		lcddata =143:pulsout enable,10  ' set cursor position
		high rs
		lcddata ="C":pulsout enable,10  ' send voted character
		low outa:low outb: low outd ' reset others
		end if
BvC:

If readvarB >= readvarC then 
	

		high outB  ' B is the highest level or the same as C
		low rs
		lcddata =143:pulsout enable,10  ' set cursor position
		high rs
		lcddata ="B":pulsout enable,10  ' send voted character
		low outa:low outb: low outd ' reset others
            else 
        
            high outC ' select C
            low rs
		lcddata =143:pulsout enable,10  ' set cursor position
		high rs
		lcddata ="C":pulsout enable,10  ' send voted character
         	low outa:low outb: low outd ' reset others
            end if
            
            
            
        return
 

nick12ab

Senior Member
I haven't got the output select working right. My logic doesn't seem to work with regard to selecting the best output. Output C indicates and causes C.2 to go high but the others don't follow the varying inputs??????
For output B, it's because when you are 'resetting the others', you are making B low again so it won't stay on.
Code:
If readvarB >= readvarC then 
	

		high outB  ' B is the highest level or the same as C
		low rs
		lcddata =143:pulsout enable,10  ' set cursor position
		high rs
		lcddata ="B":pulsout enable,10  ' send voted character
		[B]low outa:low outb: low outd[/B] ' reset others
            else
The problem for output A is not obvious to me (yet) but I can't see where the code for output D is.
 

hamtech

Member
For output B, it's because when you are 'resetting the others', you are making B low again so it won't stay on.
Code:
If readvarB >= readvarC then 
	

		high outB  ' B is the highest level or the same as C
		low rs
		lcddata =143:pulsout enable,10  ' set cursor position
		high rs
		lcddata ="B":pulsout enable,10  ' send voted character
		[B]low outa:low outb: low outd[/B] ' reset others
            else
The problem for output A is not obvious to me (yet) but I can't see where the code for output D is.

Nick,

I apologise for misleading you. I hadn't actually added the code for D which is my HF Rx which is switch operated and not by ADC level. I use this switch to overide the Satellite RX audio. Have resolved all the issues with channel selection and the code is a goer , I get three lines of bargraph and a "voted output = ", A,B,C or HF on line one. Have added a signon messgae too. I have learnt from your different instruction posts how to make LCDs work in parallel mode so thank you very much.

If you think there would be any interest , I have a JPEG of the circuit and obviously can post the code but it is likely to be of limited interest I think. Is there a limit on the forum for how much you can post in any one go??
 

nick12ab

Senior Member
I apologise for misleading you. I hadn't actually added the code for D which is my HF Rx which is switch operated and not by ADC level. I use this switch to overide the Satellite RX audio. Have resolved all the issues with channel selection and the code is a goer , I get three lines of bargraph and a "voted output = ", A,B,C or HF on line one. Have added a signon messgae too. I have learnt from your different instruction posts how to make LCDs work in parallel mode so thank you very much.
Glad to hear that it now works.

If you think there would be any interest , ... and obviously can post the code but it is likely to be of limited interest I think. Is there a limit on the forum for how much you can post in any one go??
There's no reason why you cannot post it. The post character limit is something high like 10000 characters and there aren't any restrictions on the quantity of posts allowed per member. Of course, don't forget to post your finished project as a new thread (again there is no limitation on the number you can have).

I have a JPEG of the circuit
What do you mean "a JPEG of the circuit"? JPEGs are suitable for photos only and if you save a circuit diagram as one it will look terrible. If it it a circuit diagram you are talking about then please re-export (don't convert the JPG) it as a PNG image before you upload it.
 

nick12ab

Senior Member
Improved version of 'The already done one'

This is an improved version of the original bargraph, now with extra customizability. It addresses the following issues with the original:
  • The original would overwrite the character to the right of the actual bargraph which makes it disastrous if you don't want it to occupy an entire line. The new version does not do that so it is safe to put another character to the right of the bargraph display.
  • The original would always show at least one vertical line even when the input variable was zero. The new version allows whether it does this or not to be chosen by the user.
  • The old version had LCD positions specified by constants which made it more difficult to change it for your needs. The new version uses variables throughout.
The new version uses a subprocedure for the part that displays the bargraph to make it easier to create a bargraph from different parts of the program. The bargraph is controlled using these variables:
  • startposition - the location on the LCD where the bargraph needs to start. (128 is the start of line 1 and 192 is the start of line 2 on a 16x2 LCD)
  • barlength - the number of characters you want the bargraph to take up. This can be a number as small as 1 if you need a tiny bargraph.
  • barvalue - the proportion of the bar that you want to be filled. (0 = empty, 255 = full)
  • startat - where the part of the bar that changes starts at in number of columns. Columns to the left of the specified position are always on. Setting to startat to 0 will mean that when barvalue is 0, none of the bargraph is lit and setting startat to 1 will make the 1st column be on at all times like on the old version. The startat variable can also be set to any value greater than 1 but very few people will need to do that, and most people will find that 0 is the best value for them.
Symbol definitions (pins and variables used can be changed):
Code:
[color=Blue]symbol [/color][color=Purple]enable [/color][color=DarkCyan]= [/color][color=Blue]C.0
symbol [/color][color=Purple]rs [/color][color=DarkCyan]= [/color][color=Blue]C.1
symbol [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]pinsB[/color]

[color=Blue]symbol [/color][color=Purple]barvalue [/color][color=DarkCyan]= [/color][color=Purple]b4[/color]
[color=Blue]symbol [/color][color=Purple]barlength [/color][color=DarkCyan]= [/color][color=Purple]b5[/color]
[color=Blue]symbol [/color][color=Purple]startposition [/color][color=DarkCyan]= [/color][color=Purple]b6[/color]
[color=Blue]symbol [/color][color=Purple]startat [/color][color=DarkCyan]= [/color][color=Purple]b7[/color]

[color=Blue]symbol [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]b10[/color]
[color=Blue]symbol [/color][color=Purple]charactercounter [/color][color=DarkCyan]= [/color][color=Purple]b11[/color]
Initialization sequence for LCD including CGRAM: (NEW improved initialization sequence compatible with both LCD and Winstar OLED)
Code:
[color=Blue]symbol [/color][color=Purple]loopcounter [/color][color=DarkCyan]= [/color][color=Purple]b12
      
      dirsB [/color][color=DarkCyan]= [/color][color=Navy]255
      [/color][color=Blue]low rs
      low enable
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00000001 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]608
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00000110 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]100
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00001100 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]608
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00111011 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]100
      [/color][color=Blue]setfreq m16
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]64 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]high rs
      for [/color][color=Purple]loopcounter [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]to [/color][color=Navy]47
            [/color][color=Blue]lookup [/color][color=Purple]loopcounter[/color][color=Black],[/color][color=Blue]([/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]34[/color][color=Black],[/color][color=Navy]39[/color][color=Black],[/color][color=Navy]47[/color][color=Black],[/color][color=Navy]49[/color][color=Black],[/color][color=Navy]47[/color][color=Black],[/color][color=Navy]39[/color][color=Black],[/color][color=Navy]34[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]40[/color][color=Black],[/color][color=Navy]60[/color][color=Black],[/color][color=Navy]58[/color][color=Black],[/color][color=Navy]49[/color][color=Black],[/color][color=Navy]58[/color][color=Black],[/color][color=Navy]60[/color][color=Black],[/color][color=Navy]40[/color][color=Black],[/color][color=Navy]32[/color][color=Blue])[/color][color=Black],[/color][color=Purple]lcddata
            [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]next[/color]
The display bargraph sub:
Code:
[color=Black]displayBargraph:[/color][color=Purple]
      length [/color][color=DarkCyan]= [/color][color=Purple]barlength [/color][color=DarkCyan]* [/color][color=Navy]5 [/color][color=DarkCyan]- [/color][color=Purple]startat [/color][color=DarkCyan]* [/color][color=Purple]barvalue [/color][color=DarkCyan]/ [/color][color=Navy]255 [/color][color=DarkCyan]+ [/color][color=Purple]startat
      [/color][color=Blue]low [/color][color=Purple]rs
      lcddata [/color][color=DarkCyan]= [/color][color=Purple]startposition : [/color][color=Blue]pulsout [/color][color=Purple]enable,[/color][color=Navy]1
      [/color][color=Blue]high [/color][color=Purple]rs
      charactercounter [/color][color=DarkCyan]= [/color][color=Purple]barlength
      [/color][color=Blue]do
            if [/color][color=Purple]length [/color][color=DarkCyan]=> [/color][color=Navy]5 [/color][color=Blue]then
                  [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]13 [/color][color=Purple]: [/color][color=Blue]pulsout [/color][color=Purple]enable,[/color][color=Navy]1
                  [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]length [/color][color=DarkCyan]- [/color][color=Navy]5
            [/color][color=Blue]else
                  exit
            end if
            dec [/color][color=Purple]charactercounter
      [/color][color=Blue]loop
      if [/color][color=Purple]length [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then
            [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]length [/color][color=DarkCyan]+ [/color][color=Navy]8 [/color][color=Purple]: [/color][color=Blue]pulsout [/color][color=Purple]enable,[/color][color=Navy]1
            [/color][color=Blue]dec [/color][color=Purple]charactercounter
      [/color][color=Blue]end if
      do while [/color][color=Purple]charactercounter [/color][color=DarkCyan]> [/color][color=Navy]0
            [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]32 [/color][color=Purple]: [/color][color=Blue]pulsout [/color][color=Purple]enable,[/color][color=Navy]1
            [/color][color=Blue]dec [/color][color=Purple]charactercounter
      [/color][color=Blue]loop
      return[/color]
By changing the LCD position (and optionally size) variables then using the displayBargraph sub again it is possible to have many different bargraphs on the display at once and with different sizes.

Generally you would use the symbol definitions and LCD initialization at the beginning of your BASIC file, then your main: part of your code, then finally the display bargraph sub at the end of the file.

Improved versions of the other bargraph display styles will be done shortly.
 
Last edited:

bfgstew

Senior Member
Thanks Nick for the work on these bargraphs, I just had to come back to them, they really do make a project stand out and look the business.
But I do have a problem! I am running two bargraphs, one is actual level (readadc1) the other is a trigger level (readadc2), both are on comp1 on 40X2 and an intterupt is set if actual level <= trigger level, now it works fine apart from the first two blocks on the trigger level graph, when it is running they flicker, apart from that it works fine, I just can't seem to get rid of the flicker, any idea?

Code:
	serout B.7,baud,(254,1)
		pause 30
			serout lcdpin, N2400_8, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32)
			serout lcdpin, N2400_8, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48)
			serout lcdpin, N2400_8, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56)
			serout lcdpin, N2400_8, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60)
			serout lcdpin, N2400_8, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62)
			serout lcdpin, N2400_8, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63)
		serout B.7,baud,(254,128,"ACTUAL LEVEL = ",#readvar2,"  ")
		serout B.7,baud,(254,148,"TRIGGER LEVEL = ",#readvar3,"  ")	
	do
		readadc 1,readvar2
			length = lcdsize * 5 - 1 * readvar2 / 255 + 1
				serout lcdpin,N2400_8,(254,143,#length," ",254,192)
			charactercounter = lcdsize
	do
		if length => 5 then
			serout lcdpin,N2400_8,(13)
				length = length - 5
					elseif length = 4 then
			serout lcdpin,N2400_8,(13)
				length = length - 4
			else
				exit
			end if
		dec charactercounter
	loop
		readvar2 = length + 8
			serout lcdpin,N2400_8,(readvar2)
				for loopcounter = 0 to charactercounter
			serout lcdpin,N2400_8,(32)
				readadc 2,readvar3
			next
		length1 = lcdsize1 * 5 - 1 * readvar3 / 255 + 1
			serout lcdpin,N2400_8,(254,164,#length1," ",254,212)
				charactercounter1 = lcdsize1
			do
				if length1 => 5 then
					serout lcdpin,N2400_8,(13)
				length1 = length1 - 5
					elseif length1 = 4 then
				serout lcdpin,N2400_8,(13)
			length1 = length1 - 4
				else
					exit
				end if
			dec charactercounter1
		loop
			readvar3 = length1 + 8
				serout lcdpin,N2400_8,(readvar3)
					for loopcounter1 = 0 to charactercounter1
				serout lcdpin,N2400_8,(32)
			next
		loop
 

bfgstew

Senior Member
Code:
serout B.7,baud,(254,1)
		pause 30
			serout lcdpin, baud, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32)
			serout lcdpin, baud, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48)
			serout lcdpin, baud, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56)
			serout lcdpin, baud, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60)
			serout lcdpin, baud, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62)
			serout lcdpin, baud, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63)
		serout B.7,baud,(254,128,"ACTUAL LEVEL = ",#readvar2,"  ")
		serout B.7,baud,(254,148,"TRIGGER LEVEL = ",#readvar3,"  ")	
	do
		readadc 1,readvar2
			length = lcdsize * 5 - 1 * readvar2 / 255 + 1
				serout lcdpin,baud,(254,143,#length," ",254,192)
			charactercounter = lcdsize
	do
		if length => 5 then
			serout lcdpin,baud,(13)
				length = length - 5
					elseif length = 4 then
			serout lcdpin,baud,(13)
				length = length - 4
			else
				exit
			end if
		dec charactercounter
	loop
		readvar2 = length + 8
			serout lcdpin,baud,(readvar2)
				for loopcounter = 0 to charactercounter
			serout lcdpin,baud,(32)
			
				readadc 2,readvar3
		length1 = lcdsize1 * 5 - 1 * readvar3 / 255 + 1
			serout lcdpin,baud,(254,164,#length1," ",254,212)
				charactercounter1 = lcdsize1
			do
				if length1 => 5 then
					serout lcdpin,baud,(13)
				length1 = length1 - 5
					elseif length1 = 4 then
				serout lcdpin,baud,(13)
			length1 = length1 - 4
				else
					exit
				end if
			dec charactercounter1
		loop
			readvar3 = length1 + 8
				serout lcdpin,baud,(readvar3)
					for loopcounter1 = 0 to charactercounter1
				serout lcdpin,baud,(32)
			[COLOR="#FF0000"]next:next[/COLOR]		loop
Sorted it in the end, moved the first next to sit with the last next and it works like a charm.
Thanks again Nick for the work put into doing these, much appreciated.

Stewart
 

nick12ab

Senior Member
Improved version of 'True Linear Bar'

This is the improved version of the true linear bargraph. The symbol definitions and initialization are the same as on the improved version of the done-before bargraph but the displayBargraph sub has changed.

The new version uses a subprocedure for the part that displays the bargraph to make it easier to create a bargraph from different parts of the program. The bargraph is controlled using these variables:
  • startposition - the location on the LCD where the bargraph needs to start. (128 is the start of line 1 and 192 is the start of line 2 on a 16x2 LCD)
  • barlength - the number of characters you want the bargraph to take up. This can be a number as small as 1 if you need a tiny bargraph.
  • barvalue - the proportion of the bar that you want to be filled. (0 = empty, 255 = full)
  • startat - where the part of the bar that changes starts at in number of columns. Columns to the left of the specified position are always on. Setting to startat to 0 will mean that when barvalue is 0, none of the bargraph is lit and setting startat to 1 will make the 1st column be on at all times like on the old version. The startat variable can also be set to any value greater than 1 but very few people will need to do that, and most people will find that 0 is the best value for them.
Symbol definitions (pins and variables used can be changed):
Code:
[color=Blue]symbol [/color][color=Purple]enable [/color][color=DarkCyan]= [/color][color=Blue]C.0
symbol [/color][color=Purple]rs [/color][color=DarkCyan]= [/color][color=Blue]C.1
symbol [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]pinsB[/color]

[color=Blue]symbol [/color][color=Purple]barvalue [/color][color=DarkCyan]= [/color][color=Purple]b4[/color]
[color=Blue]symbol [/color][color=Purple]barlength [/color][color=DarkCyan]= [/color][color=Purple]b5[/color]
[color=Blue]symbol [/color][color=Purple]startposition [/color][color=DarkCyan]= [/color][color=Purple]b6[/color]
[color=Blue]symbol [/color][color=Purple]startat [/color][color=DarkCyan]= [/color][color=Purple]b7[/color]

[color=Blue]symbol [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]b10[/color]
[color=Blue]symbol [/color][color=Purple]charactercounter [/color][color=DarkCyan]= [/color][color=Purple]b11[/color]
Initialization sequence for LCD including CGRAM: (NEW improved initialization sequence compatible with both LCD and Winstar OLED)
Code:
[color=Blue]symbol [/color][color=Purple]loopcounter [/color][color=DarkCyan]= [/color][color=Purple]b12
      
      dirsB [/color][color=DarkCyan]= [/color][color=Navy]255
      [/color][color=Blue]low rs
      low enable
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00000001 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]608
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00000110 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]100
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00001100 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]608
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00111011 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]100
      [/color][color=Blue]setfreq m16
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]64 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]high rs
      for [/color][color=Purple]loopcounter [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]to [/color][color=Navy]47
            [/color][color=Blue]lookup [/color][color=Purple]loopcounter[/color][color=Black],[/color][color=Blue]([/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]34[/color][color=Black],[/color][color=Navy]39[/color][color=Black],[/color][color=Navy]47[/color][color=Black],[/color][color=Navy]49[/color][color=Black],[/color][color=Navy]47[/color][color=Black],[/color][color=Navy]39[/color][color=Black],[/color][color=Navy]34[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]40[/color][color=Black],[/color][color=Navy]60[/color][color=Black],[/color][color=Navy]58[/color][color=Black],[/color][color=Navy]49[/color][color=Black],[/color][color=Navy]58[/color][color=Black],[/color][color=Navy]60[/color][color=Black],[/color][color=Navy]40[/color][color=Black],[/color][color=Navy]32[/color][color=Blue])[/color][color=Black],[/color][color=Purple]lcddata
            [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]next[/color]
The display bargraph sub:
Code:
[color=Black]displayBargraph:
      [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]barlength [/color][color=DarkCyan]* [/color][color=Navy]6 [/color][color=DarkCyan]- [/color][color=Purple]startat [/color][color=DarkCyan]* [/color][color=Purple]barvalue [/color][color=DarkCyan]/ [/color][color=Navy]255 [/color][color=DarkCyan]+ [/color][color=Purple]startat
      [/color][color=Blue]low rs
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]startposition [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]high rs
      [/color][color=Purple]charactercounter [/color][color=DarkCyan]= [/color][color=Purple]barlength
      [/color][color=Blue]do
            if [/color][color=Purple]length [/color][color=DarkCyan]=> [/color][color=Navy]6 [/color][color=Blue]then
                  [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]13 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
                  [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]length [/color][color=DarkCyan]- [/color][color=Navy]6
            [/color][color=Blue]elseif [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Navy]5 [/color][color=Blue]then
                  [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]13 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
                  [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]length [/color][color=DarkCyan]- [/color][color=Navy]5
            [/color][color=Blue]else
                  exit
            end if
            dec [/color][color=Purple]charactercounter
      [/color][color=Blue]loop
      if [/color][color=Purple]length [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then
            [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]length [/color][color=DarkCyan]+ [/color][color=Navy]8 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
            [/color][color=Blue]dec [/color][color=Purple]charactercounter
      [/color][color=Blue]end if
      do while [/color][color=Purple]charactercounter [/color][color=DarkCyan]> [/color][color=Navy]0
            [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]32 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
            [/color][color=Blue]dec [/color][color=Purple]charactercounter
      [/color][color=Blue]loop
      return[/color]
By changing the LCD position (and optionally size) variables then using the displayBargraph sub again it is possible to have many different bargraphs on the display at once and with different sizes.

Generally you would use the symbol definitions and LCD initialization at the beginning of your BASIC file, then your main: part of your code, then finally the display bargraph sub at the end of the file.

Improved versions of the 'Something a bit more unique' bargraph style will be done shortly, and possibly serial display versions too - although really I don't like the use of slow serial LCDs and the bargraph will perform poorly on them anyway.
 
Last edited:

hamtech

Member
Nick,

Have tried the newer versions and they are very good, display bargraph is better as a subroutine.
Thank you for all your past help and suggestions. I will post my project in the Projects area later this week and circuit diagram as a PNG file too....
all the best

Bob
 

nick12ab

Senior Member
Improved version of 'Something a bit more unique'

This is the improved version of the bargraph with the +/- arrows at the ends. The symbol definitions are the same as on the improved version of the done-before bargraph but the displayBargraph sub has changed plus the initialization has changed because this bargraph requires different CGRAM content.

The new version uses a subprocedure for the part that displays the bargraph to make it easier to create a bargraph from different parts of the program. The bargraph is controlled using these variables:
  • startposition - the location on the LCD where the bargraph needs to start. (128 is the start of line 1 and 192 is the start of line 2 on a 16x2 LCD)
  • barlength - the number of characters you want the bargraph to take up. This can be a number as small as 1 if you need a tiny bargraph.
  • barvalue - the proportion of the bar that you want to be filled. (0 = empty, 255 = full)
  • startat - where the part of the bar that changes starts at in number of columns. Columns to the left of the specified position are always on. Setting to startat to 0 will mean that when barvalue is 0, none of the bargraph is lit and setting startat to 1 will make the 1st column be on at all times like on the old version. The startat variable can also be set to any value greater than 1 but very few people will need to do that, and most people will find that 0 is the best value for them.
Symbol definitions (pins and variables used can be changed):
Code:
[color=Blue]symbol enable [/color][color=DarkCyan]= [/color][color=Blue]C.0
symbol rs [/color][color=DarkCyan]= [/color][color=Blue]C.1
symbol [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]pinsB[/color]

[color=Blue]symbol [/color][color=Purple]barvalue [/color][color=DarkCyan]= [/color][color=Purple]b4[/color]
[color=Blue]symbol [/color][color=Purple]barlength [/color][color=DarkCyan]= [/color][color=Purple]b5[/color]
[color=Blue]symbol [/color][color=Purple]startposition [/color][color=DarkCyan]= [/color][color=Purple]b6[/color]
[color=Blue]symbol [/color][color=Purple]startat [/color][color=DarkCyan]= [/color][color=Purple]b7[/color]

[color=Blue]symbol [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]b10[/color]
[color=Blue]symbol [/color][color=Purple]charactercounter [/color][color=DarkCyan]= [/color][color=Purple]b11[/color]

[color=Blue]symbol [/color][color=Purple]loopcounter [/color][color=DarkCyan]= [/color][color=Purple]b12[/color]
Initialization sequence for LCD including CGRAM: (NEW improved initialization sequence compatible with both LCD and Winstar OLED) (setfreq m16 can be changed)
Code:
      [color=Purple]dirsB [/color][color=DarkCyan]= [/color][color=Navy]255
      [/color][color=Blue]low rs
      low enable
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00000001 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]608
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00000110 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]100
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00001100 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]608
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]%00111011 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]100
      [/color][color=Blue]setfreq m16
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]64 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]high rs
      for [/color][color=Purple]loopcounter [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]to [/color][color=Navy]47
            [/color][color=Blue]lookup [/color][color=Purple]loopcounter[/color][color=Black],[/color][color=Blue]([/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]48[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]52[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]53[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]34[/color][color=Black],[/color][color=Navy]39[/color][color=Black],[/color][color=Navy]47[/color][color=Black],[/color][color=Navy]49[/color][color=Black],[/color][color=Navy]47[/color][color=Black],[/color][color=Navy]39[/color][color=Black],[/color][color=Navy]34[/color][color=Black],[/color][color=Navy]32[/color][color=Black],[/color][color=Navy]40[/color][color=Black],[/color][color=Navy]60[/color][color=Black],[/color][color=Navy]58[/color][color=Black],[/color][color=Navy]49[/color][color=Black],[/color][color=Navy]58[/color][color=Black],[/color][color=Navy]60[/color][color=Black],[/color][color=Navy]40[/color][color=Black],[/color][color=Navy]32[/color][color=Blue])[/color][color=Black],[/color][color=Purple]lcddata
            [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]next[/color]
The display bargraph sub:
Code:
[color=Black]displayBargraph:
      [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]barlength [/color][color=DarkCyan]- [/color][color=Navy]2 [/color][color=DarkCyan]* [/color][color=Navy]3 [/color][color=DarkCyan]- [/color][color=Purple]startat [/color][color=DarkCyan]* [/color][color=Purple]barvalue [/color][color=DarkCyan]/ [/color][color=Navy]255 [/color][color=DarkCyan]+ [/color][color=Purple]startat
      [/color][color=Blue]low rs
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]startposition [/color][color=DarkCyan]+ [/color][color=Purple]barlength [/color][color=DarkCyan]- [/color][color=Navy]1 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]high rs
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]13 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]low rs
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]startposition [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Blue]high rs
      [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]12 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
      [/color][color=Purple]charactercounter [/color][color=DarkCyan]= [/color][color=Purple]barlength [/color][color=DarkCyan]- [/color][color=Navy]2
      [/color][color=Blue]do
            if [/color][color=Purple]length [/color][color=DarkCyan]> [/color][color=Navy]3 [/color][color=Blue]then
                  [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]11 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
                  [/color][color=Purple]length [/color][color=DarkCyan]= [/color][color=Purple]length [/color][color=DarkCyan]- [/color][color=Navy]3
            [/color][color=Blue]else
                  exit
            end if
            dec [/color][color=Purple]charactercounter
      [/color][color=Blue]loop
      if [/color][color=Purple]length [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then
            [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Purple]length [/color][color=DarkCyan]+ [/color][color=Navy]8 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
            [/color][color=Blue]dec [/color][color=Purple]charactercounter
      [/color][color=Blue]end if
      do while [/color][color=Purple]charactercounter [/color][color=DarkCyan]> [/color][color=Navy]0
            [/color][color=Purple]lcddata [/color][color=DarkCyan]= [/color][color=Navy]8 [/color][color=Black]: [/color][color=Blue]pulsout enable[/color][color=Black],[/color][color=Navy]1
            [/color][color=Blue]dec [/color][color=Purple]charactercounter
      [/color][color=Blue]loop
      return[/color]
 

radiogareth

Senior Member
A little bit of help please....

In searching for a bargraph LCD I found this thread. Some lovely work here, just what I was hoping for. My hardware : AXE132 driving a 16*2 Blue/White LCD which works fine on the Picaxe sample code.
I'm puzzled by the last listing though (Nick12ab's post above). C.0 and C.1 and C.2 are uncommitted on the 18M2 driver - partly why I chose it as I need to measure 2 voltages and flash an LED using them. I've looked at the code (lots) but I'm still at a loss to work out which variable actually controls the bargraph. Ideally I'd like it just to take the ADC value from e.g. b13 and display it (Readadc c.0,b13). If someone could add a line or two to make the demo software run a nice little rising/falling bargraph like the GIF on the posts I would be very grateful.

The project is not hugely complex - using a UV led to detect sunlight intensity (approximately = bargraph), and LDR to provide a go/no go light level (possibly on another bargraph as it seems I could have two side by side) with either values capable of flashing an LED or squeaking a PIEZO.
If the listing was commented a bit I could probably fathom whats going on (yes I have read the defines in text above the listing).

TIA

Gareth
 
Last edited:

hamtech

Member
Have a look at my digital voter which displays three bargraphs on three lines of a 4 line lcd

Nick12ab's new improved and revised bargraph code is very good but for me the original 'something unique' code display was best for my purposes. In my digital voter I used the earlier version of code. Either will be fine and in my posted project i read three adcs to get the different levels to display ( best using a parallel lcd display though).
 

hamtech

Member
Hi Nick ,

I am making an HF aerial rotator and displaying its position with a 3 digit bearing number and also a bar graph using your Serial 'Something more Unique' version. ( no need for speed on this one). I would like to use all of the display for the bar graph and not have the end arrows showing. In which case a 20 Character LCD I have will suit my purpose. Can you let me know how I avoid using the two CGRAMS for the arrows in this instance. I want to have |||||||||||||||---- all the way across the screen.

Grateful for you assistance once again. I am making good use of the bar graphs thanks you so much.

All the best Hamtech
 

nick12ab

Senior Member
Hi Nick ,

I am making an HF aerial rotator and displaying its position with a 3 digit bearing number and also a bar graph using your Serial 'Something more Unique' version. ( no need for speed on this one). I would like to use all of the display for the bar graph and not have the end arrows showing. In which case a 20 Character LCD I have will suit my purpose. Can you let me know how I avoid using the two CGRAMS for the arrows in this instance. I want to have |||||||||||||||---- all the way across the screen.

Grateful for you assistance once again. I am making good use of the bar graphs thanks you so much.

All the best Hamtech
The end arrows are defined using these lines:
Code:
	serout lcdpin, N2400_8, (254, 96, 34, 39, 47, 49, 47, 39, 34, 32)
	serout lcdpin, N2400_8, (254, 104, 40, 60, 58, 49, 58, 60, 40, 32)
Remove those two lines to prevent the arrows from being stored in the CGRAM.

The end arrows are then displayed in this line, as is the value of the length variable which I presume you don't want:
Code:
		serout lcdpin,N2400_8,(254,128,#length," ",254,endposition,13,254,192,12)
Change it to this:
Code:
		serout lcdpin,N2400_8,(254,192)
All this will do now is reposition the cursor to the start of the second line where the first character of the bargraph should appear.

Set the lcdsize constant to 20.

Please post if these modifications worked or not.
 

hamtech

Member
The end arrows are defined using these lines:
Code:
	serout lcdpin, N2400_8, (254, 96, 34, 39, 47, 49, 47, 39, 34, 32)
	serout lcdpin, N2400_8, (254, 104, 40, 60, 58, 49, 58, 60, 40, 32)
Remove those two lines to prevent the arrows from being stored in the CGRAM.

The end arrows are then displayed in this line, as is the value of the length variable which I presume you don't want:
Code:
		serout lcdpin,N2400_8,(254,128,#length," ",254,endposition,13,254,192,12)
Change it to this:
Code:
		serout lcdpin,N2400_8,(254,192)
All this will do now is reposition the cursor to the start of the second line where the first character of the bargraph should appear.

Set the lcdsize constant to 20.

Please post if these modifications worked or not.

Thanks Nick,

I will give them a try tonight before or after the football if I can and report back!!

Regards Hamtech
 

hamtech

Member
Thanks Nick,

I will give them a try tonight before or after the football if I can and report back!!

Regards Hamtech
Didn't work Nick. I still get the two arrows with the two CGram lines removed but they are overwritten then displayed and then overwritten and so on. The other thing is that in my program the bargraph line is printed on the 4th line (212) but after I made your changes one arrow is printed on the first line and the other one the 4th.???? Without the changes all works well but I have the two surplus (in this case) arrows.

I attach my code to help you see what I am doing!

Code:
Start0:      ' Task 1 -  Display segment of program

#picaxe 20M2

'20M2  code for aerial rotator project 
 
'using a 4x20 Chars LCD display  i.e. 

'Cur Brg        line 1
'New brg        line 2 
'Compass points line 3   
'Brg bargraph   line 4

symbol lcdpin = b.3    		' Serial Out to LCD
symbol adcpin = C.7		' Analogue voltage in from rotator Pot   

symbol heading = w0   		' Beam Heading to display in degrees 
symbol readvar = w1		' Read voltage into 10 bits
symbol tempvar = w2
symbol cur_brg = w3		' bearing read by readadc10  on Pot
Symbol new_brg = w4		' shared and get value from keypad routine
symbol length  = b10
symbol loopcounter = b11
symbol charactercounter = b12
symbol endposition = b13
	
Symbol HTH =b14 	
symbol HH= b15
symbol HT=b16
symbol HU=b17


symbol lcdsize = 20   ' 2 less than display width because of arrows at ends
symbol baud    = N2400


' Initialise the screen	

Pause 500            		' let things settle



serout lcdpin,baud,(255,0)  	' select upper 2 lines
pause 100	
Serout lcdpin,baud, (254,1) 	' clear upper 2 lines
pause 100
serout lcdpin,baud,(255,1)  	' select lower 2 lines
pause 100	
Serout lcdpin,baud, (254,1) 	' clear lower 2 lines
pause 100
serout lcdpin,baud,(255,0)  	
pause 100
Serout lcdpin,baud, (254,128)	' start pos line 1
Pause 200


pwrup: ' power up  message

Serout lcdpin,baud, (254,128, "    PICAXE 20M2     ")
serout lcdpin,baud, (254,192, "DIRECT BEARING ENTRY")
serout lcdpin,baud, (254,148, " ANTENNA CONTROLLER ")
serout lcdpin,baud, (254,212, "   G4LIJ JUNE 2014  ")

Pause 3500   			' wait a few secs


 				' next clear pwrup message

serout lcdpin,baud,(255,0)  	' select upper 2 lines
pause 100	
Serout lcdpin,baud, (254,1) 	' clear upper 2 lines
pause 100
serout lcdpin,baud,(255,1)  	' select lower 2 lines
pause 100	
Serout lcdpin,baud, (254,1) 	' clear lower 2 lines
pause 100
serout lcdpin,baud,(255,0)  	'
pause 100
Serout lcdpin,baud, (254,128)	' start pos line 1
Pause 500




' send Cgram characters for bargraph display

serout lcdpin, baud, (254, 64, 32, 32, 32, 53, 32, 32, 32, 32)
serout lcdpin, baud, (254, 72, 32, 48, 48, 53, 48, 48, 32, 32)
serout lcdpin, baud, (254, 80, 32, 52, 52, 53, 52, 52, 32, 32)
serout lcdpin, baud, (254, 88, 32, 53, 53, 53, 53, 53, 32, 32)


'serout lcdpin, baud, (254, 96, 34, 39, 47, 49, 47, 39, 34, 32)
'serout lcdpin, baud, (254, 104, 40, 60, 58, 49, 58, 60, 40, 32)


endposition = lcdsize + 213 ' line 4,  2nd character



main:		' START OF MAIN PROGRAM TASK 1

Serout lcdpin,baud, (254,148,"N    E   S    W    N")' start pos line 3 ' sET CARDINAL POINTS

do

readadc10 c.7,readvar

let heading  = readvar    ' value of adc 10 bit mode holds current beam heading



gosub cur_brg_disp


Serout lcdpin,baud, (254,128,"Cur Brg = ",#HH,#HT,#HU," deg",254,endposition, 13,254,212,12)' 


gosub new_brg_disp
Serout lcdpin,baud, (254,192,"New Brg = ",#HH,#HT,#HU," deg",254,endposition,13,254,212,12)' start pos line 4


length = lcdsize * 3 - 1 * readvar / 1023 + 1


'serout lcdpin,baud,(254,128,254,endposition,13,254,212,12)  '  length variable removed as not required to display

serout lcdpin, baud, (254,212)
charactercounter = lcdsize


let cur_brg= heading/4*14/10 ' 16bit var change to  Degrees = adc/4 * 1.4 for display as degrees



do
dec charactercounter

if length > 3 then
serout lcdpin,baud,(11)
length = length - 3

else
     exit

end if

loop

readvar = length + 8
serout lcdpin,baud,(readvar)

looplabel:

if charactercounter > 0 then
	serout lcdpin,baud,(8)
	dec charactercounter

else
	goto main

end if

goto looplabel

loop


cur_brg_disp:  ' get values to display as bearing

let HTH =  cur_brg /1000   '  returns quotient
let w2= cur_brg// 1000
let HH= w2  /100     ' returns quotient   =  hundreds
let b10= w2 //100    ' remainder modulus divide  b14 (not displayed)
let HT=b10       /10	  ' returns quotient   =  tens
let HU=b10        //10    ' remainder of modulus divide  =  units

return


new_brg_disp:  ' get values to display as bearing

let HTH =  new_brg /1000   '  returns quotient
let w2= new_brg// 1000
let HH= w2  /100     ' returns quotient   =  hundreds
let b10= w2 //100    ' remainder modulus divide  b14 (not displayed)
let HT=b10       /10	  ' returns quotient   =  tens
let HU=b10        //10    ' remainder of modulus divide  =  units

return



Start1:  ' Task 2 - start of key press routines


PAUSE 1000

Symbol IO_ADR = $40 	' I2C address of 8574 with  address lines(A0-A2) low

Symbol reserved = b18 	' reserved for bit twiddling
symbol keypressed = b19
symbol intTemp = b20 	' used in interrupt routine
symbol chars = b21
Symbol bitFlags = b22 	' some flag bits
symbol keyflag=b23


HI2cSetup I2CMASTER, IO_ADR, I2CSLOW, I2CBYTE ' Set up I2C bus


HI2cOut(%11110000)  	'all rows low, all columns high so any key down will fire interrupt pin

setint %00000000,%00000010,c   'interrupt on C.1 (20X2) - 8574 INT pin is active low

let chars = 1 



'*******************************************************************************************************

main2:  ' TASK 2 MAIN PROGRAM



if keyFlag = 1 then 'has interrupt set flag 

   if chars=1 then let new_brg=0: endif
    
    if keypressed  <> 11  and chars<>4 then  ' hash key = 11 used as enter key which should be 4th character

  	select case chars    ' 3 characters for bearing plus enter character
  
     	case  1  ' 1st number of three`
     	
     	  new_brg = keypressed * 100 + new_brg          ' hundreds
     	 
     	case  2  ' second number of three 
  
     		 new_brg = keypressed * 10 + new_brg	' tens
     	 
        case  3  ' third number of three  
  
          new_brg = new_brg + keypressed		' units
      
     end select 
       
      
end if 
   
 if keypressed = 10 then ' clear entries cancel was pressed!

     	gosub cancel

endif
 

if keypressed = 11  then 'enter key pressed and valid bearing to initiate drve to motors

   	if new_brg > 355 then let new_brg = 355 : endif ' set limit going west to 355 degrees
	if new_brg < 5 then let new_brg = 5: endif	' set limit going east

gosub motor


endif


keyFlag = 0 		' clear interrupt flag
  chars = chars + 1 	'set at first character for next bearing

end if



goto main2

'***************************************************************************************************


cancel:

let new_Brg = 0
let chars = 0

return


'*******************************************************************************************


motor:  ' routine to turn beam


cw:  ' routine to drive motor clockwise  i.e.  N-> E-> S-> W->N  


if new_brg > cur_brg then         ' test for direction of travel - if true DO!


high C.4 ' switch on relay drive and drive direction LED indicator -  CW relay activated


Do until Cur_brg >=  New_brg '

'Pause 1000 '  may not need this delay in reality
loop

low c.4 ' switch off relay & LED  it has reached its destination bearing

goto sub_exit

end if





CCW:	' routine to drive motor anticlockwise  i.e.  N-> W-> S-> E-> N		

if new_brg < cur_brg   then	 ' test for direction of travel

high c.2  ' switch on relay drive and drive direction LED indicator - CCW relay activated

Do until Cur_brg <=  New_brg '

'Pause 1000 '  may not need this delay in reality
loop

low c.2  ' switch off relay & LED it has reached its destination bearing

end if



Sub_exit:

let chars = 0	 
return

'********************************************************************************************

interrupt:

'returns with keyFlag = 1 if key was pressed
'puts low on each Row pin and checks column pin for change
'uses lookdown table to translate port value to 0-15 left in keyPressed variable

keyFlag = 0 'default value = key not found


HI2cIn (intTemp)
if intTemp = %11110000 then goto exitInt 'key was not held long enough and we missed it

'inline code to clear each row line and check for key on that row
HI2cOut(%11111110) 'write the row value
HI2cIn (intTemp) 'read in port


if intTemp <> %11111110 then goto foundKey 'if read and write value are different, a key was pressed

HI2cOut(%11111101)   ' Row 2
HI2cIn (intTemp)

if intTemp <> %11111101 then goto foundKey

HI2cOut(%11111011)   ' Row 3
HI2cIn (intTemp)

if intTemp <> %11111011 then goto foundKey

HI2cOut(%11110111)    ' Row 4
HI2cIn (intTemp)

if intTemp <> %11110111 then goto foundKey

goto exitInt 'if we got here we still missed it

foundKey:
keypressed = 255 'default value in case of no match in lokdown table


lookdown intTemp,($d7,$EE,$DE,$BE, $ED,$DD,$BD, $EB,$DB,$BB, $E7,$B7),keypressed
if keypressed <> 255 then
keyFlag = 1 'must have found it in lookdown table

endif


exitInt:
HI2cOut(%11110000) 'all rows low, all columns 
do
HI2cIn (intTemp)
loop until intTemp = %11110000 'wait for no keys pressed

setint %00000000,%0000010,c ' reset interrupt on C.1 low
return ; return from interrupt




[/code]
 

nick12ab

Senior Member
Didn't work Nick. I still get the two arrows with the two CGram lines removed but they are overwritten then displayed and then overwritten and so on. The other thing is that in my program the bargraph line is printed on the 4th line (212) but after I made your changes one arrow is printed on the first line and the other one the 4th.???? Without the changes all works well but I have the two surplus (in this case) arrows.
Nice to see use of the #picaxe directive!

However the glaring flaw in your code is this:
Code:
Serout lcdpin,baud, (254,128,"Cur Brg = ",#HH,#HT,#HU," deg",254,endposition, 13,254,212,12)' 


gosub new_brg_disp
Serout lcdpin,baud, (254,192,"New Brg = ",#HH,#HT,#HU," deg",254,endposition,13,254,212,12)' start pos line 4
The arrows occupy CGRAM locations 12 and 13 so any reference to these must be removed. Doing a Ctrl+F for 13 is a good place to start.

Additionally beware of 'hardcoded' display location constants (e.g. 212 in the code above). These are my fault for sloppy code writing but the new improved versions (parallel display only) are much better in this regard.
 

hamtech

Member
Nick,

Thanks , I must say I haven't really understood how the barcode code worked. I will remove the references to chars 12& 13 and report back.

Thanks for your assistance.

Hamtech
 

hamtech

Member
Nick,

Removing the end of the lines as in your previous post and with the other changes you mentioned it now works as I want it to. Thanks again for your help and for a very useful piece of code that you have kindly shared.

Hamtech
 
Top