Spurious reset with interrupt

jikmar

New Member
Hello,

I am having a problem with my Picaxe 40X1 crashing. It crashes approximately every 5-15 minutes and resets to the beginning of the program (variable values are not retained, so it doesn't "goto 0").

Hardware includes...
  • an axe033 LCD display, with DS1307 clock on the i2c bus
  • pwm contolled 12v motor via darlington transistor
  • 3 off, smartec digital temperature probes
  • analogue pressure transducer
  • various valves controlled by solid state relays


The program has an interrupt which is called approximately every 0.125 of a second. The interrupt serves to keep the transducer inputs up to date so that they can be interrogated at any point in the program.

Interrestingly, in order to debug it, I commented out most of the interrupt (except for the user variable poking/peeking; interrupt timer reset) and the program doesn't crash.

More interestingly, I also commented out the whole program and put in some new code, just enough so I could see whether the interrupt was causing the crash - no crashes.

Therefore, I know that there is something in the interraction between the main program and the interrupt, which causes the crash.

Moreover I added sertxd commands to the beginning and end of each subroutine, and a breakpoint at the beginning of the program, so I now know the last place it goes before it crashes. This is consistent - I have checked it a number of times.

As the interrupt is called around 8 times per second and it can take up to 15 mins for the crash to occur, I suspect that the crash only occurs when the interrupt falls at an inopportune time within the loop. This is speculation, though, and I know that the crash does not always happen at exactly the same time with respect to the interrupt.

I shall post the code below. The program is a full 4kB so I will only post the parts I know to be problematic. I hope this gives someone enough info to tell me what's wrong. I am happy to post the full code on request.

So here we go.

Symbol declaration...
Code:
symbol dispcode=b6		'this byte tells lcd what to display at its next refresh -- see lcddisplay subroutine.
symbol cwt=b7			'cwt in degrees C
symbol hwt=b8			'hwt in degrees C
symbol mwt=b9			'mwt in tenths of degrees C above 30°C.  Therefore 000=30°C; 255=55.5°C
symbol mpress=w5			'mw pressure.  10 bit adc.  0 = 0bar, 1024 ~= 10bar
symbol ticker=b12			'used to handle timing events
symbol tickerflag=b13		'check whether clock has 'ticked'

symbol muloc=87			'menu location
symbol varcode=86			'value of the system variable currently being changed
symbol varcode_old = 85
symbol muloc_old=88		'previous menu location

symbol dcpr_bot=90
symbol dcpr_top=91

symbol dcprevtop=230
symbol dcprevbot=231

symbol btnspace1=232
symbol btnspace2=233
symbol btnspace3=234

symbol ptdoneflag=106

symbol storeb4pt =107
symbol storeb5pt =108

symbol mpstore 			= 210
symbol mphighestword 		= 212
symbol mpnexthighestword	= 214
symbol mplowestword		= 216
symbol mpnextlowestword		= 218
symbol mpinitial 			= 220

symbol settmp			= 110 'equivalent to 41 degC - ie. temp*10-300

symbol mwtprevious		= 89

continues in next post...
 
Last edited:

jikmar

New Member
Here is the subroutine which the crash ALWAYS occurs during. Crashes occur when DISPCODE = 0,1 or 85: possibly others as well, but these are the ones I have focussed my attention on. As stated before, the crash doesn't occur every time, but usually after 5 minutes or more, sometimes less.

Code:
lcdisplay:	

 	;dispcode - byte code tells this routine what to display

	poke 100,b0			'store current values 	poke 101,b1			
	poke 102,b2
	poke 103,b3
	poke 104,b4
		
	peek 92,b0		'92 is previous value of dispcode
	poke 92,dispcode		'put back for next time.
	
	b1 = dispcode & %11000000	
	b1 = b1 / 64
	branch b1,(bothlines,topline,bottomline,other)
	
	goto dispend
	
bothlines:
	gosub clearscreen
	
	poke dcpr_bot,0

	branch dispcode,(dc0,dc1)',dc2,dc3)		
	goto dispend 	
	
dc0:	
	if b0=0 then goto printtemps	

	nap 0
	writei2c 0,("  . ",223,"C   ",223,"C   ",223,"C",255)
	nap 0
	writei2c 0,(254,192,255)	'to bottom line
	nap 0
	writei2c 0,(" MWT   HWT  CWT ",255)
	nap 0

printtemps:

;;write cold temp
	
	b2 = cwt
	b1=b2//10
	writei2c 0,(254,141,255)	'move cursor to correct position
	nap 0
	b1=b1+48				'convert to ascii
	writei2c 0,(b1,255)
	nap 0
	b2=b2/10
	b1=b2//10
	writei2c 0,(254,140,255)	'move cursor
	nap 0
	b1=b1+48				'convert to ascii 
	writei2c 0,(b1,255)
	nap 0
	
;;write hot temp

	b2 = hwt
	b1=b2//10
	writei2c 0,(254,136,255)	'move cursor 
	nap 0
	b1=b1+48				'convert to ascii 
	writei2c 0,(b1,255)
	nap 0
	b2=b2/10
	b1=b2//10
	writei2c 0,(254,135,255)	'move cursor
	nap 0
	b1=b1+48				'convert to ascii 
	writei2c 0,(b1,255)
	nap 0
	
;;write mixed temp

	b2 = mwt
	b1=b2//10
	writei2c 0,(254,131,255)	'move cursor
	nap 0
	b1=b1+48				'convert to ascii 
	if mwt = 0 then let b1=76	'display 'L' if the temp is below 30.1 
	endif
	if mwt = 255 then let b1=72	'display 'H' if the temp is above 55.4 
	endif
	writei2c 0,(b1,255)
	nap 0
	b2=b2/10
	b1=b2//10
	writei2c 0,(254,129,255)	'cursor to
	nap 0
	b1=b1+48				'convert to ascii 
	if mwt = 0 then let b1=76	''L' if the temp is below 30.1 degrees
	endif
	if mwt = 255 then let b1=72	''H' if the temp is above 55.4 degrees
	endif
	writei2c 0,(b1,255)
	nap 0
	b2=b2/10
	b1=b2//10
	writei2c 0,(254,128,255)	'cursor to 
	nap 0
	
	b1=b1+51				'convert to ascii (not 48 this time but 51 so as to add 3 to the tens digit).
	if mwt = 0 then let b1=76	''L' if the temp is below 30.1 degrees
	endif
	if mwt = 255 then let b1=72	''H' if the temp is above 55.4 degrees
	endif
	writei2c 0,(b1,255)
	nap 0
	
	goto dispend
	
dc1:	;pressure sensor output 

	w0 = mpress
	b2=w0//10
	writei2c 0,(254,135,255)	'cursor to line 1, pos 8 on lcd
	nap 0
	b2=b2+48				'convert to ascii 
	writei2c 0,(b2,255)		'write digit
	nap 0
	w0=mpress/10
	b2=w0//10
	writei2c 0,(254,134,255)	'move cursor to line 1, pos 7 on lcd
	nap 0
	b2=b2+48				'convert to ascii 
	writei2c 0,(b2,255)		'write digit
	nap 0
	w0=mpress/100
	b2=w0//10
	writei2c 0,(254,132,255)	'cursor to line 1, pos 5 on lcd
	nap 0
	b2=b2+48				'convert to ascii 
	writei2c 0,(b2,".",255)		'write digit, then decimal point
	nap 0
	w0=mpress/1000
	b2=w0//10
	writei2c 0,(254,131,255)	'cursor to line 1, pos 4 on lcd
	nap 0
	b2=b2+48				'convert to ascii 
	writei2c 0,(b2,255)		'write digit
	nap 0
		
	writei2c 0,(254,137,255)	'cursor to line 1, pos 10 on lcd
	nap 0
	writei2c 0,("BAR",255)		'write "bar"
	nap 0
	writei2c 0,(254,194,255)	'to line 2, posn 3
	nap 0
	writei2c 0,("BODY PRESSURE",255)
	
	
	goto dispend
	
	
topline:		;come here if the dispcode only required the top line to be displayed.

	if b0<64 then gosub clearscreen		;clear screen if previous message was a 2-liner.

	peek dcpr_top,b0					;dcpr-top stores the last value of dispcode that applied to the top line.

	peek muloc_old,b1
	peek varcode, b2
	peek muloc, b3
	peek varcode_old,b4

	poke varcode_old,b2

	
	if b0=dispcode and b1 = b3 and b2=b4 then goto dispend	'don't rewrite if display hasn't changed.
	
	
	poke dcpr_top,dispcode	


	if dispcode <>67 then writei2c 0,(254,128,255)	;go to beginning of first line
		nap 0
		writei2c 0,("                ",255)
		nap 0
		writei2c 0,(254,128,255) 	'move to line 1, pos.1
		nap 0	
		endif
	
	let b1 = dispcode & %00111111
	branch b1,(dc64,dc65,dc66,dc67,dc68,dc69,dc70,dc71,dc72,dc73,dc74,dc75,dc76,dc77,dc78,dc79,dc80,dc81,dc82,dc83,dc84,dc85,dc86) 
	goto dispend
	
	
dc64: ;stuff to display from muloc

	peek muloc,b0
	
	b0 = b0 & %01111000
	b0 = b0/8
	b0 = b0+239
	
	read b0,b1		;read eeprom location b0 into the variable b1
		
	b2 = b1 & %00000111
	if b2 = 0 then writei2c 0,("ht_",255)		
	endif
	if b2 = 1 then writei2c 0,("cd_",255)			
	endif	
	if b2 = 2 then writei2c 0,("mx_",255)			
	endif
	if b2 = 3 then writei2c 0,("tmp_",255)			
	endif	
	if b2 = 4 then writei2c 0,("buz",255)			
	endif
	if b2 = 5 then writei2c 0,("pres_",255)			
	endif
	if b2 = 6 then writei2c 0,("motor",255)			
	endif
	
	nap 0
	
	b2 = b1 & %00011000
	b2 = b2 / 8
	if b2 = 1 then writei2c 0,("water_",255)	
	endif
	if b2 = 2 then writei2c 0,("air_",255)
	endif
	if b2 = 3 then writei2c 0,("o/p",255)
	endif
	
	nap 0
	
	b2 = b1 & %11100000
	b2 = b2 / 32
	if b2 = 0 then writei2c 0,("vv",255)			
	endif
'	if b2 = 1 then writei2c 0,("fwd",255)			
'	endif
	if b2 = 2 then writei2c 0,("rev",255)			
	endif
	if b2 = 3 then writei2c 0,("spd",255)			
	endif	
	;if b2 = 4 then do nothing.
	
	nap 0
	goto dispend
	
dc65: ;stuff to display "ch.var"

	writei2c 0,("CH.VAR:",255)
	nap 0
	peek muloc,b0
	b0 = b0 & %01111000
	b0 = b0 / 8				;find the correct number of loops to do to get the right name
	
	b2 =32
	for b1 = 1 to b0
nextzero1:
	read b2,b4
	b2 = b2 +1
	if b4<>0 then goto nextzero1
	next b1
	
	b2 = b2+1
nextchar1:
	read b2,b4
	writei2c 0,(b4,255)		
	nap 0
	b2 = b2+1
	if b4<>0 then goto nextchar1
	
	goto dispend
	
dc66: ;stuff to display variable name & value

	peek muloc,b0
	b0 = b0 & %01111000
	b0 = b0 / 8
	
	b2 =32
	for b1 = 1 to b0
	
nextzero2:

		read b2,b4
		b2 = b2 +1
		if b4<>0 then goto nextzero2
	next b1

	read b2,b3			;b3 will become VARCODE later
	poke 105,b2			;store the location, that the variable must be 'poked' back to 
	b2 = b2 +1
nextchar2:
	read b2,b4
	writei2c 0,(b4,255)
	nap 0
	b2 = b2+1 
	if b4<>0 then goto nextchar2
	

	peek varcode,b1
	if b1 = 0 then poke varcode,b3	;returns the appropriate value of varcode for this muloc if varcode was set to zero
	endif
	let b2=b1
	writei2c 0,(254,143,255)	;move to last pos on line1
	nap 0
	for b3=0 to 2			
		let b2=b1//10
		b2=b2+48				;convert to ascii
		writei2c 0,(b2,255)		;write digit
		writei2c 0,(254,16,255)		;move 1 space left
		writei2c 0,(254,16,255)		
		let b1 = b1/10
	next b3
	
	

	goto dispend
	
dc67: writei2c 0,(254,16,255)  	;backspace
	writei2c 0,(254,16,255)		
	writei2c 0,("FAIL",255)
	high 7
	nap 4
	low 7
	goto dispend
	
dc68: writei2c 0,("PURGING AIR",255)		
	goto dispend
	
dc69:	writei2c 0,("PRESS TEST OK",255)		
	goto dispend
	
dc70: writei2c 0,("SET TEMP OK",255)		
	goto dispend
	
dc71:	writei2c 0,("COLD FAIL OK",255)	
	goto dispend
	
dc72:	writei2c 0,("HOT FAIL OK",255)		
	goto dispend
	
dc73: writei2c 0,("RTRN 2 TEMP OK",255)		
	goto dispend
	
dc74:	writei2c 0,("PURGING WATER",255)		
	goto dispend
	
dc75:	'writei2c 0,("ER: I/L TEMPS",255)		
	'goto dispend
	
dc76:	writei2c 0,("TEST RUNNING",255)		
	goto dispend
	
dc77:	writei2c 0,("TEST FAIL",255)		
	goto dispend
	
dc78:	writei2c 0,("TEST PASS",255)			
	goto dispend
	
dc79:	writei2c 0,("T/R FAULT",255)		
	high 7						'sound the buzzer
	nap 4
	low 7
	goto dispend
	
dc80:	;print nothing !
	goto dispend
	
dc81:	writei2c 0,("ERR: ISOL.VALVE",255)		
	high 7						
	pause 500
	low 7
	goto dispend
	
dc82:	writei2c 0,("DIAG MODE",255)		
	goto dispend	
	
dc83:	writei2c 0,("CHG VARS",255)
	goto dispend
	
dc84:	writei2c 0,("MEAN CYCLE",255)		
	goto dispend
	
dc85:	writei2c 0,("RET 2 TEST",255)		
	goto dispend
	
dc86:	writei2c 0,("TESTRIG READY",255)	
	goto dispend


	
bottomline:		;come here if the dispcode only required the bottom line to be displayed.


	peek dcpr_bot,b1				;dcpr-bot stores last value of dispcode that applied to bottom line.
	if b0 <64 then gosub clearscreen	'(b0 is still the previous value of dispcode - clearscreen if the previous
							'message occupied both lines.
	
	if b1 = dispcode then goto dispend	'don't update if the display message hasn't changed 
	poke dcpr_bot,dispcode	


	writei2c 0,(254,192,255)		;go to beginning of second line
	nap 0
	writei2c 0,("                ",255)	'clear second line
	nap 0
	writei2c 0,(254,192,255)		'move to line 2, pos.1. in readiness for printing
	nap 0	
		
	let b1 = dispcode & %00111111	
	branch b1,(dc128,dc129,dc130,dc131,dc132,dc133,dc134,dc135) 
	goto dispend

dc128:	writei2c 0,("NEXT..   SELECT>",255)
		goto dispend
		
dc129:	writei2c 0,("          START>",255)
		goto dispend
		
dc130:	;PRINT NOTHING
		goto dispend				
		
dc131:	writei2c 0,("<PURGE  RESTART>",255)
		goto dispend
		
dc132:	writei2c 0,("     START NEW>",255)
		goto dispend
		
dc133:	writei2c 0,("<DOWN       UP>",255)
		goto dispend
		
dc134:	writei2c 0,("<OFF        ON>",255)
		goto dispend

dc135:	writei2c 0,("RUNTIME ERR ##",255)			;"RUNTIME ERROR ##"
		high 7
		nap 4
		low 7
		goto dispend


'	goto dispend
	
other:	; this is saved for future use
	
	goto dispend
	
	
			
dispend:

;	if dispcode >1 then let dispcode =4
;	endif

	
	peek 104,b4
	peek 103,b3			'retrieve values of variables needed by the main program loop
	peek 102,b2			
	peek 101,b1
	peek 100,b0


	nap 0				;wait for display to update

	

return				;return from LCDISPLAY
 

jikmar

New Member
And here is the interrupt...

Code:
interrupt:				'interrupt is triggered by toflag (timer overflow flag)
					'toflag triggers when timer exceeds $ffff

	poke 93,b0			'store current values of variables needed by the interrupt in
	poke 94,b1			'CPU registers 93-96 for safe keeping.
	poke 95,b2
	poke 96,b3
	poke 97,b4
	poke 98,b5		


; note that we can use b10 and b11 in the interrupt routine because they are the components of w5 which maps
; to mpress.  the value for mpress is read at the end of the interrupt, so there is no harm in using
; b10 and b11 prior to that in the interrupt routine.


	i2cslave $d0,i2cslow,i2cbyte		;set i2c interface for clock
	readi2c 0, (b0)				;read clock seconds
	
	if b0<>tickerflag then dec ticker
			if ticker =255 then let ticker =0
			endif
		endif

	let tickerflag=b0

	if ticker=1 then 
		peek muloc,b2
		let b2=b2 & %01111111		;logical AND to change the MS bit to zero.
		poke muloc,b2
		endif

'	sertxd ("t=",#ticker,13,10)

	
	i2cslave $C6,i2cslow,i2cbyte	'set i2c interface to lcd mode again.
	
	
; get values of water temp

	for b10 = 0 to 2		'loop to read & write temp values to various registers as explained below.
	
					'note that b10 is one of the components of w5=mpress (b10 & b11)
					
					
					
		pulsin b10,1,b2		'get the on-time value from pin b1.
		pulsin b10,1,b3		'same again	
						'pulse on-time is read twice for reasons of improving arithmetical accuracy (reduces rounding errors).
					
						
		w0=b2+b3			'add the two values


		let b4 = b10*4+192
		
		peek b4, word w1 		'get aggregated value of on-times from cpureg
		
		
		let w1=w1+w0		'add the new value to the total.  w1 is now the total on-time.
		

		let b4=b4+2							
		
		peek b4, word w0		'get aggregated value of off-times from cpureg	
		
		pulsin b10,0,b5		'get off-time from the pulse input
		
		pulsin b10,0,b11		'get off-time again and divide by 2 to average/smooth


				
		
		let b5=b5+b11/2
		
		let w0=w0+b5		'w0 is now the total off-time.
		
		
		
		if w1>240 then 		'w1 is total on-time
			let w0=w0/2		'w1 must be no more than 240 otherwise when multiplied by 265 below
			let w1=w1/2		'it will overflow.  Dividing numerator and denominator by 2
			endif			'preserves the ratio, though losing a little precision.  Hence
						'we only do this when w1 reaches 240.
						
		poke b4, word w0		
		let b4=b4-2
		poke b4, word w1
			
			
			
		let w0=w1/2+w0		'change w0 from being off-time to denominator of duty cycle.
						'now w1 is the numerator of the duty cycle (x3)
						'and w0 is the denominator of the duty cycle
				
	
						
		let w1=w1*265	
		
		let w1=w1/w0	
		let w2=w1//w0		'calculate the remainder
		
		
		let w2=w2*4			'multiply the remainder by 4 (NEEDS A WORD VARIABLE!!!)
		let b4=w2/w0		'divide the remainder*4 by w0 (this gives a number 0-3 corresponding
						'to the number after the point from w1/w0 times 4)

		
		let w1=w1*4			;the above lines multiply the numerator (which is already 2 times the on-time)
						;by 2120/2 and divide by the denominator
						
		let w1=w1+b4		;this gives a fairly accurate temp reading.


		
		let w1=w1-676		;MIN does not work here, because due to underflow, the number becomes big, not small.
		
		'this routine outputs the temp to the word variable w1.			
		
		if b10=0 then let w1=w1-300		'now put it into the appropriate temperature variable.
		endif
		if b10<>0 then let w1=w1+5/10		'+5 makes it round up if the fraction is greater than 0.5
								'then divide by 10.
		endif
		
		
		if w1>60000 then let w1 = 0		'this traps a potential UNDERFLOW problem that cannot trapped by min.
		endif
		

		if w1>255 then let w1=255		'TRAPS OVERFLOW: truncate this word to a byte neatly if the mwt is greater than 55.4 degrees.
		endif						' i've done this at storemixed as well (both needed due to averaging routine).


;store the temperature in the appropriate variable register.


		branch b10,(storemixed,storehot,storecold)
		
		
storemixed:	
		if b3<>0 then let b2 = 255			;quicker than: if w1>255 then let b2 = 255
		endif
		mwt = b2		'update the mwt value (b2 is LSB of w1)
		
		
		
		goto storeend
		
storehot:	
			
		
		hwt = b2		'update the mwt value (b2 is LSB of w1)
		
		goto storeend



storecold:	
		
		cwt = b2		'update the mwt value (b2 is LSB of w1)
		
		'goto storeend



storeend:
	

		
	next b10

			
					
	
;CALIBRATION ADJUSTMENT

	peek 111,b11

	mwt = mwt-100+b11


;MWT smoothing
	
	peek mwtprevious,b11
	let mwt = mwt+b11/2
	
	poke mwtprevious,mwt
	
	
	
	
;READ PRESSURE SENSOR

	readadc10 0,mpress

;


buttons:		;following routine to check button status and store button presses in cpureg 81,82,83



	peek btnspace1,b0
	peek btnspace2,b1
	peek btnspace3,b2


	button 5,0,200,100,b0,1,btn1
	button 6,0,200,100,b1,1,btn2
	button 7,0,200,100,b2,1,btn3
	
goto endbutton

	
	
btn1:	poke 81,1		;store button presses in the 81,82,83 cpu registers...

	goto beep
	
btn2:	poke 82,1

	goto beep
	
btn3: poke 83,1
	
	goto beep
	
	
	
beep:
	high 7
	pause 20
	low 7
	
	
endbutton:

	poke btnspace3,b2
	poke btnspace2,b1
	poke btnspace1,b0

	peek 98,b5
	peek 97,b4
	peek 96,b3			'retrieve values of variables needed by the main program loop
	peek 95,b2			'from CPU registers 93-96
	peek 94,b1
	peek 93,b0
	







	
	toflag = 0			'clear the timer overflow flag
	timer=$ffff			'initialise the timer to interrupt on next count
	setintflags $80,$80	'enable the timer interrupt
	return			'return from interrupt

The program runs correctly except for the spurious crashing/resetting.

Can anyone suggest what the cause of the problem is.

I would be most grateful!

Mike.
 

BeanieBots

Moderator
OK, I,ve not gone through your code but here are some things to check in the hardware first.
Double check that reset is pulled high and serin is not left floating.
A floating serin is sometimes only apparent when other inputs change state.
Whilst debugging, completely disconnect the PWM driven motor. Does the "resetting" stop when the motor is disconnected?
 

jikmar

New Member
Checked.

Reset is pulled high
Serial in is low

This should be the case as I have an axe022 board, but I have double checked with voltmeter. I have also added some extra resistors & capacitors as outlined in this post to be sure there are no electrical noise issues.

https://picaxeforum.co.uk/index.php?posts/25556/

Disconnecting the PWM output completely makes no difference. This comes down a shielded cable anyway and the shield is earthed.

Thanks for the advice though. I have been round in circles on this quite a lot and am really running out of ideas. Any further help would be much appreciated.
 

hippy

Ex-Staff (retired)
With all those Pokes with variables for addressing I would strongly suspect that one of them is writing to somewhere it shouldn't and causing the firmware to bale out.
 

jikmar

New Member
Interesting thought. Can you explain a bit more? Are there any pokes in particular that worry you?

Do you mean ones where I have poke [variable],x? perhaps addressing the wrong byte, or something else?
 

Dippy

Moderator
I reckon you should check the things based on hippy's suggestion.

I'm afraid I haven't got time to wrestle with all that code, but I see you increment/decrement a variable then Poke to that address. Could it be that the variable can equal a number outside the ranges specified in the Basic Manual and mugger it up as hippy suggests?

Maybe run it in the simulator if poss and put a test-print within an IF statement to see if goes outside spec?

Alternatively, break the code up and try and run it in pieces to zero in on the error.
A pain yes, but I've to do that with much bigger code on PIC so you ain't alone :)

Example:
Code:
poke b4, word w0		
		let b4=b4-2
		poke b4, word w1
 

hippy

Ex-Staff (retired)
Yes that's the sort of thing I'm thinking of. It's all a bit too complicated to be able to just look at the code and say, "oh look; that's where you've gonr wrong".
 

jikmar

New Member
I have checked the poking in the interrupt using serial output from the picaxe. It performs exactly as expected.

Incidentally, I tried using the simulator but did not find the interface window very intuitive - can anyone point me to documentation for what the simulator toolbar inputs/outputs mean?

Also per your suggestion, Dippy, I am trying to home in on exactly where the crash occurs (encouraging to know I am not alone in having to do this :)). It occurs in a slightly different part of the LCDisplay subroutine each time, but always in that subroutine. I am still suspecting it depends on where the interrupt falls within the routine.

At the beginning of my code, I issue

Code:
settimer 61630	'set interrupt to overflow every 3906*256 clock cycles
so I tried adding the following to tell me when the interrupt is coming

Code:
sertxd ("interrupt at ",#timer,13,10)
but timer is always 65535. There must be another variable that tells how imminent the next interrupt is. I would like the program to tell me this every time it enters the problem routine. Can someone tell me what that system variable would be?

Thanks again...
 

jikmar

New Member
Thanks for everyone's help so far: I think I am just about to bottom this out but need a little more help.

After some exhaustive debugging I have established that the 'firmware bale out' is always caused by a 'nap 0' command. There are quite a few in the program, but it always crashes at one of them, never anywhere else. These nap 0 commands always follow a writei2c command to the axe033 display. The manual recommends a pause of 10ms following a write to the lcd, but I preferred not to use 'pause 10' (or 'pause 20' as I am running at 8MHz) because these can be interrupted by the timer interrupt, whereas nap cannot.

I shall try replacing all of my naps with pauses and add another pause at the beginning of the interrupt and see if that fixes it. But even if it does that won't tell me why this crashes - and I am the kind of guy who like to know this sort of stuff (I hope you'll understand).

Another piece of circumstantial evidence...

I have changed the interrupt (old version shown in post #3) because I realised lately that as I have a picaxe 40x1 I can use variables b15 through b27. Hence I removed the poke/peek b0 through b5 at the beginning/end of the interrupt routine and used the upper b-numbers for the interrupt solely. This reduces the frequency of crashes from every few minutes to every few hours, but doesn't solve the problem. This must be a significant piece of evidence to someone who understands the firmware.

Can anyone shed any more light on this for me, please?
 

Technical

Technical Support
Staff member
The writei2c command is a background hardware command, ie the PIC hardware does this automatically whilst the PICAXE bootstrap gets on with doing something else.

Therefore it is quite possible you are telling the chip to 'nap' as the writei2c is still completing in the background. nap switches off peripherals, hence killing the writei2c.

This could possibly corrupt the background i2c communications, and hence could cause the i2chardware to lockup, causing the chip to reset. If its 'borderline' on timing it may work somethimes, not others.

It will be interesting to see if pauses not naps solve the problem.
 

jikmar

New Member
Yes, changing the naps to pauses seems to fix it - several tens of running hours now without trouble.

Thanks to everyone who looked at it.

Mike.
 
Top