No changes between revisions
/Designs/Measuring_instruments/AWS01A/SW/AVR/config.h
0,0 → 1,19
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
 
// SHT11 hum/temp sensor
#define SHT11_PORT D
#define SHT11_SCL (1<<PD4)
#define SHT11_SDA (1<<PD7)
#define SHT11_LOWRES 1 // 0: 12/14bit (SHT11), 1: 8/12bit (SHT11+FOST02)
 
#define GLUE(a, b) a##b
#define PORT(x) GLUE(PORT, x)
#define PIN(x) GLUE(PIN, x)
#define DDR(x) GLUE(DDR, x)
 
#define setBits(port,mask) do{ (port) |= (mask); }while(0)
#define clrBits(port,mask) do{ (port) &= ~(mask); }while(0)
#define tstBits(port,mask) ((port) & (mask))
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/Designs/Measuring_instruments/AWS01A/SW/AVR/sht11.c
0,0 → 1,224
#include "config.h"
#include "sht11.h"
 
#define SHT11_CMD_TEMP 0x03
#define SHT11_CMD_HUMID 0x05
#define SHT11_CMD_WSTAT 0x06
#define SHT11_CMD_RSTAT 0x07
#define SHT11_CMD_RESET 0x1E
 
/////////////////////////////////////////////////////////////////////////////
// This version needs external pullups on SDA!
/////////////////////////////////////////////////////////////////////////////
 
static void delay(void) { _delay_us(2); }
 
static void scl_hi(void) { setBits(PORT(SHT11_PORT), SHT11_SCL); }
static void scl_lo(void) { clrBits(PORT(SHT11_PORT), SHT11_SCL); }
static void sda_hi(void) { clrBits(DDR(SHT11_PORT), SHT11_SDA); }
static void sda_lo(void) { setBits(DDR(SHT11_PORT), SHT11_SDA); }
static void scl_pulse(void) { scl_hi(); delay(); scl_lo(); }
static uint8_t sda_val(void) { return (PIN(SHT11_PORT) & SHT11_SDA) != 0; }
 
/////////////////////////////////////////////////////////////////////////////
 
static uint8_t crc_value;
 
static void
crc8(uint8_t b)
{
for (uint8_t i = 0; i < 8; ++i) {
if ((crc_value ^ b) & 0x80) {
crc_value <<= 1;
crc_value ^= 0x31;
} else
crc_value <<= 1;
b <<= 1;
}
}
 
/////////////////////////////////////////////////////////////////////////////
 
static uint8_t
send(uint16_t b)
{
crc8(b);
// data
for (uint8_t i = 0; i < 8; ++i) {
if (b & 0x80)
sda_hi();
else
sda_lo();
b <<= 1;
delay();
scl_pulse();
}
 
// acknowledge
sda_hi();
delay();
uint8_t ack = sda_val();
scl_pulse();
return ack;
}
 
static uint8_t
recv_data(void)
{
// data
uint8_t b = 0;
for (uint8_t i = 0; i < 8; ++i) {
// data is transmitted MSB first
b <<= 1;
if (sda_val())
b |= 1;
scl_pulse();
delay();
}
 
// lo acknowledge
sda_lo();
delay();
scl_pulse();
sda_hi();
delay();
 
crc8(b);
return b;
}
 
static uint8_t
recv_crc(void)
{
// data
uint8_t b = 0;
for (uint8_t i = 0; i < 8; ++i) {
// CRC is transmitted LSB first
b >>= 1;
if (sda_val())
b |= 0x80;
scl_pulse();
delay();
}
 
// hi acknowledge
sda_hi();
delay();
scl_pulse();
delay();
 
return b;
}
 
static void
start(void)
{
clrBits(PORT(SHT11_PORT), SHT11_SCL | SHT11_SDA); // SCK output low, SDA input/high
setBits(DDR(SHT11_PORT), SHT11_SCL);
clrBits(DDR(SHT11_PORT), SHT11_SDA);
delay();
 
// reset communication
for (uint8_t i = 0; i < 10; ++i) {
scl_pulse();
delay();
}
 
// "start" sequence
scl_hi(); delay();
sda_lo(); delay();
scl_lo(); delay();
scl_hi(); delay();
sda_hi(); delay();
scl_lo(); delay();
}
 
/////////////////////////////////////////////////////////////////////////////
// Measurement sequence.
 
uint8_t
sht11_start_temp(void)
{
crc_value = SHT11_LOWRES << 7; // bit-reversed
start();
return send(SHT11_CMD_TEMP) == 0;
}
 
uint8_t
sht11_start_humid(void)
{
crc_value = SHT11_LOWRES << 7; // bit-reversed
start();
return send(SHT11_CMD_HUMID) == 0;
}
 
uint8_t
sht11_ready(void)
{
return sda_val() == 0;
}
 
static int16_t
result(void)
{
if (!sht11_ready())
return SHT11_UNAVAIL;
int16_t v = recv_data() << 8; v |= recv_data();
uint8_t crc = recv_crc();
if (crc != crc_value)
return SHT11_CRC_FAIL;
return v;
}
 
int16_t
sht11_result_temp(void)
{
int16_t v = result();
if (sht11_valid(v)) {
#if SHT11_LOWRES
v = v * 4 - 4000;
#else
v -= 4000;
#endif
}
return v;
}
 
int16_t
sht11_result_humid(void)
{
int16_t v = result();
if (sht11_valid(v)) {
#if SHT11_LOWRES
// inspired by Werner Hoch, modified for low resolution mode
const int32_t C1 = (int32_t)(-4.0 * 100);
const int32_t C2 = (int32_t)(0.648 * 100 * (1L<<24));
const int32_t C3 = (int32_t)(-7.2e-4 * 100 * (1L<<24));
v = (int16_t)((((C3 * v + C2) >> 7) * v + (1L<<16)) >> 17) + C1;
#else
// inspired by Werner Hoch
const int32_t C1 = (int32_t)(-4.0 * 100);
const int32_t C2 = (int32_t)(0.0405 * 100 * (1L<<28));
const int32_t C3 = (int32_t)(-2.8e-6 * 100 * (1L<<30));
v = (int16_t)((((((C3 * v) >> 2) + C2) >> 11) * v + (1L<<16)) >> 17) + C1;
#endif
}
return v;
}
 
/////////////////////////////////////////////////////////////////////////////
// Initialize.
 
void
sht11_init(void)
{
start();
send(SHT11_CMD_RESET);
_delay_ms(11);
 
start();
send(SHT11_CMD_WSTAT);
send(SHT11_LOWRES);
}
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/Designs/Measuring_instruments/AWS01A/SW/AVR/sht11.h
0,0 → 1,31
/*
* Initialize.
*/
void sht11_init(void);
 
 
/*
* Start measurement (humidity or temperature).
* Return "device found".
* Afterwards poll sht11_ready.
*/
uint8_t sht11_start_temp(void);
uint8_t sht11_start_humid(void);
 
/*
* Return 0 unless measurement completed.
*/
uint8_t sht11_ready(void);
 
/*
* Return result of measurement.
* H: 100*%RH (0..10000)
* T: 100*T
* Return -32xxx on failure.
*/
int16_t sht11_result_temp(void);
int16_t sht11_result_humid(void);
 
#define SHT11_UNAVAIL -32768
#define SHT11_CRC_FAIL -32767
#define sht11_valid(v) ((v) > -32000)
Property changes:
Added: svn:executable
+*
\ No newline at end of property