' 'color blending relative thermometer ' ' 'A piece of modern tech art that pulses and changes color 'in response to relative temperature changes. That is, 'is has to keep changing color enough to be interesting. ' 'The specs: '- senses being handled '- pulses at approx 1Hz for 1 minute when picked up, 1/10Hz when resting '- color of pulse changes in response to relative temp change '- color change relative to a few seconds when handled, a few minutes when resting '- color based on bicolor LED blending (ideally Red-Blue) '- LED projects light onto frosted surface with omnidirectional visibility '- can be mounted in a pingpong ball or mounted in cute clay figure ' 'Uses a DS18B20 to sense temperature, Bi-color LED to indicate temp 'mercury, tilt switch, LDR, or even LEDs themselves as sensor to detect handling ' ' 'Changelog ' v1 initial version ' v2 slight changes, working but no modes, quite readable ' v3 optimized for memory, includes modes ' v4 more memory optimizations, uses mercury switch tilt sensor ' v5,using LED to sense light levels for handling determination ' v6,more optimizations, remove bitpacked color encoding ' '(C)2007 by A. Stein, MedCosm, LLC ' ' ' ' 08M variable table (for convenience) ' b0:b1 b2:b3 b4:b5 b6:b7 b8:b9 b10:b11 b12:b13 ' w0 w1 w2 w3 w4 w5 w6 ' pinouts symbol LEDred=2 'LED1 (red) pin, also used to sense light! symbol LEDgreen=1 'LED2 (green) pin symbol TempSense=4 'DS18B20 pin 'variables symbol LEDvalue=b0 'Byte Red/Green value of LED when at full intensity symbol oldLEDvalue=b1 'old ambient light value symbol modecycles=b1 'counts number of cycles when in "handled" mode, (shares var with above!) symbol TReading = W1 'temp reading from DS18B20 symbol tmpW1=w2 'tmp word variable symbol tmpB1=b6 'tmp byte variable symbol mode=b7 'keeps track of "resting" and "handled" modes 'B8 blank! symbol intensity=b9 'intensity of LED symbol minT=b10 'min temperature in stored samples symbol maxT=b11 'max temperature in stored samples symbol tmpB2=b12 'tmp byte variable symbol tmpB3=b13 'tmp byte variable 'constants symbol RESTING=0 symbol HANDLED=1 symbol numSamplesResting=20 'num samples to store when resting, up to 48 free bytes in RAM symbol numSamplesHandled=4 'num samples to store when handled, keep small to make responsive symbol memPtr=$50 'ptr to start of 48 bytes of free RAM at $50-$7F symbol maxIntensity=31 'max value that is of LED intensity symbol maxLEDvalue=31 'max value held by LEDvalue (Red/Green encoding) symbol maxLEDvalueByTwo=15 'max value held by LEDvalue symbol numPWMcycles=1 symbol TByteOffset=218 'at room temp, allows 12 bit temp word to fit to 8 bit byte symbol LEDsenseDelta=6 'delta for LED sensor to trigger "HANDLED" mode, lower is more sensitive symbol LEDsenseDly=20 'time delay between fake read and read light sense read from LED symbol CyclesToRest=10 'number of cycles in handled mode until resting mode takes over init: mode=HANDLED ' modecycles=0 gosub gettemp 'init data storage in RAM initData: for tmpB1=0 to numSamplesResting 'fill max number of samples with reasonable data tmpB2=memPtr+tmpB1 poke tmpB2, TReading 'and save it to sample(tmpB1) next tmpB1 start: if mode=RESTING then 'RESTING mode for tmpB1=0 to 40 ' nap .233 secs * 40 iterations max readadc LEDred, tmpB2 'fake read to stabilize if mode=RESTING then pause LEDsenseDly 'pause after fake read endif readadc LEDred, tmpB2 'get new light value if tmpB2 > oldLEDvalue then 'effectively tmpB3=abs(tmpB2-oldLEDvalue) tmpB3=tmpB2 - oldLEDvalue else tmpB3=oldLEDvalue - tmpB2 endif ' serTxD(#tmpB2, " ") ' serTxD(#modeCycles, " ") ' serTxD(13, 10) if tmpB3CyclesToRest then 'if no handling activity for a predefined number of cycles mode=RESTING 'then change mode to resting readadc LEDred, tmpB2 'fake read to stabilize pause LEDsenseDly 'pause after fake read readadc LEDred, tmpB2 'read ambient light oldLEDvalue=tmpB2 'use cycles counter to store old LED sense value while in resting mode endif tmpW1=numSamplesHandled-1 'num data samples, used in storeDataAndFindMinMax endif gosub gettemp 'store current temp in RAM with N-1 samples, shifts data along removing oldest sample, 'and finds min and max values while we're at it storeDataAndFindMinMax: minT=TReading 'minT=first sample maxT=TReading 'maxT=first sample ' tmpW1 now loaded above to save memory, holds number of samples for tmpB2=tmpW1 to 0 step -1 'iterate on stored samples tmpB1=memPtr + tmpB2 peek tmpB1, tmpB3 'get stored sample(tmpB2) tmpB1=tmpB1+1 poke tmpB1, tmpB3 'move it to sample(tmpB2+1) if minT>tmpB3 then minT=tmpB3 'update minT if needed endif if maxT 0 then 'but if valid data (not all same value), compute real color tmpB2=TReading-minT 'subtract minT offset tmpW1=maxLEDvalue*tmpB2/tmpB1 'byte value of color LEDvalue=tmpW1 'compute red value and set in RGB encoding endif 'pulse LED, rampup then rampdown pulse: setfreq m8 'overclock reduces flicker rampup: 'rampup LED brightness for intensity=0 to MaxIntensity gosub glowBlend next intensity rampdown: 'rampdown LED brightness for intensity=MaxIntensity to 0 step -1 gosub glowBlend next intensity setfreq m4 'restore normal clock so new downloads aren't screwed up goto start 'get temp from DS18B20, use 12 bit 0.125 degree mode for sensitivity, fit into byte value gettemp: ReadTemp12 TempSense,TReading TReading=Treading-TByteOffset 'fit into byte storage, may fail if temp not around room temperature return 'display blended colors on LED glowBlend: tmpW1=LEDvalue * 255 / maxLEDvalue 'scale LEDvalue to full byterange tmpB1=tmpW1 'save intermediate tmpW1=tmpW1 * intensity / MaxIntensity 'RED value adjusted for intensity pwm LEDred, tmpW1, numPWMcycles tmpW1=255-tmpB1 'GREEN LEDvalue tmpW1=tmpW1 * intensity / MaxIntensity pwm LEDgreen, tmpW1, numPWMcycles return