Help reducing program size

Hi,
I've built a simple temperature controller that compares two temperatures and switches a relay if the difference between the two is greater than an amount set by reading an analogue input.

Problem is the program is a little too large for a 14M, any ideas how I can improve it to be more efficient?
 

Attachments

eclectic

Moderator
Hi,
I've built a simple temperature controller that compares two temperatures and switches a relay if the difference between the two is greater than an amount set by reading an analogue input.

Problem is the program is a little too large for a 14M, any ideas how I can improve it to be more efficient?
Could you re-post please , using the
[ code / code tags

(See Sticky Readme First)

Otherwise, people have to
1. Download the file.
2. Save the file.
3. Open Programming Editor
4. Load the file.
5. View the file.

e
 

SilentScreamer

Senior Member
My slightly improved version - 107 bytes over

Code:
#PICAXE 14M
symbol Ta = b0
symbol Tb = b1
symbol DT = b2
symbol DT_setpoint = b3
symbol relaypin = 2
symbol LCDpin = 1
symbol manual_on_pin = pin4
symbol manual_off_pin = pin3
symbol DS18B20_a_pin = 2
symbol DS18B20_b_pin = 1
symbol adc_pin = 0
symbol baud = N2400


serout LCDpin,baud,(254,1)
pause 30

main:

'readadc 0,Ta		'note remember to remove these before downloading to Pic
'readadc 1,Tb


'read DT_setpoint
readadc adc_pin,DT_setpoint
DT_setpoint = DT_setpoint/10

'check if manual overide is active
if manual_on_pin = 1 then manual_on
if manual_off_pin = 1 then manual_off

'Check temp sensor A and B
readtemp DS18B20_a_pin,Ta
readtemp DS18B20_b_pin,Tb 					
if TA > 127 then neg_A 	
if Tb > 127 then neg_B 				
serout LCDpin,baud,(254,128,"A=",#Ta,223,"C  B=",#Tb,223,"C ")				

'Compare readings
if Tb>Ta then 
goto calcdif 
else goto manual_on:				
endif

manual_on:
high relaypin
serout LCDpin,baud,(254,135,"A=",#Ta,223,"C  B=",#Tb,223,"C ")
gosub serout_man
gosub serout_on
goto main

manual_off:
low relaypin
gosub serout_man
gosub serout_off
serout LCDpin,baud,(254,192,"Set DT=",#DT_setpoint,223,"C","      ")
goto main

Tb_less_than_Ta:
serout LCDpin,baud,(254,192,"B<A     Fan off")
goto Fan_off

calcdif:
let DT=Tb-Ta
serout LCDpin,baud,(254,192,"DT=",#DT,223,"C  ")
if DT > DT_setpoint then 
goto Fan_on
else goto Fan_off
endif

Fan_on:
high relaypin
gosub serout_on
goto main

Fan_off:
low relaypin
gosub serout_off
goto main

neg_B:
let Tb = Tb - 128 					
serout LCDpin,baud,(254,128,"B=-",#Tb,223,"C ")
serout LCDpin,baud,(254,192,"- temp  ")
goto Fan_off
	
neg_A:
let Ta = Ta - 128 					
serout LCDpin,baud,(254,135,"A=-",#TA,223,"C  ",254,192,"- temp  ") 
goto Fan_off

serout_man:
	serout LCDpin,baud,(254,128,"Manual")
	return

serout_on:
	serout LCDpin,baud,(254,128,"Fan on ")
	return

serout_off:
	serout LCDpin,baud,(254,128,"Fan off")
	return
Original - 126 bytes over

Code:
symbol Ta = b0
symbol Tb = b1
symbol DT = b2
symbol DT_setpoint = b3
symbol relaypin = 2
symbol LCDpin = 1
symbol manual_on_pin = pin4
symbol manual_off_pin = pin3
symbol DS18B20_a_pin = 2
symbol DS18B20_b_pin = 1
symbol adc_pin = 0
symbol baud = N2400


serout LCDpin,baud,(254,1)
pause 30

main:

'readadc 0,Ta		'note remember to remove these before downloading to Pic
'readadc 1,Tb


'read DT_setpoint
readadc adc_pin,DT_setpoint
DT_setpoint = DT_setpoint/10

'check if manual overide is active
if manual_on_pin = 1 then manual_on
if manual_off_pin = 1 then manual_off

'Check temp sensor A and B
readtemp DS18B20_a_pin,Ta
readtemp DS18B20_b_pin,Tb 					
if TA > 127 then neg_A 	
if Tb > 127 then neg_B 				
serout LCDpin,baud,(254,128,"A=",#Ta,223,"C  B=",#Tb,223,"C ")				

'Compare readings
if Tb>Ta then 
goto calcdif 
else goto manual_on:				
endif

manual_on:
high relaypin
serout LCDpin,baud,(254,135,"A=",#Ta,223,"C  B=",#Tb,223,"C ")
serout LCDpin,baud,(254,192,"Manual  Fan on   ")
goto main

manual_off:
low relaypin
serout LCDpin,baud,(254,128,"Manual Fan off")
serout LCDpin,baud,(254,192,"Set DT=",#DT_setpoint,223,"C","      ")
goto main

Tb_less_than_Ta:
serout LCDpin,baud,(254,192,"B<A     Fan off")
goto Fan_off

calcdif:
let DT=Tb-Ta
serout LCDpin,baud,(254,192,"DT=",#DT,223,"C  ")
if DT > DT_setpoint then 
goto Fan_on
else goto Fan_off
endif

Fan_on:
high relaypin
serout LCDpin,baud,(254,200,"Fan on ")
goto main

Fan_off:
low relaypin
serout LCDpin,baud,(254,200,"Fan off")
goto main

neg_B:
let Tb = Tb - 128 					
serout LCDpin,baud,(254,128,"B=-",#Tb,223,"C ")
serout LCDpin,baud,(254,192,"- temp  ")
goto Fan_off
	
neg_A:
let Ta = Ta - 128 					
serout LCDpin,baud,(254,135,"A=-",#TA,223,"C  ",254,192,"- temp  ") 
goto Fan_off
 

SilentScreamer

Senior Member
Why does it use 135 rather than 128 in this line? "serout LCDpin,baud,(254,135,"A=",#Ta,223,"C B=",#Tb,223,"C ")"

I've got it down to 81 bytes over now, you're problem is you are using a LOT of serout commands which are very space hungry.

EDIT: Can you remove all the extra spaces at the ends of the serout commands? It saves 28 bytes.
 
Last edited:

Jeremy Leach

Senior Member
The most code-hungry parts of your code are all the separate Serout statements, so you need to reduce these as much as possible. Remember that every character you type into a serout command will take up code space. Look for any common messages or even redesign your messages so parts of them ARE common. Or just simplify your system so it doesn't need so many messages?

Another technique I've used is to have a 'display buffer' in RAM or EEPROM and modify the bytes in this, then have a single Serout routine that 'refreshes' the real display by dumping the bytes in the buffer to the LCD. This can save code space sometimes - but it all depends !
 

SilentScreamer

Senior Member
Without modifying the function of the code I can't do any better than this, I'm sure someone can improve it further but I'd be amazed if they get it down enough without modifying its function.

Code:
#PICAXE 14M
symbol Ta = b0
symbol Tb = b1
symbol DT = b2
symbol DT_setpoint = b3
symbol relaypin = 2
symbol LCDpin = 1
symbol manual_on_pin = pin4
symbol manual_off_pin = pin3
symbol DS18B20_a_pin = 2
symbol DS18B20_b_pin = 1
symbol adc_pin = 0
symbol baud = N2400
symbol position = b3


serout LCDpin,baud,(254,1)
pause 30

main:

'readadc 0,Ta		'note remember to remove these before downloading to Pic
'readadc 1,Tb


'read DT_setpoint
readadc adc_pin,DT_setpoint
DT_setpoint = DT_setpoint/10

'check if manual overide is active
if manual_on_pin = 1 then manual_on
if manual_off_pin = 1 then manual_off

'Check temp sensor A and B
readtemp DS18B20_a_pin,Ta
readtemp DS18B20_b_pin,Tb 					
if TA > 127 then neg_A 	
if Tb > 127 then neg_B 		
position = 128
gosub serout_letter						

'Compare readings
if Tb>Ta then calcdif

manual_on:
high relaypin
position = 135
gosub serout_letter
gosub serout_man
gosub serout_on
goto main

manual_off:
low relaypin
gosub serout_man
gosub serout_off
serout LCDpin,baud,(254,192,"Set DT=",#DT_setpoint,223,"C","      ")
goto main

Tb_less_than_Ta:
serout LCDpin,baud,(254,192,"B<A     ")
gosub serout_off
goto Fan_off

calcdif:
let DT=Tb-Ta
serout LCDpin,baud,(254,192,"DT=",#DT,223,"C  ")
if DT > DT_setpoint then 
goto Fan_on
else goto Fan_off
endif

Fan_on:
high relaypin
gosub serout_on
goto main

Fan_off:
low relaypin
gosub serout_off
goto main

neg_B:
let Tb = Tb - 128 					
serout LCDpin,baud,(254,128,"B=-",#Tb,223,"C ")
serout LCDpin,baud,(254,192,"- temp  ")
goto Fan_off
	
neg_A:
let Ta = Ta - 128 					
serout LCDpin,baud,(254,135,"A=-",#TA,223,"C  ",254,192,"- temp  ") 
goto Fan_off

serout_man:
	serout LCDpin,baud,(254,128,"Manual")
	return

serout_on:
	serout LCDpin,baud,(254,128,"Fan on ")
	return

serout_off:
	serout LCDpin,baud,(254,128,"Fan off")
	return

serout_letter:
	serout LCDpin,baud,(254,position,"A=",#Ta,223,"C  B=",#Tb,223,"C ")
	return
How did I do it? You can skip this if you like but it might prove helpful for if you have to do it again. The main thing I did was look for common serout text and I moved them into sub routines. These are access by gosub and when the return command is used it goes back to the original location of the program (the line below the line with the gosub command in it). Look in manual two for a better explanation if you want. Also look how I've added the position variable, can you work out what it is used for?

As stated in the above post other techniques can be used such as storing on the LCD Firmware chip but the easiest is to just remove some characters. As a rough estimate 1 character = 1 byte from my experience.

I've just checked, even with my optimised code the serout commands are 214 bytes even when placed on there own. Making it just about impossible (I daren't say its fully impossible, I've seen wonders done by hippy).

EDIT: I hadn't thought of using variables for individual letters, very clever Ibenson.
 
Last edited:

lbenson

Senior Member
As people have said, serout is the big culprit. As an example of compression, the first bit of code following takes 47 bytes, and the second takes 39. Similar imaginative condensation may squeeze everything in. Shorten the messages as much as possible. Put varying codes into variables and call one subroutine to serout instead of one per message.

Code:
' Memory used = 47 bytes out of 256
symbol LCDpin = 1
symbol baud = N2400

main:
  gosub serout_on
  gosub serout_off
  end
  
serout_on:
	serout LCDpin,baud,(254,128,"Fan on ")
	return

serout_off:
	serout LCDpin,baud,(254,128,"Fan off")
	return
Code:
' Memory used = 39 bytes out of 256
symbol LCDpin = 1
symbol baud = N2400

main:
  b12 = "n"
  b13 = " "
  gosub serout_on_off
  b12 = "f"
  b13 = "f"
  gosub serout_on_off
  end
  
serout_on_off:
	serout LCDpin,baud,(254,128,"Fan o",b12,b13)
	return
 
Thanks for all these ideas, a lot of food for thought and I've learnt a few things. I will probably change the function of the program slightly to reduce the size enough.
 

Dippy

Moderator
Suggest you consider the lines of J's thoughts.

If you use RAM like an array you can keep the number of Serout commands down.

Also, can you...

Instead of saying "Fan On " and "Fan Off" , can't you leave out the second "Fan" and just overwrite changes?
Many moons ago I had to make trivial changes like that to get things to fit onto a Stamp2.

Have a play and look to deleting duplication. Use subs where you can.
Wouldn't it be nice just to build your message into a byte string and just have one Serout subroutine...
 

vttom

Senior Member
Well, I made some improvements by simply re-arranging the code and getting rid of lots of gotos.

But while I was doing that, I discovered that the code snippet labelled "Tb_less_than_Ta" was a section of the code that would never be reached the way it was originally written. I relocated it to where it looks like it wanted to go.

Code:
#PICAXE 14M
symbol Ta = b0
symbol Tb = b1
symbol DT = b2
symbol DT_setpoint = b3
symbol relaypin = 2
symbol LCDpin = 1
symbol manual_on_pin = pin4
symbol manual_off_pin = pin3
symbol DS18B20_a_pin = 2
symbol DS18B20_b_pin = 1
symbol adc_pin = 0
symbol baud = N2400


serout LCDpin,baud,(254,1)
pause 30

main:

'readadc 0,Ta		'note remember to remove these before downloading to Pic
'readadc 1,Tb


'read DT_setpoint
readadc adc_pin,DT_setpoint
DT_setpoint = DT_setpoint/10

'check if manual overide is active
if manual_on_pin = 1 then manual_on
if manual_off_pin = 1 then manual_off

'Check temp sensor A and B
readtemp DS18B20_a_pin,Ta
readtemp DS18B20_b_pin,Tb 					

if Ta > 127 then
  let Ta = Ta - 128 					
  serout LCDpin,baud,(254,135,"A=-",#Ta,223,"C  ",254,192,"- temp  ") 
  goto Fan_off
end if

if Tb > 127 then			
  let Tb = Tb - 128 					
  serout LCDpin,baud,(254,128,"B=-",#Tb,223,"C  ",254,192,"- temp  ")
  goto Fan_off
end if

serout LCDpin,baud,(254,128,"A=",#Ta,223,"C  B=",#Tb,223,"C ")				

'Compare readings
if Tb>Ta then 
  let DT=Tb-Ta
  serout LCDpin,baud,(254,192,"DT=",#DT,223,"C  ")
  if DT > DT_setpoint then Fan_on
  goto Fan_off
end if

Tb_less_than_Ta:
serout LCDpin,baud,(254,192,"B<A     Fan off")
goto Fan_off

manual_on:
serout LCDpin,baud,(254,135,"A=",#Ta,223,"C  B=",#Tb,223,"C ")
gosub serout_man

Fan_on:
high relaypin
serout LCDpin,baud,(254,128,"Fan on")
goto main


manual_off:
serout LCDpin,baud,(254,192,"Set DT=",#DT_setpoint,223,"C","      ")
gosub serout_man

Fan_off:
low relaypin
serout LCDpin,baud,(254,128,"Fan off")
goto main


serout_man:
serout LCDpin,baud,(254,128,"Manual")
return
This got me down to 71 bytes over, without any serout optimizations.
 

kevrus

New Member
I had a quick look...some of the serout display lines seemed to clash a bit so I changed it a little
Code:
#PICAXE 14m 
symbol Ta = b0
symbol Tb = b1
symbol DT = b2
symbol DT_setpoint = b3
symbol relaypin = 2
symbol LCDpin = 1
symbol manual_on_pin = pin4
symbol manual_off_pin = pin3
symbol DS18B20_a_pin = 2
symbol DS18B20_b_pin = 1
symbol adc_pin = 0
symbol baud = N2400


serout LCDpin,baud,(254,1)
pause 30

main:

'readadc 0,Ta		'note remember to remove these before downloading to Pic
'readadc 1,Tb


'read DT_setpoint
readadc adc_pin,DT_setpoint
DT_setpoint = DT_setpoint/10

'check if manual overide is active
if manual_on_pin = 1 then manual_on
if manual_off_pin = 1 then manual_off

'Check temp sensor A and B
readtemp DS18B20_a_pin,Ta
readtemp DS18B20_b_pin,Tb 					

if Ta > 127 then let Ta = Ta - 128
if Tb > 127 then let Tb = Tb - 128 					
 serout LCDpin,baud,(254,128,"A=-",#Ta,223,"C  B=-",#Tb,223,"C ",254,192,"- temp ") 
  goto Fan_off
  end if
  else
gosub display_temp				
end if


'Compare readings
if Tb>Ta then 
  let DT=Tb-Ta
  serout LCDpin,baud,(254,192,"DT=",#DT)
  if DT > DT_setpoint then Fan_on
else serout LCDpin,baud,(254,192,"B<A    Fan off") 
  goto Fan_off
end if



manual_on:
gosub manual


Fan_on:
high relaypin
serout LCDpin,baud,(254,199,"Fan on ")
goto main


manual_off:
gosub manual

Fan_off:
low relaypin
serout LCDpin,baud,(254,199,"Fan off")
goto main


manual:
serout LCDpin,baud,(254,192,"Manual")
return

display_temp:
serout LCDpin,baud,(254,128,"A=",#Ta,223,"C  B=",#Tb,223,"C ")
return
This is now 13 bytes under...try and see if it does what you want
 
Top