Variable keeps resetting

RustyH

Senior Member
I was wondering if anyone could spot in the below code any reason why my b0 variable keep resetting? Basically, I have a switch on the board that each time its pressed it increases the b0 vaiable by 1. This then operates the length of the pause time between each color change.

However, If I say set the pause at 4, with 4 presses of the button, it for some reason just resets itself back to 0

:confused:

Code:
#picaxe 08m2
#no_data
setfreq m16

symbol Red = 0
symbol Green = 1
symbol Blue = 2
symbol speed = w0
symbol on_time = w2
symbol off_time = w3

setint %00001000, %00001000


main:
readadc C.4,b3  ‘read the value
if b3<2 then chase  ‘range 0-1
if b3>10 then lightsoff
goto main

lightsoff:
Low Green
Low Red
Low Blue
goto main


chase:
speed = b0 * 10000

	RedOn: 
		for on_time = 0 to 5000 step 10
            	pulsout Red,on_time
            	off_time = 5000 - on_time
            	pauseus off_time
        	next on_time
        high Red
        
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
        
	BlueOff:
		for on_time = 0 to 5000 step 10
          		pulsout Blue,on_time
          		off_time = 5000 - on_time
          		pauseus off_time
       	next on_time
       low Blue        

	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed

	GreenOn: 
		for on_time = 0 to 5000 step 10
            	pulsout Green,on_time
            	off_time = 5000 - on_time
            	pauseus off_time
        	next on_time
	  high Green
	  
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
        
	RedOff:
		for on_time = 0 to 5000 step 10
          		pulsout Red ,on_time
          		off_time = 5000 - on_time
          		pauseus off_time
       	next on_time
        low Red

	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed

	BlueOn: 
		for on_time = 0 to 5000 step 1000
            	pulsout Blue,on_time
            	off_time = 5000 - on_time
            	pauseus off_time
        	next on_time
        high Blue

	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
        
	GreenOff:
		for on_time = 0 to 5000 step 10
          		pulsout Green ,on_time
          		off_time = 5000 - on_time
          		pauseus off_time
       	next on_time
        low Green

	pause speed
	pause speed
	pause speed
	pause speed
	pause speed
	pause speed

goto main


interrupt:
    if pinc.3 = 1 then
      do while pinc.3 = 1 : loop ' wait for release
	b0 = b0 + 1 // 7 ' 0 to 6
	endif
	
setint %00001000, %00001000
	
	do
	for b1 = 1 to b0
	pause 1000
	high Red
	high Blue
	high Green
	pause 2000
	low Red
	low Blue
	low Green
	pause 1000
	next b1
	exit
	loop
return
 

nick12ab

Senior Member
Your code is uncommented and you haven't said what pin your switch is connected to. But...

Regarding this code:
Code:
       if pinc.3 = 1 then
          do while pinc.3 = 1 : loop ' wait for release
 	  b0 = b0 + 1 // 7 ' 0 to 6
 	endif
I'm not sure how the PICAXE handles the modulus divide but for any number under 7 when it comes to the initial division bit you'll always get 0 as you get a decimal which the PICAXE can't do.
 

Haku

Senior Member
Your problem is that w0 uses the variable space of b0 & b1, giving w0 a new number changes the contents of b0 & b1. Word and byte variables share the same memory space in the Picaxe, as in:

w0 uses the same space as b0 & b1
w1 uses the same space as b2 & b3
w2 uses the same space as b4 & b5
etc.

Use different variables and you won't have the problem of them mysteriously resetting.


The "b0 = b0 + 1 // 7 ' 0 to 6" line is correct, but the subsequent "for b1 = 1 to b0" line probably needs to be changed to "for b1 = 0 to b0" because as it stands it will only loop once when b0 is 0 or 1.
 

RustyH

Senior Member
Thanks guys, really appriciate your help.

I will take note of the W and B variable references as I didnt know that, thanks. Will give it ago and let you know how it runs.

Also, i will comment out my code (something I must learn to do) so its easier for future reference

Thanks again :eek:
 

westaust55

Moderator
I will take note of the W and B variable references as I didnt know that, thanks. Will give it ago and let you know how it runs.
Have a read of PICAXE manual 2 (currently V7.7) page 10 which covers variables and the overlap between bit, byte or word variables.

The variable map info at Post 10 here: http://www.picaxeforum.co.uk/showthread.php?11514-PICAXE-Memory-Map-and-SFR-Details-Chart
May help you "See" the overlap between variables.

Note that by convention in the computer industry the least significant bit/byte is displayed at the right and the most significant bit/byte is shown to the left.
 

mrburnette

Senior Member
Thanks guys, really appriciate your help.

I will take note of the W and B variable references as I didnt know that, thanks. Will give it ago and let you know how it runs.

Also, i will comment out my code (something I must learn to do) so its easier for future reference

Thanks again :eek:
I have programmed for 40 years and I still mess-up with the overlapping memory on the PICAXE. I appreciate why it works the way it does and why it is so useful, but some late nights, it can be a pain when I slip-up. So, as a constant reminder of the slippery path ahead, I import a code template that I made for each of the PICAXE chips I use which set-up the SYMBOL area to constantly remind me... I can clean all of these remarks when I finish the code.

Example:
Code:
#picaxe 20x2
#Terminal 2400
#No_Table
#No_Data
#freq m4	'm4 is 4MHz and the default is 8MHz which will not work with all commands
'
' SYMBOL table - aliases for byte values
SYMBOL ChangeMe00 = B0		' B1-B0 overmapped by W0 & by bit0 - bit7
SYMBOL ChangeMe01 = B1
SYMBOL ChangeMe02 = B2		' B3-B2 overmapped by W1 & by bit8 - bit15
SYMBOL ChangeMe03 = B3
SYMBOL ChangeMe04 = B4		' B5-B4 overmapped by W2 & by bit16 - bit31
SYMBOL ChangeMe05 = B5
SYMBOL ChangeMe06 = B6		' B7-B6 overmapped by W3
SYMBOL ChangeMe07 = B7
SYMBOL ChangeMe08 = B8		' B9-B8 overmapped by W4
SYMBOL ChangeMe09 = B9
SYMBOL ChangeMe10 = B10		' B11-10 overmapped by W5
SYMBOL ChangeMe11 = B11
SYMBOL ChangeMe12 = B12		' B13-B12 overmapped by W6
SYMBOL ChangeMe13 = B13
SYMBOL ChangeMe14 = B14		' B15-B14 overmapped by W7
SYMBOL ChangeMe15 = B15
SYMBOL ChangeMe16 = B16		' B17-B16 overmapped by W8
SYMBOL ChangeMe17 = B17
SYMBOL ChangeMe18 = B18		' B19-B18 overmapped by W9
SYMBOL ChangeMe19 = B19
'SYMBOL table - aliases for word values
SYMBOL ChangeMe99 = W10
SYMBOL ChangeMe98 = W11
SYMBOL ChangeMe97 = W12
SYMBOL ChangeMe96 = W13
SYMBOL ChangeMe95 = W14
SYMBOL ChangeMe94 = W15
SYMBOL ChangeMe93 = W16
SYMBOL ChangeMe92 = W17
SYMBOL ChangeMe91 = W18
SYMBOL ChangeMe90 = W19
SYMBOL ChangeMe89 = W21
SYMBOL ChangeMe88 = W22
SYMBOL ChangeMe87 = W23
Even old code dogs need little tricks to keep neurons firing properly.

- Ray
 

RustyH

Senior Member
Im pretty new to coding etc, so sorry to be a pain but what does that code mean/do that you posted??

I had a look at those tables that were posted and I can see why people get mixed up, blimey its complicated!!! :eek:
 

RustyH

Senior Member
Ok Guys, Have add a load of notes in and also changed the variable so there is better spacing between them. Hopefully the below will look better

Code:
#picaxe 08m2
#no_data
setfreq m16

symbol Red = 0 'Red LED strip assigned to pin 0
symbol Green = 1 'Green LED strip assigned to pin 1
symbol Blue = 2 'Blue LED strip assigned to pin 2
symbol hold = w0 'Use W0 to hold the pause info
symbol on_time = w1
symbol off_time = w2

setint %00001000, %00001000

main:
readadc C.4,b6 'read the LDR value in to b6
if b6<2 then chase  ‘range 0-1 'if LDR is less that 2 then goto chase
if b6>3 then lightsoff 'if LDR is more than 3 then go to lights off to ensure all lights are off
goto main

lightsoff:
Low Green
Low Red
Low Blue
goto main


chase:
hold = b8 * 10000 'take the value stored in b8 from the interrupt sub routine and multiplies by 10k to give a puase time

	RedOn: 'Red LED Fade ON Loop
		for on_time = 0 to 5000 step 10
            	pulsout Red,on_time
            	off_time = 5000 - on_time
            	pauseus off_time
        	next on_time
        high Red
        
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
        
	BlueOff: 'Blue LED Fade OFF Loop
		for on_time = 0 to 5000 step 10
          		pulsout Blue,on_time
          		off_time = 5000 - on_time
          		pauseus off_time
       	next on_time
       low Blue        

	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold

	GreenOn: 'Green LED Fade ON Loop
		for on_time = 0 to 5000 step 10
            	pulsout Green,on_time
            	off_time = 5000 - on_time
            	pauseus off_time
        	next on_time
	  high Green
	  
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
        
	RedOff: 'Red LED Fade OFF Loop
		for on_time = 0 to 5000 step 10
          		pulsout Red ,on_time
          		off_time = 5000 - on_time
          		pauseus off_time
       	next on_time
        low Red

	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold

	BlueOn: 'Blue LED Fade ON Loop
		for on_time = 0 to 5000 step 1000
            	pulsout Blue,on_time
            	off_time = 5000 - on_time
            	pauseus off_time
        	next on_time
        high Blue

	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
        
	GreenOff: 'Green LED Fade OFF Loop
		for on_time = 0 to 5000 step 10
          		pulsout Green ,on_time
          		off_time = 5000 - on_time
          		pauseus off_time
       	next on_time
        low Green

	pause hold
	pause hold
	pause hold
	pause hold
	pause hold
	pause hold

goto main


interrupt: 'pin C.3 is an external button that changes the pause time up to 7 modes. 
    if pinc.3 = 1 then
      do while pinc.3 = 1 : loop ' wait for release
	b8 = b8 + 1 // 7 ' 0 to 6
	endif
	
setint %00001000, %00001000
	
	'The following loop flashes all LEDs by the number that is stored in b8 above, 
	'this given a visual indication of what pause time is set, for example,
	'0 flahses = zero pause time (b8 = 0)
	'1 flash = 10,000 msec (b8 = 1)
	'2 flash = 20,000 msec (b8 = 2)
	'and so on
	do
	for b10 = 1 to b0
	pause 1000
	high Red
	high Blue
	high Green
	pause 2000
	low Red
	low Blue
	low Green
	pause 1000
	next b10
	exit
	loop
return
 

hippy

Ex-Staff (retired)
Your ' for b10 = 1 to b0' in the interrupt routine is a bit of a mystery to me seeing as b0 isn't referenced otherwise within the interrupt and it also possibly conflicts with the "Symbol hold=w0" used elsewhere.
 

geoff07

Senior Member
I had a bit of time to spare so took the liberty of editing your program to illustrate some of the things you can do to make it more readable and easier to maintain. You might find some of these pointers useful. Don't take this as heavy criticism, you should have seen the code I first wrote. And that was in Fortran. But you can get up the learning curve a bit faster with a bit of input! I hope I understood what your code was doing, I have not tested this version so it may well have errors and I may have misunderstood how it works. But the points are valid whatever you intended.

Code:
#picaxe 08m2
#no_data
setfreq m16

symbol Red      = 0     'Red LED strip assigned to pin 0
symbol Green    = 1     'Green LED strip assigned to pin 1
symbol Blue     = 2     'Blue LED strip assigned to pin 2
symbol thisled  = b2
symbol hold     = w20    'Use W0 to hold the pause info
symbol on_time  = w21
symbol off_time = w22
'initialise
      gosub init_int
'main program
      do
         readadc C.4,b6 'read the LDR value in to b6
         select b6
            case < 2 gosub chase'if LDR is less that 2 then call chase
            case > 3 gosub lights_off'if LDR is more than 3 then call lights off to ensure all lights are off
            else '?what happens here?
      loop
      end
'================================
lights_off:
      Low Green
      Low Red
      Low Blue
      return
'================================
chase:
      hold = b8 * 10000 'take the value stored in b8 from the interrupt 
                'sub routine and multiplies by 10k to give a puase time
RedOn: 'Red LED Fade ON Loop
      this_led = Red
      gosub led_fade_up   
BlueOff: 'Blue LED Fade OFF Loop
      for on_time = 0 to 5000 step 10
         pulsout Blue,on_time
         off_time = 5000 - on_time
         pauseus off_time
      next on_time
      low Blue        
      gosub pause_hold
GreenOn: 'Green LED Fade ON Loop
      this_led = Green
      gosub led_fade_up   
RedOff: 'Red LED Fade OFF Loop
      for on_time = 0 to 5000 step 10
         pulsout Red ,on_time
         off_time = 5000 - on_time
         pauseus off_time
      next on_time
      low Red
      gosub pause_hold
BlueOn: 'Blue LED Fade ON Loop
      this_led = Blue
      gosub led_fade_up
GreenOff: 'Green LED Fade OFF Loop
      for on_time = 0 to 5000 step 10
         pulsout Green ,on_time
         off_time = 5000 - on_time
         pauseus off_time
      next on_time
      low Green
      gosub pause_hold
      return
'================================
pause_hold:
    'how about long_hold = 6 * hold:pause long_hold
    pause hold
    pause hold
    pause hold
    pause hold
    pause hold
    pause hold
return
'================================
led_fade_up:
      for on_time = 0 to 5000 step 10
         pulsout this_led,on_time
         off_time = 5000 - on_time
         pauseus off_time
      next on_time
      high this_led  
      gosub pause_hold  
      return
'================================
interrupt: 'pin C.3 is an external button that changes the pause time up to 7 modes. 
      do:loop until pinC.3 <> 1 ' wait for release
      b8 = b8 + 1 // 7 ' 0 to 6
    'The following loop flashes all LEDs by the number that is stored in b8 above, 
    'this given a visual indication of what pause time is set, for example,
    '0 flahses = zero pause time (b8 = 0)
    '1 flash = 10,000 msec (b8 = 1)
    '2 flash = 20,000 msec (b8 = 2)
    'and so on
    'do
     for b10 = 1 to b0
        pause 1000
        high Red
        high Blue
        high Green
        pause 2000
        gosub lights_off
        pause 1000
      next b10
      'exit
      'loop
init_int:
      setint 001000, 001000
      return
This is what I did:

- replaced labels and gotos with Do/Loop constructs. It is easier then to see where the execution path goes, and helps others to understand your code.
- put the setint into a tail-end part of the interrupt routine so it is not repeated code
- take sections that repeat and put them in subroutines, e.g. pause_hold, lights_off and the fade up/down sections (which don't seem very different from each other). I did the UP routine, you can do the down routine. By the way, I didn't grasp how they were supposed to fade, as the For/Next loops are the same. Did you mean (for Down) For on_time = 5000 to 0 step -10 ?
- I did a bit of indenting. It helps a lot if the two sides of each bracket (For:Next, Do:Loop, Select:endselect etc.) are aligned in the text. Though the indenting does not seem to work fully in this forum.
- there seemed to be a redundant do/loop in the interrupt service routine. It would always exit after one pass, so as it was always going to do that it seemed unnecessary
- changed the word symbol addresses to leave space for some bytes (that share the same address space) to avoid errors later


Things that you might still do:
- remove the bulk of the code from the interrupt routine. Whilst what you have will work, in general the interrupt routine should assess the situation, set flags, and exit asap, so as not to miss other interrupts. It is good practice to do this all the time. You could set a flag e.g. bit0 in the ISR and if that flag was set then the main program could call the routine to flash the lights (and reset the flag). That way, if the interrupt occurred mid-way through it could start again.
- rejig the pause_hold code - why not calculate the proper length rather than repeat something six times?
- make the up and down routines the same one, driven by a flag that you set that says up or down, much as I made the led name a variable.
- complete the changing of storage locations to variable names, e.g. b6, b8, and also the hardware e.g. pinC.3. Personally I use B_ as a prefix for bytes, HI_ for hardware inputs. There are other ideas just as good, the point being that when reading the code you always know what a name means and is capable of.
- what happens if b6 is 3?
- what are the labels for (BlueOn etc.)? You don't (shouldn't) jump there with gotos. Are they really comments?

Good luck with the project however you progress it!
 

Goeytex

Senior Member
Hi Rusty,

The fadeOff and fadeOn routines are identical except for the LED being faded and whether the LED Pin is high or low when the routine starts. If the LED is on (Pin is high) then the LED will fade off and a LOW is asserted at the end. If Low, then it will fade on and high asserted at the end.
Therefore only 1 Fade sub routine is needed with 2 variable passed to it. The code below exploits that and eliminates a lot of unnecessary lines.

Also I think you had the "blue off" out of sequence in the code you posted. When I originally wrote that fade routine, it assumed that the LED was already low when fading up and already high when fading down. So the way you have it the blue0ff will fade up and then abruptly go off since the LED was already low .

Code:
#picaxe 08m2
#no_data
setfreq m16

symbol Red =   0 [COLOR=#008000] 'Red LED strip assigned to pin 0[/COLOR]
symbol Green = 1 [COLOR=#008000] 'Green LED strip assigned to pin 1[/COLOR]
symbol Blue =  2 [COLOR=#008000] 'Blue LED strip assigned to pin 2[/COLOR]

symbol hold =     w0 [COLOR=#008000] 'Use W0 to hold the pause info[/COLOR]
symbol on_time =  w1
symbol off_time = w2
symbol Mode = b11
symbol LED = b12

setint 001000, 001000

MAIN:

   do
      readadc C.4,b6 'read the LDR value in to b6
      if b6 < 2 then
      gosub chase [COLOR=#008000] 'range 0 - 1 'if LDR is less than 2 then goto chase[/COLOR]
      else if b6 > 3 then  [COLOR=#008000]'if LDR is more than 3 then turn all lights off [/COLOR]
         Low Green    
         Low Red
         Low Blue
      endif  
     
    [COLOR=#008000] 'Note: An LDR value of 2 shgould return to main ??? ??????[/COLOR]
   loop  

CHASE:
'=======================================
hold = b8 * 10000  [COLOR=#008000] 'take the value stored in b8 from the interrupt sub routine and multiplies by 10k to give a puase time[/COLOR]
[COLOR=#008000]'Note: B8 will be zero until changed in interrupt routine[/COLOR]
[COLOR=#008000]'B8 Never seems to change past a value of 1... ???? [/COLOR]

Mode = 1
Gosub  Fade  [COLOR=#008000] 'Fade on[/COLOR]

Mode = 0
Gosub  Fade  [COLOR=#008000] 'Fade Off[/COLOR]

return


Fade:[COLOR=#008000] 'Fades On  if Mode = 1 [/COLOR]
       [COLOR=#008000] 'Fades OFF if Mode = 0 [/COLOR]
    
    For LED = Red to Blue [COLOR=#008000] '( 0 to 2,  RED,Green, Blue)[/COLOR]
       for on_time = 0 to 500 step 100
               pulsout LED, on_time
               off_time = 500 - on_time
               pauseus off_time
            next on_time
           if mode = 1 then
           high LED
           elseif mode = 0 then
           low LED :  endif
      next LED 
      gosub longpause 
    return

INTERRUPT:  [COLOR=#008000] 'pin C.3 is an external button that changes the pause time up to 7 modes. [/COLOR]
    if pinc.3 = 1 then
      do while pinc.3 = 1 : loop [COLOR=#008000] ' wait for release[/COLOR]
    b8 = b8 + 1 // 7 ' 0 to 6
    endif
    
   [COLOR=#008000] 'The following loop flashes all LEDs by the number that is stored in b8 above, 
    'this given a visual indication of what pause time is set, for example,
    '0 flahses = zero pause time (b8 = 0)
    '1 flash = 10,000 msec (b8 = 1)
    '2 flash = 20,000 msec (b8 = 2)
    'and so on[/COLOR]
    do
       for b10 = 1 to b8
         pause 1000
         high Red
         high Blue
         high Green
         pause 2000
        low Red
        low Blue
        low Green
        pause 1000
      next b10
    exit [COLOR=#008000]'  ?????????[/COLOR]
    loop
    
setint 001000, 001000   [COLOR=#008000] 'reinitialize interrupt[/COLOR]
return [COLOR=#008000] ' RETURNS TO main [/COLOR]

LONGPAUSE:    
    pause hold
   [COLOR=#008000] ;pause hold  'remarked out for  faster simulation
    ;pause hold
    ;pause hold
    ;pause hold
    ;pause hold[/COLOR]
return
You will need to change the on_time, off_time and step values back since I changed them for faster simulation

Bill
 

RustyH

Senior Member
Guys, will take a look at the revised code now, but just wanted to quickly say that I really appriciate the criticism as I know I am far from a good coder....I only started recently!!! :) so any pointers will as you say help me learn. So for that I really am grateful, thank you
 

RustyH

Senior Member
By the way, I would love to know Fotran!!! I do quite a bit of CFD software, and I want to integrate some CFD features in to a website......just a shame I wouldnt know where to start!! lol
 

geoff07

Senior Member
Software design and coding is an art and absolutely is not implementing wiring in software - done really well there is an elegance to it, analogous to, but quite different from, a really good pcb design! One way to think of a programming problem is in layers: a main program that describes the solution in a few high level subroutine calls. You can write this first. Then each called subroutine is written, in more detail, and with more calls, until at the bottom layer there are routines that listen to or influence the world outside via the hardware. As long as you know what your hardware is capable of, you can write a complex program entirely in the abstract, building down layer by layer, until you get to the hardware routines. That may be one or ten layers deep depending on how complex your problem is. I would write the hardware layer early on so I knew exactly what I was able to control. But the idea is to think in layers and implement them with meaningful names so the code can tell its story to a new reader, and keep the clutter away from the story.

In the old days, microcontrollers had little code space and every byte mattered, leading to some working but hard-to-follow code. These days an 08M2 can hold 2000 bytes of tokenised code, which removes all the constraints and allows room for elegant and clear code, which in previous incarnations would have had to be massively compressed.
 
Top