HS1101 Nem sensörü Yardım!.

Başlatan LukeSkywalker, 05 Temmuz 2011, 16:37:59

LukeSkywalker

Arkadaşlar bir projede kullanılmak üzere bu sensörlerden alınmış. Sensör kapasitif ve datasheet'inde 555 ile kullanılıyor gördüğüm kadarı ile. Fakat mikrodenetleyici ile bu devreden gelen frekans değerini nasıl RH değerine çevireceğimiz anlatılmamış detaylı bir şekilde. Bunu kullanan arkadaşların yardımını bekliyorum.
[IMG]http://img546.imageshack.us/img546/6793/adszkq.jpg[/img]

Bu formülden RH değerini çeken, ve paylaşan arkadaşa saygılarımı sunarım...




Okan AKÇA


LukeSkywalker

Datasheete baktık hocam. Adam gibi cevap verecekler versin... Artizler gelmesin...

mufitsozen

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

The Gariban

Sanırım şemanın altındaki o formüle göre RH değeri çekiliyor.
Eğer o datasheetin linkini verirsen daha da emin olunur.

LukeSkywalker


The Gariban

Linke baktım .Gördüğüm kadarı ile herhangi bir formüle  gerek yok.
Yani siz o devreyi birkaç kriterine dikkat ederek yaparsanız muhtelemelen düzgün ölçecektir.
Dikkat edilmesi gerekenlerde devredeki R1 ve R2 dirençlerinin değerleri ve 555 in firmasına göre bu değerlerde değişiyor(3.sayfada sağ sütünda izah ediyor) ayrıca dirençlerin toleranslarda düşük olacak.
Diğer formül kısımları sensorün kalibrasyonunda kullanılan değerler -yani sensörün cevabının ayrıntıarı

LukeSkywalker

#7
Yani oradaki tabloya gere 10luk değerler şeklinde mi hesaplayacağız nem oranını? Sensör frekansa bağlı olarak nasıl veriyor peki nem değerini? Yani sormak istediğim frekansı nem değerine nasıl çeviriyoruz?

The Gariban

Bu aşağıda PIC ile yapılmış bir uygulaması var.
Pekçok sorunuza cevap verecektir.
http://www.antratek.nl/pdf/27920-HS1101-v1.0.pdf


LukeSkywalker

Hocam teşekkürler fakat bunu incelemiştim. Burada hazır kütüphane kullanılıyor basicstamp için. Ayrıca hassasiyeti daha düşük katalogdaki devreye göre.

mufitsozen

#10
daha once verdigim linkde PIC16F684 icin C source kodu dahil butun bilgiler var.

/*--------------------------------------------------------------------
  humidity1: A humidity meter using a HS1101 sensor and a 2-digit
             LED readout.

  Processor: PIC16F684

  Discussion:
    This project is based on the LED frequency meter, frequency1.
    The reason is that the humidity sensor is set in an oscillator
    circuit generating a singal whose frequency is a function of the
    humidity, so the PIC needs to measure the signal frequency and
    convert it to percent humidity using a lookup table and
    interpolation. Note that the frequency range in the circuit used
    varies between 7351 Hz (0%) and 6033 Hz (100%), so the frequency
    range measured is quite limited.

    Timer1 is used as a 16 bit counter with external clock, the
    clock being the input signal. By turning on the timer for
    exactly 1 second, the frequency can be directly taken from
    the timer register word. There is no need to implement timer
    overflow in this application since the highest frequency measured
    is well below the 64K capability of the timer1 counter.
    
    Timer0 is used to generate 1 second intervals, at which time
    the timer1 counter is inspected,  
--------------------------------------------------------------------*/                
#include <system.h>
#include "itoa.h"

#pragma CLOCK_FREQ      4000000

// Config Bits: 11 0000 1100 0100
// bit 13-12: unimplemented, set to 1
// bit 11:    FCMEN  0 = fail safe clock disabled
// bit 10:    IESO   0 = internal external switchover disabled
// bits 9-8:  BODEN  00 = Brown out detect disabled
// bit 7:     !CPD   1 = data memory code protection disabled
// bit 6:     !CP    1 = program memory code protection disabled
// bit 5:     MCLRE  0 = RA3/!MCLR pin function is RA3
// bit 4:     ^PWRTE 0 = PWRT enabled
// bit 3:     WDTE   0 = watchdog timer disabled
// bits 2-0:  FOSC   100 = INTOSC oscillator, I/O on RA4/OSC2/CLKOUT, I/O on RA5/OSC1/CLKIN
// bits 2-0:  FOSC   101 = INTOSC oscillator, CLKOUT on RA4/OSC2/CLKOUT, I/O on RA5/OSC1/CLKIN

#pragma DATA _CONFIG, 0x30c5

#define TIMER0_START_CNT	56		// tewak this value to calibrate
#define MIN_RH				0
#define MAX_RH				99

// Global Variables

// static unsigned short usOverflowCtr;
// static unsigned long  ulTimer1Ctr;
static unsigned int  uiTimer1Ctr;

// Functions

static unsigned short freq2rh( unsigned short uiFreq );
static void initCPU( void );
static void ledDigit( char cDigit );
static void ledOutput( char cNumber );

/*---------------------------------------------------------------------
  main()
---------------------------------------------------------------------*/
void main()
{
  char buffer[4];
  char cDigit, cNumber, cLen, cStrt;
  int  iRh;
  
  initCPU();                	// initialize hardware
  // usOverflowCtr = 0;
  uiTimer1Ctr = 0;
  set_bit( t1con, TMR1ON );		// start timer1 counter

  // The mainline job is to convert timer1 counts to ascii and display
  // the LED digits. Everything else is managed by timer0 and timer1
  // interrupt handlers.

  while ( 1 )
  {
    // Convert the frequency reading (7351..6033 Hz) to relative
    // humidity.
    
    iRh = freq2rh( uiTimer1Ctr );
    
    // The number in buffer has no leading zeroes. We want to display
    // the digits right-justified. To do this we skip the high-order
    // digit when there is nothing to display.
   
    itoa( iRh, buffer );
    cLen = strlen( buffer );
    cStrt = 2 - cLen;
    
    for ( cDigit=0; cDigit<cLen; ++cDigit, ++cStrt )
    {
      cNumber = buffer[cDigit];
      ledDigit( 0 );					// turn both digits off
      ledOutput( cNumber );				// output a number
      ledDigit( cStrt + 1 );			// turn the digit on
      delay_ms( 2 );
    }  
  }
}

/*---------------------------------------------------------------------
  interrupt()
  
  Handles the timer interrupts.
---------------------------------------------------------------------*/
void interrupt( void )
{
  static unsigned short t0ctr=0;
  // unsigned short usTimer1_word;
  
  if ( test_bit( intcon, T0IF ) )
  {
    // The timer0 interrupt occurs ( Fosc/4 * prescale * t0 counts ). When 
    // Fosc/4 is 1 microsecond and prescale is 1:2, the timer increments
    // every 2 microseconds. If we count 250 times, we get an interrupt every 
    // 500 microseconds. Since we are timing one second intervals, we need to
    // count to 2000.
    ++t0ctr;
    if ( t0ctr == 2000 )
    {
      clear_bit( t1con, TMR1ON );		// stop timer1 counter
      MAKESHORT( uiTimer1Ctr, tmr1l, tmr1h );
      // ulTimer1Ctr = ( (unsigned long) usOverflowCtr << 16 ) | (unsigned long) usTimer1_word;

      // usOverflowCtr = 0;
      tmr1l = tmr1h = 0;
      set_bit( t1con, TMR1ON );		// start timer1 counter
      
      tmr0 = TIMER0_START_CNT;		// set timer0 starting value
      t0ctr = 0;					// reset the interrupt counter
    }
    
    clear_bit( intcon, T0IF );		// reset timer0 overflow interrupt flag
    return;
  }
  
#if 0
  if ( test_bit( pir1, TMR1IF ) )
  {
    // The timer1 interrupt occurs when Timer1, operating as a 
    // counter, rolls over its 16 bit register. We just like to 
    // keep track of the overflows in a separate counter.
    ++usOverflowCtr;
    clear_bit( pir1, TMR1IF );		// reset timer1 overflow interrupt flag
    return;
  }
#endif  
}

/*---------------------------------------------------------------------
  initCPU()
---------------------------------------------------------------------*/
static void initCPU()
{
  // Initialize the internal clock:
  osccon = 01100000b;		// internal clock @ 4MHz, use FOSC (config)

  // PORTC connections as follows:
  //  RC0 - (out) LED data 'A'
  //  RC1 - (out) LED data 'B'
  //  RC2 - (out) LED data 'C'
  //  RC3 - (out) LED data 'D'
  //  RC4 - (out) LED digit select 'DIG1'
  //  RC5 - (out) LED digit select 'DIG2'

  portc = 0;
  cmcon0 = 00000111b;			// comparators off
  ansel = 0;					// digital I/O
  trisc = 00000000b;            // 1=input, 0=output

  // PORTA connections as follows:
  //  RA0/AN0/ICSPDAT - (in) (used for programming only)
  //  RA1/AN1/ICSPCLK - (in) (used for programming only)
  //  RA2/AN2/T0CKI - (out) not used
  //  RA3/!MCLR/Vpp - (in) (used for programming only)
  //  RA4/AN3 - (out) - CLKOUT
  //  RA5/T1CKI - (in) signal input to timer1 counter

  porta = 00000000b;			// make RA4 low, LED off
  trisa = 00101011b;			// 1=input, 0=output

  // Timer0 initialization. Use Timer0 to measure one second intervals.
  tmr0 = TIMER0_START_CNT;		// set timer0 starting value
  option_reg = 11010000b;		// internal clock; 1:2 prescale;
  set_bit( intcon, T0IE );		// enable timer0 interrupts
  
  // Timer1 initialization. Use Timer1 as 16-bit counter with
  // input on RA5/T1CKI.

  tmr1l = tmr1h = 0;
  t1con = 00000110b;      	// 1:1 prescale; LP osc off; no sync; ext. clock; stopped
  // set_bit( pie1, TMR1IE );      // Timer1 interrupts

  // Enable interrupts for Timer0

  set_bit( intcon, GIE );       // enable global interrupts
  set_bit( intcon, PEIE );      // enable peripheral interrupts
}

/*---------------------------------------------------------------------
  ledDigit(...)
  
  Selects a digit of the led display. Ports RC4-RC5 are connected
  to DIG1 and DIG2 of the 2-digit LED display.
  
  Input: 0 = deactivate both digits
         1 = activate digit 1
         2 = activate digit 2
---------------------------------------------------------------------*/
static void ledDigit( char cDigit )
{
  if ( cDigit == 1 )
  {
    // Activate digit 1
    set_bit( portc, 5 );
    clear_bit( portc, 4 );
  }
  else
    if ( cDigit == 2 )
    {
      // Activate digit 2
      set_bit( portc, 4 );
      clear_bit( portc, 5 );
    }
    else
    {
      set_bit( portc, 4 );
      set_bit( portc, 5 );
    }
}

/*---------------------------------------------------------------------
  ledOutput(...)
  
  Outputs a number to the led display. Ports RC0..RC3 are connected
  to the A-B-C-D inputs of a 74LS47 which decodes the number and
  activates the corresponding segments of the bank of LEDs. Note that
  A is the low-order input and D is the high order input to the '47.
  
  Input: a single numeric digit, range 0..9.
---------------------------------------------------------------------*/
static void ledOutput( char cNumber )
{
  // Output the digit as BCD on RC0..RC3

  if ( test_bit( cNumber, 0 ) )
    set_bit( portc, 0 );
  else
    clear_bit( portc, 0 );

  if ( test_bit( cNumber, 1 ) )
    set_bit( portc, 1 );
  else
    clear_bit( portc, 1 );

  if ( test_bit( cNumber, 2 ) )
    set_bit( portc, 2 );
  else
    clear_bit( portc, 2 );

  if ( test_bit( cNumber, 3 ) )
    set_bit( portc, 3 );
  else
    clear_bit( portc, 3 );
}

/*---------------------------------------------------------------------
  freq2rh(...)

  Converts the frequency to relative humidity, using linear interpolation.

  Linear interpolation takes two data points, say (Xa,Ya) and (Xb,Yb),
  and the interpolant (X,Y) is given by:

           (X - Xa) (Yb - Ya)
  Y = Ya + ------------------
               (Xb - Xa)

  In this case X is frequency and Y is relative humidity.

  Input: frequency 7351..6033 Hz
---------------------------------------------------------------------*/
static unsigned short freq2rh( unsigned short uiFreq )
{
  static short sFreq[11] =
  {
    7351, 7224, 7100, 6976, 6853, 6728, 6600, 6468, 6330, 6186, 6033
  };
  static short sRh[11] =
  {
    MIN_RH, 10, 20, 30, 40, 50, 60, 70, 80, 90, MAX_RH
  };

  char  ii;
  unsigned usRH;
  short sTerm1, sTerm2, sTerm3;

  // Check for boundary values
  if ( uiFreq <= (unsigned short) sFreq[10] ) return MAX_RH;
  if ( uiFreq >= (unsigned short) sFreq[0] )  return MIN_RH;

  for ( ii=0; ii<11; ++ii )
  {
    if ( uiFreq >= (unsigned) sFreq[ii] )
      break;
  }

  if ( uiFreq == (unsigned) sFreq[ii] )
    return (unsigned) sRh[ii];          // no interpolation necessary

  sTerm1 = (short) uiFreq - sFreq[ii-1];
  sTerm2 = sRh[ii] - sRh[ii-1];
  sTerm3 = sFreq[ii] - sFreq[ii-1];
  usRH = (unsigned) ( sRh[ii-1] + ( ( sTerm1 * sTerm2 ) / sTerm3 ) );

  return usRH;
}
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

LukeSkywalker

Millet bu cihazın kataloğunda verilen ve 10'ar 10'ar büyüyen değerlerin arasında kalan değerlere interpolasyon yaparak ulaşmış. Yani kimse formülle uğraşmamış. Bence bu yöntem hassas ölçüm yapılacak yerlerde kullanılamaz, çünkü interpolasyondan elde edilecek değerler kesin değerler olmayacaktır. Fakat kimse de formül ile hesaplamamış ilginç. En iyisi SHT11 gibi bir sensör kullanmak.  Nem ölçmek için çok daha hassas ve kolay kunabilen bir sensör önerecek olan var mı?