Ran out of memory Where can I compact code?

gengis

New Member
I've been reworking my pwm fan control a bit. I have a bit of ADC jitter when the fan is inside my computer - on the bench it works fine. So I added averaging to the thermistor input. While I'm at it I thought I could rework the alarms too.

What I want is the fan pwm control to work normally while an alarm is sounding and I want the alarm to sound no more than once every ten minutes - and alarm progressively as the temp continues to rise (alarm point one beeps the horn once, two twice, three thrice, etc..)

Could someone peruse my code and see how I can compact the code a bit to eliminate the 7 bytes over? I'm no software wizz so there's probably some obvious better way to do it.

Code:
'08M
'This should average the thermistor 60 times over the course of .6 seconds
'Then the pwm should continue normally while high temp alarms go off
'The high temp alarms should only alarm once every ten minutes 



'Error: Memory full - 7 bytes over. Reduce program length by 7 bytes 


symbol analogcontrol = 1    'This is the ADC input pin
symbol anaval = w1        'raw analog value
symbol anaavg = w2        'averaged analog value
symbol pwmport = 2        'pwm output on out#2
symbol buzzer = 4        'alarm buzzer output on out#4

goto runn

runn:    

    for b11=1 to 60                 'averages 60 readings of thermistor
         readadc10 analogcontrol ,anaval
      anaval = anaval + anaval
    pause 10
       Next
    anaavg = anaval / 60            'calculate average
   
    
    anaavg = anaavg *2            'massage values to something the fan can use
    anaavg = anaavg -790

    
    if anaavg <= 10 then alarmx        'sensor failure alarm (open)
    if anaavg>= 700 then alarmx        'sensor failure alarm (shorted)

    if anaavg <= 120 then stop1        'fan stops if temp too low

    pwmout pwmport, 100, anaavg        'on/off pwm ratio based on temperature

    if anaavg<= 415 then runn        'no alarms proceed normally

    pause 2350                    'necessary pause to limit alarms to every 10 minutes

    if anaavg>= 415 then  gosub setflag 

'    if anaavg>= 495 then alarm5        'temperature critical
    if anaavg>= 475 then alarm4
    if anaavg>= 455 then alarm3
    if anaavg>= 435 then alarm2    
    if anaavg>= 415 then alarm1        'temperature warm

    goto runn                

setflag:                        'increments a counter (b12)
    b12 = b12 + 1
    return

resetflag:                        'clears counter (b12)
    b12 = 0
    return

stop1:
    pwmout pwmport, 0, 0            'stops fan entirely when temperature is low
    goto runn
    

alarm1:
        
    if b12 <= 254 then runn            'alarm once every `10 minutes (or greater)
    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times        
    high buzzer                 'turn on buzzer for 1/3 second
    pause 300
    low buzzer                    'buzzer hi temp alarm
    goto runn



alarm2:

    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 2
    high buzzer         
    pause 200                    'turn on buzzer for 2/10 second
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn            


alarm3:

    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 3
    high buzzer                 'turn on buzzer for 2/10 second
    pause 200
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn

alarm4:

    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 4
    high buzzer                 'turn on buzzer for 2/10 second
    pause 200
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn

alarm5:

    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 5
    high buzzer                 'turn on buzzer for 2/10 second
    pause 200
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn





alarmx:
    pwmout pwmport, 0, 0    'stops pwm
    high pwmport        'sends DC voltage to fan (no pwm)
    high buzzer 
    pause 1000
    low buzzer            'buzzer sensor failure alarm
    pause 400
    low pwmport
    goto runn
 

Chavaquiah

Senior Member
4 changes:

1) Get rid of the first "goto runn"

2) Calc anaavg in a single command: anaval / 60 * 2 - 790

3) Those "if b12..." are used in all alarm conditions. Include them only once.

4) Include #no_end directive

Code:
#no_end
'08M
'This should average the thermistor 60 times over the course of .6 seconds
'Then the pwm should continue normally while high temp alarms go off
'The high temp alarms should only alarm once every ten minutes 



'Error: Memory full - 7 bytes over. Reduce program length by 7 bytes 


symbol analogcontrol = 1    'This is the ADC input pin
symbol anaval = w1        'raw analog value
symbol anaavg = w2        'averaged analog value
symbol pwmport = 2        'pwm output on out#2
symbol buzzer = 4        'alarm buzzer output on out#4

'goto runn

runn:    

    for b11=1 to 60                 'averages 60 readings of thermistor
         readadc10 analogcontrol ,anaval
      anaval = anaval + anaval
    pause 10
       Next
    anaavg = anaval / 60 * 2 -790            'calculate average
   
    
    'anaavg = anaavg *2            'massage values to something the fan can use
    'anaavg = anaavg -790

    
    if anaavg <= 10 then alarmx        'sensor failure alarm (open)
    if anaavg>= 700 then alarmx        'sensor failure alarm (shorted)

    if anaavg <= 120 then stop1        'fan stops if temp too low

    pwmout pwmport, 100, anaavg        'on/off pwm ratio based on temperature

    if anaavg<= 415 then runn        'no alarms proceed normally

    pause 2350                    'necessary pause to limit alarms to every 10 minutes

    if anaavg>= 415 then  gosub setflag 

'    if anaavg>= 495 then alarm5        'temperature critical
	 if anaavg>=415 then
	    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
   	 if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
	 endif
    if anaavg>= 475 then alarm4
    if anaavg>= 455 then alarm3
    if anaavg>= 435 then alarm2    
    if anaavg>= 415 then alarm1        'temperature warm

    goto runn                

setflag:                        'increments a counter (b12)
    b12 = b12 + 1
    return

resetflag:                        'clears counter (b12)
    b12 = 0
    return

stop1:
    pwmout pwmport, 0, 0            'stops fan entirely when temperature is low
    goto runn
    

alarm1:
        
'    if b12 <= 254 then runn            'alarm once every `10 minutes (or greater)
'    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times        
    high buzzer                 'turn on buzzer for 1/3 second
    pause 300
    low buzzer                    'buzzer hi temp alarm
    goto runn



alarm2:

'    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
'    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 2
    high buzzer         
    pause 200                    'turn on buzzer for 2/10 second
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn            


alarm3:

'    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
'    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 3
    high buzzer                 'turn on buzzer for 2/10 second
    pause 200
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn

alarm4:

'    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
'    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 4
    high buzzer                 'turn on buzzer for 2/10 second
    pause 200
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn

alarm5:

'    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
'    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
    for b13=1 to 5
    high buzzer                 'turn on buzzer for 2/10 second
    pause 200
    low buzzer                    'buzzer hi temp alarm
    pause 200
    next
    goto runn





alarmx:
    pwmout pwmport, 0, 0    'stops pwm
    high pwmport        'sends DC voltage to fan (no pwm)
    high buzzer 
    pause 1000
    low buzzer            'buzzer sensor failure alarm
    pause 400
    low pwmport
    goto runn
Edit:

I missed something...

5) Don't make unecessary tests:

Code:
'if anaavg>= 415 then
    'No need to test for > 415 again...
    gosub setflag 

	 if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
	 'endif
'    if anaavg>= 495 then alarm5        'temperature critical
    if anaavg>= 475 then alarm4
    if anaavg>= 455 then alarm3
    if anaavg>= 435 then alarm2    
    if anaavg>= 415 then alarm1        'temperature warm

    goto runn
 
Last edited:

MartinM57

Moderator
Remove the "goto runn" at the start - does nothing

Change
anaavg = anaval / 60
anaavg = anaavg *2
anaavg = anaavg -790
to
anaavg = anaavg / 60 * 2 -790

Change
if anaavg>= 415 then gosub setflag
to
if anaavg>= 415 then
inc b12
end if
...and delete
setflag: 'increments a counter (b12)
b12 = b12 + 1
return
...since you only use "setflag" once (at the moment)
...251 bytes - 5 spare.

But I can't for the life of me understand the code. It's called spaghetti code - it goes everywhere. A redesign in a more structured way would possibly bring this way down.

I'm also a bit dubious about some of your >=, <= tests missing out the = value - but as I can't understand the code I may be wrong
 

hippy

Ex-Staff (retired)
Replace -

for b13=1 to 2
high buzzer
pause 200
low buzzer
pause 200
next

with -

for b13 = 0 to 3
toggle buzzer
pause 200
next

Or better still, put all those in a subroutine, load b13 with an appropriate number and use -

b13 = 4
Gosub BeepBuzzer

BeepBuzzer:
Do
Toggle buzzer
Pause 200
b13 = b13 - 1
Loop While b13 <> 0
Return

Also take a look at your averaging routine, it doesn't !
 

gengis

New Member
Thanks Chavaquiah first two suggestions brings it to 255.

The rest?

How does your change allow alarm 5 to work? (what in the program is pointing it to alarm branch #5 for five beeps?)

I had the counter test only once, but somehow I convinced myself it had to be in each alarm branch - but I don't see how I thought it was necessary now - that little change saves ~50 bytes!

What do you mean by "4) Include #no_end directive"

Only downside an alarm condition must be present for 10 minutes before the first audible indication - but I couldn't see a way around that - and the temperature can only rise so fast, so its probably not important.

and thanks Martin I had no idea there was an "increment" command. And the spaghetti code - I'm in my 60's and learned on vacuum toobs, this is probably as good as it gets for me. (well we did have transistors then, but they cost more than tubes - valves to you)

I have the chip programmed and will swap it next time the computer is shut down.

Thanks again.

Hippy, thanks for the suggestions and where did I go wrong with the averaging?

Do I need another variable there? like: anaval2 = anaval2 + anaval '?
 

Andrew Cowan

Senior Member
for b11=1 to 60 'averages 60 readings of thermistor
readadc10 analogcontrol ,anaval
anaval = anaval + anaval
pause 10
Next
anaavg = anaval / 60 * 2 -790 'calculate average

Imagine that anaval is initially five. So the first time round, anaval will become ten. Then it will become double the next two readings. Then the next two... You need (as you guessed):

for b11=1 to 60 'averages 60 readings of thermistor
readadc10 analogcontrol ,anaval
anaval2 = anaval2 + anaval
pause 10
Next
anaavg = anaval2 / 60 * 2 -790 'calculate average


A
 

westaust55

Moderator
Right now would seem to be the time for Flooby to tidy up his program code in line wioth comments received thus far (including program structure/flow) and repost if further assistane is needed.

Further reduction may just be poossible even once below 255 bytes, though hippy usually propduces the most optimised code for space requirements.
 

MartinM57

Moderator
anaval2 = 0
for b11=1 to 60 'averages 60 readings of thermistor
readadc10 analogcontrol ,anaval
anaval2 = anaval2 + anaval
pause 10
Next
anaavg = anaval2 / 60 * 2 -790 'calculate average

...would be even better, otherwise anaval2 will just get bigger and bigger and bigger and bigger and...
 

Andrew Cowan

Senior Member
Well spotted Martin - that's not the first time I've missed thta out, either ;).

Make sure you use a word variable for anaval2.

A
 

Dippy

Moderator
Flooby,
have a look to see how you can use 'else' . As mentioned above there is no point doing multiple tests, it wastes time if not programme space.

And things like:
Code:
    if b12 <= 254 then runn            'the alarm once every `10 minutes (or greater)
    if b12 >= 254 then gosub resetflag    '2350 ms pause multiplied by 254 times
are inefficient. A simple 'else' used will save a couple of bytes.

Why waste lines in maths?
You have:
Code:
    anaavg = anaval / 60            'calculate average
 
 
    anaavg = anaavg *2            'massage values to something the fan can use
why not just

Code:
 anaavg = anaval / 30            'calculate average


I think if you sit down with it in front of you then you will find for yourself a few unneccesary bits which will improve speed and space.
As this is your 'baby' you should find it easier than 3rd parties to see where you can chop and change.
 

ckoehn

Member
You need something like this. When you use a section of code more than once, I like to make it a sub.

Code:
'08M
'This should average the thermistor 60 times over the course of .6 seconds
'Then the pwm should continue normally while high temp alarms go off
'The high temp alarms should only alarm once every ten minutes 



'171 bytes out of 256 


symbol analogcontrol = 1    'This is the ADC input pin
symbol anaval = w1        'raw analog value
symbol anaavg = w2        'averaged analog value
symbol pwmport = 2        'pwm output on out#2
symbol buzzer = 4        'alarm buzzer output on out#4
symbol alarm_rings=b0	 'number of alarm rings

runn:    
    anaavg=0
    for b11=1 to 60                 'averages 60 readings of thermistor
         readadc10 analogcontrol ,anaval
         anaavg = anaavg + anaval
         pause 10
    Next
    anaavg = anaavg / 30-790            'calculate average
   						    'massage values to something the fan can use

    
    if anaavg <= 10 or anaavg>=700 then alarmx        'sensor failure alarm (open)
    								      'sensor failure alarm (shorted)
    if anaavg <= 120 then stop1        'fan stops if temp too low

    pwmout pwmport, 100, anaavg        'on/off pwm ratio based on temperature

    if anaavg<= 415 then runn        'no alarms proceed normally

    pause 2350                    'necessary pause to limit alarms to every 10 minutes

    if anaavg>= 415 then  gosub setflag 

    if anaavg>= 495 then
    	alarm_rings=5        'temperature critical
    elseif anaavg>= 475 then
    	alarm_rings=4
    elseif anaavg>= 455 then
    	alarm_rings=3
    elseif anaavg>= 435 then
    	alarm_rings=2    
    elseif anaavg>= 415 then
    	alarm_rings=1        'temperature warm
    else
    	goto runn
    endif
    
    gosub SoundAlarm
    
    goto runn                

setflag:                        'increments a counter (b12)
    b12 = b12 + 1
    return

resetflag:                        'clears counter (b12)
    b12 = 0
    return

stop1:
    pwmout pwmport, 0, 0            'stops fan entirely when temperature is low
    goto runn
    

SoundAlarm:

    if b12 >= 254 then
      gosub resetflag    '2350 ms pause multiplied by 254 times
    	for b13=1 to alarm_rings
	    high buzzer         
	    pause 200                    'turn on buzzer for 2/10 second
	    low buzzer                    'buzzer hi temp alarm
	    pause 200
    	next
    endif
    return            

alarmx:
    pwmout pwmport, 0, 0    'stops pwm
    high pwmport        'sends DC voltage to fan (no pwm)
    high buzzer 
    pause 1000
    low buzzer            'buzzer sensor failure alarm
    pause 400
    low pwmport
    goto runn
 

gengis

New Member
Thanks ckoehn

Almost works the way I want it to. I only had to make one minor change to get it alarming once in ten minutes.
 

gengis

New Member
28 replies, but I can't see more than 14 of them?


What gives?

Oh, don't bother, it would just be another reply I can't see.
 
Top