Archive

Posts Tagged ‘Electronics’

Electric Imp & SHTxx sensors

December 17th, 2012

There have been a couple people requesting the code to drive an SHT temp/humidity sensor from an electric imp, so I’ll post it below.  No warrantee implied..  Also, it’s ugly as someone else wrote it for some other microprocessor and I just tweaked it; I would never write such aesthetically displeasing code.    Obviously, I’m big banging pins 8 and 9; adjust to suite your needs.  Don’t forget the pullup resistor on one of those lines.  This is also written for the SHT71, tweak for whichever unit you are using.

 

class SHT {
       
    function delay_us(x) {imp.sleep(0.000001 * x);}

     noACK =0;
     ACK=1;
                                //adr  command  r/w
     STATUS_REG_W =0x06;   //000   0011    0
     STATUS_REG_R =0x07;   //000   0011    1
     MEASURE_TEMP =0x03;   //000   0001    1
     MEASURE_HUMI =0x05;   //000   0010    1
     RESET        =0x1e;   //000   1111    0
    
    data_output = true;
   
    function constructor() {
        hardware.pin8.configure(DIGITAL_OUT);
        hardware.pin9.configure(DIGITAL_OUT);
        s_softreset( );
    }
   
   
   
    function sck_set(x) {
        hardware.pin8.write(x);
       
    }
    function data_set(x) {
        if (!data_output) {
            hardware.pin9.configure(DIGITAL_OUT); 
            data_output = true;
        }
        hardware.pin9.write(x);
       
    }
   
    function data_get() {
        if (data_output) {
            hardware.pin9.configure(DIGITAL_IN);
            data_output = false;
            }
        return hardware.pin9.read();
    }
   
   
    function SCK( val) {
        if (val) {
            sck_set(1);
        } else {
            sck_set(0);
        }
    }
   
    function DATA( val) {
        if (val) {
            //input w/ pullup resistor
            data_get();
        } else  {
            //output – gnd
            data_set(0);
        }
    }           
   
   
    function sht_init() {
        s_write_statusreg(0, 0x00); //8/12 bit resolution
    }
   
   
       
   
   
    //———————————————————————————-
    function s_write_byte( value) {
    //———————————————————————————-
    // writes a byte on the Sensibus and checks the acknowledge
      local error=0; 
   
      for (local i=0x80; i>0; i=i/2)             //shift bit for masking
      {
          if (i & value) DATA( 1);          //masking value with i , write to SENSI-BUS
          else DATA(0);                       
            delay_us(5);
          SCK( 1);                          //clk for SENSI-BUS
          delay_us(5);        //pulswith approx. 5 us     
          SCK( 0);
      }
      delay_us(5);
      DATA( 1);                           //release DATA-line
      SCK( 1);                            //clk #9 for ack
    
      error=data_get();                       //check ack (DATA will be pulled down by SHT11)
      SCK( 0);  
      return error;                     //error=1 in case of no acknowledge
    }
   
    //———————————————————————————-
    function s_read_byte( ack)
    //———————————————————————————-
    // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
    {
      local val=0;
      DATA( 1);                     //release DATA-line
      for (local i=0x80; i>0 ; i = i>>1)  {           //shift bit for masking
       SCK( 1);                    //clk for SENSI-BUS
        if (data_get()) val=(val | i);        //read bit 
        SCK( 0);                      
      }
      if (ack) {
          DATA(0);
      } else {
          DATA(1);
      }
     
      SCK( 1);                      //clk #9 for ack
      delay_us(5);          //pulswith approx. 5 us
      SCK( 0);                           
      DATA( 1);                     //release DATA-line
      return val;
    }
   
    //———————————————————————————-
    function s_transstart( )
    //———————————————————————————-
    // generates a transmission start
    //       _____         ________
    // DATA:      |_______|
    //           ___     ___
    // SCK : ___|   |___|   |______
    { 
       DATA( 1);
       SCK( 0);//Initial state
       delay_us(2);
       SCK( 1);
       delay_us(2);
       DATA( 0);
       delay_us(2);
       SCK( 0); 
       delay_us(6);
       SCK( 1);
       delay_us(2);
       DATA( 1);          
       delay_us(2);
       SCK( 0);          
    }
   
    //———————————————————————————-
    function s_connectionreset( )
    //———————————————————————————-
    // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
    //       _____________________________________________________         ________
    // DATA:                                                      |_______|
    //          _    _    _    _    _    _    _    _    _        ___     ___
    // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
    { 
      server.log("connectionreset()");
      DATA( 1);
      SCK( 0);                    //Initial state
      for(local i=0;i<9;i++)                  //9 SCK cycle
      {
          SCK( 1); delay_us(1);
        SCK( 0); delay_us(1);
      }
      s_transstart();                   //transmission start
    }
   
    //———————————————————————————-
    function s_softreset( )
    //———————————————————————————-
    // resets the sensor by a softreset
    {
      local error=0; 
      s_connectionreset();              //reset communication
      error = s_write_byte( RESET);       //send RESET-command to sensor
      return error;                     //error=1 in case of no response form the sensor
    }
   
    //———————————————————————————-
    function  s_read_statusreg() {
    //———————————————————————————-
    // reads the status register with checksum (8-bit)
      local error=0;
      local ret = {};
      s_transstart();                   //transmission start
      error=s_write_byte(STATUS_REG_R); //send command to sensor
      ret.value <- s_read_byte(ACK);
      ret.checksum <- s_read_byte(noACK);
      ret.error <- error;
     
      return ret;                     //error=1 in case of no response form the sensor
    }
   
    //———————————————————————————-
    function s_write_statusreg( p_value)
    //———————————————————————————-
    // writes the status register with checksum (8-bit)
    {
      local error=0;
      s_transstart();                   //transmission start
      error= error+s_write_byte( STATUS_REG_W);//send command to sensor
      error= error+s_write_byte( p_value);    //send value of status register
      return error;                     //error>=1 in case of no response form the sensor
    }
                                   
   
    function s_getHumidity( ) {
        local timer=0.0;
        local data=0.0;
        local a;
        local b;
        local crc;
        local result=0;
        local errorString="";
   
        s_transstart();
        if (s_write_byte( MEASURE_HUMI)) {
            server.log("s_getHumidity:writing data error");
            return 0;
        }
       
        // wait up until 2 seconds for DATA to go low
        while (timer < 2 && data_get()) {
            imp.sleep(0.01);
            timer = timer + 0.01;
        }
        // see if an error occured (data_get is still high) 
        if (data_get()) {
            server.log("s_getHumidity:no response");
            return 0;
        }
       
   
        a = s_read_byte( ACK); //MSB
        b = s_read_byte( ACK); //LSB
     
        crc = s_read_byte( noACK); //checksum
        result = a<<8 | b;
       
    //    data = -4.0 + (result * 0.0405) – (0.0000028 *result * result); 
   
        return result;
    //    return data;
    }
   
    function s_getTemperature( ) {
        local timer=0.0;
        local data=0.0;
        local a;
        local b;
        local crc;
        local result=0;
        local errorString="";
   
        s_transstart();
        if (s_write_byte( MEASURE_TEMP)) {
            server.log("s_getTemperature:writing data error");
            return 0;
        }
       
        // wait up until 2 seconds for DATA to go low
        while (timer < 2) {
            if (data_get() == 0) break;
            imp.sleep(0.01);
            timer = timer + 0.01;
        }
        // see if an error occured (data_get is still high) 
        if (data_get()) {
            server.log("s_getTemperature:no response");
            return 0;
        }
   
        a = s_read_byte( ACK); //MSB
        b = s_read_byte( ACK); //LSB
        crc = s_read_byte( noACK); //checksum
        result = a<<8 | b;
   
    //    data = -40.2 + ( .018 * result );
    //    return data;
        return result;
    }
   
    //—————————————————————————————-
    function get()
    //—————————————————————————————-
    // calculates temperature [°C] and humidity [%RH]
    // input :  humi [Ticks] (12 bit)
    //          temp [Ticks] (14 bit)
    // output:  humi [%RH]
    //          temp [°C]
    { local C1=-4.0;              // for 12 Bit
      local C2=0.0405;           // for 12 Bit
      local C3=-0.0000028;        // for 12 Bit
      local T1=0.01;             // for 14 Bit @ 5V
      local T2=0.00008;           // for 14 Bit @ 5V   
      local rh_lin;                     // rh_lin:  Humidity linear
      local rh_true;                    // rh_true: Temperature compensated humidity
      local t_C;                        // t_C   :  Temperature [°C]
   
    //  s_connectionreset();
    // imp.sleep(1);
         
      local hum_data=s_getHumidity();             // rh:      Humidity [Ticks] 12 Bit
      local temp_data=s_getTemperature();           // t:       Temperature [Ticks] 14 Bit
   
   
      t_C=temp_data*0.01 – 40;                  //calc. temperature from ticks to [°C]
      rh_lin=C3*hum_data*hum_data + C2*hum_data + C1;     //calc. humidity from ticks to [%RH]
      rh_true=(t_C-25)*(T1+T2*hum_data)+rh_lin;   //calc. temperature compensated humidity [%RH]
      if(rh_true>100)rh_true=100;       //cut if the value is outside of
      if(rh_true<0.1)rh_true=0.1;       //the physical possible range
     
      local t_F = t_C * 9 / 5 + 32;
     
      local ret = {};
      ret.temp <- t_F;
      ret.humidity <- rh_true;
     
      return ret;
    }
}

 

sht <- SHT(); //instantiate class only once

local tempHum = sht.get(); //call as often as you want
server.log("temp="+tempHum.temp+" hum="+tempHum.humidity);

Uncategorized

rStep PCB v3

November 20th, 2010

After a failed order (and 2+ months of waiting) for a PCB order from dorkbot, I reordered the PCB through seeedstuio. $40 shipped for 10 PCBs was great, but they ended up shipping me 18 (must have had extra space on the panels). I paid an extra $10 for the white soldermask (I’m so sick of green. I never want to see a gree PCB). A few weeks later, I got them.

P1040334_Medium.jpg

For those of you who have stopped following my CNC posts, I’ve still be active working on an open-source project called rStep. Yes, the r is for Reza. I’m egotistical that way. Anyhow, it’s been a really interesting experience and I’ve gained a lot of insight in running an open-source group. Last I checked, there were 78 members subscribed to the mailing list, and we have about 1/2 dozen active participants who are submitting code, testing, etc. I love seeing an idea start to become something real with people who are interested in the same stuff as I am and see the advantages to such a system. Check out the rStep page for more information.

The parts order is in place, this will be the final beta version (v3) and v4 will be a production run.

Uncategorized

Nixie Tubes

September 14th, 2009

nixie0001.jpg

My nixie tubes arrived today from Russia. Trying to decide what to make with them. Any ideas? The one on the left displays numerals, and the one on the right is bar graph. I have 10 of each. I was thinking of perhaps a 10 channel spectral analyzer for my stereo with the bar graphs. A lot of people make clocks with the tubes on the left, but that seems almost a bit too generic.

Uncategorized