Sida 1 av 1

LM335 och AVR

Postat: 19 augusti 2008, 20:59:41
av PaNiC
Det dröjer längre mellan gångerna jag behöver fråga om programmeringshjälp, men nu är det dags igen.
Värdet från LM335 finns i ADCH och ADCL. Nu ska detta räknas om till riktiga grader Kelvin.
Vad jag har gjort är:

Kod: Markera allt

int t = ((ADCH<<8)|ADCL);
t = (((5*t)/1023)*100);
sprintf(str, "%.3d\r\n", t);
Här tappar jag bort tiotalen och entalen. Antar att det är för att decimalerna inte hanteras riktigt, men hur går jag runt det?
Aref = 5V.

Postat: 19 augusti 2008, 21:22:58
av ie
En bra övning är att göra uträkningen med min och max-värden binärt på papper för att kolla. Då kommer du nog att märka att (5*t)/1023 gör att några bitar hamnar "utanför" bitplatserna i din int-variabel. Du skulle i så fall behöva multiplicera med 100 (om talet inte är för stort från början) innan du delar med 1023.

Dessutom borde du inte se några decimaler över huvud taget eftersom du jobbar med int.

Utan att ha kollat noggrannare skulle jag dessutom misstänka att du skulle dela med 1024 (vilket enkelt kan göras med en shiftoperation).

Postat: 19 augusti 2008, 21:31:56
av PaNiC
Talet blir för stort om jag börjar med att multiplicera med 100.
Jag ser inga decimaler heller, utan jag syftade till de teoretiska som blir efter divisionen med 1023.

Postat: 19 augusti 2008, 21:58:01
av ie
Jag vet inte vad LM335 ger för värde. Kan du ge exempel på vad t innehåller (binärt) efter första raden?

Postat: 19 augusti 2008, 22:30:12
av haklu
LM335 verkar mäta mellan 233 och 373 K och ger 10mV per K. Vid 373 K så ska alltså t vara 373*1024/500=764. Om man använder en unsigned int så borde man alltså kunna multiplicera t med floor(2^16/764)=85 utan att få overflow.

(t*5/1024)*100 = t*500/1024 = t*125/256

Om man ska kunna mäta nära 100 grader C så kan man alltså inte ta hela multiplikationen med 125 på en gång, men man kan börja med att multiplicera med 25 och skifta ner ett steg (dividera med 2) och sedan multiplicera med de resterande 5 och skifta de resterande 7 stegen.

unsigned int t = ((ADCH<<8)|ADCL);
t *= 25;
t >>= 1;
t *= 5;
t >>= 7;
sprintf(str, "%.3d\r\n", t);

PS. Detta var förövrigt min första post i detta trevliga forum efter att ha läst en hel del intressant.

Postat: 19 augusti 2008, 22:38:34
av PaNiC
haklu, din lösning är provad och fungerar. Tackar, och välkommen till forumet!

le, för intressets skull, runt 620 (viss feltolerans finns) vid rumstemp, dvs 1001101100.

Postat: 19 augusti 2008, 23:10:06
av sodjan
Notera att en kombination av en lookup tabell och
eventuellt en linjär aproximation mellan tabellvärderna
sannolikt är betydligt snabbare än alla beräkningar.
Om det nu spelar någon roll...