diff --git a/lib/adc.c b/lib/adc.c index 66a4482..33938be 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -23,7 +23,7 @@ void adc_disable() /** Sample analog pin with 8-bit precision */ uint8_t adc_read_byte(uint8_t channel) { - write_low_nibble(ADMUX, channel); // Select channel to sample + set_low_nibble(ADMUX, channel); // Select channel to sample sbi(ADMUX, ADLAR); // Align result to left sbi(ADCSRA, ADSC); // Start conversion @@ -36,7 +36,7 @@ uint8_t adc_read_byte(uint8_t channel) /** Sample analog pin with 10-bit precision */ uint16_t adc_read_word(uint8_t channel) { - write_low_nibble(ADMUX, channel); // Select channel to sample + set_low_nibble(ADMUX, channel); // Select channel to sample cbi(ADMUX, ADLAR); // Align result to right sbi(ADCSRA, ADSC); // Start conversion diff --git a/lib/dht11.c b/lib/dht11.c new file mode 100644 index 0000000..70b57f1 --- /dev/null +++ b/lib/dht11.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +#include "iopins.h" +#include "dht11.h" + +/** Read one bit */ +bool _dht11_rxbit(const uint8_t pin) +{ + // Wait until start of pulse + while (is_low_n(pin)); + + uint8_t cnt = 0; + while (is_high_n(pin)) + { + cnt++; + _delay_us(5); + } + + return (cnt > 8); +} + + +/** Read one byte */ +uint8_t _dht11_rxbyte(const uint8_t pin) +{ + uint8_t byte = 0; + + for (uint8_t i = 0; i < 8; i++) + { + if (_dht11_rxbit(pin)) + byte |= (1 << (7 - i)); + } + + return byte; +} + + +/** Read tehmperature and humidity from the DHT11, returns false on failure */ +bool dht11_read(const uint8_t pin, dht11_result_t* result) +{ + // bus down for > 18 ms + as_output_n(pin); + pin_low_n(pin); + _delay_ms(20); + + // bus up for 20-40us + pin_high_n(pin); + _delay_us(20); + + // release + as_input_pu_n(pin); + + // DHT should send 80us LOW & 80us HIGH + + _delay_us(40); + if (!is_low_n(pin)) + return false; // init error + + _delay_us(80); + if (!is_high_n(pin)) + return false; // init error + + // skip to start of first bit + _delay_us(50); + + // Receive 5 data bytes (Rh int, Rh dec, Temp int, Temp dec, Checksum) + // Decimal bytes are zero for DHT11 -> we can ignore them. + uint8_t bytes[5]; + uint8_t sum = 0; + + for (uint8_t i = 0; i < 5; i++) + { + uint8_t b = _dht11_rxbyte(pin); + bytes[i] = b; + if (i < 4) sum += b; + } + + // Verify checksum + if (sum != bytes[4]) return false; + + result->rh = bytes[0]; + result->temp = bytes[2]; + + return true; +} diff --git a/lib/dht11.h b/lib/dht11.h new file mode 100644 index 0000000..53300e3 --- /dev/null +++ b/lib/dht11.h @@ -0,0 +1,16 @@ +#pragma once + +// +// Reading temperature and relative humidity from DHT11 +// + +#include +#include + +typedef struct { + int8_t temp; + int8_t rh; +} dht11_result_t; + +/** Read tehmperature and humidity from the DHT11, returns false on failure */ +bool dht11_read(const uint8_t pin, dht11_result_t* result); diff --git a/lib/onewire.c b/lib/onewire.c index ac9e58e..97bea71 100644 --- a/lib/onewire.c +++ b/lib/onewire.c @@ -26,7 +26,7 @@ bool ow_reset(const uint8_t pin) /** Send a single bit */ -void ow_tx_bit(const uint8_t pin, const bool bit) +void _ow_tx_bit(const uint8_t pin, const bool bit) { as_output_n(pin); pin_low_n(pin); @@ -48,13 +48,13 @@ void ow_send(const uint8_t pin, const uint8_t byte) { for (uint8_t i = 0; i < 8; i++) { - ow_tx_bit(pin, (byte >> i) & 0x01); + _ow_tx_bit(pin, (byte >> i) & 0x01); } } /** Read a single bit */ -bool ow_rx_bit(const uint8_t pin) +bool _ow_rx_bit(const uint8_t pin) { as_output_n(pin); pin_low_n(pin); @@ -78,7 +78,7 @@ uint8_t ow_read(const uint8_t pin) for (uint8_t i = 0; i < 8; i++) { - byte = (byte >> 1) | (ow_rx_bit(pin) << 7); + byte = (byte >> 1) | (_ow_rx_bit(pin) << 7); } return byte; @@ -186,6 +186,7 @@ uint8_t crc8(uint8_t *addr, uint8_t len) // --- utils for DS1820 --- + /** Read temperature in 0.0625°C, or TEMP_ERROR on error */ int16_t ds1820_read_temp(uint8_t pin) { @@ -222,3 +223,19 @@ int16_t ds1820_read_temp_c(uint8_t pin) return (int16_t) temp; } + +bool ds1820_single_measure(uint8_t pin) +{ + ow_reset(pin); + ow_send(pin, SKIP_ROM); + ow_send(pin, CONVERT_T); + + if(!ow_wait_ready(pin)) { + return false; + } + + ow_reset(pin); + ow_send(pin, SKIP_ROM); + + return true; +} diff --git a/lib/onewire.h b/lib/onewire.h index bf0c252..24e4a6c 100644 --- a/lib/onewire.h +++ b/lib/onewire.h @@ -1,5 +1,9 @@ #pragma once +// +// Utils for Dallas OneWire bus (DS1820 etc) +// + #include #include @@ -10,47 +14,45 @@ /** Perform bus reset. Returns true if any device is connected */ bool ow_reset(const uint8_t pin); - -/** Send a single bit */ -void ow_tx_bit(const uint8_t pin, const bool bit); - - /** Send a single byte */ void ow_send(const uint8_t pin, const uint8_t byte); - -/** Read a single bit */ -bool ow_rx_bit(const uint8_t pin); - - /** Read a single byte */ uint8_t ow_read(const uint8_t pin); - /** Wait until the device is ready. Returns false on timeout */ bool ow_wait_ready(const uint8_t pin); - /** Read bytes into an array */ void ow_read_arr(const uint8_t pin, uint8_t* array, const uint8_t count); - /** Compute a CRC16 checksum */ uint16_t crc16( uint8_t *data, uint8_t len); - /** Compute a CRC8 checksum */ uint8_t crc8(uint8_t *addr, uint8_t len); - // --- utils for DS1820 --- #define TEMP_ERROR -32768 -/** Read temperature in 0.0625°C, or TEMP_ERROR on error */ +/** + * Read temperature in 0.0625°C, or TEMP_ERROR on error + * Use this where you'd normally use READ_SCRATCHPAD + */ int16_t ds1820_read_temp(uint8_t pin); -/** Read temperature in 0.1°C, or TEMP_ERROR on error */ +/** + * Read temperature in 0.1°C, or TEMP_ERROR on error + * Use this where you'd normally use READ_SCRATCHPAD + */ int16_t ds1820_read_temp_c(uint8_t pin); +/** + * Perform a temperature measurement with single DS1820 device on the line + * Can be followed by a call to read temperature (READ_SCRATCHPAD). + * + * Returns false on failure (device not connected) + */ +bool ds1820_single_measure(uint8_t pin);