Timing long periods whilst polling with serin

mjy58

Member
I have an RFID tag reader (based on marks code snippet) which is reading serial data from an RDM6300.

The reader is being used to detect presence of one of two cats and dispense food depending on which one it is.

To calculate the food requirements, I need to track the total time over a 24 hour period as well as the time since either cat last activated the feeder.

As polling with serin disables the timing functions within the PICAXE, I am struggling to think how to accomplish the basic timing functions whilst still monitoring the reader for tag presence?

The timing requirements are not accurate, minute resolution would be sufficient. I was hoping to do this without any external timing components.

Any suggestions welcome.

Code:
;Based on http://www.picaxeforum.co.uk/showthread.php?18886-RDM630-125khz-RFID-tag-Reader-CODE-EXAMPLE
;
#Terminal 19200
#picaxe 18m2
 eeprom   0,(2,48,50,48,48,70,51,56,57,69,55,57,70,3)    'RFID TAG1
 eeprom  14,(2,48,50,48,48,70,52,53,49,49,65,66,68,3)    'RFID TAG2
 eeprom  28,(2,48,50,48,48,70,51,57,54,68,53,66,50,3)    'RFID TAG3 (Drut)
 eeprom  42,(2,48,50,48,48,70,52,52,49,69,57,53,69,3)    'RFID TAG4 (Charlie)
 SetFreq M16		;Needed to read output from RDM6300 at 9600 baud
 dirsc = %00000011	;c1, c0 as output
 ;Variables
 	SYMBOL RDM630     = B.4
 	SYMBOL LED		= C.1
 	SYMBOL Feed		= C.0
 	SYMBOL stx		= B0
 	SYMBOL country1   = B1
 	SYMBOL country2	= B2
 	SYMBOL data1      = B3
 	SYMBOL data2      = B4	
 	SYMBOL data3      = B5	
 	SYMBOL data4      = B6	
 	SYMBOL data5      = B7	
 	SYMBOL data6      = B8	
 	SYMBOL data7      = B9
	SYMBOL data8      = B10
 	SYMBOL checksum1  = B11  	
 	SYMBOL checksum2  = B12
 	SYMBOL etx		= B13	
 	SYMBOL verify     = b14
 	SYMBOL code       = b15 	
 	SYMBOL checking   = b16	
 	SYMBOL tag       = b17
 	SYMBOL tagposition=b18
 	SYMBOL tagno	= b19
 ;Constants
 	SYMBOL numboftags = 4	;Ensure this aligns with the number of tags in EEPROM
 	SYMBOL maxbytes	 = numboftags*14
 	SYMBOL RFIDBaud	= t9600_16
Init:
pause 2000	;Wait 0.5 sec for serial line to settle
sertxd("RFID reader V5.bas",CR,LF)	;Current source file 
high Feed	;Feed is normally held high and taken low to dispense food;
;
Main:
  tagposition = 0 	;Check first tag
  call ScanTag		;Read the tag
  verify=1
  do while verify <=12
	  tag=verify+tagposition
	  READ tag,code
	  call Checktag
	  inc verify
	  If code <> checking then	;Found a mismatch
	   verify = 1
	   tagposition = tagposition + 14	;So move to the next tag
	    if tagposition > maxbytes then
	     verify = 14	;No valid tags found abort and read a new tag
	     sertxd(cr,lf,"Tag not matched!")
	    endif
	  endif 
  loop
  if verify < 14 then	;Tag successfully matched  
     pulsout LED,20000
     tagno=tagposition/14+1 
     SerTxd(CR,LF,"VERIFY OK  ","Tag No ",#tagno,CR,LF)
     pulsout LED,20000		;0.05 secs for LED
     low Feed
     SerTxd(CR,LF,"Feed motor on",CR,LF)
     pause 24000	;Keep feed motor on for 6 sec (at 16MHz)
     high feed
     SerTxd(CR,LF,"Feed motor off",CR,LF)
  endif
 goto Main

ScanTag:
     SerIn [800,ScanTag],RDM630,RFIDBaud,stx,country1,country2,data1,data2,data3,data4,data5,data6,data7,data8,checksum1,checksum2,etx
     SerTxd(CR,LF,"READ RFID TAG ",#b0," ",#b1," ",#b2," ",#b3," ",#b4," ",#b5," ",#b6," ",#b7," ",#b8," ",#b9," ",#b10," ",#b11," ",#b12," ",#b13,CR,LF)
     pulsout LED,60000
return

Checktag: 
 SELECT CASE verify                       
	 case  1 :checking = country1	
	 case  2 :checking = country2	
	 case  3 :checking = data1	
	 case  4 :checking = data2	
	 case  5 :checking = data3	
	 case  6 :checking = data4	
	 case  7 :checking = data5	
	 case  8 :checking = data6	
	 case  9 :checking = data7	
	 case 10 :checking = data8	
	 case 11 :checking = checksum1
	 case 12 :checking = checksum2
 END SELECT
return
 

mjy58

Member
Have you considered a Real Time Clock Module? When a cat feeds you can just read a time-stamp.
Yes, I have considered that. But I do not actually need the time, just a number of minutes/seconds from a reference.

So I was hoping to be able to do this simply within the PICAXE, rather than having the complexity of an external chip.
 

g6ejd

Senior Member
Use the TIME variable which is a 1-sec elapsed time count maybe, or use another SLOT to increment a variable at say 1-min intervals and read the value in another slot so you have a pseudo real time clock running, but check the serial commands as they may hold the CPU and prevent the other slot from running.
 

mjy58

Member
As I understand it, SERIN inhibits timing activities in any SLOT as the PICAXE is fundamentally a single task machine.
 

MartinM57

Moderator
The timing requirements are not accurate, minute resolution would be sufficient.
Don't confuse accuracy with resolution. I suspect you want reasonable accuracy (up to you to decide - 5 minutes per day, 10 minutes per day?) and then you can think about the resolution you want

Use the TIME variable which is a 1-sec elapsed time count maybe...
...with an emphasis on the maybe. There are many commands that affect TIME and in my experience (maybe I'm just unlucky) I always seem to have programs that mean it really is quite inaccurate. I think I posted about being confused with the accuracy of TIME a year or so (or two, or three..) ago
 

mjy58

Member
Solved

I have found a solution to this, although rather inelegant!

The SERIN command has an optional 'TIMEOUT' parameter that can direct program control to a label after a number of milliseconds. I have used this to increment a timer variable on each timeout period.

As I am running the 18M2 at 16MHz the timeout values are 0.25ms rather than 1ms (found be trial and error, as not mentioned in the manual!) so a timeout value of 8000 should give a real time delay of 2 secs (I cannot use 1 sec as I need to monitor 24 hours and a word variable at 1 sec interval will only go up to 18hours).

In practice, a timeout value of 7600 gave an error of < 1% with the current level of intervening code.

This would not be very satisfactory for any sort of complex code, as manual corrections have to be applied to the incremental timer variable whenever serin is not being called. However I may get away with it, if I can keep the code relatively simple.

Code:
;Based on http://www.picaxeforum.co.uk/showthread.php?18886-RDM630-125khz-RFID-tag-Reader-CODE-EXAMPLE
;
#Terminal 19200
#picaxe 18m2
 eeprom   0,(2,48,50,48,48,70,51,56,57,69,55,57,70,3)    'RFID TAG1
 eeprom  14,(2,48,50,48,48,70,52,53,49,49,65,66,68,3)    'RFID TAG2
 eeprom  28,(2,48,50,48,48,70,51,57,54,68,53,66,50,3)    'RFID TAG3 (Drut)
 eeprom  42,(2,48,50,48,48,70,52,52,49,69,57,53,69,3)    'RFID TAG4 (Charlie)
 SetFreq M16		;Needed to read output from RDM6300 at 9600 baud
 dirsc = %00000011	;c1, c0 as output
 ;Variables
 	SYMBOL RDM630     = B.4
 	SYMBOL LED		= C.1
 	SYMBOL Feed		= C.0
 	SYMBOL stx		= B0
 	SYMBOL country1   = B1
 	SYMBOL country2	= B2
 	SYMBOL data1      = B3
 	SYMBOL data2      = B4	
 	SYMBOL data3      = B5	
 	SYMBOL data4      = B6	
 	SYMBOL data5      = B7	
 	SYMBOL data6      = B8	
 	SYMBOL data7      = B9
	SYMBOL data8      = B10
 	SYMBOL checksum1  = B11  	
 	SYMBOL checksum2  = B12
 	SYMBOL etx		= B13	
 	SYMBOL verify     = b14
 	SYMBOL code       = b15 	
 	SYMBOL checking   = b16	
 	SYMBOL tag       = b17
 	SYMBOL tagposition=b18
 	SYMBOL tagno	= b19
 	SYMBOL tempw1	= w12
 	SYMBOL inctime	= w13
 ;Constants
 	SYMBOL numboftags = 4	;Ensure this aligns with the number of tags in EEPROM
 	SYMBOL maxbytes	 = numboftags*14
 	SYMBOL RFIDBaud	= t9600_16
Init:
pause 1600	;Wait 0.4 sec (at 16MHz)for serial line to settle
sertxd("RFID reader V6.bas",CR,LF)	;Current source file
inctime = 0	;Zero the incrementatl time
high Feed	;Feed is normally held high and taken low to dispense food;
;
Main:
  tagposition = 0 				;Check first tag
  call ScanTag					;Read the tag
  verify=1	
  do while verify <=12
	  tag=verify+tagposition
	  READ tag,code
	  call Checktag
	  inc verify
	  If code <> checking then		;Found a mismatch
	   verify = 1
	   tagposition = tagposition + 14	;So move to the next tag
	    if tagposition > maxbytes then
	     verify = 14				;No valid tags found abort and read a new tag
	     sertxd(cr,lf,"Tag not matched!")
	    endif
	  endif 
  loop
  if verify < 14 then				;Tag successfully matched  
     pulsout LED,20000
     tagno=tagposition/14+1 
     SerTxd(CR,LF,"VERIFY OK  ","Tag No ",#tagno,CR,LF)
     pulsout LED,20000				;0.05 secs for LED
     low Feed					;Start feed motor
     SerTxd(CR,LF,"Feed motor on",CR,LF)
	pause 24000					;6 secs at 16MHz
	inctime = inctime + 3			;Add 3 (6secs) to inctimer to keep on time
	high feed					;Stop feed motor
     SerTxd(CR,LF,"Feed motor off",CR,LF)
  endif
 goto Main

ScanTag:
;7600 corresponds to approx 2 sec time out at 16MHz
     SerIn [7600,Incrementtime],RDM630,RFIDBaud,stx,country1,country2,data1,data2,data3,data4,data5,data6,data7,data8,checksum1,checksum2,etx
     SerTxd(CR,LF,"READ RFID TAG ",#b0," ",#b1," ",#b2," ",#b3," ",#b4," ",#b5," ",#b6," ",#b7," ",#b8," ",#b9," ",#b10," ",#b11," ",#b12," ",#b13,CR,LF)
     pulsout LED,60000
return

Checktag: 
 SELECT CASE verify                       
	 case  1 :checking = country1	
	 case  2 :checking = country2	
	 case  3 :checking = data1	
	 case  4 :checking = data2	
	 case  5 :checking = data3	
	 case  6 :checking = data4	
	 case  7 :checking = data5	
	 case  8 :checking = data6	
	 case  9 :checking = data7	
	 case 10 :checking = data8	
	 case 11 :checking = checksum1
	 case 12 :checking = checksum2
 END SELECT
return
;
Incrementtime:
inc inctime	;Each increment corresponds to ~2 secs
sertxd("Inctime = ",#inctime,cr,lf)
goto ScanTag
 
Top