Setfreq Issue

bfgstew

Senior Member
Hi again folks,

Optimizing my coding I have created a bit of a cock up!
Basically I needed part of my code speeding up, so using the setfreq command crancked it up to em64 to see what happened. I did have a baudrate of N2400 but now using serout B.7,N19200_64,(#readvar, cr,lf) to see what was happening, OK so far, getting reading on OLED screen and on serial terminal, but still not fast enough, so removed the 4Mhz crystal and replaced it with a 16Mhz crystal, now all I get is a jumble on the OLED, now on the serial terminal I changed the baud rate to max 76800 and is fine on the terminal but still garbage on the OLED, so I tried all baud rates and is still a mess.
Any ideas?

Using 28 X 2
 
Last edited:

srnet

Senior Member
Its not at all clear what you have connected where, or if and when your using the internal oscillator.

Code ?

Circuit diagram ?

PICAXE ?

Which OLED ?

Got a Crystal ball ?
 

bfgstew

Senior Member
Code:
setfreq em64
	serout B.7,N19200_64,(254,1)
	pause 50
	high PG_ON
	pause 50
	serout B.7, N19200_64, (254, 64, 32, 32, 32, 32, 32, 32, 32, 32) ; BLANK CHARACTER (0)	 
	serout B.7, N19200_64, (254, 72, 48, 48, 48, 48, 48, 48, 48, 48) ; 1st segment = (1)
	serout B.7, N19200_64, (254, 80, 56, 56, 56, 56, 56, 56, 56, 56) ; 1st and 2nd segment = (2)
	serout B.7, N19200_64, (254, 88, 60, 60, 60, 60, 60, 60, 60, 60) ; 1st, 2nd and 3rd segment = (3)
	serout B.7, N19200_64, (254, 96, 62, 62, 62, 62, 62, 62, 62, 62) ; 1st, 2nd, 3rd and 4th segment = (4)
	serout B.7, N19200_64, (254, 104, 63, 63, 63, 63, 63, 63, 63, 63); whole block = (5)
	do
		readadc C.7,readvar
		sertxd (#readvar,cr,lf)
		length = lcdsize * 5 - 1 * readvar / 255 + 1
		serout B.7,N19200_64,(254,128,"MONITORING..........")
			serout B.7,N19200_64,(254,192,"ACTUAL LEVEL = ",#length," ")
			serout B.7,N19200_64,(254,148,"0................100",254,212)
		charactercounter = lcdsize
		do
			if length => 6 then
				serout B.7,N19200_64,(13)
				length = length - 5
			elseif length = 5 then
				serout B.7,N19200_64,(13)
				length = length - 4
			else
				exit
			end if
			dec charactercounter 
		loop 
		readvar = length + 8
		serout B.7,N19200_64,(readvar)
		for loopcounter = 0 to charactercounter
			serout B.7,N19200_64,(32)
		next	
	inc b11 
	loop until b11 = 30 gosub TT7
This is the code (part of) that I need speeding up, it's a slight adaptation of Nicks' Bargraph display (TA).
It worked fine as it is with a 4Mhz crystal in circuit, now I have changed the crystal to a 16Mhz one, I can no longer get anything legible on the OLED, when this part of the code is running, as soon as this part stops, its Ok again.
Everything else works OK apart from this.
 

Jeremy Harris

Senior Member
If you're driving a serial OLED, then there is an issue with the maximum baud rate at which it will receive, and you may possibly have some timing problems if you've tweaked the speed up. The software serial ports aren't as reliable as the hardware ones under certain circumstances.

If you're directly driving the OLED via a parallel connection, then you may have timing issues, as the OLED needs time to handle some commands.

As mentioned above, we need more info.
 

nick12ab

Senior Member
The OLED will not automatically change to the new baud rate when a faster crystal is used with the PICAXE. When using the 4MHz crystal the baud rate when the specified baud rate is N19200_64 will be N4800 (so presumably you have changed the serial OLED firmware) and when you change it to a 16Mhz crystal the baud rate is now N19200.

If you need the display code to execute more quickly then you should use the parallel display version of the bargraph display code. I've noticed that when running the code in a loop the bargraph is much more responsive when using a parallel display than when using a serial display and this is part of the reason why I always choose parallel over serial LCDs wherever possible.
 

Jeremy Harris

Senior Member
What happens if you slow it down to transmit out to the serial OLED, then speed it up again for the bits you need to run faster?

My guess is that the serial OLED is struggling at that baud rate, as it's driven via a software serial port at its input and my experience has been that this starts to get a bit flaky when you push the baud rate up a bit. I'm assuming here that you've adjusted the firmware in the AXE134 to try and accept 19200?
 

srnet

Senior Member
The OLED is from Rev-Ed, using B.7 on the 28 x 2 to serout to the OLED's 18M2+.
You normally wont be able to drive it at more than 2400 Baud, although you might just get away with 4800 baud.

Run the serouts to the LCD at setfreq m8, then swap to em64 (16mhz crystal) for the rest of the code.

Incidently with a 4Mhz crystal and a setfreq em64 the processor would only be running at 16mhz.
 

bfgstew

Senior Member
Jeremy and srnet, thanks for the input, I am running the rest of my code at m8 and baudrate N2400 and all is well with that, just the graph bit needs speeding up as per Nicks post.

Nick, thanks for your input. No not changed baudrate on the OLED 18m2+, still at default setting. Reason for speeding up is as you say unresponsive using the serial version, I thought I could just speed the code up at this section to get a more responsive output as it misses a lot of changes on the readadc channel. I think I will have a go at the parallel version, now I am not being stupid here, but is it the code that is either parallel or serial or the display?
 

Jeremy Harris

Senior Member
bfgstew,

Have you thought of just using the AXE134 for your project? There are four pins you can get at on the AXE133/134 and by loading your code into the 18M2 on the back of the display (with some tweaks to access the display directly) you can drive the display much faster than you can by using the serial connection.

I did this for a bargraph display on my electric bike control system and found it worked pretty well. If you need more than 4 pins, then you can use another Picaxe to send data periodically via a serial connection, but have the code you need to run quickly running on the 18M2 on the back of the AXE134.

For some simple projects I've found this versatility very useful, hats off to Rev Ed for thinking to bring the unused pins out and add a programming port to give this versatility.
 

bfgstew

Senior Member
If only Jeremy, if only. All pins on the 28X2 are used up, and the 4 spare on the 18M2+ as well!!!!!!!!
 

nick12ab

Senior Member
Nick, thanks for your input. No not changed baudrate on the OLED 18m2+, still at default setting. Reason for speeding up is as you say unresponsive using the serial version, I thought I could just speed the code up at this section to get a more responsive output as it misses a lot of changes on the readadc channel. I think I will have a go at the parallel version, now I am not being stupid here, but is it the code that is either parallel or serial or the display?
Both.

When you have the AXE133 programmed with the serial firmware and connected to another PICAXE, you are using a serial display and the serout command in code.

When you are using the AXE133 programmed with some custom code to control the display directly or you have removed the display from the AXE133 you are using parallel mode.

Example code that should work when programmed onto the AXE133 18M2:
Code:
#picaxe 18m2
#no_data
#no_end
#terminal off
symbol enable = C.6
symbol rs = C.7
symbol lcddata = pinsB
symbol loopcounter = b4

	setfreq m16
	dirsB = $FF
	dirsC = $03
start:lcddata = %00000110 : pulsout enable,16
	lcddata = %00001100 : pulsout enable,608
	lcddata = %00111011 : pulsout enable,16
	lcddata = %00000001 : pulsout enable,608
main:
	low rs
	lcddata = 128 : pulsout enable,1
	high rs
	for loopcounter = 0 to 15
		lookup loopcounter,("LCD TEST LINE 1 "),lcddata
		pulsout enable,1
	next
	low rs
	lcddata = 192 : pulsout enable,1
	high rs
	for loopcounter = 0 to 15
		lookup loopcounter,("LCD TEST LINE 2 "),lcddata
		pulsout enable,1
	next
	pause 10000
	goto start
If only Jeremy, if only. All pins on the 28X2 are used up, and the 4 spare on the 18M2+ as well!!!!!!!!
Switch to a 40X2.
 

srnet

Senior Member
It would be nice to see an upgrade for the AXE132, that allows for higher baud rates.

I wrote a serial LCD driver for the 18F25K22 (28X2) that drove the parallel LCD display in 8 bit mode and used the busy flag, easy code, done in Mikrobasic.

The PCB (using an SMT 18F25K22) is smaller than the AXE132 and the extra I\O pins allow for a range of jumpers to set options etc.

I was just powering one up this morning, its set for and works at 38400baud.

If I can do it, it cant be that hard.
 

bfgstew

Senior Member
I have had to revert back to the original code, I just couldn't get it to go fast enough with the bargraph display, so will just have a readout of the readadc on screen.

But thanks to Nick, I now know 'how' to make it faster for future reference.

Thanks anyhow guys, always appreciate your input.

Stewart
 

nick12ab

Senior Member
I have had to revert back to the original code, I just couldn't get it to go fast enough with the bargraph display, so will just have a readout of the readadc on screen.

But thanks to Nick, I now know 'how' to make it faster for future reference.
I have another idea that will allow you to use a serial display and have the bargraph display - modify the AXE133 firmware so that it has an additional command which creates the bargraph. This means that you only need to send two bytes (a command byte e.g. 251 then the value to display) and the AXE133 firmware then draws the bargraph by interfacing directly with the parallel display so this doesn't cause the main PICAXE to run slow.
 

srnet

Senior Member
One easy mod to the AXE133 is to connect one of the 'spare' I\O pins so that the busy flag on the controller can be read.

Then instead of just using delays between display writes, which can be too long especially for the OLEDs, the program can continue as soon as the display has actually processed the last command.
 

nick12ab

Senior Member
One easy mod to the AXE133 is to connect one of the 'spare' I\O pins so that the busy flag on the controller can be read.

Then instead of just using delays between display writes, which can be too long especially for the OLEDs, the program can continue as soon as the display has actually processed the last command.
I've found that using delays or the busy flag on LCDs when interfacing them with PICAXEs is unnecessary (even on a 64MHz X2 part) because the PICAXE's interpreter makes the code execution slow. Of course the busy flag is probably needed if using a plain PIC with a compiler.

It wouldn't help with the serial anyway as the sender PICAXE's interpreter uses a delay between bytes that cannot be customized.
 

bfgstew

Senior Member
I have another idea that will allow you to use a serial display and have the bargraph display - modify the AXE133 firmware so that it has an additional command which creates the bargraph. This means that you only need to send two bytes (a command byte e.g. 251 then the value to display) and the AXE133 firmware then draws the bargraph by interfacing directly with the parallel display so this doesn't cause the main PICAXE to run slow.
Good idea Nick, I will endevour to give it a try, many thanks.
 

bfgstew

Senior Member
OK, I have had a few hours at altering both my code and the AXE 134OLED firmware, and have made a little headway.
I can only get a few solid blocks on the OLED, but that is all, and it will not come back to execute the next stage of code.?
Below are the code segments.

Added the segment 252 to initialise the graph routine.

Code:
main:

	serin RX,baud,b1			; wait for the next byte

	; NB keep character mode test as first item in this list to optimise speed
	if b1 < 252 then
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		goto main			; quickly loop back to top
	else if b1 = 254 then
		low rs 	     		; change to command mode for next character
		serin RX,baud,b1		; wait for the command byte
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		high rs			; back to character mode
		goto main			; quickly loop back to top
	else if b1 = 253 then
		serin RX,baud,b1		; wait for the next byte
		gosub msg			; do the 16 character message
		goto main			; back to top
	elseif b1 = 252 then
		serin RX,baud,b1
		gosub graph
		goto main
	else ; must be 255
		serin RX,baud,b1		; wait for the next byte
		let pinsC = b1 & %00000111 | %10000000
						; output the data on C.0 to C.1, keep RS high
		goto main			; back to top
	end if
This is the bargraph routine on the OLED's 18M2+(kindly done by Nick)

Code:
graph:
	dirsB = 255
	low rs
	low enable
	setfreq m8
	lcddata = %00000001 : pulsout enable,100
	lcddata = %00000010 : pulsout enable,100
	lcddata = %00001100 : pulsout enable,100
	lcddata = %00111000 : pulsout enable,100
	lcddata = 64 : pulsout enable,1
	high rs
	for loopcounter = 0 to 47
		lookup loopcounter,(32,32,32,32,32,32,32,32,48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,60,60,60,60,60,60,60,60,62,62,62,62,62,62,62,62,63,63,63,63,63,63,63,63),lcddata
		pulsout enable,1
	next
	endposition = lcdsize + 193
main1:
	do
		
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		low rs
		lcddata = 128 : pulsout enable,1
		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 = 192 : pulsout enable,1
		high rs
		lcddata = 12 : pulsout enable,1
		charactercounter = lcdsize
		do
			dec charactercounter
			if length => 6 then
				lcddata = 13 : pulsout enable,1
				length = length - 6
			else
				lcddata = 13 : pulsout enable,1
				length = length - 5
			
				exit
			end if
		loop
		lcddata = length + 8 : pulsout enable,1
		
looplabel:
		if charactercounter > 0 then
			lcddata = 32 : pulsout enable,1
			dec charactercounter
		else
			goto main1
		end if
		goto looplabel
	loop
This is my code snippet to get the graph on screen, I need to send the data of readvar to the OLED chip so it can display it and run the code correctly.

Code:
SETTING:
	serout B.7,N2400,(254,1) ; clears OLED
	pause 50
	high PG_ON			 ;sets C.1 high for photogate voltage supply
	pause 50
	do
		readadc PG_IN,readvar ; readadc on photogate output on C.7 into variable
			serout B.7,N2400,(254,128,"MONITORING..........")        ; OLED first line
			serout B.7,N2400,(254,192,"ACTUAL LEVEL = ",#length," ") ; OLED second line
			serout B.7,N2400,(254,148,"0................100")        ; OLED third line
			serout B.7,N2400,(252,#readvar,254,212)                  ; command for BARGRAPGH?
			
	inc b11 
	loop until b11 = 30 gosub TT7                                        ;loop countdown to pick up background readings on readvar
Any ideas on how to improve, correct, my mess????

Cheers

Stewart
 

bfgstew

Senior Member
This is the full OLED code -

Code:
; AXE134 Serial 20x4 OLED using PICAXE-18M2
; Emulates basic serial operation of the popular AXE033 module
; CPS, May 2011
; JB,  Jan 2012

#picaxe 18M2


; Supported Commands
; 0-7, 8-15	CGRAM characters
; 16-252	normal ASCII characters, according to selected character map table
; 253, X	display 12 character pre-saved message from EEPROM memory, X can be 0-11
; 254, X	OLED command, X can be 0 to 255 
; 255, X	control outputs C.2, C.1, C.0 (via lower 3 bits of X)

#define use_welcome	; display the welcome message upon power up

symbol baud = N2400_16	; Serial baud rate 2400,N,8,1. Note main program runs at 16MHz

symbol spare0 	= C.0 ; spare output 0
symbol spare1 	= C.1 ; spare output 1
symbol spare2 	= C.2 ; spare output 2
symbol RX		= C.5	; serial receive pin
symbol enable 	= C.6	; OLED enable
symbol rs 		= C.7	; OLED RS 
symbol readvar = b6
symbol length = b7
symbol loopcounter = b8
symbol charactercounter = b9
symbol endposition = b10 
symbol lcddata = pinsB
symbol lcdsize = 20

	

; OLED data pins are on B.0 to B.7

; Store the 20 character user defined messages in EEPROM data memory
; First two messages are optionally used as welcome message

; Please remember 4 line displays always use the strange 1-3-2-4 line layout.

EEPROM  00, ("") 	; store msg 0 in the EEPROM memory
EEPROM  20, ("") 	; store msg 1 in the EEPROM memory
EEPROM  40, ("") 	; store msg 2 in the EEPROM memory
EEPROM  60, ("") 	; store msg 3 in the EEPROM memory
EEPROM  80, ("") 	; store msg 4 in the EEPROM memory
EEPROM 100, ("") 	; store msg 5 in the EEPROM memory
EEPROM 120, ("") 	; store msg 6 in the EEPROM memory
EEPROM 140, ("") 	; store msg 7 in the EEPROM memory
EEPROM 160, ("") 	; store msg 8 in the EEPROM memory
EEPROM 180, ("") 	; store msg 9 in the EEPROM memory
EEPROM 200, ("") 	; store msg 10 in the EEPROM memory
EEPROM 220, ("") 	; store msg 11 in the EEPROM memory

;initialise OLED
init:
	gosub OLED_init 		; initialise OLED

; display welcome message if desired
#ifdef use_welcome	
	let b1 = 0			; message 0 on top line
	gosub msg			; do it

	low rs			; command mode
	let pinsB = 192		; move to line 2, instruction 192
	pulsout enable,1  	; pulse the enable pin to send data.
	high rs			; character mode again
	
	let b1 = 1 			; message 1 on bottom line
	gosub msg			; do it
#endif		
		
; main program loop, runs at 16MHz

main:

	serin RX,baud,b1			; wait for the next byte

	; NB keep character mode test as first item in this list to optimise speed
	if b1 < 252 then
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		goto main			; quickly loop back to top
	else if b1 = 254 then
		low rs 	     		; change to command mode for next character
		serin RX,baud,b1		; wait for the command byte
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		high rs			; back to character mode
		goto main			; quickly loop back to top
	else if b1 = 253 then
		serin RX,baud,b1		; wait for the next byte
		gosub msg			; do the 16 character message
		goto main			; back to top
	elseif b1 = 252 then
		serin RX,baud,b1
		gosub graph
		goto main
	else ; must be 255
		serin RX,baud,b1		; wait for the next byte
		let pinsC = b1 & %00000111 | %10000000
						; output the data on C.0 to C.1, keep RS high
		goto main			; back to top
	end if


; power on OLED initialisation sub routine
OLED_init:
	let dirsC = %11000111	; PortC 0,1,2,6,7 all outputs
	let dirsB = %11111111	; PortB all outputs

	; Winstar OLED Module Initialisation
	; according to WS0010 datasheet (8 bit mode)

	pause 500 			; Power stabilistation = 500ms

	; Function set - select only one of these 4 character table modes
	;let pinsB = %00111000 	; 8 bit, 2 line, 5x8 , English_Japanese table
	let pinsB = %00111001 	; 8 bit, 2 line, 5x8 , Western_European table1
	;let pinsB = %00111010 	; 8 bit, 2 line, 5x8 , English_Russian  table
	;let pinsB = %00111011 	; 8 bit, 2 line, 5x8 , Western_European table2
	
	pulsout enable,1  	; 
		
	let pinsB = %00001100	; Display on, no cursor, no blink
	pulsout enable,1 	

	let pinsB = %00000001 	; Display Clear
	pulsout enable,1
	pause 7			; Allow 6.2ms to clear display

	setfreq m16			; now change to 16Mhz

	let pinsB = %00000010 	; Return Home
	pulsout enable,1

	let pinsB = %00000110 	; Entry Mode, ID=1, SH=0
	pulsout enable, 1

	high rs			; Leave in character mode
	return

graph:
	dirsB = 255
	low rs
	low enable
	setfreq m8
	lcddata = %00000001 : pulsout enable,100
	lcddata = %00000010 : pulsout enable,100
	lcddata = %00001100 : pulsout enable,100
	lcddata = %00111000 : pulsout enable,100
	lcddata = 64 : pulsout enable,1
	high rs
	for loopcounter = 0 to 47
		lookup loopcounter,(32,32,32,32,32,32,32,32,48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,60,60,60,60,60,60,60,60,62,62,62,62,62,62,62,62,63,63,63,63,63,63,63,63),lcddata
		pulsout enable,1
	next
	endposition = lcdsize + 193
main1:
	do
		
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		low rs
		lcddata = 128 : pulsout enable,1
		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 = 192 : pulsout enable,1
		high rs
		lcddata = 12 : pulsout enable,1
		charactercounter = lcdsize
		do
			dec charactercounter
			if length => 6 then
				lcddata = 13 : pulsout enable,1
				length = length - 6
			else
				lcddata = 13 : pulsout enable,1
				length = length - 5
			
				exit
			end if
		loop
		lcddata = length + 8 : pulsout enable,1
		
looplabel:
		if charactercounter > 0 then
			lcddata = 32 : pulsout enable,1
			dec charactercounter
		else
			goto main1
		end if
		goto looplabel
	loop
	
; display message from EEPROM sub routine
; message number 0-11 must be in b1 when called
; uses (alters) b1, b2, b3, b4
msg:
	let b2 = b1 // 12 * 20		; EEPROM start address is 0 to 11 multiplied by 20
	let b3 = b2 + 20 - 1 		; end address is start address + (20 - 1)
	for b4 = b2 to b3			; for 20 times
		read b4,b1			; read next character from EEPROM data memory into b1
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
	next b4				; next loop
	return
 

nick12ab

Senior Member
Any ideas on how to improve, correct, my mess????
This part of the code needs to be removed as the OLED is already initialized so it doesn't need to be done again - that will just slow down the bargraph routine.
Code:
	dirsB = 255
	low rs
	low enable
	setfreq m8
	lcddata = %00000001 : pulsout enable,100
	lcddata = %00000010 : pulsout enable,100
	lcddata = %00001100 : pulsout enable,100
	lcddata = %00111000 : pulsout enable,100

This part of the code should be moved to the beginning of the AXE133 code and placed just after where the display is initialized.
Code:
	low rs
	lcddata = 64 : pulsout enable,1
	high rs
	for loopcounter = 0 to 47
		lookup loopcounter,(32,32,32,32,32,32,32,32,48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,60,60,60,60,60,60,60,60,62,62,62,62,62,62,62,62,63,63,63,63,63,63,63,63),lcddata
		pulsout enable,1
	next
Finally do you have a return command at the end of the bargraph routine?
 

bfgstew

Senior Member
OK Nick, I have followed your advice and things are getting better but not there yet!

This what I get on the OLED now

01NITORING.......... = first line
[][][] = second line [] is representing a solid block on the oled
0.................100 = third line
[] = fourth line

Just to make sure the code for the OLED now -

Code:
; AXE134 Serial 20x4 OLED using PICAXE-18M2
; Emulates basic serial operation of the popular AXE033 module
; CPS, May 2011
; JB,  Jan 2012

#picaxe 18M2


; Supported Commands
; 0-7, 8-15	CGRAM characters
; 16-252	normal ASCII characters, according to selected character map table
; 253, X	display 12 character pre-saved message from EEPROM memory, X can be 0-11
; 254, X	OLED command, X can be 0 to 255 
; 255, X	control outputs C.2, C.1, C.0 (via lower 3 bits of X)

#define use_welcome	; display the welcome message upon power up

symbol baud = N2400_16	; Serial baud rate 2400,N,8,1. Note main program runs at 16MHz

symbol spare0 	= C.0 ; spare output 0
symbol spare1 	= C.1 ; spare output 1
symbol spare2 	= C.2 ; spare output 2
symbol RX		= C.5	; serial receive pin
symbol enable 	= C.6	; OLED enable
symbol rs 		= C.7	; OLED RS 
symbol readvar = b6
symbol length = b7
symbol loopcounter = b8
symbol charactercounter = b9
symbol endposition = b10 
symbol lcddata = pinsB
symbol lcdsize = 20

	

; OLED data pins are on B.0 to B.7

; Store the 20 character user defined messages in EEPROM data memory
; First two messages are optionally used as welcome message

; Please remember 4 line displays always use the strange 1-3-2-4 line layout.

EEPROM  00, ("") 	; store msg 0 in the EEPROM memory
EEPROM  20, ("") 	; store msg 1 in the EEPROM memory
EEPROM  40, ("") 	; store msg 2 in the EEPROM memory
EEPROM  60, ("") 	; store msg 3 in the EEPROM memory
EEPROM  80, ("") 	; store msg 4 in the EEPROM memory
EEPROM 100, ("") 	; store msg 5 in the EEPROM memory
EEPROM 120, ("") 	; store msg 6 in the EEPROM memory
EEPROM 140, ("") 	; store msg 7 in the EEPROM memory
EEPROM 160, ("") 	; store msg 8 in the EEPROM memory
EEPROM 180, ("") 	; store msg 9 in the EEPROM memory
EEPROM 200, ("") 	; store msg 10 in the EEPROM memory
EEPROM 220, ("") 	; store msg 11 in the EEPROM memory

;initialise OLED
init:
	gosub OLED_init 		; initialise OLED
	low rs
	lcddata = 64 : pulsout enable,1
	high rs
	for loopcounter = 0 to 47
		lookup loopcounter,(32,32,32,32,32,32,32,32,48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,60,60,60,60,60,60,60,60,62,62,62,62,62,62,62,62,63,63,63,63,63,63,63,63),lcddata
		pulsout enable,1
	next

; display welcome message if desired
#ifdef use_welcome	
	let b1 = 0			; message 0 on top line
	gosub msg			; do it

	low rs			; command mode
	let pinsB = 192		; move to line 2, instruction 192
	pulsout enable,1  	; pulse the enable pin to send data.
	high rs			; character mode again
	
	let b1 = 1 			; message 1 on bottom line
	gosub msg			; do it
#endif		
		
; main program loop, runs at 16MHz

main:

	serin RX,baud,b1			; wait for the next byte

	; NB keep character mode test as first item in this list to optimise speed
	if b1 < 252 then
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		goto main			; quickly loop back to top
	else if b1 = 254 then
		low rs 	     		; change to command mode for next character
		serin RX,baud,b1		; wait for the command byte
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		high rs			; back to character mode
		goto main			; quickly loop back to top
	else if b1 = 253 then
		serin RX,baud,b1		; wait for the next byte
		gosub msg			; do the 16 character message
		goto main			; back to top
	elseif b1 = 252 then
		serin RX,baud,b1
		gosub graph
		goto main
	else ; must be 255
		serin RX,baud,b1		; wait for the next byte
		let pinsC = b1 & %00000111 | %10000000
						; output the data on C.0 to C.1, keep RS high
		goto main			; back to top
	end if


; power on OLED initialisation sub routine
OLED_init:
	let dirsC = %11000111	; PortC 0,1,2,6,7 all outputs
	let dirsB = %11111111	; PortB all outputs

	; Winstar OLED Module Initialisation
	; according to WS0010 datasheet (8 bit mode)

	pause 500 			; Power stabilistation = 500ms

	; Function set - select only one of these 4 character table modes
	;let pinsB = %00111000 	; 8 bit, 2 line, 5x8 , English_Japanese table
	let pinsB = %00111001 	; 8 bit, 2 line, 5x8 , Western_European table1
	;let pinsB = %00111010 	; 8 bit, 2 line, 5x8 , English_Russian  table
	;let pinsB = %00111011 	; 8 bit, 2 line, 5x8 , Western_European table2
	
	pulsout enable,1  	; 
		
	let pinsB = %00001100	; Display on, no cursor, no blink
	pulsout enable,1 	

	let pinsB = %00000001 	; Display Clear
	pulsout enable,1
	pause 7			; Allow 6.2ms to clear display

	setfreq m16			; now change to 16Mhz

	let pinsB = %00000010 	; Return Home
	pulsout enable,1

	let pinsB = %00000110 	; Entry Mode, ID=1, SH=0
	pulsout enable, 1

	high rs			; Leave in character mode
	return

graph:
	
	endposition = lcdsize + 193
main1:
	do
		
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		low rs
		lcddata = 128 : pulsout enable,1
		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 = 192 : pulsout enable,1
		high rs
		lcddata = 12 : pulsout enable,1
		charactercounter = lcdsize
		do
			dec charactercounter
			if length => 6 then
				lcddata = 13 : pulsout enable,1
				length = length - 6
			else
				lcddata = 13 : pulsout enable,1
				length = length - 5
			
				exit
			end if
		loop
		lcddata = length + 8 : pulsout enable,1
		
looplabel:
		if charactercounter > 0 then
			lcddata = 32 : pulsout enable,1
			dec charactercounter
		else
			goto main1
		end if
		goto looplabel
		inc b11 
	loop until b11 = 30 return

	
; display message from EEPROM sub routine
; message number 0-11 must be in b1 when called
; uses (alters) b1, b2, b3, b4
msg:
	let b2 = b1 // 12 * 20		; EEPROM start address is 0 to 11 multiplied by 20
	let b3 = b2 + 20 - 1 		; end address is start address + (20 - 1)
	for b4 = b2 to b3			; for 20 times
		read b4,b1			; read next character from EEPROM data memory into b1
		let pinsB = b1 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
	next b4				; next loop
	return
 

nick12ab

Senior Member
OK Nick, I have followed your advice and things are getting better but not there yet!

This what I get on the OLED now

01NITORING.......... = first line
[][][] = second line [] is representing a solid block on the oled
0.................100 = third line
[] = fourth line
I'm not sure what the intended display for the last two lines is meant to be but I can tell that the first line is not supposed to be 01NITORING.

The 01 on the first line is there because my bargraph example displays the bargraph value on the display using the lines in bold:
Code:
graph:
	
	endposition = lcdsize + 193
main1:
	do
		
		length = lcdsize * 6 - 1 * readvar / 255 + 1
		low rs
[B]		lcddata = 128 : pulsout enable,1
		bintoascii length,b25,b26,b27
		high rs
		lcddata = b26 : pulsout enable,1
		lcddata = b27 : pulsout enable,1
		low rs[/B]
		lcddata = endposition : pulsout enable,1
		high rs
		lcddata = 13 : pulsout enable,1
		low rs
		lcddata = 192 : pulsout enable,1
		high rs
		lcddata = 12 : pulsout enable,1
		charactercounter = lcdsize
		do
			dec charactercounter
			if length => 6 then
				lcddata = 13 : pulsout enable,1
				length = length - 6
			else
				lcddata = 13 : pulsout enable,1
				length = length - 5
			
				exit
			end if
		loop
		lcddata = length + 8 : pulsout enable,1
		
looplabel:
		if charactercounter > 0 then
			lcddata = 32 : pulsout enable,1
			dec charactercounter
		else
			goto main1
		end if
		goto looplabel
		inc b11 
	loop until b11 = 30 return
Removal of the bold lines should fix that.
 

bfgstew

Senior Member
Thanks Nick, will give that a try.

The third line is a simple 0 to 100 scale to represent the bargraph on the fourth line.
 

bfgstew

Senior Member
Sorry Nick, can't see any 'BOLD' lines on that code....

First line just says MONITORING..........
second line should display length variable as ACTUAL LEVEL = ?
third line is the scale 0............................100
forth line is the bargraph [][][][][][][][][][][][][][]

Bargraph should move according to the readadc value and actual level should alter according to the length variable.
 

nick12ab

Senior Member
Try this and see if it produces a 20 character bargraph on the bottom line:
Code:
; AXE133 Serial LCD/OLED using PICAXE-18M2
; Emulates basic serial operation of the popular AXE033 module
; CPS, May 2011
; v2 18/01/2012

#picaxe 18M2
#no_data
; ********************************************
; Note you must uncomment just one of these two options
; depending on whether you have an LCD or OLED module
;#define use_OLED
#define use_LCD
; ********************************************


; Supported Commands
; 0-7, 8-15	CGRAM characters
; 16-252	normal ASCII characters, according to selected character map table
; 253, X	display 16 character pre-saved message from EEPROM memory, X can be 0-15
; 254, X	LCD command, X can be 0 to 255 
; 255, X	control outputs C.2, C.1, C.0 (via lower 3 bits of X)
;		So, if using a backlit LCD with the active low transistor driver
;		on output C.2, then 255,%000 switches backlight on and 255,%100 switches off


'#define use_welcome	; display the welcome message upon power up
symbol line_length = 20	; change to 20 for displays with 20 character lines

symbol baud = N2400_16	; Serial baud rate 2400,N,8,1. Note main program runs at 16MHz

symbol spare0 	= C.0 ; spare output 0
symbol spare1 	= C.1 ; spare output 1
symbol spare2 	= C.2 ; spare output 2 (or optional backlight)
symbol backlight 	= C.2 ; optional backlight control for backlit LCDs, active low
symbol RX		= C.5	; serial receive pin
symbol enable 	= C.6	; LCD enable
symbol rs 		= C.7	; LCD RS 
symbol recvar = b1
symbol loopcounter = b4
symbol endposition = b5
symbol length = b6
symbol lcddata = pinsB

; LCD data pins are on B.0 to B.7

; Store the 16 character user defined messages in EEPROM data memory
; First two messages are optionally used as welcome message

; If using a display with 20 characters you will need to edit 
; the start addresses to be multiples of 20 (currently at 16) 
; and add 4 characters to each message.
; Please remember 4 line displays always use the strange 1-3-2-4 layout.

#ifdef use_OLED		
EEPROM $00, ("  Serial OLED   ") 	; store msg in the EEPROM memory
#else
EEPROM $00, ("   Serial LCD   ") 	; store msg in the EEPROM memory
#endif


EEPROM $10, (" www.picaxe.com ") 	; store msg in the EEPROM memory

EEPROM $20, ("This is msg 2   ") 	; store msg in the EEPROM memory
EEPROM $30, ("This is msg 3   ") 	; store msg in the EEPROM memory
EEPROM $40, ("This is msg 4   ") 	; store msg in the EEPROM memory
EEPROM $50, ("This is msg 5   ") 	; store msg in the EEPROM memory
EEPROM $60, ("This is msg 6   ") 	; store msg in the EEPROM memory
EEPROM $70, ("This is msg 7   ") 	; store msg in the EEPROM memory
EEPROM $80, ("This is msg 8   ") 	; store msg in the EEPROM memory
EEPROM $90, ("This is msg 9   ") 	; store msg in the EEPROM memory
EEPROM $A0, ("This is msg 10  ") 	; store msg in the EEPROM memory
EEPROM $B0, ("This is msg 11  ") 	; store msg in the EEPROM memory
EEPROM $C0, ("This is msg 12  ") 	; store msg in the EEPROM memory
EEPROM $D0, ("This is msg 13  ") 	; store msg in the EEPROM memory
EEPROM $E0, ("This is msg 14  ") 	; store msg in the EEPROM memory
EEPROM $F0, ("This is msg 15  ") 	; store msg in the EEPROM memory

;initialise LCD
init:
	gosub LCD_init 		; initialise LCD

; display welcome message if desired
#ifdef use_welcome	
	let recvar = 0			; message 0 on top line
	gosub msg			; do it

	low rs			; command mode
	let pinsB = 192		; move to line 2, instruction 192
	pulsout enable,1  	; pulse the enable pin to send data.
	high rs			; character mode again
	
	let recvar = 1			; message 1 on bottom line
	gosub msg			; do it
#endif		
		
; main program loop, runs at 16MHz

main:

	serin RX,baud,recvar			; wait for the next byte

	; NB keep character mode test as first item in this list to optimise speed
	if recvar < 252 then
		let pinsB = recvar 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		goto main			; quickly loop back to top
	else if recvar = 254 then
		low rs 	     		; change to command mode for next character
		serin RX,baud,recvar		; wait for the command byte
		let pinsB = recvar 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
		high rs			; back to character mode
		goto main			; quickly loop back to top
	else if recvar = 253 then
		serin RX,baud,recvar		; wait for the next byte
		gosub msg			; do the 16 character message
		goto main			; back to top
	elseif recvar = 252 then
		serin RX,baud,recvar
		length = line_length * 5 - 1 * recvar / 255 + 1
		low rs
		lcddata = endposition : pulsout enable,1
		high rs
		lcddata = 13 : pulsout enable,1
		low rs
		lcddata = 212 : pulsout enable,1
		high rs
		loopcounter = line_length
		do
			if length => 5 then
				lcddata = 13 : pulsout enable,1
				length = length - 5
			else
				exit
			end if
			dec loopcounter
		loop
		lcddata = length + 8 : pulsout enable,1
		do
			if loopcounter > 0 then
				lcddata = 32 : pulsout enable,1
				dec loopcounter
			else
				goto main
			end if
		loop
	else ; must be 255
		serin RX,baud,recvar		; wait for the next byte
		let pinsC = recvar & %00000111 | %10000000
						; output the data on C.0 to C.1, keep RS high
		goto main			; back to top
	end if


; power on LCD initialisation sub routine
LCD_init:
	let dirsC = %11000111	; PortC 0,1,2,6,7 all outputs
	let dirsB = %11111111	; PortB all outputs
	

	
#ifdef use_OLED
	; Winstar OLED Module Initialisation
	; according to WS0010 datasheet (8 bit mode)

	pause 500 			; Power stabilistation = 500ms

	; Function set - select only one of these 4 character table modes
	;let pinsB = %00111000 	; 8 bit, 2 line, 5x8 , English_Japanese table
	let pinsB = %00111001 	; 8 bit, 2 line, 5x8 , Western_European table1
	;let pinsB = %00111010 	; 8 bit, 2 line, 5x8 , English_Russian  table
	;let pinsB = %00111011 	; 8 bit, 2 line, 5x8 , Western_European table2
	
	pulsout enable,1  	; 
		
	let pinsB = %00001100	; Display on, no cursor, no blink
	pulsout enable,1 	

	let pinsB = %00000001 	; Display Clear
	pulsout enable,1
	pause 7			; Allow 6.2ms to clear display

	setfreq m16			; now change to 16Mhz

	let pinsB = %00000010 	; Return Home
	pulsout enable,1

	let pinsB = %00000110 	; Entry Mode, ID=1, SH=0
	pulsout enable, 1


#else	
	; Standard LCD Module Initialisation
	pause 15 			; Wait 15ms for LCD to reset.

	let pinsB = %00110000 	; 8 bit, 2 line
	pulsout enable,1  	; Send data by pulsing enable
	pause 5 			; Wait 5 ms
	pulsout enable,1 	 	; Send data 48 again
	pulsout enable,1  	; Send data 48 again
	
	setfreq m16			; now change to 16Mhz

	let pinsB = %00111000 	; LCD  - 8 bit, 2 line, 5x8  
	pulsout enable,1
			
	let pinsB = %00000001	; Clear Display
	pulsout enable,1 	
	pause 8			; 8 = 2ms at 16MHz
	
	let pinsB = %00000010 	; return home
	pulsout enable,1

	let pinsB = %00000110	; Entry mode
	pulsout enable,1 	
	pause 1			

	let pinsB = %00001100	; Display on, no cursor, no blink
	pulsout enable,1 	
#endif
	low rs
	lcddata = 64 : pulsout enable,1
	high rs
	for loopcounter = 0 to 47
		lookup loopcounter,(32,32,32,32,32,32,32,32,48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,60,60,60,60,60,60,60,60,62,62,62,62,62,62,62,62,63,63,63,63,63,63,63,63),lcddata
		pulsout enable,1
	next
	endposition = line_length + 213
	return


; display message from EEPROM sub routine
; message number 0-15 must be in recvar when called
; uses (alters) recvar, b2, b3, b4
msg:
	let b2 = recvar & %00001111 * line_length
						; EEPROM start address is 0 to 15 multiplied by 16
	let b3 = b2 + line_length - 1 ; end address is start address + (line_length - 1)
	for loopcounter = b2 to b3			; for 16 times
		read loopcounter,recvar			; read next character from EEPROM data memory into recvar
		let pinsB = recvar 		; output the data
		pulsout enable,1  	; pulse the enable pin to send data.
	next b4				; next loop
	return
	
; Check end user has defined just one type of display
#ifndef use_OLED
#ifndef use_LCD
#error "Oops - no OLED / LCD type defined at top of program!"
#endif
#endif

#ifdef use_OLED
#ifdef use_LCD
#error "Oops - both OLED / LCD types defined at top of program!"
#endif
#endif
 

bfgstew

Senior Member
Seems to have done the trick Nick, thank you very much indeed.

I found it a bit of a struggle as not tried communicating with another chip like this so was a good learning curve, I did manage to get the display correctly orientated before you posted the new code, but still needed a fair bit of work to get it going properly, yours has taken a lot of hardwork out of it and is much apprecited.

Will hook up the photogate shortly and see if works in anger.

Thanks once again.

Stewart
 

Buzby

Senior Member
Just for information, the code was written by CPS.

CPS, afaik, is Clive Seager,
Technical Director of Rev-Ed

e
It was Clive who got me into PICAXE, via a long and tortuous route involving trying to run Ethernet, and lots more, on a tiny PIC.

The project was doomed to failure. I think we all, except my Boss !, knew that.

So thanks to Clive for all he has done for PICAXE, and the education of our future engineers.
( Except my lad, who upon seeing my PICAXE said 'Oh yes, we did that last year', then went back to playing Thrash Metal on his acoustic drum kit. )

Cheers,

Buzby
 

westaust55

Moderator
For nick12ab's bargraph add-in, untested but if you try this alternate FOR...NEXT loop it should (hopefully) give the same results, save 57 bytes, and may (?) even be faster as the LOOKUP command is I believe slower as more parameters are added to the list.
Code:
	for loopcounter = 0 to 47
		lcddata = loopcounter /8
		lookup lcddata,(32,48,56,60,62,63),lcddata
		pulsout enable,1
	next
	endposition = line_length + 213
	return
 

bfgstew

Senior Member
Nice one westaust55, I will give it a try but first I am struggling getting the data from the readvar variable to the OLED?????
 

AllyCat

Senior Member
may (?) even be faster as the LOOKUP command is I believe slower as more parameters are added to the list.
Hi,

Yes indeed; I measured that each parameter adds about 250 raw PIC instruction cycles (250us with a 4MHz clock) to the execution time of each LOOKUP command. The reason is that "under the hood" each parameter in the command is executed by a separate "IF...", with NO early exit when the required element is found. I calculate that that loop in nick's code would take around half a second with a 4MHz clock (125ms with the declared m16) !

Cheers, Alan.
 

srnet

Senior Member
I've found that using delays or the busy flag on LCDs when interfacing them with PICAXEs is unnecessary (even on a 64MHz X2 part) because the PICAXE's interpreter makes the code execution slow. Of course the busy flag is probably needed if using a plain PIC with a compiler.

It wouldn't help with the serial anyway as the sender PICAXE's interpreter uses a delay between bytes that cannot be customized.
Your right, I was confused.

I just came across the code, it was for the bare PIC version of the 16F1827 to replace the 18M2 on the AXY133Y.

That did run at 38400baud and needed a simple PCB hack to get access to the busy flag.
 

bfgstew

Senior Member
Need your help again guys!
Everthing is looking good with the bargraph now, but how do I get the value of the readadc input on the 28X2 into the code in the 18M2, so the bargraph actually moves with the changing value?
 

nick12ab

Senior Member
Need your help again guys!
Everthing is looking good with the bargraph now, but how do I get the value of the readadc input on the 28X2 into the code in the 18M2, so the bargraph actually moves with the changing value?
Use 252,value in the serout command. The code I posted will scale the received value so simply send the 0-255 ADC reading without modification. If it doesn't display properly, try sending the command (252) and the value in two separate serout commands.
 
Top