Browse Source

Fix incorrect check for CRC when reading temperature. Fix Celsius conversion. Preliminary support for programmable resolution.

main
David Antliff 8 years ago
parent
commit
4e58944a8a
  1. 28
      main/ds18b20.c
  2. 18
      main/ds18b20.h
  3. 2
      main/ds18b20_main.c
  4. 49
      main/owb.c

28
main/ds18b20.c

@ -76,6 +76,29 @@ static bool _is_init(const DS18B20_Info * ds18b20_info)
return ok; return ok;
} }
static bool _check_resolution(DS18B20_RESOLUTION resolution)
{
return (resolution >= DS18B20_RESOLUTION_9_BIT) && (resolution <= DS18B20_RESOLUTION_12_BIT);
}
static float _decode_temp(uint8_t lsb, uint8_t msb, DS18B20_RESOLUTION resolution)
{
float result = 0.0f;
if (_check_resolution(resolution))
{
// masks to remove undefined bits from result
static const uint8_t lsb_mask[4] = { ~0x03, ~0x02, ~0x01, ~0x00 };
uint8_t lsb_masked = lsb_mask[resolution - DS18B20_RESOLUTION_9_BIT] & lsb;
int16_t raw = (msb << 8) | lsb_masked;
result = raw / 16.0f;
}
else
{
ESP_LOGE(TAG, "Unsupported resolution %d", resolution);
}
return result;
}
DS18B20_Info * ds18b20_malloc(void) DS18B20_Info * ds18b20_malloc(void)
{ {
DS18B20_Info * ds18b20_info = malloc(sizeof(*ds18b20_info)); DS18B20_Info * ds18b20_info = malloc(sizeof(*ds18b20_info));
@ -109,6 +132,7 @@ void ds18b20_init(DS18B20_Info * ds18b20_info, OneWireBus * bus, OneWireBus_ROMC
ds18b20_info->bus = bus; ds18b20_info->bus = bus;
ds18b20_info->rom_code = rom_code; ds18b20_info->rom_code = rom_code;
ds18b20_info->use_crc = false; ds18b20_info->use_crc = false;
ds18b20_info->resolution = DS18B20_RESOLUTION_12_BIT;
ds18b20_info->init = true; ds18b20_info->init = true;
} }
else else
@ -149,7 +173,7 @@ float ds18b20_get_temp(DS18B20_Info * ds18b20_info)
uint8_t temp_LSB = 0; uint8_t temp_LSB = 0;
uint8_t temp_MSB = 0; uint8_t temp_MSB = 0;
if (ds18b20_info->use_crc) if (!ds18b20_info->use_crc)
{ {
// Without CRC: // Without CRC:
temp_LSB = owb_read_byte(bus); temp_LSB = owb_read_byte(bus);
@ -173,7 +197,7 @@ float ds18b20_get_temp(DS18B20_Info * ds18b20_info)
} }
ESP_LOGD(TAG, "temp_LSB 0x%02x, temp_MSB 0x%02x", temp_LSB, temp_MSB); ESP_LOGD(TAG, "temp_LSB 0x%02x, temp_MSB 0x%02x", temp_LSB, temp_MSB);
temp = (float)(((temp_MSB << 8) + temp_LSB) >> 4); temp = _decode_temp(temp_LSB, temp_MSB, ds18b20_info->resolution);
} }
else else
{ {

18
main/ds18b20.h

@ -40,16 +40,28 @@
extern "C" { extern "C" {
#endif #endif
/**
* @brief Symbols for the supported temperature resolution of the device.
*/
typedef enum
{
DS18B20_RESOLUTION_9_BIT = 9, ///< 9-bit resolution, LSB bits 2,1,0 undefined
DS18B20_RESOLUTION_10_BIT = 10, ///< 10-bit resolution, LSB bits 1,0 undefined
DS18B20_RESOLUTION_11_BIT = 11, ///< 11-bit resolution, LSB bit 0 undefined
DS18B20_RESOLUTION_12_BIT = 12, ///< 12-bit resolution (default)
} DS18B20_RESOLUTION;
/** /**
* @brief Structure containing information related to a single DS18B20 device connected * @brief Structure containing information related to a single DS18B20 device connected
* via a 1-Wire bus. * via a 1-Wire bus.
*/ */
typedef struct typedef struct
{ {
bool init; ///< True if struct has been initialised, otherwise false. bool init; ///< True if struct has been initialised, otherwise false
bool use_crc; ///< True if CRC checks are to be used when retrieving information from a device on the bus bool use_crc; ///< True if CRC checks are to be used when retrieving information from a device on the bus
OneWireBus * bus; ///< Pointer to 1-Wire bus information relevant to this device. OneWireBus * bus; ///< Pointer to 1-Wire bus information relevant to this device
OneWireBus_ROMCode rom_code; ///< The ROM code used to address this device on the bus. OneWireBus_ROMCode rom_code; ///< The ROM code used to address this device on the bus
DS18B20_RESOLUTION resolution; ///< Temperature measurement resolution per reading
} DS18B20_Info; } DS18B20_Info;
/** /**

2
main/ds18b20_main.c

@ -42,7 +42,7 @@
void app_main() void app_main()
{ {
esp_log_level_set("*", ESP_LOG_INFO); esp_log_level_set("*", ESP_LOG_DEBUG);
// Create a 1-Wire bus // Create a 1-Wire bus
#ifdef USE_STATIC #ifdef USE_STATIC

49
main/owb.c

@ -42,28 +42,27 @@ static const char * TAG = "owb";
/// @cond ignore /// @cond ignore
struct _OneWireBus_Timing struct _OneWireBus_Timing
{ {
int A, B, C, D, E, F, G, H, I, J; uint32_t A, B, C, D, E, F, G, H, I, J;
}; };
//// @endcond //// @endcond
// 1-Wire timing delays (standard) in ticks (quarter-microseconds). // 1-Wire timing delays (standard) in microseconds.
// Labels and values are from https://www.maximintegrated.com/en/app-notes/index.mvp/id/126
static const struct _OneWireBus_Timing _StandardTiming = { static const struct _OneWireBus_Timing _StandardTiming = {
6 * 4, 6, // A - read/write "1" master pull DQ low duration
64 * 4, 64, // B - write "0" master pull DQ low duration
60 * 4, 60, // C - write "1" master pull DQ high duration
10 * 4, 10, // D - write "0" master pull DQ high duration
9 * 4, 9, // E - read master pull DQ high duration
55 * 4, 55, // F - complete read timeslot + 10ms recovery
0, // G 0, // G - wait before reset
480 * 4, // H 480, // H - master pull DQ low duration
70 * 4, // I 70, // I - master pull DQ high duration
410 * 4, // J 410, // J - complete presence timeslot + recovery
}; };
static void _tick_delay(int ticks) static void _us_delay(uint32_t time_us)
{ {
// Each tick is 0.25 microseconds.
float time_us = ticks / 4.0;
ets_delay_us(time_us); ets_delay_us(time_us);
} }
@ -90,7 +89,7 @@ bool _is_init(const OneWireBus * bus)
} }
/** /**
* @brief Generate a 1-Wire reset. * @brief Generate a 1-Wire reset (initialization).
* @param[in] bus Initialised bus instance. * @param[in] bus Initialised bus instance.
* @return true if device is present, otherwise false. * @return true if device is present, otherwise false.
*/ */
@ -101,15 +100,15 @@ static bool _reset(const OneWireBus * bus)
{ {
gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT); gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT);
_tick_delay(bus->timing->G); _us_delay(bus->timing->G);
gpio_set_level(bus->gpio, 0); // Drive DQ low gpio_set_level(bus->gpio, 0); // Drive DQ low
_tick_delay(bus->timing->H); _us_delay(bus->timing->H);
gpio_set_level(bus->gpio, 1); // Release the bus gpio_set_level(bus->gpio, 1); // Release the bus
_tick_delay(bus->timing->I); _us_delay(bus->timing->I);
gpio_set_direction(bus->gpio, GPIO_MODE_INPUT); gpio_set_direction(bus->gpio, GPIO_MODE_INPUT);
int level1 = gpio_get_level(bus->gpio); int level1 = gpio_get_level(bus->gpio);
_tick_delay(bus->timing->J); // Complete the reset sequence recovery _us_delay(bus->timing->J); // Complete the reset sequence recovery
int level2 = gpio_get_level(bus->gpio); int level2 = gpio_get_level(bus->gpio);
present = (level1 == 0) && (level2 == 1); // Sample for presence pulse from slave present = (level1 == 0) && (level2 == 1); // Sample for presence pulse from slave
@ -131,9 +130,9 @@ static void _write_bit(const OneWireBus * bus, int bit)
int delay2 = bit ? bus->timing->B : bus->timing->D; int delay2 = bit ? bus->timing->B : bus->timing->D;
gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT); gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT);
gpio_set_level(bus->gpio, 0); // Drive DQ low gpio_set_level(bus->gpio, 0); // Drive DQ low
_tick_delay(delay1); _us_delay(delay1);
gpio_set_level(bus->gpio, 1); // Release the bus gpio_set_level(bus->gpio, 1); // Release the bus
_tick_delay(delay2); _us_delay(delay2);
} }
} }
@ -148,13 +147,13 @@ static int _read_bit(const OneWireBus * bus)
{ {
gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT); gpio_set_direction(bus->gpio, GPIO_MODE_OUTPUT);
gpio_set_level(bus->gpio, 0); // Drive DQ low gpio_set_level(bus->gpio, 0); // Drive DQ low
_tick_delay(bus->timing->A); _us_delay(bus->timing->A);
gpio_set_level(bus->gpio, 1); // Release the bus gpio_set_level(bus->gpio, 1); // Release the bus
_tick_delay(bus->timing->E); _us_delay(bus->timing->E);
gpio_set_direction(bus->gpio, GPIO_MODE_INPUT); gpio_set_direction(bus->gpio, GPIO_MODE_INPUT);
int level = gpio_get_level(bus->gpio); int level = gpio_get_level(bus->gpio);
_tick_delay(bus->timing->F); // Complete the timeslot and 10us recovery _us_delay(bus->timing->F); // Complete the timeslot and 10us recovery
result = level & 0x01; result = level & 0x01;
} }
return result; return result;

Loading…
Cancel
Save