sht.c
1 | // Sensirion SHT Sensor
| 2 | #include <io430.h>
| 3 | #include <intrinsics.h>
| 4 | #include "sht.h"
| 5 | #include "delay.h"
| 6 |
| 7 | #define SHTDIR P5DIR
| 8 | #define SHTOUT P5OUT
| 9 | #define SHTIN P5IN
| 10 |
| 11 | #define PIN_CLK 0x40
| 12 | #define PIN_DAT 0x80
| 13 |
| 14 | #define SHT_CMD_TEMP 0x03
| 15 | #define SHT_CMD_HUMID 0x05
| 16 | #define SHT_CMD_WR_STAT 0x06
| 17 | #define SHT_CMD_RD_STAT 0x07
| 18 | #define SHT_CMD_RESET 0x1E
| 19 |
| 20 | #define SHT_VOLTAGE_COMPENSATION_D1_5V -40.1
| 21 | #define SHT_VOLTAGE_COMPENSATION_D1_4V -39.8
| 22 | #define SHT_VOLTAGE_COMPENSATION_D1_3_5V -39.7
| 23 | #define SHT_VOLTAGE_COMPENSATION_D1_3_3V -39.7
| 24 | #define SHT_VOLTAGE_COMPENSATION_D1_3V -39.6
| 25 | #define SHT_VOLTAGE_COMPENSATION_D1_2_5V -39.4
| 26 |
| 27 | #define SHT_VOLTAGE_COMPENSATION_D1 SHT_VOLTAGE_COMPENSATION_D1_3_3V
| 28 |
| 29 | #define NOP __no_operation()
| 30 |
| 31 | inline static char sht_getdat(void)
| 32 | {
| 33 | NOP;
| 34 | return (SHTIN&PIN_DAT);
| 35 | }
| 36 |
| 37 | inline static void sht_setdat(unsigned char c)
| 38 | {
| 39 | if (c) SHTDIR&=~PIN_DAT; // bei 1 Pullup wirken lassen
| 40 | else SHTDIR|=PIN_DAT; // ansonsten auf Ausgang schalten,
| 41 | // wo eine 0 ausgegeben wird
| 42 | NOP;
| 43 | }
| 44 |
| 45 | inline static void sht_clkhi(void)
| 46 | {
| 47 | SHTOUT|=PIN_CLK;
| 48 | NOP;
| 49 | }
| 50 |
| 51 | inline static void sht_clklo(void)
| 52 | {
| 53 | SHTOUT&=~PIN_CLK;
| 54 | NOP;
| 55 | }
| 56 |
| 57 | void sht_init(void)
| 58 | {
| 59 | SHTDIR|=PIN_CLK;
| 60 | SHTDIR&=~PIN_DAT;
| 61 | SHTOUT&=~(PIN_CLK|PIN_DAT);
| 62 | delayms(50); // Power Up Delay
| 63 | }
| 64 |
| 65 | static void sht_start(void)
| 66 | {
| 67 | int i;
| 68 | sht_setdat(1);
| 69 | for (i=0;i<10;i++)
| 70 | {
| 71 | sht_clkhi();
| 72 | sht_clklo();
| 73 | }
| 74 | sht_clkhi();
| 75 | sht_setdat(0);
| 76 | sht_clklo();
| 77 | sht_clkhi();
| 78 | sht_setdat(1);
| 79 | sht_clklo();
| 80 | }
| 81 |
| 82 | static void sht_sendbyte(unsigned char c)
| 83 | {
| 84 | int i;
| 85 | // Datenbits rausschieben
| 86 | for (i=8;i>0;--i)
| 87 | {
| 88 | sht_setdat(c&0x80);
| 89 | sht_clkhi();
| 90 | sht_clklo();
| 91 | c<<=1;
| 92 | }
| 93 | // Ack empfangen
| 94 | sht_setdat(1);
| 95 | sht_clkhi();
| 96 | sht_clklo();
| 97 | // while(sht_getdat());
| 98 | }
| 99 |
| 100 | static unsigned char sht_recvbyte_msb(unsigned char a)
| 101 | {
| 102 | int i;
| 103 | unsigned char c;
| 104 | sht_setdat(1);
| 105 | // Datenbits reinschieben
| 106 | for (i=8;i>0;--i)
| 107 | {
| 108 | c<<=1;
| 109 | sht_clkhi();
| 110 | if (sht_getdat()) c|=1;
| 111 | sht_clklo();
| 112 | }
| 113 | // Ack senden
| 114 | sht_setdat(a);
| 115 | sht_clkhi();
| 116 | sht_clklo();
| 117 | sht_setdat(1);
| 118 | return c;
| 119 | }
| 120 |
| 121 | static unsigned char sht_recvbyte_lsb(unsigned char a)
| 122 | {
| 123 | int i;
| 124 | unsigned char c;
| 125 | sht_setdat(1);
| 126 | // Datenbits reinschieben
| 127 | for (i=8;i>0;--i)
| 128 | {
| 129 | c>>=1;
| 130 | sht_clkhi();
| 131 | if (sht_getdat()) c|=128;
| 132 | sht_clklo();
| 133 | }
| 134 | // Ack senden
| 135 | sht_setdat(a);
| 136 | sht_clkhi();
| 137 | sht_clklo();
| 138 | sht_setdat(1);
| 139 | return c;
| 140 | }
| 141 |
| 142 | static unsigned char sht_crc(unsigned char crc, unsigned char data)
| 143 | {
| 144 | static const unsigned char crctab[]={
| 145 | 0, 49, 98, 83,196,245,166,151,185,136,219,234,125, 76, 31, 46,
| 146 | 67,114, 33, 16,135,182,229,212,250,203,152,169, 62, 15, 92,109,
| 147 | 134,183,228,213, 66,115, 32, 17, 63, 14, 93,108,251,202,153,168,
| 148 | 197,244,167,150, 1, 48, 99, 82,124, 77, 30, 47,184,137,218,235,
| 149 | 61, 12, 95,110,249,200,155,170,132,181,230,215, 64,113, 34, 19,
| 150 | 126, 79, 28, 45,186,139,216,233,199,246,165,148, 3, 50, 97, 80,
| 151 | 187,138,217,232,127, 78, 29, 44, 2, 51, 96, 81,198,247,164,149,
| 152 | 248,201,154,171, 60, 13, 94,111, 65,112, 35, 18,133,180,231,214,
| 153 | 122, 75, 24, 41,190,143,220,237,195,242,161,144, 7, 54,101, 84,
| 154 | 57, 8, 91,106,253,204,159,174,128,177,226,211, 68,117, 38, 23,
| 155 | 252,205,158,175, 56, 9, 90,107, 69,116, 39, 22,129,176,227,210,
| 156 | 191,142,221,236,123, 74, 25, 40, 6, 55,100, 85,194,243,160,145,
| 157 | 71,118, 37, 20,131,178,225,208,254,207,156,173, 58, 11, 88,105,
| 158 | 4, 53,102, 87,192,241,162,147,189,140,223,238,121, 72, 27, 42,
| 159 | 193,240,163,146, 5, 52,103, 86,120, 73, 26, 43,188,141,222,239,
| 160 | 130,179,224,209, 70,119, 36, 21, 59, 10, 89,104,255,206,157,172
| 161 | };
| 162 |
| 163 | return crctab[crc^data];
| 164 | }
| 165 |
| 166 | unsigned short sht_measure(char is_rh)
| 167 | {
| 168 | int i;
| 169 | unsigned short s;
| 170 | unsigned char cmd,ch,cl,crc;
| 171 | unsigned char mycrc;
| 172 |
| 173 | sht_start();
| 174 | if (is_rh) cmd=SHT_CMD_HUMID;
| 175 | else cmd=SHT_CMD_TEMP;
| 176 | sht_sendbyte(cmd);
| 177 | delayms(5);
| 178 | sht_setdat(1);
| 179 | for (i=0;i<1024;i++)
| 180 | {
| 181 | if(sht_getdat()==0) break;
| 182 | delayms(5);
| 183 | }
| 184 | if (sht_getdat()) return 0xfffe;
| 185 |
| 186 | ch=sht_recvbyte_msb(0);
| 187 | cl=sht_recvbyte_msb(0);
| 188 | crc=sht_recvbyte_lsb(1);
| 189 | s=((unsigned short)ch<<8)+(unsigned short)cl;
| 190 | mycrc=sht_crc(0,cmd);
| 191 | mycrc=sht_crc(mycrc,ch);
| 192 | mycrc=sht_crc(mycrc,cl);
| 193 | if (mycrc!=crc) s=0xffff;
| 194 |
| 195 | return s;
| 196 | }
| 197 |
| 198 | // temp is returned in two-digit fixedpoint (celsius*100)
| 199 | short sht_convert_temp(unsigned short raw_temp)
| 200 | {
| 201 | return ((short)raw_temp+(((short)SHT_VOLTAGE_COMPENSATION_D1)*100));
| 202 | }
| 203 |
| 204 | // humidity is returned in one-digit fixedpoint (RH percent*10)
| 205 | unsigned short sht_convert_humid(unsigned short raw_temp,unsigned short raw_humid)
| 206 | {
| 207 | unsigned long humid;
| 208 |
| 209 | /**** first step: relative humidity ****/
| 210 |
| 211 | // constants from datasheet (values for V4 sensors), shifted and adapted
| 212 | const unsigned long c1 = (unsigned long)((2.0468 * 100 * (1L<<18))+0.5);
| 213 | const unsigned long c2 = (unsigned long)((0.0367 * 100 * (1L<<18))+0.5);
| 214 | const unsigned long c3 = (unsigned long)((1.5955e-6 * 100 * (1L<<27))+0.5);
| 215 |
| 216 | // uncompensated = c2*raw - (c3 * raw * raw) - c1
| 217 | humid = (c2 * (unsigned long)raw_humid) \
| 218 | - (((((unsigned long)raw_humid * (unsigned long)raw_humid) >> 7) * c3) >> 2) \
| 219 | - c1;
| 220 |
| 221 | // humid >> 18 would now be the uncompensated humidity in RH% * 100
| 222 |
| 223 | /**** second step: temperature compensation ****/
| 224 |
| 225 | // constants from datasheet, shifted and adapted
| 226 | const long t1 = (long)((0.01 * 100 * (1L<<18))+0.5);
| 227 | const long t2 = (long)((0.00008 * 100 * (1L<<18))+0.5);
| 228 |
| 229 | // humid += (temp-25) * (t1 + t2*raw_temp)
| 230 | humid += (long)((sht_convert_temp(raw_temp)/100)-25) \
| 231 | * (t1 + (t2 * (long)raw_humid));
| 232 |
| 233 | // humid >> 18 now is the real humidity in RH% * 100
| 234 |
| 235 | // shift it back and round to RH% * 10
| 236 | // (the sensor doesn't really provide enough accuracy to justify more resolution)
| 237 | return (unsigned short)(((humid >> 18)+5)/10);
| 238 | }
|
|