My program is not working correctly

Ray Cag

New Member
I am new to Picaxe and micro-controllers, but I decided to dive into this project. I am programming an 08M to monitor hours of on time for a machine. After 6 months of on time I need the 08M to blink a light and turn on a relay. I have tested my circuit with smaller time values and it does most of what it is supposed to do. I am using "write" commands so the 08M can remember its time count should the power be turned off, but that is not working. It's important that the 08M remember the amount of on time and not reset if power is interrupted. I don't know what I am doing wrong.
Code:
symbol light = 1				`rename output 1 'light'
symbol relay = 2				`rename output 2 'relay'
symbol minutes = b0			`rename variable b0 'minutes'
symbol start = b13			`rename variable b13 'start'
symbol hours = b12			`rename variable b12 'hours'
symbol days = b11				`rename variable b11 'days'

main:

	low 0,1,2,4
        if days = 180 then shutdown
	read minutes,start		`read value of start into minutes
	
minute:
	
	for minutes = start to 59	`count to 60 minutes
		wait 60			`wait 1 minute
		write minutes,minutes	`save the minutes value
		debug b1
	next minutes
		
	let hours = hours + 1		`increment hours + 1
	write hours,hours			`save hours value	
	
	if hours = 24 then		`check hour count
		let days = days + 1	`increment days
		let hours = 0		`reset hours
	endif
	
	let start = 0			`reset minutes start
	write days,days			`save days value
	
	if days = 180 then shutdown	`if 180 days then goto shutdown
	
	
	goto minute				
		
		
		
shutdown:

	high relay				`make relay out high
	goto flash
	
flash:

	if pin3 = 1 then
		let days = 0
		goto minute			`reset
        endif
	high light				`turn on light
	pause 500				`wait for 0.5 seconds
	low light				`turn off light
	pause 500				`wait for 0.5 seconds
	goto flash				`repeat
 
Last edited:

SgtB

Member
I haven't looked at the code, but the picaxe may not be stable enough to mesure such a large timeframe. It will be off depending on the temperature etc. 6 months is a long time to stay accurate.
 

SgtB

Member
Try adding "if days => 180 then shutdown"
If you overshoot to 181 it won't fire.

A debug sprinkled here and there will tell you what your variables are doing.
 

BCJKiwi

Senior Member
The issue is with
write minutes,minutes

This will write the current minute value (0 - 59) into the memory locations 0 - 59 (0 to 0 , 5 to 5, 59 to 59).
similarly with hours and days,
However the hours will over write the minutes, and the days will over write the minutes (and hours) so the memory storage won't contain a useful time.

Also you will likely wear out the memory locations as there is a finite number of writes to eeprom before errors occur.

Suggestions,
1. re-think the chip and use of a battery backed clock chip.
2. If sticking with the 08M only, rethink the code so a date/time stamp is created in RAM (e.g. byte variables) (no life issues), and search the forum for the many solutions that allow a write to eeprom when the supply fails. On restart, read the stored value back into ram and keep adding to it.

The minutes code should work in a similar manner to the hours and days (hours + 1).
Use a byte variable for the +1 parts of code and a separate byte variable in place of the write to accumulate the elapsed time totals.

Write the 3 byte variables to separate numbered locations in eeprom when the power fails.

As the biggest number you need to hold is 180, then byte variables will be OK.
 
Last edited:

SgtB

Member
I'd also use >= for all your comparisons.Just in case something gets out of line, it will still get caught.
 

lanternfish

Senior Member
Try this. It uses nested loops so is a bit more memory hungry. These loops can be optimised once you see what is happening within them.

Code:
eeprom 0,(0,0,0)			        `initialise eeprom locations 0 = days
						`				     1 = minutes
						`				     2 = seconds

						
symbol light = 1				`rename output 1 'light'
symbol relay = 2				`rename output 2 'relay'

symbol minutes = b1			`rename variable b1 'minutes'
symbol hours = b2				`rename variable b22 'hours'
symbol days = b3				`rename variable b3 'days'

symbol restoremin = b4			`rename variable b4 'restore minutes'
symbol restorehrs = b5			`rename variable b5 'restore hours'
symbol restoreday = b6			`rename variable b6 'restore days'

symbol storemin = 3			`eeprom address for 'mins'
symbol storehrs = 2			`eeprom address for 'hours'
symbol storeday = 1			`eeprom address for 'days'

main:

	low 0,1,2,4				`set outputs low
      if days = 180 then shutdown	`if 6 months then shutdown
	read storemin,restoremin	`restore minutes
	read storehrs,restorehrs	`restore hourss
	read storeday,restoreday	`restore days

timer:

	for days = restoreday to 179

		write storeday,days	

		for hours = restorehrs to 23

			write storehrs,hours		

			for minutes = restoremin to 59
				wait 1
				write storemin,minutes
			next minutes

			restoremin = 0
			
		next hours

		restorehrs = 0
		
	next days
		
shutdown:

	high relay				`make relay out high
	
flash:

	if pin3 = 1 then goto reset	`reset
	high light				`turn on light
	pause 500				`wait for 0.5 seconds
	low light				`turn off light
	pause 500				`wait for 0.5 seconds
	goto flash				`repeat
	
reset:

	write storemin,restoremin	`restore minutes
	write storehrs,restorehrs	`restore hourss
	write storeday,restoreday	`restore days
	goto main
You can put whatever values you want into the first line eg eeprom 0,(179,20,0) to test.

The continuous writing to the eeprom is an issue. To spread the load you may want to use variables for the storage addresses that are incremented by 3 at each reset.

Hope this helps
 
Last edited:

lanternfish

Senior Member
Regarding eeprom writes, given the tolerance you are allowing
The time keeping does not have to be perfect. Plus or minus a week or two is not a problem.
then you can probably get away with only storing the hours & days, or even just the days.

Cheers
 

hippy

Ex-Staff (retired)
I'd go for a simpler DO..LOOP for the main time-tracking code ...

Code:
#Picaxe 08M

Symbol MINS_LOC = 0
Symbol HOUR_LOC = 1
Symbol DAYS_LOC = 2

Symbol mins = b0
Symbol hour = b1
Symbol days = b2

Symbol LIGHT = 1
Symbol RELAY = 2

Eeprom( 0, 0, 0 )

Read MINS_LOC, mins
Read HOUR_LOC, hour
Read DAYS_LOC, days

Do

  Do While days < 180
    Wait 60
    mins = mins + 1 // 60   : Write MINS_LOC, mins
    If mins = 0 Then
      hour = hour + 1 // 24 : Write HOUR_LOC, hour
      If hour = 0 Then
        days = days+1       : Write DAYS_LOC, days
      End If
    End If
  Loop

  High RELAY

  Do
    Toggle LIGHT
    Pause 500
  Loop Until pin3 = 1

  mins = 0 : Write MINS_LOC, mins
  hour = 0 : Write HOUR_LOC, hour
  days = 0 : Write DAYS_LOC, days

Loop
 

Andrew Cowan

Senior Member
Say each EEPROM location can handle 100,00 writes.

Say you are writing to a location every minute (storing the minute number).

It will last around 1,000,000 minutes. 16666 hours. 700 days (about two years).

However, unless you want to replace the PIC every 2 years, you either need change the location every few months, or just note down the time every 5 or so cycles.

The perfect way of doing this is to determine when the chip is being shutdown (voltage regulator with capacitor, measuring the high voltage (12V?) side. This way you only need to save the data when poser is being lost.

Code:
Symbol milliseconds=w5
Symbol minutes=b2
Symbol hours=b4

Init:
Read 0,minutes
main:
readadc 4,b1
if b1<100 then shutdown

For b0=0 to 59
  For milliseconds=0 to 999
  pause 1
  readadc 4,b1
  if b1<100 then shutdown
  Next milliseconds
Next b0
inc minutes
if minutes = 60 then
 minutes = 0
 inc hours
endif

etc...
 

Attachments

Last edited:

hippy

Ex-Staff (retired)
Eeprom endurance on a PICAXE-08M is 1,000,000 write cycles which, written once a minute, would be about 700 days which is likely a problem with an application like this.

An ideal solution would be to only update Eeprom on power-down but a software only solution would be to only update the Eeprom once every two minutes, which gives an instant doubling of lifetime. That could be extended for every five, ten or fifteen minutes or even longer. Ten minutes would extend its lifetime from around 2 to 20 years.

The downside is that minutes used up but not written are lost so on average with a write every 10 minutes would be 5 minutes lost every power down. If powered-down once a day, and a full 10 minutes lost everytime, the 180-day alert would come 30 hours late.

That may be acceptable, maybe not, and would be worse if powered-down more frequently.

One also has to consider what happens if power fails during a write to Eeprom and there is no means for detecting that. If the data does become corrupted there will be premature alerts or no alerts when there should have been. Elapsed time logging is not as simple as it first appears.

As SgtB points out in Post #2, accuracy of the PICAXE-08M timing may also be an issue. Operating speed may be off by +/-5% which would give an alert 180 days +/- 10 days, unless the software timing loop is calibrated there will be additional lengthening of time.

The ideal solution depends upon exact requirements, circumstances of use, how accurate the time period measurement needs to be and how mission or safety critical the system is.
 

MPep

Senior Member
Just a suggestion, but would counting 'mains cycles' help?
This was recently covered in the forum. Accurate timebase.
Using a large capacitor to keep the PICAXE working, and detect the absence of incoming power to then write the count should work well enough. As suggested by Andrew Cowan.

My 2c worth.:)
 

Ray Cag

New Member
Thank you for all the suggestions. I had not given any thought to the write cycles on the eeprom. Think I will probably go with a battery backup, most likely a rechargeable one. My goal is to fit everything on a 3" x 3" or 3" x 4" PC board. I am still a little confused about writing to eeprom. Do I have to have an eeprom command or is write and read all I need.
 

BCJKiwi

Senior Member
EEPROM is usually a one-time 'write' to clear or initialise the eeprom location at program download - But all EEPROM values get cleared to 0 on program download if no eprom command is used.

from the manual;
Function:
Preload EEPROM data memory. If no EEPROM command is used the values are
automatically cleared to the value 0. The keywords DATA and EEPROM have
identical functions and either can be used.
Information:
This is not an instruction, but a method of pre-loading the microcontrollers data
memory. The command does not affect program length.


In the running program, use WRITE
 
Last edited:
Top