Weather Station

 

History

    This project is one of many others I had made to control my house with rules, web interface, logger and many more. This one is a weather station that reports almost anything about the external environment. I bought mechanical part of the wind sensor at http://www.aag.com.mx/indexaag.html I had to remove all the electronics that came with it and replace them with my own.  The lightning detector is very simple but it works very well if you have a REAL ground, not your ground of your electronic part, and don't worry about the 9v battery, after 2 years it is still working. The humidity and temperature sensors are the same ones I had used in the barometer project. I drilled a 3cm hole in 5 soup bowls, mounted upside down. The top and bottom soup bowl doesn't have holes. The sensors are place in the middle of those and this way the sensors are protected from sun heat and the air could pass through.  The light sensor is done with a simple LDR and that does a good job to tell my house to go into night mode.  Rain fall sensor is a simple tipping bucket that gives pulse to the MCU and with a simple formula you can know how many millimeter of rain fell.
 

Features

puce All direct digital reading
puce Temperature
puce Humidity
puce Light
puce Lightning
puce Humidex
puce Wind chill
puce Wind speed
puce Wind speed max in the last hour
puce Wind direction
puce Rain fall

 

Pictures

Click to enlarge

The weather station

Lightning detector

Wind speed & direction sensor

 

Rain fall sensor

Sun sheild tempereture/humidity sensor

PCB in the wind sensor who manage all

 

Sources codes & Schematics

-Schematic of the MCU Board in PDF format

-Schematic of the lightning detector in PDF format

 

//*****************************************************************************
// NetWind
// Version 10.0 Nov 2005
//
// 10.0 -> New code for 9bit protocol
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//
//                    R E T U R N   S T A C K   6 4
//                          X T A L  8 MHZ
//                      BootLoader of 1024 word
//
//*****************************************************************************
//
//                          F U S E   B I T
//
//( )7      ( )6     (X)BL12 (X)BL11  ( )BL02   ( )BL01    ( )Lock2   ( )Lock1
//( )7      ( )6     ( )     ( )      ( )       ( )M103C   ( )WDTON   ( )
//( )RSTDIS ( )WDON  (X)SPIEN(X)CKOPT (X)EESAVE ( )BOOTSZ1 (X)BOOTSZ0 (X)BOOTRST
//(X)BODLEV (X)BODEN ( )SUT1 ( )SUT0  ( )CKSEL3 ( )CKSEL2  ( )CKSEL1  ( )CKSEL0
//
//*****************************************************************************
//                          P I N   U S A G E
//
// PA0 -> Wind Direction S    0   deg
// PA1 -> Wind Direction SE   45  deg
// PA2 -> Wind Direction E    90  deg
// PA3 -> Wind Direction NE   135 deg
// PA4 -> Wind Direction N    180 deg
// PA5 -> Wind Direction NO   225 deg
// PA6 -> Wind Direction O    270 deg
// PA7 -> Wind Direction SO   315 deg
//
// PB0 -> n/c
// PB1 -> n/c
// PB2 -> n/c
// PB3 -> n/c
// PB4 -> Light Sensor
// PB5 -> HUMIDITY_DATA
// PB6 -> HUMIDITY_SCK
// PB7 -> n/c
//
// PC0 -> n/c
// PC1 -> n/c
// PC2 -> n/c
// PC3 -> n/c
// PC4 -> n/c
// PC5 -> n/c
// PC6 -> n/c
// PC7 -> n/c
//
// PD0 -> Wind Speed
// PD1 -> RS485 TXE
// PD2 -> RS485 RX
// PD3 -> RS485 TX
// PD4 -> Wind Speed
// PD5 -> n/c
// PD6 -> n/c
// PD7 -> n/c
//
// PE0 -> n/c
// PE1 -> n/c
// PE2 -> n/c
// PE3 -> n/c
// PE4 -> n/c
// PE5 -> LED Monitor
// PE6 -> Lightning Sensor
// PE7 -> Rain Tip Sensor
//
// PF0 -> Light Sensor
// PF1 -> n/c
// PF2 -> n/c
// PF3 -> n/c
// PF4 -> n/c
// PF5 -> n/c
// PF6 -> n/c
// PF7 -> n/c
//
// PG0 -> n/c
// PG1 -> n/c
// PG2 -> n/c
// PG3 -> n/c
// PG4 -> n/c
//
//*****************************************************************************
//                        T I M E R   U S A G E
//
// Timer 0 is use by real time clock
// Timer 1 not use
// Timer 2 is use by TaskManager
// Timer 3 not use
//
//*****************************************************************************
// NetWork Function
//-----------------------------------------------------------------------------
// Command
// 0xff           -> Get 16 bit software version
// 0xf5,0x55,0xaa -> Reset MCU
// 0xf0,0x55,L,V  -> Write eeprom at L value V
// 0xf1,0x55,L    -> Read eeprom at L
// 0x20           -> Get 16 bit Temperature * 10
// 0x21           -> Get 16 bit Humidity * 10
// 0x22           -> Get 16 bit Wind Speed * 10
// 0x23           -> Get 16 bit Wind Speed Max * 10
// 0x24           -> Get 16 bit Rain Day * 10
// 0x25           -> Get 16 bit Rain HRS * 10
// 0x26           -> Get 16 bit Lightning Day * 10
// 0x27           -> Get 16 bit Lightning HRS * 10
// 0x28           -> Get 16 bit Wind Chill * 10
// 0x29           -> Get 16 bit Humidex * 10
// 0x2a           -> Get 16 bit Light * 10
// 0x2b           -> Get 16 bit Night * 10
// 0x2c           -> Get 16 bit Wind Dir * 10
// 0x60           -> Setup time at 0H00
//-----------------------------------------------------------------------------
// EEprom
// 00     -> Not for use
// 01     -> Node Address
// 02     -> Night Trig
// 03     -> Day Trig
// 04     -> Wind Dir Ref
// 05@09  -> Free
// 10     -> Tip Qte float
// 11     -> Tip Qte float
// 12     -> Tip Qte float
// 13     -> Tip Qte float
// 14     -> Tip Qte float
// 15     -> Tip Qte float
// 16     -> Tip Qte float
// 17     -> Tip Qte float
// 18     -> Tip Qte float
// 19     -> Tip Qte float
// 20@xx  -> Free
//*****************************************************************************
//
// Rain Tip = 0.18868
//
//*****************************************************************************
//                            I N C L U D E
//*****************************************************************************
#include <iom64v.h>
#include <shortnametype.h>
#include <macros.h>
#include <stdlib.h>
#include <eeprom.h>
#include <math.h>
#include "TaskManager.h"

//*****************************************************************************
//                            D E F I N E
//*****************************************************************************
#define VERSION                 100
#define DEVICE                  1280
#define TRUE                    1
#define FALSE                   0
#define XTAL                    16000000
#define ACK                        1
#define noACK                      0

#define HUMIDITY_DDR            DDRB
#define HUMIDITY_PIN            PINB
#define HUMIDITY_PORT           PORTB
#define HUMIDITY_DATA           0x20
#define HUMIDITY_SCK            0x40
//adr    command r/w
#define HUMIDITY_STATUS_REG_W   0x06   //000    0011    0
#define HUMIDITY_STATUS_REG_R   0x07   //000    0011    1
#define HUMIDITY_MEASURE_TEMP   0x03   //000    0001    1
#define HUMIDITY_MEASURE_HUMI   0x05   //000    0010    1
#define HUMIDITY_RESET          0x1e   //000    1111    0

#define WIND_DDR                DDRA
#define WIND_PIN                PINA
#define WIND_PORT               PORTA

#define LED                     0x20

#define NET_DDR                 DDRD
#define NET_PIN                 PIND
#define NET_PORT                PORTD
#define NET_RX                  0x04
#define NET_TX                  0x08
#define NET_TXE                 0x02

#define NET_UBRRH               UBRR1H
#define NET_UBRRL               UBRR1L
#define NET_UCSRA               UCSR1A
#define NET_UCSRB               UCSR1B
#define NET_UCSRC               UCSR1C
#define NET_UDR                 UDR1

#define NET_RXBUFFER            10
#define NET_TXBUFFER            10

#define NET_GET_ADDRESS         200

#define NET_SPEED               19200

#define BROADCASTDEVTYPE        0xf1
#define BROADCAST               0xff

#define TIPQTE                  10
#define NIGHT                   2
#define DAY                     3
#define WINDREF                 4

//*****************************************************************************
//                            P R O T O T Y P E
//*****************************************************************************
void main(void);
void _StackOverflowed(char c);

float CalcWindChill(float Temperature,float WindSpeedMax);
float CalcHumidex(float Temperature,float Humidity);
void Timer0Ovf(void);
void Int0(void);
void Int6(void);
void Int7(void);
void ADC_interrupt(void);

void HumidityInit(void);
void HumidityDelay(void);
void HumidityWriteByte(ushort value);
ushort HumidityReadByte(ushort ack);
void HumidityTransStart(void);
void HumidityConnectionReset(void);
void HumiditySoftReset(void);
ushort HumidityReadStatus(void);
void HumidityWriteStatus(ushort value);
uint HumidityMeasure(ushort mode);
void HumidityCalc(float *p_humidity ,float *p_temperature);
void HumidityGet(float *p_humidity ,float *p_temperature);

void NetInit(void);
void NetRxChar(void);
void NetAnalyseData(void);
void NetWrite(int Value);
void NetTxByte(void);
void NetTxFinish(void);
void NetGetAddress(void);

//*****************************************************************************
//                      G L O B A L   V A R I A B L E
//*****************************************************************************
ushort NetAddress;
ushort NetRxData[NET_RXBUFFER];
ushort NetTxData[NET_TXBUFFER];
ushort *NetTxPtr;
short NetTxQte;
short NetBroadCast = FALSE;

char TipQteStr[10];
float TipQte;
char WindRef;

ushort HumiError = FALSE;

uint Revolution,RevolutionMax,RainTip,LightningStrike;

ushort BounceInt6,BounceInt7;

ushort DayTrig,NightTrig;

float Temperature,
      Humidity,
      WindSpeed,
      WindSpeedMax,
      RainDay,
      RainHRS,
      WindChill,
      Humidex,
      Light,
      Night;

uint  TemperatureInt,
      HumidityInt,
      WindSpeedInt,
      WindSpeedMaxInt,
      RainDayInt,
      RainHRSInt,
      LightningDay,
      LightningHRS,
      LightningDayInt,
      LightningHRSInt,
      WindChillInt,
      HumidexInt,
      LightInt,
      NightInt,
      WindDirInt;

float WindSpeedHRSTable[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
float RainHRSTable[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
int LightningHRSTable[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
uint WindDir = 0;

typedef struct
{
  ushort Second;
  ushort Minute;
  ushort Hour;
} TimeStruct;

TimeStruct Time;

//*****************************************************************************
//                      M A I N
//*****************************************************************************
void main()
{
  int i,j;
  float Tmp;
  int Quarter;

  //Timer0 is real time clock
  ASSR  |= (1<<AS0);            //set async mode
  TCCR0 = 0x05;                 //start timer / 128
  while ( ASSR & 0x07 ) WDR();  // Wait for Asynch mode
  TIMSK |= (1<<TOIE0);

  // Timer 1
  // Not use

  // Timer 2
  // Use by TaskManager

  // Timer 3
  // Not use

  // Port A
  WIND_DDR = 0x00;    // PortA as input for wind direction
  WIND_PORT = 0xff;   // Pull-up on PortA

  // Port B
  DDRB = 0x00;        // PortB as input
  PORTB = 0xef;       // Pull-up on NC pin

  // Port C
  DDRC = 0x00;        // PortC as input NC
  PORTC = 0xff;       // Pull-up on PortC

  // Port D
  DDRD = 0x00;        // PortD as input
  PORTD = 0xff;       // Pull-up on PortD

  // Port E
  DDRE = 0x20;        // PORTE 5 as output for led, all other are input
  PORTE = 0xff;       // Led off and pullup for all other input
  // PE6&7 are input for interrupt lightning and rain

  // Port F
  DDRF = 0x00;        // PortF as input
  PORTF = 0xfe;       // Pull-up on NC pin

  // ADC
  ADMUX = (1<<REFS0); // select input 0 with REF at VCC with external cap

  TaskInit();
  NetInit();
  HumidityInit();

  // External Int
  EICRA |= (1<<ISC01);  // Falling edge on int 0
  EICRB |= (1<<ISC61);  // Falling edge on int 6
  EICRB |= (1<<ISC71);  // Falling edge on int 7
  EIMSK |= (1<<INT7)+(1<<INT6)+(1<<INT0); // Enable Int0,6,7
  SEI();

  // WatchDog
  WDR();
  WDTCR = 0x0f;             // Enable WatchDog at 2.2 sec

  while (1)
  {
   PORTE ^= LED;
    WDR();
    _StackCheck();
    NetGetAddress();

    NightTrig = EEPROMread(NIGHT);
    DayTrig = EEPROMread(DAY);
    WindRef = EEPROMread(WINDREF);
    EEPROMReadBytes(TIPQTE,&TipQteStr[0],10);
    TipQte = atof(&TipQteStr[0]);

    if (HumiError == TRUE) HumidityInit();
    HumidityGet(&Humidity,&Temperature);
    WDR();

    // Wind Speed
    WindSpeed = (float)(1.974 * RevolutionMax); //(float)(3.9477 * RevolutionMax) / 2;
    WDR();

    // Wind Speed Max Hour
    Quarter = Time.Minute / 5;
    if (Quarter < 11) WindSpeedHRSTable[Quarter+1] = 0;
    else WindSpeedHRSTable[0]= 0;
    if (WindSpeed > WindSpeedHRSTable[Quarter]) WindSpeedHRSTable[Quarter] = WindSpeed;
    Tmp = 0;
    for (i=0;i<12;i++) if (Tmp < WindSpeedHRSTable[i]) Tmp = WindSpeedHRSTable[i];
    WindSpeedMax = Tmp;
    WDR();

    // Rain HRS
    if (Quarter < 11) RainHRSTable[Quarter+1] = 0;
    else RainHRSTable[0]= 0;
    RainHRSTable[Quarter] += RainTip;
    Tmp = 0;
    for (i=0;i<12;i++) Tmp += RainHRSTable[i];
    Tmp = Tmp * TipQte;
    RainHRS = Tmp;
    WDR();

    // Rain Day
    RainDay += RainTip * TipQte;
    RainTip = 0;
    WDR();

    // Lightning HRS
    if (Quarter < 11) LightningHRSTable[Quarter+1] = 0;
    else LightningHRSTable[0]= 0;
    LightningHRSTable[Quarter] += LightningStrike;
    j = 0;
    for (i=0;i<12;i++) j += LightningHRSTable[i];
    LightningHRS = j;
    WDR();

    // Lightning Day
    LightningDay += LightningStrike;
    LightningStrike = 0;
    WDR();

    if (WIND_PIN == ~0x01) WindDir = 0;
    if (WIND_PIN == ~0x03) WindDir = 225;
    if (WIND_PIN == ~0x02) WindDir = 450;
    if (WIND_PIN == ~0x06) WindDir = 675;
    if (WIND_PIN == ~0x04) WindDir = 900;
    if (WIND_PIN == ~0x0c) WindDir = 1125;
    if (WIND_PIN == ~0x08) WindDir = 1350;
    if (WIND_PIN == ~0x18) WindDir = 1575;
    if (WIND_PIN == ~0x10) WindDir = 1800;
    if (WIND_PIN == ~0x30) WindDir = 2025;
    if (WIND_PIN == ~0x20) WindDir = 2250;
    if (WIND_PIN == ~0x60) WindDir = 2475;
    if (WIND_PIN == ~0x40) WindDir = 2700;
    if (WIND_PIN == ~0xc0) WindDir = 2925;
    if (WIND_PIN == ~0x80) WindDir = 3150;
    if (WIND_PIN == ~0x81) WindDir = 3375;

    WindDir += (WindRef*225);
    if (WindDir >= 3600) WindDir = WindDir - 3600;
    WDR();

    // Light
    if (Light > 100) Light = 100;
    WDR();

    // Night

    // Wind Chill
    WindChill = CalcWindChill(Temperature,WindSpeedMax);
    if (WindChill > Temperature) WindChill = Temperature;
    WDR();

    // Humidex
    Humidex = CalcHumidex(Temperature,Humidity);
    if (Humidex < Temperature) Humidex = Temperature;
    WDR();

    HumidityInt = Humidity * 10;
    WDR();

    TemperatureInt = Temperature * 10;
    WDR();

    WindSpeedInt = WindSpeed * 10;
    WDR();

    WindSpeedMaxInt = WindSpeedMax * 10;
    WDR();

    RainDayInt = RainDay * 10;
    WDR();

    RainHRSInt = RainHRS * 10;
    WDR();

    LightningDayInt = LightningDay * 10;
    WDR();

    LightningHRSInt = LightningHRS * 10;
    WDR();

    WindChillInt = WindChill * 10;
    WDR();

    HumidexInt = Humidex * 10;
    WDR();

    WindDirInt = WindDir;
    WDR();

    LightInt = Light * 10;
    if (Light < NightTrig) NightInt = 10;
    if (Light > DayTrig) NightInt = 0;
    WDR();
  }
}

/******************************************************************************

Name:         void _StackOverflowed(char c)

Description:  This function is automaticaly called if
              the stack crash, PE5 will be clear.


Input:        none

Output:       PE5

Misc:
******************************************************************************/
void _StackOverflowed(char c)
{
  CLI();
  while(1);
}

/******************************************************************************

Name:         float CalcWindChill(float Temperature,float WindSpeedMax)

Description:  Calculate wind chill factor

Input:        float Temperature
              float WindSpeedMax

Output:       float WindChill

Misc:
******************************************************************************/
float CalcWindChill(float Temperature,float WindSpeedMax)
{
  float WindChill,fTemp1,fTemp2;

  if ((WindSpeedMax > 0) && (WindSpeedMax < 100))
  {
   // WindChill = 13.12 + (0.6215 * Temperature) - (11.37 * (pow(WindSpeedMax,0.16))) + (0.3965 * Temperature * (pow(WindSpeedMax,0.16)));
   fTemp1 = 0.3965 * Temperature * (pow(WindSpeedMax,0.16));
   WDR();
   fTemp2 = 11.37 * (pow(WindSpeedMax,0.16));
   WDR();
   WindChill = 0.6215 * Temperature;
   WindChill += 13.12;
   WindChill -= fTemp2;
   WindChill += fTemp1;
  }
  else WindChill = Temperature;

  return WindChill;
}

/******************************************************************************

Name:         float CalcHumidex(float Temperature,float Humidity)

Description:  Calculate wind chill factor

Input:        float Temperature
              float Humidity

Output:       float Humidex

Misc:
******************************************************************************/
float CalcHumidex(float Temperature,float Humidity)
{
  float Humidex,TempK,DewK,e,h;

  WDR();
  TempK = Temperature + 273.15;
  WDR();
  DewK = (TempK / ((-0.0001846 * log(Humidity / 100) * TempK) + 1.0));
  WDR();
  e = 6.11 * exp(5417.7530 * ((1 / 273.16) - (1 / DewK)));
  WDR();
  h = (0.5555) * (e - 10.0);
  WDR();
  Humidex = Temperature + h;
  WDR();

  return Humidex;
}

/******************************************************************************

Name:         void Timer0Ovf(void)

Description:  This function is automaticaly each second

Input:        none

Output:       none

Misc:         Drived by 32k xtal
******************************************************************************/
#pragma interrupt_handler Timer0Ovf:17
void Timer0Ovf(void)
{
  if (++Time.Second == 60)
  {
    Time.Second = 0;
    if (++Time.Minute == 60)
    {
      Time.Minute = 0;
      if (++Time.Hour == 24)
      {
        Time.Hour = 0;
        RainDay = 0;
        LightningDayInt = 0;
      }
    }
  }

  if (BounceInt6 != 0)
  {
    BounceInt6--;
    if (BounceInt6 == 0)
    {
      EIFR |= (1<<INTF6);
      EIMSK |= (1<<INT6);
    }
  }

  if (BounceInt7 != 0)
  {
    BounceInt7--;
    if (BounceInt7 == 0)
    {
      EIFR |= (1<<INTF7);
      EIMSK |= (1<<INT7);
    }
  }

  //if (RevolutionMax < Revolution) RevolutionMax = Revolution;
  //Revolution = 0;
  RevolutionMax = Revolution;
  Revolution = 0;

  ADCSRA = 0xdf;      // Start AD convertion
}

/******************************************************************************

Name:         void Int0(void)

Description:  This function is automaticaly 2 time each wind speed
revolution

Input:        none

Output:       none

Misc:
******************************************************************************/
#pragma interrupt_handler Int0:2
void Int0(void)
{
  Revolution++;
}

/******************************************************************************

Name:         void Int6(void)

Description:  This function is automaticaly called when lightning strike

Input:        none

Output:       none

Misc:
******************************************************************************/
#pragma interrupt_handler Int6:8
void Int6(void)
{
  EIMSK &= ~(1<<INT6);      // Disable int 6 for 2 second
  BounceInt6 = 2;
  LightningStrike++;
}

/******************************************************************************

Name:         void Int7(void)

Description:  This function is automaticaly called when cup tip


Input:        none

Output:       none

Misc:
******************************************************************************/
#pragma interrupt_handler Int7:9
void Int7(void)
{
  EIMSK &= ~(1<<INT7);      // Disable int 7 for 2 second
  BounceInt7 = 2;
  RainTip++;
}

/******************************************************************************

Name:         void ADC_interrupt(void)

Description:  This function is automaticaly called by the ADC interrupt
              and read light value

Input:        none

Output:       none

Misc:         Setup value LightInt & NightInt

******************************************************************************/
#pragma interrupt_handler ADC_interrupt:22
void ADC_interrupt(void)
{
  uint LightRaw;
  float Tmp;

  LightRaw = ADCL;
  LightRaw |= (int)ADCH << 8;

  // Sensor Max Output = Vcc - 1.15
  Tmp = LightRaw;
  Light = ((Tmp / 788) * 100);
}

//*****************************************************************************
//     H U M I D I T Y  & T E M P    F U N C T I O N
//*****************************************************************************
/******************************************************************************

Name:         void HumidityDelay(void)

Description:  Delay for SCLK

Input:        none

Output:       none


Misc:
******************************************************************************/
void HumidityDelay(void)
{
  int i;

  for (i=0;i<(XTAL/400000);i++) WDR();
}

/******************************************************************************

Name:         void HumidityInit(void)

Description:  Initialise port and constant used by
              the Humidity & Temp hardware


Input:        none

Output:       none

Misc:
******************************************************************************/
void HumidityInit(void)
{
  HUMIDITY_DDR |= HUMIDITY_DATA + HUMIDITY_SCK;
  HUMIDITY_PORT |= HUMIDITY_DATA + HUMIDITY_SCK;
  HumiditySoftReset();
}

/******************************************************************************

Name:         ushort HumidityWriteByte(ushort value)

Description:  writes a byte on the Sensibus and
              checks the acknowledge

Input:        ushort value -> byte to write

Output:       none


Misc:         If the device don't ACK set HumiError to TRUE;
******************************************************************************/
void HumidityWriteByte(ushort value)
{
  ushort i;

  HUMIDITY_DDR  |= HUMIDITY_DATA;       //DATA-line in output

  for (i=0x80;i>0;i/=2)                 //shift bit for masking
  {
    HumidityDelay();
    if (i & value) HUMIDITY_PORT |= HUMIDITY_DATA;
    else HUMIDITY_PORT &= ~HUMIDITY_DATA;
    HumidityDelay();
    HUMIDITY_PORT |= HUMIDITY_SCK;
    HumidityDelay();
    HUMIDITY_PORT &= ~HUMIDITY_SCK;
  }

  HUMIDITY_PORT |= HUMIDITY_DATA;       //release DATA-line
  HUMIDITY_DDR  &= ~HUMIDITY_DATA;      //DATA-line in input
  HumidityDelay();
  HUMIDITY_PORT |= HUMIDITY_SCK;        //clk #9 for ack
  HumidityDelay();
  if (HUMIDITY_PIN & HUMIDITY_DATA) HumiError = TRUE;
  HUMIDITY_PORT &= ~HUMIDITY_SCK;
  HumidityDelay();
}

/******************************************************************************

Name:         ushort HumidityReadByte(ushort ack)

Description:  reads a byte form the Sensibus and gives
              an acknowledge in case of "ack=1"

Input:        ushort ack -> ack status

Output:       ushort value readed

Misc:
******************************************************************************/
ushort HumidityReadByte(ushort ack)
{
  ushort i,val=0;

  HUMIDITY_PORT |= HUMIDITY_DATA;       //release DATA-line
  HUMIDITY_DDR  &= ~HUMIDITY_DATA;      //DATA-line in input

  for (i=0x80;i>0;i/=2)                 //shift bit for masking
  {
    HumidityDelay();
    HUMIDITY_PORT |= HUMIDITY_SCK;      //clk for SENSI-BUS
    HumidityDelay();
    if (HUMIDITY_PIN & HUMIDITY_DATA) val=(val | i);  //read bit
    HUMIDITY_PORT &= ~HUMIDITY_SCK;
  }

  if (ack == 1)
  {
    HUMIDITY_DDR  |= HUMIDITY_DATA;    //DATA-line in output
    HUMIDITY_PORT &= ~HUMIDITY_DATA;   //"ack==1" pull down DATA-Line
    HumidityDelay();
    HUMIDITY_PORT |= HUMIDITY_SCK;
    HumidityDelay();
    HUMIDITY_PORT &= ~HUMIDITY_SCK;
  }
  else
  {
    HumidityDelay();
    HUMIDITY_PORT |= HUMIDITY_SCK;
    HumidityDelay();
    HUMIDITY_PORT &= ~HUMIDITY_SCK;
  }
  return val;
}

/******************************************************************************

Name:         ushort HumidityTransStart(void)

Description:  Generates a transmission start

Input:        none

Output:       none

Misc:
      _____         ________
DATA:      |_______|
          ___     ___
SCK : ___|   |___|   |______
******************************************************************************/
void HumidityTransStart(void)
{
  HUMIDITY_DDR  |= HUMIDITY_DATA;       //DATA-line in output

  HUMIDITY_PORT |= HUMIDITY_DATA;       //DATA=1
  HUMIDITY_PORT &= ~HUMIDITY_SCK;       //SCK=0
  HumidityDelay();
  HUMIDITY_PORT |= HUMIDITY_SCK;        //SCK=1
  HumidityDelay();
  HUMIDITY_PORT &= ~HUMIDITY_DATA;      //DATA=0
  HumidityDelay();
  HUMIDITY_PORT &= ~HUMIDITY_SCK;       //SCK=0
  HumidityDelay();
  HUMIDITY_PORT |= HUMIDITY_SCK;        //SCK=1
  HumidityDelay();
  HUMIDITY_PORT |= HUMIDITY_DATA;       //DATA=1
  HumidityDelay();
  HUMIDITY_PORT &= ~HUMIDITY_SCK;       //SCK=0
  HumidityDelay();
}

/******************************************************************************

Name:         void HumidityConnectionReset(void)

Description:  communication Reset: DATA-line=1 and at
              least 9 SCK cycles followed by transstart

Input:        none

Output:       none

Misc:
      _____________________________________________________         ________
DATA:                                                      |_______|
         _    _    _    _    _    _    _    _    _        ___     ___
SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
******************************************************************************/
void HumidityConnectionReset(void)
{
  ushort i;

  HUMIDITY_DDR  |= HUMIDITY_DATA;       //DATA-line in output
  HUMIDITY_PORT |= HUMIDITY_DATA;       //DATA=1
  HUMIDITY_PORT &= ~HUMIDITY_SCK;       //SCK=0

  for (i=0;i<9;i++)                     //9 SCK cycles
  {
    HumidityDelay();
    HUMIDITY_PORT |= HUMIDITY_SCK;      //SCK=1
    HumidityDelay();
    HUMIDITY_PORT &= ~HUMIDITY_SCK;     //SCK=0
  }
  HumidityTransStart();                 //transmission start
  HumiError = FALSE;
}

/******************************************************************************

Name:         void HumiditySoftReset(void)

Description:  Resets the sensor by a softReset

Input:        none

Output:       none

Misc:

******************************************************************************/
void HumiditySoftReset(void)
{
  int i;
  HumidityConnectionReset();           //Reset communication
  HumidityWriteByte(HUMIDITY_RESET);   //send Reset-command to sensor
  for (i=0;i<100;i++) HumidityDelay(); // 11ms delay
}

/******************************************************************************

Name:         ushort HumidityReadStatus(void)

Description:  reads the status register with checksum (8-bit)

Input:        none

Output:       ushort status byte

Misc:

******************************************************************************/
ushort HumidityReadStatus(void)
{
  ushort value;

  HumidityTransStart();                     //transmission start
  HumidityWriteByte(HUMIDITY_STATUS_REG_R); //send command to sensor
  value = HumidityReadByte(ACK);            //read status register (8-bit)
  HumidityReadByte(noACK);              //dummy read checksum (8-bit)
  return value;
}

/******************************************************************************

Name:         void HumidityWriteStatus(ushort value)

Description:  writes the status register with checksum (8-bit)

Input:        ushort value to write in the status register

Output:       none

Misc:

******************************************************************************/
void HumidityWriteStatus(ushort value)
{
  HumidityTransStart();                       //transmission start
  HumidityWriteByte(HUMIDITY_STATUS_REG_W);   //send command to sensor
  HumidityWriteByte(value);                   //send value of status register
}

/******************************************************************************

Name:         uint HumidityMeasure(ushort mode)

Description:  makes a measurement (humidity/temperature)

Input:        mode -> HUMI or TEMP

Output:       unsinged int Value mesured

Misc:

******************************************************************************/
uint HumidityMeasure(ushort mode)
{
  ushort msb,lsb;
  uint i,j;

  HumidityTransStart();   //transmission start
  switch (mode)           //send command to sensor
  {
    case HUMIDITY_MEASURE_TEMP : HumidityWriteByte(HUMIDITY_MEASURE_TEMP);
    break;
    case HUMIDITY_MEASURE_HUMI : HumidityWriteByte(HUMIDITY_MEASURE_HUMI);
    break;
    default     : break;
  }

  HUMIDITY_PORT |= HUMIDITY_DATA;   //release DATA-line
  HUMIDITY_DDR  &= ~HUMIDITY_DATA;  //DATA-line in input

  for (i=0;i<=65530;i++)
  {
    for (j=0;j<10;j++) WDR();
    if((HUMIDITY_PIN & HUMIDITY_DATA) == 0) break;  //wait until sensor
  }                                           &n