Browse Source

Add support for multiple devices on single 1-Wire bus.

main
David Antliff 8 years ago
parent
commit
33a03fd31f
  1. 4
      main/ds18b20.c
  2. 59
      main/ds18b20_main.c
  3. 164
      main/owb.c
  4. 23
      main/owb.h

4
main/ds18b20.c

@ -123,7 +123,9 @@ float ds18b20_get_temp(DS18B20_Info * ds18b20_info)
// reset
owb_reset(bus);
owb_write_byte(bus, OWB_ROM_SKIP);
//owb_write_byte(bus, OWB_ROM_SKIP);
owb_write_byte(bus, OWB_ROM_MATCH);
owb_write_rom_code(bus, ds18b20_info->rom_code);
owb_write_byte(bus, DS18B20_FUNCTION_SCRATCHPAD_READ);
uint8_t temp_LSB = 0;

59
main/ds18b20_main.c

@ -4,6 +4,7 @@
#include "freertos/task.h"
#include "esp_system.h"
// Uncomment to enable static (stack-based) allocation of instances and avoid malloc/free.
//#define USE_STATIC 1
#ifdef USE_STATIC
@ -16,6 +17,7 @@
#define GPIO_DS18B20_0 (GPIO_NUM_4)
#define MAX_DEVICES (8)
void app_main()
@ -31,27 +33,72 @@ void app_main()
owb_init(owb, GPIO_DS18B20_0);
owb_use_crc(owb, true); // enable CRC check for ROM code
//owb_search(); // find all connected devices
//OneWireBusROMCode rom_code = 0x1162e87ccee28;
uint64_t rom_code = owb_read_rom(owb);
printf("1-Wire ROM code 0x%08" PRIx64 "\n", rom_code);
// find all connected devices
uint8_t device_rom_codes[8][MAX_DEVICES] = {0};
int num_devices = 0;
OneWireBus_SearchState search_state = {0};
bool found = owb_search_first(owb, &search_state);
while (found)
{
printf("Device %d found: ", num_devices);
for (int i = 7; i >= 0; i--)
{
device_rom_codes[num_devices][i] = search_state.rom_code[i];
printf("%02x", search_state.rom_code[i]);
}
printf("\n");
++num_devices;
found = owb_search_next(owb, &search_state);
}
//uint64_t rom_code = 0x0001162e87ccee28; // pink
//uint64_t rom_code = 0xf402162c6149ee28; // green
//uint64_t rom_code = 0x1502162ca5b2ee28; // orange
//uint64_t rom_code = owb_read_rom(owb);
//printf("1-Wire ROM code 0x%08" PRIx64 "\n", rom_code);
// Create a DS18B20 device on the 1-Wire bus
#ifdef USE_STATIC
DS18B20_Info_Static ds18b20_info_static; // static allocation
DS18B20_Info * ds18b20_info = &ds18b20_info_static;
DS18B20_Info devices_static[MAX_DEVICES] = {0};
DS18B20_Info * devices[MAX_DEVICES] = {0};
for (int i = 0; i < MAX_DEVICES; ++i)
{
devices[i] = &(devices_static[i]);
}
#else
DS18B20_Info * ds18b20_info = ds18b20_malloc(); // heap allocation
DS18B20_Info * devices[MAX_DEVICES] = {0};
#endif
for (int i = 0; i < num_devices; ++i)
{
#ifdef USE_STATIC
DS18B20_Info * ds18b20_info = devices[i];
#else
DS18B20_Info * ds18b20_info = ds18b20_malloc(); // heap allocation
devices[i] = ds18b20_info;
#endif
uint64_t rom_code = 0;
for (int j = 7; j >= 0; --j)
{
rom_code |= ((uint64_t)device_rom_codes[i][j] << (8 * j));
}
printf("1-Wire ROM code 0x%08" PRIx64 "\n", rom_code);
ds18b20_init(ds18b20_info, owb, rom_code); // associate with bus and device
//ds18b20_init_solo(ds18b20_info, owb); // only one device on bus
ds18b20_use_crc(ds18b20_info, true); // enable CRC check for temperature readings
}
while (1)
{
float temp = ds18b20_get_temp(ds18b20_info);
printf("Temp %.1f degrees C\n", temp);
for (int i = 0; i < num_devices; ++i)
{
float temp = ds18b20_get_temp(devices[i]);
printf("Temp %d: %.1f degrees C\n", i, temp);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}

164
main/owb.c

@ -12,7 +12,6 @@
#define TAG "owb"
struct _OneWireBus_Timing
{
int A, B, C, D, E, F, G, H, I, J;
@ -32,14 +31,6 @@ static const struct _OneWireBus_Timing _StandardTiming = {
410 * 4, // J
};
//struct _OneWireBus
//{
// bool init;
// int gpio;
// const struct _OneWireBus_Timing * timing;
// bool use_crc;
//};
static void _tick_delay(int ticks)
{
// Each tick is 0.25 microseconds.
@ -47,7 +38,7 @@ static void _tick_delay(int ticks)
ets_delay_us(time_us);
}
static bool _is_init(const OneWireBus * bus)
bool _is_init(const OneWireBus * bus)
{
bool ok = false;
if (bus != NULL)
@ -69,7 +60,6 @@ static bool _is_init(const OneWireBus * bus)
return ok;
}
/**
* @brief Generate a 1-Wire reset.
* @param[in] bus Initialised bus instance.
@ -245,6 +235,127 @@ static uint8_t _calc_crc(uint8_t crc, uint8_t data)
return table[crc ^ data];
}
static bool _search(const OneWireBus * bus, OneWireBus_SearchState * state)
{
// Based on https://www.maximintegrated.com/en/app-notes/index.mvp/id/187
// initialize for search
int id_bit_number = 1;
int last_zero = 0;
int rom_byte_number = 0;
int id_bit = 0;
int cmp_id_bit = 0;
uint8_t rom_byte_mask = 1;
uint8_t search_direction = 0;
bool search_result = false;
uint8_t crc8 = 0;
if (_is_init(bus))
{
// if the last call was not the last one
if (!state->last_device_flag)
{
// 1-Wire reset
if (!_reset(bus))
{
// reset the search
state->last_discrepancy = 0;
state->last_device_flag = false;
state->last_family_discrepancy = 0;
return false;
}
// issue the search command
_write_byte(bus, OWB_ROM_SEARCH);
// loop to do the search
do
{
// read a bit and its complement
id_bit = _read_bit(bus);
cmp_id_bit = _read_bit(bus);
// check for no devices on 1-wire
if ((id_bit == 1) && (cmp_id_bit == 1))
break;
else
{
// all devices coupled have 0 or 1
if (id_bit != cmp_id_bit)
search_direction = id_bit; // bit write value for search
else
{
// if this discrepancy if before the Last Discrepancy
// on a previous next then pick the same as last time
if (id_bit_number < state->last_discrepancy)
search_direction = ((state->rom_code[rom_byte_number] & rom_byte_mask) > 0);
else
// if equal to last pick 1, if not then pick 0
search_direction = (id_bit_number == state->last_discrepancy);
// if 0 was picked then record its position in LastZero
if (search_direction == 0)
{
last_zero = id_bit_number;
// check for Last discrepancy in family
if (last_zero < 9)
state->last_family_discrepancy = last_zero;
}
}
// set or clear the bit in the ROM byte rom_byte_number
// with mask rom_byte_mask
if (search_direction == 1)
state->rom_code[rom_byte_number] |= rom_byte_mask;
else
state->rom_code[rom_byte_number] &= ~rom_byte_mask;
// serial number search direction write bit
_write_bit(bus, search_direction);
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
if (rom_byte_mask == 0)
{
crc8 = _calc_crc(crc8, state->rom_code[rom_byte_number]); // accumulate the CRC
rom_byte_number++;
rom_byte_mask = 1;
}
}
}
while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!((id_bit_number < 65) || (crc8 != 0)))
{
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
state->last_discrepancy = last_zero;
// check for last device
if (state->last_discrepancy == 0)
state->last_device_flag = true;
search_result = true;
}
}
// if no device found then reset counters so next 'search' will be like a first
if (!search_result || !state->rom_code[0])
{
state->last_discrepancy = 0;
state->last_device_flag = false;
state->last_family_discrepancy = 0;
search_result = false;
}
}
return search_result;
}
// Public API
@ -392,3 +503,34 @@ uint8_t owb_crc8(uint8_t crc, uint8_t data)
return _calc_crc(crc, data);
}
bool owb_search_first(const OneWireBus * bus, OneWireBus_SearchState * state)
{
bool result = false;
if (state != NULL)
{
memset(state->rom_code, 0, sizeof(state->rom_code));
state->last_discrepancy = 0;
state->last_family_discrepancy = 0;
state->last_device_flag = false;
result = _search(bus, state);
}
else
{
ESP_LOGE(TAG, "state is NULL");
}
return result;
}
bool owb_search_next(const OneWireBus * bus, OneWireBus_SearchState * state)
{
bool result = false;
if (state != NULL)
{
result = _search(bus, state);
}
else
{
ESP_LOGE(TAG, "state is NULL");
}
return result;
}

23
main/owb.h

@ -2,6 +2,7 @@
#define ONE_WIRE_BUS_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
@ -54,6 +55,9 @@ void owb_use_crc(OneWireBus * bus, bool use_crc);
*/
uint64_t owb_read_rom(const OneWireBus * bus);
// TODO
bool owb_verify_rom(const OneWireBus * bus, uint64_t rom_code);
/**
* @brief Reset the 1-Wire bus.
* @param[in] bus Pointer to initialised bus instance.
@ -100,13 +104,28 @@ const uint8_t * owb_write_bytes(const OneWireBus * bus, const uint8_t * buffer,
*/
void owb_write_rom_code(const OneWireBus * bus, uint64_t rom_code);
/**
/**
* @brief 1-Wire 8-bit CRC lookup.
* @param[in] crc Starting CRC value. Pass in prior CRC to accumulate.
* @param[in] data Byte to feed into CRC.
* @return Resultant CRC value.
*/
uint8_t owb_crc8(uint8_t crc, uint8_t data);
uint8_t owb_crc8(uint8_t crc, uint8_t data);
// Search API
struct OneWireBus_SearchState
{
uint8_t rom_code[8];
int last_discrepancy;
int last_family_discrepancy;
int last_device_flag;
};
typedef struct OneWireBus_SearchState OneWireBus_SearchState;
bool owb_search_first(const OneWireBus * bus, OneWireBus_SearchState * state);
bool owb_search_next(const OneWireBus * bus, OneWireBus_SearchState * state);
#ifdef __cplusplus

Loading…
Cancel
Save