Making a program more compact?
patches
Posts: 15
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.
You 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.
Hi 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