Making a program more compact?
So I've written a simple program to measure temperatures using DS18S20 chips. It works fine but I'm trying to compact the code.
Its pretty straightforward; each sensor is read 16 times and the results are averaged. This gives better accuracy at each sensor with a small cost in variable space (1 word, 1 nib, 1 bit) over non-averaged readings.
I'm not so hot at PBASIC, and it seems fairly ugly to have 4 almost-identical subroutines called ChekTemp1,CheckTemp2,CheckTemp3,CheckTemp4... but I can't figure out a way to put them into a loop since the 1-wire addresses would then (I think) have to be put into variables which would chew all my space up.
Its pretty straightforward; each sensor is read 16 times and the results are averaged. This gives better accuracy at each sensor with a small cost in variable space (1 word, 1 nib, 1 bit) over non-averaged readings.
I'm not so hot at PBASIC, and it seems fairly ugly to have 4 almost-identical subroutines called ChekTemp1,CheckTemp2,CheckTemp3,CheckTemp4... but I can't figure out a way to put them into a loop since the 1-wire addresses would then (I think) have to be put into variables which would chew all my space up.
' -----[noparse][[/noparse] Directives ]-----------------------------------------
'
' {$STAMP BS2pe} 'specifies a BS2pe
' {$PBASIC 2.5}
'
' -----[noparse][[/noparse] Constants ]------------------------------------------
'
OWpin CON 0 '1-wire device pin
OWFERst CON %0001 'Front-End Reset
OWBERst CON %0010 'Back-End reset
OWBitMode CON %0100
SkipROM CON $CC 'Skip ROM Command
ReadROM CON $33 'Read one ID (if only one device on line)
MatchROM CON $55 ' look for specific device
SearchROM CON $F0 'Read all IDs
ReadScratch CON $BE 'Read Scratch Pad
ConverT CON $44 'Convert Temperature
MeasurementsToAverage CON 16
' -----[noparse][[/noparse] Variables ]------------------------------------------
'
TempRaw VAR Word 'Stores either a raw temperature reading or a fractional adjustment
TempRawSign VAR TempRaw.BIT15
TempFirst VAR Word 'Stores the first temperature reading on a sensor for averaging with following readings
CRem VAR Byte 'Counts remaining value
CPerC VAR Byte 'Counts per degree C value
TempSensor1 VAR Word 'Temperature Value
TempSensor2 VAR Word 'Temperature Value
TempSensor3 VAR Word 'Temperature Value
TempSensor4 VAR Word 'Temperature Value
MeasurementCounter VAR Nib
Sign VAR Bit
' ------------------[noparse][[/noparse] ID codes for connected sensors ]-----------------------
Sensor1A CON $10 'Sensor1 will be the reference standard sensor
Sensor1B CON $C5
Sensor1C CON $8F
Sensor1D CON $B8
Sensor1E CON $01
Sensor1F CON $08
Sensor1G CON $00
Sensor1H CON $7B
Sensor2A CON $10
Sensor2B CON $96
Sensor2C CON $C2
Sensor2D CON $B8
Sensor2E CON $01
Sensor2F CON $08
Sensor2G CON $00
Sensor2H CON $09
Sensor3A CON $10
Sensor3B CON $93
Sensor3C CON $50
Sensor3D CON $B8
Sensor3E CON $01
Sensor3F CON $08
Sensor3G CON $00
Sensor3H CON $D6
Sensor4A CON $10
Sensor4B CON $76
Sensor4C CON $96
Sensor4D CON $B8
Sensor4E CON $01
Sensor4F CON $08
Sensor4G CON $00
Sensor4H CON $AA
' -----[noparse][[/noparse] Initialization ]-------------------------------------
'
Setup:
PAUSE 1000 'open debug window
Main:
GOSUB CheckTemp1
GOSUB CheckTemp2
GOSUB CheckTemp3
GOSUB CheckTemp4
DEBUG CR, "1: ", DEC TempSensor1/10, ".", DEC1 TempSensor1-(TempSensor1/10*100), "F"
DEBUG " 2: ", DEC TempSensor2/10, ".", DEC1 TempSensor2-(TempSensor2/10*100), "F"
DEBUG " 3: ", DEC TempSensor3/10, ".", DEC1 TempSensor3-(TempSensor3/10*100), "F"
DEBUG " 4: ", DEC TempSensor4/10, ".", DEC1 TempSensor4-(TempSensor4/10*100), "F"
GOTO Main
END
CheckTemp1:
FOR MeasurementCounter = 0 TO (MeasurementsToAverage-1) STEP 1
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor1A,Sensor1B,Sensor1C,Sensor1D,Sensor1E,Sensor1F,Sensor1G,Sensor1H,ConverT]
GOSUB PauseToConverT
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor1A,Sensor1B,Sensor1C,Sensor1D,Sensor1E,Sensor1F,Sensor1G,Sensor1H,ReadScratch]
GOSUB GetFullTemp
IF MeasurementCounter =0 THEN
TempSensor1 = TempRaw
TempFirst = TempRaw
ELSE
GOSUB CalculateTempAdjustment
TempSensor1 = TempSensor1 + TempRaw
ENDIF
NEXT
RETURN
CheckTemp2:
FOR MeasurementCounter = 0 TO (MeasurementsToAverage-1) STEP 1
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor2A,Sensor2B,Sensor2C,Sensor2D,Sensor2E,Sensor2F,Sensor2G,Sensor2H,ConverT]
GOSUB PauseToConverT
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor2A,Sensor2B,Sensor2C,Sensor2D,Sensor2E,Sensor2F,Sensor2G,Sensor2H,ReadScratch]
GOSUB GetFullTemp
IF MeasurementCounter =0 THEN
TempSensor2 = TempRaw
TempFirst = TempRaw
ELSE
GOSUB CalculateTempAdjustment
TempSensor2 = TempSensor2 + TempRaw
ENDIF
NEXT
RETURN
CheckTemp3:
FOR MeasurementCounter = 0 TO (MeasurementsToAverage-1) STEP 1
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor3A,Sensor3B,Sensor3C,Sensor3D,Sensor3E,Sensor3F,Sensor3G,Sensor3H,ConverT]
GOSUB PauseToConverT
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor3A,Sensor3B,Sensor3C,Sensor3D,Sensor3E,Sensor3F,Sensor3G,Sensor3H,ReadScratch]
GOSUB GetFullTemp
IF MeasurementCounter =0 THEN
TempSensor3 = TempRaw
TempFirst = TempRaw
ELSE
GOSUB CalculateTempAdjustment
TempSensor3 = TempSensor3 + TempRaw
ENDIF
NEXT
RETURN
CheckTemp4:
FOR MeasurementCounter = 0 TO (MeasurementsToAverage-1) STEP 1
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor4A,Sensor4B,Sensor4C,Sensor4D,Sensor4E,Sensor4F,Sensor4G,Sensor4H,ConverT]
GOSUB PauseToConverT
OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,Sensor4A,Sensor4B,Sensor4C,Sensor4D,Sensor4E,Sensor4F,Sensor4G,Sensor4H,ReadScratch]
GOSUB GetFullTemp
IF MeasurementCounter =0 THEN
TempSensor4 = TempRaw
TempFirst = TempRaw
ELSE
GOSUB CalculateTempAdjustment
TempSensor4 = TempSensor4 + TempRaw
ENDIF
NEXT
RETURN
CalculateTempAdjustment:
'Its OK to use TempRaw as a place to store a small adjustment now, since we stored the initial reading.
Sign = TempRawSign
TempRaw = (ABS(TempFirst-TempRaw)/ MeasurementsToAverage)
IF (Sign=1) THEN TempRaw = -TempRaw
RETURN
PauseToConverT:
PAUSE 750
RETURN
GetFullTemp:
OWIN OWpin, OWBERst, [noparse][[/noparse]TempRaw.LOWBYTE,TempRaw.HIGHBYTE,CRem,CRem,CRem,CRem,CRem,CPerC]
TempRaw = (TempRaw>>1*100-25+((CPerC*100-(CRem*100))/CPerC))* 9 / 50 + 320
RETURN

Comments
Program size is cut by 50%, and the number of sensors I can monitor goes way way up.
Thank you Mike, if you have any other suggestions let me know.
' -----[noparse][[/noparse] Directives ]----------------------------------------- ' ' {$STAMP BS2pe} 'specifies a BS2pe ' {$PBASIC 2.5} ' ' -----[noparse][[/noparse] Constants ]------------------------------------------ ' OWpin CON 0 '1-wire device pin OWFERst CON %0001 'Front-End Reset OWBERst CON %0010 'Back-End reset OWBitMode CON %0100 SkipROM CON $CC 'Skip ROM Command ReadROM CON $33 'Read one ID (if only one device on line) MatchROM CON $55 ' look for specific device SearchROM CON $F0 'Read all IDs ReadScratch CON $BE 'Read Scratch Pad ConverT CON $44 'Convert Temperature MeasurementsToAverage CON 16 ' -----[noparse][[/noparse] Variables ]------------------------------------------ ' TempRaw VAR Word 'Stores either a raw temperature reading or a fractional adjustment TempRawSign VAR TempRaw.BIT15 TempFirst VAR Word 'Stores the first temperature reading on a sensor for averaging with following readings Temp1 VAR Word 'Used to store result of temperature reading, or, later, to compare with Temp2 Temp2 VAR Word 'For comparing with Temp1 CRem VAR Byte 'Counts remaining value CPerC VAR Byte 'Counts per degree C value SensorAddress0 VAR Byte SensorAddress1 VAR Byte SensorAddress2 VAR Byte SensorAddress3 VAR Byte SensorAddress4 VAR Byte SensorAddress5 VAR Byte SensorAddress6 VAR Byte SensorAddress7 VAR Byte SensorCounter VAR Nib MeasurementCounter VAR Nib Sign VAR Bit ' -----[noparse][[/noparse] Initialization ]------------------------------------- ' DATA $10,$C5,$8F,$B8,$01,$08,$00,$7B 'Sensor0 Address, starts at 0 DATA $10,$96,$C2,$B8,$01,$08,$00,$09 'Sensor1 Address, starts at 8 DATA $10,$93,$50,$B8,$01,$08,$00,$D6 'Sensor2 Address, starts at 16 DATA $10,$76,$96,$B8,$01,$08,$00,$AA 'Sensor3 Address, starts at 24 Setup: PAUSE 1000 'open debug window Main: FOR SensorCounter = 0 TO 3 STEP 1 READ (SensorCounter*8) , SensorAddress0 READ (SensorCounter*8)+1, SensorAddress1 READ (SensorCounter*8)+2, SensorAddress2 READ (SensorCounter*8)+3, SensorAddress3 READ (SensorCounter*8)+4, SensorAddress4 READ (SensorCounter*8)+5, SensorAddress5 READ (SensorCounter*8)+6, SensorAddress6 READ (SensorCounter*8)+7, SensorAddress7 GOSUB CheckTemp PUT (SensorCounter*2), Word Temp1 NEXT DEBUG CR FOR SensorCounter = 0 TO 3 STEP 1 GET (SensorCounter*2), Word Temp1 DEBUG DEC sensorcounter, ": ", DEC Temp1/10, ".", DEC1 Temp1-(Temp1/10*100), "F " NEXT GOTO Main END CheckTemp: FOR MeasurementCounter = 0 TO (MeasurementsToAverage-1) STEP 1 OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,SensorAddress0,SensorAddress1,SensorAddress2,SensorAddress3,SensorAddress4,SensorAddress5,SensorAddress6,SensorAddress7,ConverT] PAUSE 750 OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,SensorAddress0,SensorAddress1,SensorAddress2,SensorAddress3,SensorAddress4,SensorAddress5,SensorAddress6,SensorAddress7,ReadScratch] OWIN OWpin, OWBERst, [noparse][[/noparse]TempRaw.LOWBYTE,TempRaw.HIGHBYTE,CRem,CRem,CRem,CRem,CRem,CPerC] TempRaw = (TempRaw>>1*100-25+((CPerC*100-(CRem*100))/CPerC))* 9 / 50 + 320 IF MeasurementCounter =0 THEN Temp1 = TempRaw TempFirst = TempRaw ELSE 'Its OK to use TempRaw as a place to store a small adjustment now, since we stored the initial reading. Sign = TempRawSign TempRaw = (ABS(TempFirst-TempRaw)/ MeasurementsToAverage) IF (Sign=1) THEN TempRaw = -TempRaw Temp1 = Temp1 + TempRaw ENDIF NEXT RETURNYou could use a byte array for the sensor address. This would let you read the bytes of the sensor address from EEPROM using a loop rather than 8 READ statements. You'd declare "SensorAddress VAR Byte(8)", then do
FOR i = 0 to 7
READ (SensorCounter*8)+i, SensorAddress(i)
NEXT
In your OWOUT statements, you would put
OWOUT OWpin,OWFERst,[noparse][[/noparse] MatchROM, SensorAddress\8, ConverT ]
There are ways to compress your sensor address table. For example, all of your sensor addresses have what seem to be fixed bytes like $10, $xx, $xx, $B8, $01, $08, $00, $xx. The only bytes you really need to store in your table are the $xx ones.
Post Edited (Mike Green) : 3/21/2009 6:41:37 PM GMT
but instead had to use
When I tried to use the \8, the editor told me it was expecting an ]. Must have something to do with it being inside the brackets of the OWOUT statement. Is there a workaround for this?
Thanks for the advice Mike, I've never bothered to learn how to use EEPROM, ScratchPad, or arrays so this has opened up tons of new doors for me.
' -----[noparse][[/noparse] Directives ]----------------------------------------- ' ' {$STAMP BS2pe} 'specifies a BS2pe ' {$PBASIC 2.5} ' ' -----[noparse][[/noparse] Constants ]------------------------------------------ ' OWpin CON 0 '1-wire device pin OWFERst CON %0001 'Front-End Reset OWBERst CON %0010 'Back-End reset OWBitMode CON %0100 SkipROM CON $CC 'Skip ROM Command ReadROM CON $33 'Read one ID (if only one device on line) MatchROM CON $55 ' look for specific device SearchROM CON $F0 'Read all IDs ReadScratch CON $BE 'Read Scratch Pad ConverT CON $44 'Convert Temperature NumMeasurements CON 16 NumberOfSensors CON 4 ' -----[noparse][[/noparse] Variables ]------------------------------------------ ' Temp1 VAR Word TempThisReading VAR Temp1 'Stores a raw temperature reading TempAdjustment VAR Temp1 'Stores a temperature adjustment TempAdjSign VAR TempAdjustment.BIT15 Temp2 VAR Word TempFirstReading VAR Temp2 Temp3 VAR Word TempFinalResult VAR Temp3 CRem VAR Byte 'Counts remaining value CPerC VAR Byte 'Counts per degree C value SensorAddress VAR Byte(8) Counter1 VAR Nib SensorCounter VAR Counter1 Counter2 VAR Nib SensorAddressCounter VAR Counter2 Counter3 VAR Nib MeasurementCounter VAR Counter3 Sign VAR Bit ' -----[noparse][[/noparse] Initialization ]------------------------------------- ' DATA $10,$C5,$8F,$B8,$01,$08,$00,$7B 'Sensor0 Address, starts at 0 DATA $10,$96,$C2,$B8,$01,$08,$00,$09 'Sensor1 Address, starts at 8 DATA $10,$93,$50,$B8,$01,$08,$00,$D6 'Sensor2 Address, starts at 16 DATA $10,$76,$96,$B8,$01,$08,$00,$AA 'Sensor3 Address, starts at 24 'Temperature readings stored in Scratch PadRAM: 'Sensor0 at location 0 (size is Word) 'Sensor1 at location 2 (size is Word) 'Sensor2 at location 4 (size is Word) 'Sensor3 at location 6 (size is Word) Setup: PAUSE 1000 'open debug window Main: FOR SensorCounter = 0 TO (NumberOfSensors-1) FOR SensorAddressCounter = 0 TO 7 READ (SensorCounter*8)+SensorAddressCounter, SensorAddress(SensorAddressCounter) NEXT GOSUB CheckTemp PUT (SensorCounter*2), Word TempFinalResult NEXT DEBUG CR FOR SensorCounter = 0 TO 3 GET (SensorCounter*2), Word Temp1 DEBUG DEC sensorcounter, ": ", DEC Temp1/10, ".", DEC2 Temp1-(Temp1/10*100), "F " NEXT PAUSE 15000 GOTO Main END CheckTemp: FOR MeasurementCounter = 0 TO (NumMeasurements-1) OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,STR SensorAddress\8,ConverT] PAUSE 750 OWOUT OWpin,OWFERst,[noparse][[/noparse]MatchROM,STR SensorAddress\8,ReadScratch] OWIN OWpin, OWBERst, [noparse][[/noparse]TempThisReading.LOWBYTE,TempThisReading.HIGHBYTE,CRem,CRem,CRem,CRem,CRem,CPerC] TempThisReading = (TempThisReading>>1*100-25+((CPerC*100-(CRem*100))/CPerC))* 9 / 50 + 320 IF MeasurementCounter =0 THEN TempFinalResult = TempThisReading TempFirstReading = TempThisReading ELSE Sign = TempAdjSign TempAdjustment = (ABS(TempFirstReading-TempThisReading)/ NumMeasurements) IF (Sign=1) THEN TempAdjustment = -TempAdjustment TempFinalResult = TempFinalResult + TempAdjustment ENDIF NEXT RETURNHi All,
I know, I'm dragging up a pretty old thread, but it's the only one I could find where the code actually worked for the poster, as opposed to not working and they're·asking for·help.
I've never used a OW device yet, so I'm just starting to understand the protocol.
I've been looking at a DS18x20 project myself, and wondered if you've made any further tweaks to this program.
Also, did you write a seperate program to retrieve the ROM code for each 1820?
If anyone has a sample code to do that, I'd be most appreciative.
Thanks in advance,
Darlene