18M2 Timer problem

#1
I have my 18M2 timer program up and running thanks to a lot of help from various members on this board. Thank you all very much.
So today everything arrived and I have been able to connect an 18m2 starter board with an AXE133Y OLED. Using a Potentiometer I was able to vary the time required and start a clock when the enter button was hit.

Everything went according to plan except for one thing....

The timer is running slow. I stripped out all switches etc etc and then used the most simple of codes for a timer which just displays seconds on the LED display. Its like 3 lines of code, so no "blocking" can be happening and it is losing seconds in every minute.
I don't need micro second exactness, but I don't want to losing 3 or 4 seconds in every minute either.

Am I missing something or is the internal timer just not very reliable?

Will I need to get a 555 timer chip and build this into the project?
 

nick12ab

Senior Member
#2
The internal timer isn't very reliable but it isn't that unreliable. If good accuracy is required, a 28/40-pin PICAXE with external crystal should be used.

A possibility for this amount of unreliability is that you are using a serial display. The microcontroller cannot respond to the polled internal timer interrupt during the serial transmission and the serial transmission isn't very fast so for those reasons I always recommend using a parallel LCD or OLED* - it's not like the AXE133 actually does any hard work for you.

*It's possible to control a Winstar parallel OLED display with unmodified HD44780 driver code and in fact this is what the AXE033Y does.
 
#3
So effectively the internal timer on the 18m2 becomes pretty useless as it is being interrupted by the serial transmission to the AXE133Y display every second?
So there is no way I can use an AXE133Y to display an accurate seconds counter?

Isn't the M2 capable of parallel tasks? Could I use that somehow?
If I am understanding what is happening correctly, it seems very limited that the microcontroller can't keep an accurate count of time while sending a serial transmission.
 

nick12ab

Senior Member
#4
Isn't the M2 capable of parallel tasks? Could I use that somehow?
Parallel tasks is simulated multitasking on a single core microcontroller.

So there is no way I can use an AXE133Y to display an accurate seconds counter?
You can. If you only need a few I/O for other purposes, then you can reprogram the PICAXE-18M2 on the AXE133 PCB to interface directly with the OLED using the parallel interface.

If I am understanding what is happening correctly, it seems very limited that the microcontroller can't keep an accurate count of time while sending a serial transmission.
Have you also tried using hserout? That uses the UART peripheral built into the PIC microcontroller which shouldn't interfere with the timer.

If this doesn't solve the problem, also try only updating the display once a minute to make sure that you don't happen to have a PIC with severe internal oscillator drift.
 
#5
Thanks Nick. Yehh I tried refreshing the display every 5sec and that helped, but still off. I'm losing about 12sec in every minute with this code:
Code:
Symbols 
{
symbol varA = b0
symbol varB = b1
symbol varC = b2
symbol varD = b3
symbol varE = b4
symbol varF = b5
symbol varG = b6
symbol varH = b7
symbol varI = b14
symbol varJ = b15
symbol varK = b16
symbol varL = b17
symbol varM = b18
symbol varN = b19
symbol varO = b20
symbol varP = b21
symbol varQ = b22
symbol varR = b23
symbol varS = b24
symbol varT = b25
symbol timer = time
}


let dirsB = %11111111


main:
		let varA = 5  	'Expression command
label_11:	serout 7,N2400_4,(254,128,"PRESS ENTER TO  ")
		serout 7,N2400_4,(254,192,"START           ")
		if pinC.6 = 1 then label_14	'Decision command
		if pinC.7 = 1 then label_14	'Decision command
		goto label_11

label_14:
		let timer = 0  	'Expression command
		pause 500	'Wait command
		enabletime		'time on 

label_19:
		if timer >= 59 then label_20	'Compare command
label_22:	bintoascii varM,b8,b9,b10
		timer = timer & 255
		bintoascii timer,b11,b12,b13
		serout 7,N2400_4,(254,128,b8,b9,b10,":",b11,b12,b13,"      ")
	bintoascii varA,b8,b9,b10
			serout 7,N2400_4,(254,192,b8,b9,b10," Minute Item ")
		pause 500	'Wait command
		if pinC.6 = 1 then label_3	'Decision command
		if pinC.7 = 1 then label_3	'Decision command
		if varM >= varA then label_27	'Compare command
		goto label_19

label_27:	high 6
		goto label_19

label_3:	low 6
		let varR = varR + 1	'Inc command
		if varM > varA then label_2	'Compare command
		if varM < varA then label_28	'Compare command
		if varM = varA then label_8	'Compare command
label_29:
		let timer = 0  	'Expression command
		let varM = 0  	'Expression command
label_31:
		if varR = 1 then label_18	'Compare command
		if varR = 2 then label_36	'Compare command
		if varR = 3 then label_37	'Compare command
		high 2
loop0:
		goto loop0

label_37:
		if varD = 0 then label_40	'Compare command
		let varA = varD - varE	'Expression command
		goto label_19

		goto label_19

label_36:
		if varC = 0 then label_37	'Compare command
		let varA = varC - varE	'Expression command
		goto label_19

label_18:
		let varA = varB - varE	'Expression command
		goto label_19

label_8:
		let varE = 0  	'Expression command
label_9:
		let varM = varE  	'Expression command
		goto label_31

label_28:
		let varE = 0  	'Expression command
		goto label_29

label_2:
		let varE = varM - varA	'Expression command
		goto label_9

label_20:	let varM = varM + 1	'Inc command
		let timer = 0  	'Expression command
		goto label_22

label_40:	let outpinsB = 0
		stop
#no_data	'reduce download time
I know its probably not the most elegant for what it does, but surely its not going to cause a loss of 12 secs every minute.

I need three input switches and an analogue input, and an output to an led when I'm finished. SO probably too much to reprogram 18M2 on Axe133. Could I set up timer on the Axe133 though, have it display through the parallel interface, but store the timer value somewhere that I can read from the other 18M2?

Will try the hserout now and see what happens.

Then I'll check to see if PIC faulty?
 

nick12ab

Senior Member
#6
I need three input switches and an analogue input, and an output to an led when I'm finished. SO probably too much to reprogram 18M2 on Axe133. Could I set up timer on the Axe133 though, have it display through the parallel interface, but store the timer value somewhere that I can read from the other 18M2?
There are enough free pins for this on the AXE133 including three on one header, one on another header, plus the Serial Out pin.
 

hippy

Technical Support
Staff member
#7
I know its probably not the most elegant for what it does, but surely its not going to cause a loss of 12 secs every minute.
It's possible. While doing something else ticks can be missed so 'time' increments slower than it should and long SEROUT commands can cause quite a few ticks to be lost.

Te best things to do are; only update or do anything when time has changed, and use SEROUT to output just one byte or character at a time. For example, where C.3 outputs to Terminal via download cable ...

Code:
#Picaxe 18M2
#Terminal 2400
Do
  BinToAscii time, b1,b2,b3,b4,b5
  SerOut C.3, N2400, ( b1,b2,b3,b4,b5, CR, LF )
Loop
Loses a tremendous amount of time; takes 140 seconds for the PICAXE to have elapsed 60 seconds.

In contrast the following is far more accurate -

Code:
#Picaxe 18M2
#Terminal 2400
Do
  Do : Loop While time = w10
  w10 = time
  BinToAscii w10, b1,b2,b3,b4,b5
  SerOut C.3, N2400, ( b1 )
  SerOut C.3, N2400, ( b2 )
  SerOut C.3, N2400, ( b3 )
  SerOut C.3, N2400, ( b4 )
  SerOut C.3, N2400, ( b5 )
  SerOut C.3, N2400, ( CR )
  SerOut C.3, N2400, ( LF )
Loop
 
#8
Have you also tried using hserout? That uses the UART peripheral built into the PIC microcontroller which shouldn't interfere with the timer.
Gave this a go, but I couldn't get the timer to display. I think I need to use a hsersetup to make this work, but any variations I tried gave me nothing on the display.
What would the hsersetup command need to be?
 
#13
And with an 18M2, hserout data is always on PinB.5 / Leg 11.
Yehh that caught me out. The code was ok, the pin out wasn't. Learning as I go :)

But the display is just giving me back junk. I've tried everything I can think of. But maybe I have a problem with hardware rather than program.
Can someone show me exactly how I should get this code to output to the display using the "hserout" command -- PLEASE.

At least then I can know for sure that the code is right and maybe its a problem with hardware. I;ve been at it for ages and the best I managed was the numbers to come up in sequence, but along the line. So it looked like :
001002003004005006007
008009010011012013014

I just need 001 to be replaced by 002 then 003 and so on....

Code:
{
symbol timer = time
}


let dirsB = %11111111


main:
		let timer = 10  	'Expression command
		enabletime		'time on 

label_5:	pause 200	'Wait command
		timer = timer & 255
		bintoascii timer,b8,b9,b10
		serout 7,N2400_4,(254,128,b8,b9,b10,"          ")
		goto label_5


#no_data	'reduce download time
 
#14
At least then I can know for sure that the code is right and maybe its a problem with hardware. I;ve been at it for ages and the best I managed was the numbers to come up in sequence, but along the line. So it looked like :
001002003004005006007
008009010011012013014
With no colons?...

Can you post your version of the code that uses hserout?
 

hippy

Technical Support
Staff member
#15
If you have -

Code:
serout 7,N2400_4,(254,128,b8,b9,b10,"          ")
Then, as HSEROUT. that should be -

Code:
hsersetup B2400_4, %010
:
hserout 0,(254,128,b8,b9,b10,"          ")
 
#16
With no colons?...

Can you post your version of the code that uses hserout?
Originally Posted by nick12ab
With no colons?...

Can you post your version of the code that uses hserout?
Code:
{

symbol timer = time
}


let dirsB = %11111111

hsersetup B2400_4,%010

main:
		let timer = 10  	'Expression command
		enabletime		'time on 

label_5:	pause 200	'Wait command
		timer = timer & 255
		bintoascii timer,b8,b9,b10
		hserout 0,(254,128,b8,b9,b10,)
		
		goto label_5


#no_data	'reduce download time
I also tried many variations of the hserout such as:
hserout 0,(254,128,b8)
hserout 0,(254,128,b9)
hserout 0,(254,128,b10)

Then I tried clearing the screen after each run using
hserout 0,(254,1)
hserout 0,(254,128,b8)
hserout 0,(254,128,b9)
hserout 0,(254,128,b10)

And so on and so on. I forget all the combinations I tried to be honest.
 
#17
Try this:
Code:
{

symbol timer = time
}


let dirsB = %11111111

hsersetup B2400_4,%010

main:
		let timer = 10  	'Expression command
		enabletime		'time on 

label_5:	pause 200	'Wait command
		timer = timer & 255
		bintoascii timer,b8,b9,b10
		hserout 0,(254)
		pause 5
		hserout 0,(128)
		pause 5
		hserout 0,(b8)
		pause 5
		hserout 0,(b9)
		pause 5
		hserout 0,(b10)
		pause 5
		goto label_5
Also make sure that the Serial OLED is connected to the hardware serial out pin (this is not the same as the Serial Out pin used for programming).
 
#18
If you have -

Code:
serout 7,N2400_4,(254,128,b8,b9,b10,"          ")
Then, as HSEROUT. that should be -

Code:
hsersetup B2400_4, %010
:
hserout 0,(254,128,b8,b9,b10,"          ")

Ok so this is the exact code I used

Code:
{
symbol timer = time
}

hsersetup B2400_4,%010

main:
		let timer = 10  	'Expression command
		enabletime		'time on 

label_5:	pause 200	'Wait command
		timer = timer & 255
		bintoascii timer,b8,b9,b10
		hserout 0,(254,128,b8,b9,b10,"             ")
		goto label_5
And the screen comes on show the serial Oled message for a fratcion of a second and then just goes blank. If I disconnect the serIN cable coming from b5, and reconnect the screen to the power, the message just come on and stays on. Then as soon as I connect the serIn cable the screen just goes blank.
 
#19
Try this:
Code:
{

symbol timer = time
}


let dirsB = %11111111

hsersetup B2400_4,%010

main:
		let timer = 10  	'Expression command
		enabletime		'time on 

label_5:	pause 200	'Wait command
		timer = timer & 255
		bintoascii timer,b8,b9,b10
		hserout 0,(254)
		pause 5
		hserout 0,(128)
		pause 5
		hserout 0,(b8)
		pause 5
		hserout 0,(b9)
		pause 5
		hserout 0,(b10)
		pause 5
		goto label_5
Also make sure that the Serial OLED is connected to the hardware serial out pin (this is not the same as the Serial Out pin used for programming).
Thanks Nick, but I also get the welcome message and then a blank screen when I input this code.
 
#20
Ok. This may be an issue.

I went back to a serout set up just to check if everything was ok. Same thing started happening. Screen starts up then just goes blank.

I wondered if it was a power issue. I am using 3AA batt box. But I had rechargables in there. Good ones mind, Duracell fully charged.
Anyway found some normal batteries, swapped them in for the rechargeable's and now the serout is ticking over fine.

About to switch back to hserout on b5 to see what happens.

Could rechargeable's not be providing enough power?
 
#22
Have you measured the voltage?

e
Yehh. Just finished a test.
Rechargeable's are falling short. Individually only giving 1.3 -1.4
The normal batts are giving a solid 1.5

So I went back to hserout with the normal batts in the box. Using this code
Code:
symbol timer = time
}


let dirsB = %11111111

hsersetup B2400_4,%010

main:
		let timer = 0  	'Expression command
		enabletime		'time on 

label_5:	pause 5	'Wait command
		timer = timer & 255
		bintoascii timer,b8,b9,b10
		hserout 0,(254)
		pause 5
		hserout 0,(128)
		pause 5
		hserout 0,(b8)
		pause 5
		hserout 0,(b9)
		pause 5
		hserout 0,(b10)
		pause 5
		goto label_5
I am getting seconds ticking over, but after about 5 or 6 seconds the screen goes blank again.
V is 4.34 when the screen is active, then when it goes blank it rises to 4.43 -
any reason why the screen is going blank?
If i disconnect the power to the screen and then reconnect it, the screen lights up again and show the seconds have still been counting, so the 18m2 is still working away.
 
#23
Serial on the PICAXE usually works with power supply voltages all the way down to 2V. But try using fresh non-rechargeable batteries.

You haven't posted your circuit and it could lack decoupling and bulk capacitors. That could cause issues.

I don't know why you don't just use the parallel interface - once you learn how to use it you'll never want to go back.
 
#24
I don't know why you don't just use the parallel interface - once you learn how to use it you'll never want to go back.
Oh Nick, you make that sound so easy :)

I'll give it a lash and see how I go. Any good tips on a starting place to learn this. I've been looking around for a simple starter project on this but haven't been able to find one. Just something that gets " hello world " up and running would be useful to understand the basics.

It really would be a much neater and tidy project if I just made use of the AXE133Y, so it is certainly worth my while looking into it further.

I have downloaded the AXE133Y preprogramed Bas file and I don't even know where to start. Obviously the protocol that the serout commands use are of no use. I'm guessing using 254,1 to clear the screen etc is useless?

I'll have a search for any previous threads on this.
 
#25
Oh Nick, you make that sound so easy :)
The easiest (and fastest) parallel LCD interface to use is the 8-bit one. On the AXE133, port B of the PICAXE is connected to the data bus of the OLED, C.6 to Enable and C.7 to RS.

To send a data byte to the OLED, the data is put on portB (i.e. let portB = "A") and Enable is briefly pulsed (pulsout enable,1). When RS is high, the data byte is processed exactly the same as it is if you send it serially to the AXE133. When RS is low, the data byte is processed exactly the same as if you send 254 then the byte to the AXE133.

It's as simple as that. You can see that it isn't any harder than using a serial display. The only extra bit you need to do is to initialize the OLED, but if you use the modified AXE133 firmware below, you don't need to worry about it.
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

; ********************************************
; 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 = 16	; 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 


; 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 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:
'Your program goes here
	goto main


; 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
	
	high rs			; Leave in character mode
	return


; display message from EEPROM sub routine
; message number 0-15 must be in b1 when called
; uses (alters) b1, b2, b3, b4
msg:
	let b2 = b1 & %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 b4 = b2 to b3			; for 16 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
	
; 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
Since you can't send a text string to the OLED as easily as when using the serout command, you can instead use a for:next loop and a lookup command.
 
#26
The easiest (and fastest) parallel LCD interface to use is the 8-bit one. On the AXE133, port B of the PICAXE is connected to the data bus of the OLED, C.6 to Enable and C.7 to RS.

To send a data byte to the OLED, the data is put on portB (i.e. let portB = "A") and Enable is briefly pulsed (pulsout enable,1). When RS is high, the data byte is processed exactly the same as it is if you send it serially to the AXE133. When RS is low, the data byte is processed exactly the same as if you send 254 then the byte to the AXE133.

It's as simple as that. You can see that it isn't any harder than using a serial display. The only extra bit you need to do is to initialize the OLED, but if you use the modified AXE133 firmware below, you don't need to worry about it.
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

; ********************************************
; 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 = 16	; 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 


; 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 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:
'Your program goes here
	goto main


; 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
	
	high rs			; Leave in character mode
	return


; display message from EEPROM sub routine
; message number 0-15 must be in b1 when called
; uses (alters) b1, b2, b3, b4
msg:
	let b2 = b1 & %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 b4 = b2 to b3			; for 16 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
	
; 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
Since you can't send a text string to the OLED as easily as when using the serout command, you can instead use a for:next loop and a lookup command.
Nick thats fantastic. Thanks for taking the time. I'll read it more carefully now and start experimenting with this. Again thank you for your help.
 
#27
I'm really confused as to why I can't even get the most basic hserout to work even
Code:
main:
hserout 0,("Hello")   'send the message
pause 1000            'wait a second
goto main             'keep repeating the message
is failing. I am sending it from b5 but should it be going to the "IN" pin on the AXE133Y where the serin command would usually go or should I be sending it somewhere else? I do see that there is hserin on b2 of the 133Y's 18M2 but isn't that being used already by the display?

As regards this:
You haven't posted your circuit and it could lack decoupling and bulk capacitors. That could cause issues.
Its just an 18m2 starter pack, already constructed and the Axe133Y .

I know Nick is trying to get me to go the parallel interface route, which I will spend more time on, but I would just like to understand for my own education why this is not working.
 

hippy

Technical Support
Staff member
#28
HSEROUT might not be working because it sends back to backk with no gaps between each byte or character sent. That's probably too fast for the AXE133Y which is receiving the data and needs some time to action the last received before being ready for the next.

Try sending one byte at a time with HSEROUT, then a PAUSE 5 after each, as per nick12ab's code in post #17.

When I was earlier suggesting conversions of SEROUT to HSEROUT code I had forgotten this was to an AXE133Y and forgot about the inter-byte gap times required. Sorry about that.
 
#29
HSEROUT might not be working because it sends back to backk with no gaps between each byte or character sent. That's probably too fast for the AXE133Y which is receiving the data and needs some time to action the last received before being ready for the next.

Try sending one byte at a time with HSEROUT, then a PAUSE 5 after each, as per nick12ab's code in post #17.

When I was earlier suggesting conversions of SEROUT to HSEROUT code I had forgotten this was to an AXE133Y and forgot about the inter-byte gap times required. Sorry about that.
Yehh this works fine - to a count of 3 and then the screen goes blank. If I disconnect the screen and reconnect it, the timer will show that it has continued counting, just not being displayed, so that when I reconnect the screen i see 039 (or however many secs it took ) and it counts to about 041 then goes blank again.
I wonder if its something in the AXE133Y code that tells the screen to go into low power mode of something if no serin is being received?

Little things like this can be so frustrating.
 
#30
I wonder if its something in the AXE133Y code that tells the screen to go into low power mode of something if no serin is being received?
No there is nothing like this.

Try increasing the pause. It does sound like sometimes the '128' byte isn't completely received so it is instead received as an instruction to turn off the OLED.
 

hippy

Technical Support
Staff member
#31
Little things like this can be so frustrating.
Did the SEROUT one character at a time method not work ?

It would be worth retrying that anyway to see if that has problems driving the AXE133Y as HSEROUt does or not. It may help isolate what the problem is.
 

hippy

Technical Support
Staff member
#32
Both of these work for me. Run for 1000 PICAXE 'time' seconds (16:40) results were as follows -

SEROUT : 1007 real seconds, approx 0.7% accuracy
HSEROUT : 999 real seconds, approx 0.1% accuracy

Same hardware for both, AXE132Y to B.5, 5V regulated supply. No OLED going off or any other problems like that.

Code:
#Picaxe 18M2
#No_Data

Do
  Do : Loop Until w10 <> time
  w10 = time

  b1 = w10 /  3600       /  10 + "0"
  b2 = w10 /  3600       // 10 + "0"
  b3 = w10 // 3600 /  60 /  10 + "0"
  b4 = w10 // 3600 /  60 // 10 + "0"
  b5 = w10         // 60 /  10 + "0"
  b6 = w10         // 60 // 10 + "0"

  SerOut B.5, N2400, ( 254 )
  SerOut B.5, N2400, ( $80 )
  SerOut B.5, N2400, ( b1  )
  SerOut B.5, N2400, ( b2  )
  SerOut B.5, N2400, ( ":" )
  SerOut B.5, N2400, ( b3  )
  SerOut B.5, N2400, ( b4  )
  SerOut B.5, N2400, ( ":" )
  SerOut B.5, N2400, ( b5  )
  SerOut B.5, N2400, ( b6  )

Loop
Code:
#Picaxe 18M2
#No_Data

HSerSetup B2400_4, %010

Do
  Do : Loop Until w10 <> time
  w10 = time

  b1 = w10 /  3600       /  10 + "0"
  b2 = w10 /  3600       // 10 + "0"
  b3 = w10 // 3600 /  60 /  10 + "0"
  b4 = w10 // 3600 /  60 // 10 + "0"
  b5 = w10         // 60 /  10 + "0"
  b6 = w10         // 60 // 10 + "0"

  HSerOut 0, ( 254 ) : Pause 5
  HSerOut 0, ( $80 ) : Pause 5
  HSerOut 0, ( b1  ) : Pause 5
  HSerOut 0, ( b2  ) : Pause 5
  HSerOut 0, ( ":" ) : Pause 5
  HSerOut 0, ( b3  ) : Pause 5
  HSerOut 0, ( b4  ) : Pause 5
  HSerOut 0, ( ":" ) : Pause 5
  HSerOut 0, ( b5  ) : Pause 5
  HSerOut 0, ( b6  ) : Pause 5

Loop
 
Last edited:
#33
Both of these work for me. Run for 1000 PICAXE 'time' seconds (16:40) results were as follows -

SEROUT : 1007 real seconds, approx 0.7% accuracy
HSEROUT : 999 real seconds, approx 0.1% accuracy

Same hardware for both, AXE132Y to B.5, 5V regulated supply. No OLED going off or any other problems like that.

Code:
#Picaxe 18M2
#No_Data

Do
  Do : Loop Until w10 <> time
  w10 = time

  b1 = w10 /  3600       /  10 + "0"
  b2 = w10 /  3600       // 10 + "0"
  b3 = w10 // 3600 /  60 /  10 + "0"
  b4 = w10 // 3600 /  60 // 10 + "0"
  b5 = w10         // 60 /  10 + "0"
  b6 = w10         // 60 // 10 + "0"

  SerOut B.5, N2400, ( 254 )
  SerOut B.5, N2400, ( $80 )
  SerOut B.5, N2400, ( b1  )
  SerOut B.5, N2400, ( b2  )
  SerOut B.5, N2400, ( ":" )
  SerOut B.5, N2400, ( b3  )
  SerOut B.5, N2400, ( b4  )
  SerOut B.5, N2400, ( ":" )
  SerOut B.5, N2400, ( b5  )
  SerOut B.5, N2400, ( b6  )

Loop
Code:
#Picaxe 18M2
#No_Data

HSerSetup B2400_4, %010

Do
  Do : Loop Until w10 <> time
  w10 = time

  b1 = w10 /  3600       /  10 + "0"
  b2 = w10 /  3600       // 10 + "0"
  b3 = w10 // 3600 /  60 /  10 + "0"
  b4 = w10 // 3600 /  60 // 10 + "0"
  b5 = w10         // 60 /  10 + "0"
  b6 = w10         // 60 // 10 + "0"

  HSerOut 0, ( 254 ) : Pause 5
  HSerOut 0, ( $80 ) : Pause 5
  HSerOut 0, ( b1  ) : Pause 5
  HSerOut 0, ( b2  ) : Pause 5
  HSerOut 0, ( ":" ) : Pause 5
  HSerOut 0, ( b3  ) : Pause 5
  HSerOut 0, ( b4  ) : Pause 5
  HSerOut 0, ( ":" ) : Pause 5
  HSerOut 0, ( b5  ) : Pause 5
  HSerOut 0, ( b6  ) : Pause 5

Loop
hippy, you have no idea how much I appreciate you testing that. I downloaded your first code exactly and sure enough the timer started up, gets to maybe 3 sec then lcd goes blank. Sometimes only gets to 1 sec, no real pattern, but no more than 5sec before going blank.
Check V getting to the display and its 4.3V -

So either I have a faulty display or I damaged something in putting it together - either way it would explain that the problem is not with the code I've been using but the display.
Back to the shopping basket :)
 
#34
I actually just tried something else.

If I connect the display to the power with no serin cable attached, the display stays on no problem. But as soon as I connect the serin cable, the counter shows its current state (say 00:01:33) and then the screen goes blank.
Something is happening when I connect the serin cable. Obviously its nothing to do with the code, that has been tested and is fine,
So the serin cable must be causing some kind of short circuit? But sometimes its quick, other times it takes a few seconds.

NOt sure if it means anything, but when I test v across the 0v v+ (underneath C2, C1, C0 ) that reads 4.14 with no serin cable and rises to 4.26 when I attach the serin cable.


OK. So I just nobbled together a 5v power supply, I'm getting 4.58v now at the screen and now it stays on unitl 34sec or 2minutes or some other random amount of time. Its staying on longer, but still going blank eventually.

Time for a new AXE133Y.
 
Last edited:
#35
Revolution did a clock upgrade for the LCD displays. The kit was AXE034 - but it's vanished. I'm quizzing them about the vanishing trick.
There was an 8-pin clock chip and crystal which just kept the time of day and gave you a kick if you set an alarm. Handy as it "just does the time" in a separate pot. You can shut-down and wake up when you're kicked, for example. Can save battery well using this trick - however, another bit of hardware to buy and interface - although very straingforward to do.
Having a bit of a scratchabout, the clock chip is an DS1307, still readily available. There's a good article about it here (as at 27.3.2013):
http://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/what-is-an-rtc
Another idea is to receive the time over radio using the LongWave RUGBY transmitter. The receivers are £8, tiny and and very easy to talk to with a Picaxe. Needs 'sight' of the radio transmission from RUGBY, though. Radio time from RUGBY is derived from the National Physics Lab's atomic clock.
Then, there's very accurate time from any handy GPS receiver you have nearby ...
The mains power is guaranteed to have a certain number of mains cycles per day, too !
... and there's Radio4 longwave on 200KHz - which is a damn-fine clock signal at 200KHz. That's quite easy to receive and you could check your internal timing against it, now and again.
I'd go for the DS1307 and a button cell.
 
#36
Time for a new AXE133Y.
it's got to be something to do with corrupted bytes being received by the AXE133 PCB and it then turning off the OLED (because there is a command to do that). I suggest adding a generous pause between each hserout command on the other PICAXE and reprogramming the PICAXE on the AXE133 PCB with a modified version of the firmware that sends whatever byte it receives over the download cable then see what bytes it received when the display turned off.

After this line:
Code:
	serin RX,baud,b1			; wait for the next byte
add:
Code:
	sertxd (#b1,cr,lf)
Revolution did a clock upgrade for the LCD displays. The kit was AXE034 - but it's vanished. I'm quizzing them about the vanishing trick.
There was an 8-pin clock chip and crystal which just kept the time of day and gave you a kick if you set an alarm.... the clock chip is an DS1307, still readily available.
The clock upgrade consisted of a DS1307 and a CR2032 coin cell. It is for the AXE033 and can't be used with the AXE132-AXE134 because there is no IC/cell socket.

They still sell it, but it is still more expensive than buying the coin cell and DS1307 separately from the PICAXE Store.

The receivers are £8, tiny and and very easy to talk to with a Picaxe. Needs 'sight' of the radio transmission from RUGBY, though. Radio time from RUGBY is derived from the National Physics Lab's atomic clock.
No line if sight is required since it is only 60kHz so basically unaffected by big hills. But the signal is affected by interference so taking advantage of every error-checking feature offered by the signal (and using decoupling capacitors) is vital.

A receiver with flashing LED can be used to help position it where it doesn't pick up interference. The ferrite rod antenna needs to be positioned horizontally.
 
#38
I have had similar problems , if I set break to 1 for commands and 0 for data the display seems to work
hserout 1 ,(254,128)
hserout 0 ,("HELP!")
I have yet to try sending a nul which is zero before a command to see if that works
 

Buzby

Senior Member
#39
... and there's Radio4 longwave on 200KHz - which is a damn-fine clock signal at 200KHz. ...
I must have missed this post when it first appeared.

Yes, the Radio 4 Longwave signal is easy to receive, but it ain't 200Khz !. See http://forums.digitalspy.co.uk/showthread.php?t=463316

Anyway, it don't look like it will be there for much longer. See http://www.theguardian.com/media/2011/oct/09/bbc-radio4-long-wave-goodbye and http://en.wikipedia.org/wiki/Radio_teleswitch#Transmitter_Obsolescence
 
Top