Time variable

giuseppe

Member
Hello all again,

I have come to the point in my project that I need to monitor time elapsed in the background. I know the M2 chips have a internal variable called 'time' and increments every second. But I am using a 20X2... so what are my options without additional hardware?
 

giuseppe

Member
I just found something called timer3, could this be useful? Since I am running at 64MHz I guess I have to make my own preload. I wanted to do 1 second for a major tick but at 64MHz, this does not look possible since there are 4us per minor tick and 1,000,000us / 4us = 250,000 minor ticks which is bigger than 65536. And a half second for major tick fails for the same reason. So could I just use quarter second for a major tick by doing 250,000us / 4us = 62,500 minor ticks, then 65,536 - 62,500 = 3,036 = preload constant. So I guess:

Code:
settimer 3036
 

DaveC166

Member
The 20X2 has a TIMER comand, which in association with a preload value can be used to count exact 1 second intervals.The 20x2 Toflag can be used to trigger an interupt each second.
I use the following code in my main programe to count elapsed hours and mins
IF Timer=60 then
INC MINS: Timer=0 'MINS is a byte variable
Endif
If MINS=60 Then
Inc HRS:MINS=0 'HRS is a byte variable
 

giuseppe

Member
The 20X2 has a TIMER comand, which in association with a preload value can be used to count exact 1 second intervals.The 20x2 Toflag can be used to trigger an interupt each second.
Okay this sounds good but don't I have to set the timer first with the settimer command as showed in my first post?
 

DaveC166

Member
Settimer preload.
IE, Settimer T1s_8 sets 1 second increments @ 8mhz clock. The T1s_8 preloads the timer with 34286. My projects uses 3 DS18B20 temp sensors which when a READTEMP12 is done every 60 seconds causes my elapsed minute counter to run slow by 1.66 seconds per minute. I have overcome this by increasing the preload vaue to 35109 which means my elapsed minute counter is about 1 second fast per hour. I've allso reduced pause durations in my MAIN: prog so that MAIN: cycles every 100 ms, and the timer value is checked approx 10 times a second which increases acuracy.
 

giuseppe

Member
Okay, well, I think I understand the settimer command well enough to use it as a free running time variable that counts seconds as the program runs (like the time variable in the M series chips). However, when I put this into my code of my current project, my program seems to 'crash'. See I am using a LED display and it stops working whenever I use the settimer command. To make sure I wasn't crazy, I tested my concept of the timer variable as such:

Code:
#picaxe 20x2
setfreq m64
settimer 3036	'every major tick occurs every quarter second in timer

do

let b0 = timer / 4			'convert into seconds
if b0 = 10 then high b.6 endif	'after ten seconds light the LED
if b0 = 20 then low b.6 endif		'after twenty seconds turn off the LED

loop
This was just simple code to make sure my idea worked, and as expected, it worked fine. However, when I try this for my actual program for my project (which grew considerably over the last few days :) ), the LED display (which is multiplexed) stops displaying time. Here is my main loop for my program:

Code:
'===============================================================================
'  Initialization
'===============================================================================
#picaxe 20x2     'define picaxe type
setfreq m64      'run internal oscillator @ 64MHz

hi2csetup i2cmaster,%11010000,i2cslow_64,i2cbyte   'paramters set,20x2 is master
pause 1000       ' pause a little
settimer 3036    'every major tick occurs every one second @ 64MHz

'===============================================================================
'  Main
'===============================================================================
Main: 
hi2cin 1,(minute,hour)		   'obtain minute and hour information from DS1307
gosub Convert_Time_BCD_2_DEC	   'convert hour and minute data to decimal
gosub Convert_Time_DEC_2_DISPLAY 'convert hour and minute data to display
gosub Half_Day_Indicator	   'checks to see if AM/PM indicator should be on
gosub Display_Time		   'display converted data
gosub Read_NES_Controller	   'read NES controller's button status
gosub Check_Alarm			   'check if alarm should be activated

Menu:
if nesregister = %11011111 then goto Set_Time	'hold "down" to set current time
if nesregister = %10111111 then goto Set_Alarm	'hold "left" to set alarm time

goto Main		'go to main
I did not show my sub routines because I did not want to take too much space on the forum but when the line "settimer 3036 " (under 'Initialization' banner) is commented out, the code works just fine. But once I uncomment it and make it a part of the program, the display would show briefly the current time and then go blank.

My Main and one of my routines (Check_Alarm) use the i2c commands to read from the DS1307 and two sub routines use the pulsout command (Display_Time and Read_NES_Controller). I do not think it is the i2c commands not functioning but I have no proof why that is and I am sure it isn't the pulsout commands acting wacky per this thread post #6 and #7 http://www.picaxeforum.co.uk/showthread.php?17815-18M2-touch(16)-command-and-timer1-use

Also, after I run the 'bad' code, I cannot perform a download on the chip again unless I leave the circuit on, click program in the programming editor, and then toggle the circuit power off then on. So after the seeming 'crash', it interferes with a new download in some way.

Any ideas?
 

inglewoodpete

Senior Member
Faults that involve both foreground and background execution are among the more difficult to debug.

Without you posting ALL of your code, we can't help you much with it.

Firstly, make sure you are using the latest version of the Programming Editor. Although unlikely in your case, I was caught out with a compiler (tokeniser) fault in 2009.

To debug your problem, I suggest you insert 10 or 20 SerTxd ("a") statements at strategic locations in your program. Increment the "a" to "b", "c"... for each insertion. Run a test with the PE's terminal window open, logging the characters being sent by your PICAXE. Locate the last character to be logged (or repeated, if the program gets stuck in a loop). In the course of hunting down the problem, move your SerTxds or add more to further identify/isolate the problem code.

I'm fairly certain you may want to give yourself a slap when you find the problem.:):)
 
Last edited:

giuseppe

Member
Without you posting ALL of your code, we can't help you much with it.
Here is the first half:

Code:
#rem
================================================================================

    File........... NES_Controller_Alarm_Clock_20M2.bas
    Purpose........ Alarm Clock Functionality
    Author......... Joseph Corleto
    E-mail......... jc269@njit.edu
    Started........ 05/14/2012
    Finished....... --/--/----
    Updated........ --/--/----
 
================================================================================
   Notes
================================================================================
Seven Segment Display Convention:

  Symbol	bit7	bit6	bit5	bit4	bit3	bit2	bit1  bit0	binary eq	decimal 
-------------------------------------------------------------------------------
	0    	0	0	1	1	1	1	1     1    	00111111   	63
-------------------------------------------------------------------------------
	1    	0	0	0	0	0	1	1	0	00000110	6
-------------------------------------------------------------------------------
	2    	0	1	0	1	1	0	1	1	01011011	91
-------------------------------------------------------------------------------
	3    	0	1	0	0	1	1	1	1	01001111	79
-------------------------------------------------------------------------------
	4    	0	1	1	0	0	1	1	0	01100110	102
-------------------------------------------------------------------------------
	5    	0	1	1	0	1	1	0	1	01101101	109
-------------------------------------------------------------------------------
	6    	0	1	1	1	1	1	0	1	01111101	125
-------------------------------------------------------------------------------
	7    	0	0	1	0	0	1	1	1	00100111	39
-------------------------------------------------------------------------------
	8    	0	1	1	1	1	1	1	1	01111111	127
-------------------------------------------------------------------------------
	9    	0	1	1	0	0	1	1	1	01100111	103
-------------------------------------------------------------------------------
	H    	0	1	1	1	0	1	1	0	01110110	118
-------------------------------------------------------------------------------
	i    	0	0	0	1	0	0	0	0	01100111	16
-------------------------------------------------------------------------------
	n    	0	1	0	1	0	1	0	0	01010100	84
-------------------------------------------------------------------------------
	E    	0     1	1	1	1	0	0	1	01111001	121
-------------------------------------------------------------------------------
	F    	0     1	1	1	0	0	0	1	01110001	113
-------------------------------------------------------------------------------
	r    	0	1	0	1	0	0	0	0	01010000	80
-------------------------------------------------------------------------------
	o    	0	1	0	1	1	1	0	0	01011100	92
-------------------------------------------------------------------------------
      A     0     1     1     1     0     1     1     1     01110111    119
-------------------------------------------------------------------------------
	.    	1	0	0	0	0	0	0	0	10000000	128

          -------------
         |             |
         |     bit0    |
         |             | 
   ------- ------------ ------
  |      |             |      |
  |      |             |      |
  |      |             |      |
  | bit5 |             | bit1 |
  |      |             |      |
  |      |             |      |
  |      |             |      |
  |      |             |      |
   -----  ------------- ------					
         |             |
         |    bit6     |
         |             |
   ------ ------------- ------
  |      |             |      |
  |      |             |      |
  |      |             |      |
  | bit4 |             | bit2 |
  |      |             |      |
  |      |             |      |
  |      |             |      |
  |      |             |      |
  |      |             |      |
   ------ ------------- ------   ------
         |             |	  |      |
         |     bit3    |        | bit7 |
         |             |        |      |
          -------------          ------

================================================================================
NES Controller Function's Description:

- The NES controller contains one 8-bit 4021 shift register inside. 

- This register takes parallel inputs and converts them into a serial output.

- This code first latches the data and then shifts in the first bit on the data 
  line. Then it clocks and shifts in on the data line until all bits are 
  recieved.
  
- What is debugged are the button states of the NES controller.

- A logical "1" means the button is not pressed. A logical "0" means the button 
  is pressed.
  
- This code shifts the first bit of data into the LSB.

- The order of shifting for the buttons is shown in the table below:

				Bit# | Button   
				--------------
				  0  |   A  
				--------------
				  1  |   B  
				--------------
				  2  | Select   
				--------------
 			        3  | Start  
				--------------
				  4  |   Up  
				--------------
				  5  |  Down  
				--------------
				  6  |  Left   
				--------------
				  7  | Right   
				--------------
				
- The NES controller pinout is shown below:
	 _________
	|	    \
	| 1 O      \	1 - Ground
	|           |	2 - Clock
	| 2 O   O 7 |     3 - Latch
	|           |	4 - Data Out
	| 3 O   O 6 |	5 - No Connection
	|           |     6 - No Connection
	| 4 O   O 5 |     7 - +5V
	|___________|
	
================================================================================
DS1307 RTC Specs and Configurations:

- Slave address: 1101000x 

- Address size: 1 byte 

- Bus speed: 100kHz

- Below is a table of the adresses and regsiters:

Address	Register
------------------------------------
  00		Seconds ($0-$59)
------------------------------------
  01		Minutes ($0-$59)
------------------------------------
  02		Hours	  ($0-$23)
------------------------------------
  03		Day of week ($1-$7)
------------------------------------
  04		Date ($1-$31)
------------------------------------
  05		Month ($1-$12)
------------------------------------
  06		Year ($00-$99)
------------------------------------
  07		Control (set to $10)
------------------------------------
08-$3F	General Purpose RAM

- Below is table of 12 hour day and how the DS1307 RTC denotes it

12 hour	24 hour
--------------------
  12  am	   0
--------------------
   1  am       1
--------------------
   2  am	   2
--------------------
   3  am       3
--------------------
   4  am       4
--------------------
   5  am       5
--------------------
   6  am       6
--------------------
   7  am       7
--------------------
   8  am       8
--------------------
   9  am       9
--------------------
  10  am       10
--------------------
  11  am       11
--------------------
  12  pm       12
--------------------
   1  pm       13
--------------------
   2  pm       14
--------------------
   3  pm       15
--------------------
   4  pm       16
--------------------
   5  pm       17
--------------------
   6  pm       18
-------------------
   7  pm       19
--------------------
   8  pm       20
--------------------
   9  pm       21
--------------------
  10  pm       22
--------------------
  11  pm       23

"...Bit 6 of hours register is defined as the 12-hour or 24-hours mode-select 
bit; 0 = AM; 1 = PM; In the 24-hour mode, bit 5 is the second 10-hour bit 
(20-23 hours). The hours value must be re-entered whenever the 12/24-hour mode 
bit is changed..."

================================================================================
  Updates
================================================================================

#endrem
'===============================================================================
'  EEPROM Data
'===============================================================================
 

giuseppe

Member
Second half:

Code:
'===============================================================================
'  Constants
'===============================================================================
symbol mode        = 	  1	    'MSB first, idle low - shiftout for display
symbol ontime      =     20  	    'on time for one display digit
symbol MINUS_6     =  $10000 - 6  'represents "-6" for BCD to decimal conversion
symbol alarmmin    =      0	    'eeprom location to save minute of the alarm
symbol alarmhr     =      1	    'eeprom location to save hour of the alarm
symbol alarmstatus =      2	    'eeprom location to save if alarm is on or off
symbol alarmtune   =      3       'eeprom location to save alarm tune
symbol empty       =     99	    'represents an empty charactor for LED display

'===============================================================================
'  Variables
'===============================================================================
symbol nesregister =	 b0	    'holds what second it is
symbol minute	 =	 b1	    'holds what minute it is
symbol hour		 =	 b2	    'holds what hours it is
symbol hourtens    =     b3	    'holds tens place of the hour
symbol hourones	 =	 b4	    'holds ones place of the hour
symbol minutetens  =     b5	    'holds tens place of the minute
symbol minuteones	 =     b6	    'holds ones place of the minute
symbol temp1	 =     b18	    'temporary byte holder for calculations
symbol temp2	 =	 b19	    'temporary byte holder for calculations

'===============================================================================
'  Pin Declarations
'===============================================================================
'Inputs:
symbol nesdata     = pinc.6	'serial data to receive from 4021 (NES)

'Outputs:
symbol latch       = c.0	'latch pin for 74HC595            (LED display)
symbol sdata       = c.1	'serial data to feed into 74HC595 (LED display)
symbol sclk        = c.2	'clock for 74HC595                (LED display)
symbol neslatch    = c.5	'latch pin for 4021               (NES)
symbol nesclk      = c.7	'clock for 4021                   (NES)
symbol digit1      = b.0	'control pin for the hour's tens place
symbol digit2      = b.1	'control pin for the hour's ones place
symbol digit3      = b.2	'control pin for the minute's tens place
symbol digit4      = b.3	'control pin for the minute's ones place
symbol am_pm       = b.4      'am/pm indicator led
symbol alarmpower  = b.6	'power pin for 08M2 tune module
symbol tune1	 = c.3	'tells 08M2 module to play tune 1 when high
symbol tune2	 = c.4	'tells 08M2 module to play tune 2 when high

'===============================================================================
'  Initialization
'===============================================================================
#picaxe 20x2     'define picaxe type
setfreq m64      'run internal oscillator @ 64MHz

hi2csetup i2cmaster,%11010000,i2cslow_64,i2cbyte   'paramters set,20x2 is master

'===============================================================================
'  Main
'===============================================================================
Main: 
hi2cin 1,(minute,hour)		   'obtain minute and hour information from DS1307
gosub Convert_Time_BCD_2_DEC	   'convert hour and minute data to decimal
gosub Convert_Time_DEC_2_DISPLAY 'convert hour and minute data to display
gosub Half_Day_Indicator	   'checks to see if AM/PM indicator should be on
gosub Display_Time		   'display converted data
gosub Read_NES_Controller	   'read NES controller's button status
gosub Check_Alarm			   'check if alarm should be activated

Menu:
if nesregister = %11011111 then goto Set_Time	'hold "down" to set current time
if nesregister = %10111111 then goto Set_Alarm	'hold "left" to set alarm time

goto Main		'go to main

'===============================================================================
Set_Time:
do
hi2cin 1,(minute,hour)		   'obtain minute and hour information from DS1307
gosub Convert_Time_BCD_2_DEC	   'convert hour and minute data to decimal
gosub Convert_Time_DEC_2_DISPLAY 'convert hour and minute data to display
gosub Half_Day_Indicator	   'checks to see if AM/PM indicator should be on
gosub Display_Time		   'display converted data
gosub Read_NES_Controller	   'read NES controller's button status

if nesregister = %11011101 then goto Set_Time_Hour   '"down"+"B" increments hour
if nesregister = %11011110 then goto Set_Time_Minute '"down"+"A" increments min
if nesregister = %11111111 then goto Main		     'no buttons pressed so main
loop

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set_Time_Hour:
pause 500				'"debounce" time
hi2cin 1,(minute,hour)		'obtain minute and hour information from DS1307
gosub Convert_Time_BCD_2_DEC	'convert hour and minute data to decimal

if hour = 23 then			'hour is 23?
	let hour = 0		'if so then reset to zero
else 					'if not...
	let hour = hour + 1	'...then increment it by one
endif					'done deciding

gosub Convert_Hour_DEC_2_BCD	'convert decimal hour to BCD

hi2cout 2,(hour)			'write to DS1307 new hour

goto Set_Time			'go back to setting time menu

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set_Time_Minute:
pause 500				'"debounce" time 
hi2cin 1,(minute,hour)		'obtain minute and hour information from DS1307
gosub Convert_Time_BCD_2_DEC	'convert hour and minute data to decimal

if minute = 59 then		'minute is 59?
	let minute = 0		'if so then reset to zero
else 					'if not...
	let minute = minute + 1	'...then increment it by one
endif					'done deciding

gosub Convert_Minute_DEC_2_BCD'convert decimal minute to BCD

hi2cout 1,(minute)		'write to DS1307 new hour

goto Set_Time			'go back to setting time menu

'===============================================================================
Set_Alarm:
do
read alarmhr,hour			   'obtain last set alarm hour from memory
read alarmmin,minute		   'obtain last set alarm minute from memory
gosub Convert_Time_BCD_2_DEC	   'convert hour and minute data to decimal
gosub Convert_Time_DEC_2_DISPLAY 'convert hour and minute data to display
gosub Half_Day_Indicator	   'checks to see if AM/PM indicator should be on
gosub Display_Time		   'display converted data
gosub Read_NES_Controller	   'read NES controller's button status
gosub Play_Tune

if nesregister = %10111011 then goto Set_Alarm_Tune  '"left"+"select" for tune
if nesregister = %10111101 then goto Set_Alarm_Hour  '"left"+"B" increments hour
if nesregister = %10111110 then goto Set_Alarm_Minute'"left"+"A" increments min
if nesregister = %10110111 then goto Set_Alarm_Status'"left"+"start" toggles
									'alarm status (on/off)
if nesregister = %11111111 then exit		     'no buttons pressed so main
loop

gosub Disable_Tune		'disable all tune pins and power pin to 08M2

goto Main				'go to main

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set_Alarm_Tune:
pause 500				'"debounce" time
gosub Disable_Tune		'disable all tune pins and power pin to 08M2
read alarmtune,temp1		'read previous set tune
if temp1 = 0 then let temp2 = 1 endif	'if prior was tune 1 make it tune 2
if temp1 = 1 then let temp2 = 0 endif	'if prior was tune 2 make it tune 1

write alarmtune,temp2		'save new alarm tune

goto Set_Alarm			'go back to setting alarm menu

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set_Alarm_Hour:
pause 500				'"debounce" time
read alarmhr,hour			'read previous saved hour
gosub Convert_Time_BCD_2_DEC	'convert hour and minute data to decimal

if hour = 23 then			'hour is 23?
	let hour = 0		'if so then reset to zero
else 					'if not...
	let hour = hour + 1	'...then increment it by one
endif					'done deciding
				
gosub Convert_Hour_DEC_2_BCD	'convert decimal hour to BCD

write alarmhr,hour		'save new alarm hour

goto Set_Alarm			'go back to setting alarm menu
 

giuseppe

Member
Third half :p

Code:
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set_Alarm_Minute:
pause 500				'"debounce" time
read alarmmin,minute		'read previous set minute
gosub Convert_Time_BCD_2_DEC	'convert hour and minute data to decimal

if minute = 59 then		'minute is 59?
	let minute = 0		'if so then reset to zero
else 					'if not...
	let minute = minute + 1	'...then increment it by one
endif					'done deciding

gosub Convert_Minute_DEC_2_BCD'convert decimal minute to BCD

write alarmmin,minute		'save new alarm minute

goto Set_Alarm			'go back to setting alarm menu

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set_Alarm_Status:
pause 500				'"debounce" time
read alarmstatus,temp1		'read previous alarm status
let temp1 = 1 &/ temp1 		'toggle status; if on then off, if off then on
					 '0 = alarm off; 1 = alarm on
write alarmstatus,temp1		'save new alarm status

if temp1 = 0 then goto Display_Off	'if new status is off then display this
if temp1 = 1 then goto Display_On	'if new status is on then display this

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Display_Off:
'a for...next loop is used to create a delay while operating display
'basically, the alarm status, in this case off, shows this for a brief moment
for temp2 = 0 to 100		'execute loop 100 times		
	let hourtens = 119	'preload the letter "A" to be displayed in digit 1
	let hourones = 92		'preload the letter "o" to be displayed in digit 2
	let minutetens = 113	'preload the letter "F" to be displayed in digit 3
	let minuteones = 113	'preload the letter "F" to be displayed in digit 4
	gosub Display_Time	'display converted data
      gosub Disable_Tune	'disable all tune pins and power pin to 08M2
next					'continue until temp2 = 100

goto Set_Alarm			;go back to setting alarm menu

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Display_On:
'a for...next loop is used to create a delay while operating display
'basically, the alarm status, in this case on, shows this for a brief moment
for temp1 = 0 to 100		'execute loop 100 times
	let hourtens = 119	'preload the letter "A" to be displayed in digit 1
	let hourones = empty	'preload the letter " " to be displayed in digit 2
	let minutetens = 92	'preload the letter "o" to be displayed in digit 3
	let minuteones = 84	'preload the letter "n" to be displayed in digit 4
	gosub Display_Time	'display converted data
next					'continue until temp2 = 100

goto Set_Alarm			'go back to setting alarm data

'===============================================================================
'  Sub-Routines
'===============================================================================
Read_NES_Controller:
'code below grabs data from the NES controller's hardware (4021)
pulsout neslatch,1	'latch the button states into the NES controller's 4021

let bit0 = nesdata	'grab "A" button state
pulsout nesclk,1		'clock for next button

let bit1 = nesdata	'grab "B" button state
pulsout nesclk,1		'clock for next button

let bit2 = nesdata	'grab "Select" button state
pulsout nesclk,1		'clock for next button

let bit3 = nesdata	'grab "Start" button state
pulsout nesclk,1		'clock for next button

let bit4 = nesdata	'grab "Up" button state
pulsout nesclk,1		'clock for next button

let bit5 = nesdata	'grab "Down" button state
pulsout nesclk,1		'clock for next button

let bit6 = nesdata	'grab "Left" button state
pulsout nesclk,1		'clock for next button

let bit7 = nesdata	'grab "Right" button state

return			'back where you came from

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
Convert_Time_BCD_2_DEC:
'code below takes time digits in BCD form and coverts them to decimal
let hour = hour / 16 * MINUS_6 + hour	   'hippy's amazing BCD to DEC formula
let hourtens = hour dig 1		  	   'grab tens place of the hour
let hourones = hour dig 0			   'grab ones place of the hour

let minute = minute / 16 * MINUS_6 + minute  'hippy's amazing BCD to DEC formula
let minutetens = minute dig 1			   'grab tens place of the minute
let minuteones = minute dig 0			   'grab ones place of the minute

return			'back where you came from

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Convert_Time_DEC_2_DISPLAY:
'code below takes time digits in decimal form and converts them to display
lookup hourtens ,(63,6,91,79,102,109,125,39,127,103),hourtens
lookup hourones ,(63,6,91,79,102,109,125,39,127,103),hourones
lookup minutetens ,(63,6,91,79,102,109,125,39,127,103),minutetens
lookup minuteones ,(63,6,91,79,102,109,125,39,127,103),minuteones
let hourones = hourones + 128			  'light up part of colon on display
let minutetens = minutetens + 128		  'light up part of colon on display
return			'back where you came from

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Convert_Hour_DEC_2_BCD:
'code below takes the hour in decimal form and converts into BCD
let hourtens = hour /  10     	 'grab the tens place of the hour
let hourones = hour // 10		 'grab the ones place of the hour
let hourtens = hourtens * 16		 'shift tens place of hour to upper 4 bits
let hour = hourtens OR hourones	 'OR hourtens w/ hourones; hour now BCD

return			'back where you came from

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Convert_Minute_DEC_2_BCD:
'code below takes the minute in decimal form and converts into BCD
let minutetens = minute /  10     	 'grab the tens place of the minute
let minuteones = minute // 10		 'grab the ones place of the minute
let minutetens = minutetens * 16	 'shift tens place of hour to upper 4 bits
let minute = minutetens OR minuteones'OR minutetens w/ minuteones;minute now BCD

return			'back where you came from

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Display_Time:
'code below takes display data from hourtens, hourones, minutetens, and 
'minuteones and displays it to the LED display via a shift register
Hour_Tens:
if hourtens = 63 then goto Hour_Ones	  'removes leading zero on display
if hourtens = empty then goto Hour_Ones	  'if empty then skip this digit
shiftout sclk,sdata,mode,(hourtens)		  'display tens place of the minute
pulsout latch,1					  'latch data out to display
low digit1					  	  'turn on tens place of the hour
pause ontime					  'pause a little
input digit1					  'turn off tens place of the hour

Hour_Ones:
if hourones = empty then goto Minute_Tens	  'if empty then skip this digit
shiftout sclk,sdata,mode,(hourones)		  'display ones place of the hour
pulsout latch,1					  'latch data out to display
low digit2						  'turn on ones place of the hour
pause ontime					  'pause a little
input digit2					  'turn off ones place of the hour

Minute_Tens:
if minutetens = empty then goto Minute_Ones 'if empty then skip this digit
shiftout sclk,sdata,mode,(minutetens)	  'display tens place of the minute
pulsout latch,1					  'latch data out to display
low digit3						  'turn on tens place of the minute
pause ontime					  'pause a little
input digit3					  'turn off tens place of the minute

Minute_Ones:
if minuteones = empty then goto Done	  'if empty then skip this digit
shiftout sclk,sdata,mode,(minuteones)	  'display ones place of the minute
pulsout latch,1					  'latch data out to display
low digit4						  'turn on ones place of the minute
pause ontime					  'pause a little
input digit4					  'turn off ones place of the minute

Done:
return			'back where you came from

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Half_Day_Indicator:
if hour >= 12 then high am_pm endif		'AM/PM led on when hour is >= to 12
if hour <  12 then low am_pm endif		'AM/PM led off when hour is < 12

return			'back where you came from

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Check_Alarm:
'code below compares saved alarm to current time and activates buzzer if need be
read alarmstatus,temp1		   'check to see if alarm was set 
					   '0 = not set; 1 = set
					
if temp1 = 0 then return endif   'if 0 then alarm was not set so exit routine

'but if temp1 = 1 then code below now checks to see if the alarm should sound
hi2cin 1,(minute,hour)		   'obtain minute and hour information from DS1307
read alarmhr,temp1		   'read hour of the alarm that was set
read alarmmin,temp2		   'read minute of the alarm that was set

'when the saved hour/minute matches current hour/minute, a 1 indicates this
if temp1 = hour   then let temp1 = 1 else let temp1 = 0 endif	  
if temp2 = minute then let temp2 = 1 else let temp2 = 0 endif

'when ANDing match indicators and result is 0 there is no match but is 1 if so
let temp1 = temp1 & temp2	   

if temp1 = 0 then gosub Disable_Tune	'if no match turn off alarm tune
if temp1 = 1 then gosub Play_Tune		'if a match turn on alarm tune

return

Play_Tune:
'code below signals the 08M2 sound module to play respective tune saved
read alarmtune,temp1		'read previous set tune
high alarmpower			'turn on 08M2 sound module
if temp1 = 0 then high tune1 endif		'if a 0 then signal to play tune 1
if temp1 = 1 then high tune2 endif		'if a 1 then signal to play tune 2

return			'back where you came from

Disable_Tune:
'code below signals the 08M2 sound module to disable all tunes
low alarmpower		'disable 08M2 sound module's power
low tune1			'disable alarm tune 1 signal
low tune2			;disable alarm tune 2 signal

return			'back where you came from
 

giuseppe

Member
To debug you problem, I suggest you insert 10 or 20 SerTxd ("a") statements at strategic locations in your program. Increment the "a" to "b", "c"... for each insertion. Run a test with the PE's terminal window open, logging the characters being sent by your PICAXE. Locate the last character to be logged (or repeated, if the program gets stuck in a loop). In the course of hunting down the problem, move your SerTxds or add more to further identify/isolate the problem code.
Yes I do this whenever I am debugging problem code I cannot find and it does result in a slap in the face most of he times :)
 

inglewoodpete

Senior Member
I printed your code out so that I could read on the ride home yesterday. Its well documented and fairly well structured too, which makes the job easier. It is written in a style similar to what I use, although I actively avoid the "goto" statement:rolleyes:. I see that you possibly have an academic background.

I can't see any obvious problems but I notice there are no timer-related statements in it. Aren't they what you sespect is causing the problem?

1. Can you show which Timer commands you are using and where they go in the code and why you are using them?

2. Also you mentioned that you'd used SerTxd to try to isolate the problem. Any indication where the code gets lost?
 

inglewoodpete

Senior Member
By chance, I have a 20X2 and a DS1307 set up on a stripboard that I used as a temperature logger. I used the cut-down code you posted a couple of days ago and added a few bits to make its syntax complete. Also added logging to the terminal to show that it was running as expected:

Code:
'===============================================================================
'  Initialization
'===============================================================================
#picaxe 20x2     'define picaxe type
#terminal 76800
setfreq m64      'run internal oscillator @ 64MHz

hi2csetup i2cmaster,%11010000,i2cslow_64,i2cbyte   'paramters set,20x2 is master
pause 1000       ' pause a little
settimer 3036    'every major tick occurs every one second @ 64MHz
'
Symbol minute      = b1
Symbol hour        = b2
Symbol nesregister = b0
'===============================================================================
'  Main
'===============================================================================
Main: 
        hi2cin 1,(minute,hour)		'obtain minute and hour information from DS1307
        gosub Convert_Time_BCD_2_DEC		'convert hour and minute data to decimal
        gosub Convert_Time_DEC_2_DISPLAY	'convert hour and minute data to display
        gosub Half_Day_Indicator		'checks to see if AM/PM indicator should be on
        gosub Display_Time			'display converted data
        gosub Read_NES_Controller		'read NES controller's button status
        gosub Check_Alarm			'check if alarm should be activated
        b27 = timer / 4			'convert into seconds
        SerTxd(#hour, ":", #minute, ":", #b27," ")
Menu:
        if nesregister = %11011111 then goto Set_Time	'hold "down" to set current time
        if nesregister = %10111111 then goto Set_Alarm	'hold "left" to set alarm time
Set_Time:
Set_Alarm:
        goto Main			'go to main
'===============================================================================
'  Subroutines
'===============================================================================
Convert_Time_BCD_2_DEC: Return	'convert hour and minute data to decimal
Convert_Time_DEC_2_DISPLAY: Return	'convert hour and minute data to display
Half_Day_Indicator: Return		'checks to see if AM/PM indicator should be on
Display_Time: Return		'display converted data
Read_NES_Controller: Return		'read NES controller's button status
Check_Alarm: Return		'check if alarm should be activated
The logs looked like what I expected. (Although my DS1307 has been running is little fast over the last year while it has been sitting in the cupboard!)
 

giuseppe

Member
I printed your code out so that I could read on the ride home yesterday. Its well documented and fairly well structured too, which makes the job easier. It is written in a style similar to what I use, although I actively avoid the "goto" statement:rolleyes:. I see that you possibly have an academic background.
Wow thanks for taking the time to look at it so closely! Also, thanks for the compliment on the code structure, I thought it was messy and was going to clean it up later if possible:p And yes, you are right, I am a university student enrolled in a EE program and really the only experience in embedded design we have done is a lab with a Motorola 68000 microprocessor (a pain to program if you ask me). How could you tell I had an academic background?

I can't see any obvious problems but I notice there are no timer-related statements in it. Aren't they what you sespect is causing the problem?
Yes it is but I still can't see where the problem is coming from.

1. Can you show which Timer commands you are using and where they go in the code and why you are using them?
You mean where I use the syntax "Timer" or "Timer3"?

My test code (in post#6) showed how I used it on a 20x2 out of my circuit and where I implemented while in circuit.

The reason I wanted to use a background timer is because I wanted to create a "snooze" button for the alarm clock project I am working on. When the snooze button is pressed, I wanted to set off a flag of some sort and in one of the subroutines or a new sub routine (didn't determine where to put this yet) check to see if the flag is set, turn off the alarm power pin (or disable the alarm somehow) and reactivate it when the snooze duration (9 minutes) has elapsed.

2. Also you mentioned that you'd used SerTxd to try to isolate the problem. Any indication where the code gets lost?
Not really, it seemed to work fine but I want to double and triple check this again. I'll let you know how this goes.

Sorry for not getting back sooner, I was so annoyed at the problem that I kinda shoved it off to the side and started to work on the other features of the project (better composed alarm tunes, different segment displays for color options, 12/24hr selection mode, louder piezo sound, etc). Ha but unfortunately most of the other stuff is completed so now I am back to this.
 
Top