Skip to content

Commit

Permalink
rmt_onewire: refactor example with component manager
Browse files Browse the repository at this point in the history
Closes #10790
  • Loading branch information
suda-morris committed Apr 28, 2023
1 parent 961018d commit 14dac35
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 1,156 deletions.
2 changes: 1 addition & 1 deletion components/driver/rmt/rmt_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ static bool IRAM_ATTR rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan)
rmt_ll_rx_enable(hal->regs, channel_id, false);
uint32_t offset = rmt_ll_rx_get_memory_writer_offset(hal->regs, channel_id);
// sanity check
assert(offset > rx_chan->mem_off);
assert(offset >= rx_chan->mem_off);
rmt_ll_rx_set_mem_owner(hal->regs, channel_id, RMT_LL_MEM_OWNER_SW);
// copy the symbols to user space
size_t stream_symbols = offset - rx_chan->mem_off;
Expand Down
2 changes: 1 addition & 1 deletion docs/en/api-reference/peripherals/rmt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ Application Examples
* RMT transactions in queue: :example:`peripherals/rmt/musical_buzzer`
* RMT based stepper motor with S-curve algorithm: : :example:`peripherals/rmt/stepper_motor`
* RMT infinite loop for driving DShot ESC: :example:`peripherals/rmt/dshot_esc`
* RMT simulate 1-wire protocol (take DS18B20 as example): :example:`peripherals/rmt/onewire_ds18b20`
* RMT simulate 1-wire protocol (take DS18B20 as example): :example:`peripherals/rmt/onewire`

API Reference
-------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(onewire_ds18b20)
project(onewire)
74 changes: 74 additions & 0 deletions examples/peripherals/rmt/onewire/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |

# Advanced RMT Transmit & Receive Example -- Simulate 1-Wire Bus

(See the README.md file in the upper level 'examples' directory for more information about examples.)

RMT peripheral has independent transmit and receive channels. We can simulate the [1-Wire](https://www.analog.com/en/technical-articles/guide-to-1wire-communication.html) bus by attaching a pair of transmit and receive channel to the same GPIO, and turning on the open-drain mode of the GPIO pad.

We've made the 1-Wire protocol implementation into a component called `onewire_bus`, which has been uploaded to the [component registry](https://components.espressif.com/components/espressif/onewire_bus).

This example demonstrates how to use that `onewire_bus` library to read temperature from the [DS18B20](https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf) sensor. Likewise, the DS18B20 device is also made as a single component and pushed to the [component registry](https://components.espressif.com/components/espressif/ds18b20).

One of the amazing feature that offered by the `onewire_bus` driver is that, is can support enumerate the devices on the bus, thus you can connect multiple DS18B20 sensors to the same bus and read their temperature one by one.

## How to Use Example

### Hardware Required

* A development board with any supported Espressif SOC chip (see `Supported Targets` table above)
* One or more DS18B20 sensors connected to the same bus by a 4.7 KΩ pull-up resistor

Connection :

```plain
┌──────────────────────────┐
│ 3.3V├───────┬─────────────┬──────────────────────┐
│ │ ┌┴┐ │VDD │VDD
│ ESP Board │ 4.7k│ │ ┌──────┴──────┐ ┌──────┴──────┐
│ │ └┬┘ DQ│ │ DQ│ │
│ ONEWIRE_GPIO_PIN├───────┴──┬───┤ DS18B20 │ ┌───┤ DS18B20 │ ......
│ │ └───│-------------│────┴───│-------------│──
│ │ └──────┬──────┘ └──────┬──────┘
│ │ │GND │GND
│ GND├─────────────────────┴──────────────────────┘
└──────────────────────────┘
```

The GPIO number used in this example can be changed according to your board, by the macro `EXAMPLE_ONEWIRE_BUS_GPIO` defined in [onewire_example_main.c](main/onewire_example_main.c).

> **Note**
> Parasite power mode is not supported, you have to connect VDD pin to make DS18B20 functional.
### Build and Flash

Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.

(To exit the serial monitor, type ``Ctrl-]``.)

See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.

## Console Output

```plain
I (340) main_task: Started on CPU0
I (350) main_task: Calling app_main()
I (350) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (360) gpio: GPIO[0]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (370) example: 1-Wire bus installed on GPIO0
I (370) example: Device iterator created, start searching...
I (490) example: Found a DS18B20[0], address: 070822502019FC28
I (590) example: Found a DS18B20[1], address: FC0921C076034628
I (590) example: Searching done, 2 DS18B20 device(s) found
I (1620) example: temperature read from DS18B20[0]: 22.50C
I (2430) example: temperature read from DS18B20[1]: 22.81C
I (3440) example: temperature read from DS18B20[0]: 22.50C
I (4250) example: temperature read from DS18B20[1]: 22.81C
I (5260) example: temperature read from DS18B20[0]: 22.50C
I (6070) example: temperature read from DS18B20[1]: 22.81C
```

## Troubleshooting

For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
2 changes: 2 additions & 0 deletions examples/peripherals/rmt/onewire/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "onewire_example_main.c"
INCLUDE_DIRS ".")
2 changes: 2 additions & 0 deletions examples/peripherals/rmt/onewire/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
ds18b20: "^0.1.0"
76 changes: 76 additions & 0 deletions examples/peripherals/rmt/onewire/main/onewire_example_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_check.h"
#include "onewire_bus.h"
#include "ds18b20.h"

static const char *TAG = "example";

#define EXAMPLE_ONEWIRE_BUS_GPIO 0
#define EXAMPLE_ONEWIRE_MAX_DS18B20 2

void app_main(void)
{
// install new 1-wire bus
onewire_bus_handle_t bus;
onewire_bus_config_t bus_config = {
.bus_gpio_num = EXAMPLE_ONEWIRE_BUS_GPIO,
};
onewire_bus_rmt_config_t rmt_config = {
.max_rx_bytes = 10, // 1byte ROM command + 8byte ROM number + 1byte device command
};
ESP_ERROR_CHECK(onewire_new_bus_rmt(&bus_config, &rmt_config, &bus));
ESP_LOGI(TAG, "1-Wire bus installed on GPIO%d", EXAMPLE_ONEWIRE_BUS_GPIO);

int ds18b20_device_num = 0;
ds18b20_device_handle_t ds18b20s[EXAMPLE_ONEWIRE_MAX_DS18B20];
onewire_device_iter_handle_t iter = NULL;
onewire_device_t next_onewire_device;
esp_err_t search_result = ESP_OK;

// create 1-wire device iterator, which is used for device search
ESP_ERROR_CHECK(onewire_new_device_iter(bus, &iter));
ESP_LOGI(TAG, "Device iterator created, start searching...");
do {
search_result = onewire_device_iter_get_next(iter, &next_onewire_device);
if (search_result == ESP_OK) { // found a new device, let's check if we can upgrade it to a DS18B20
ds18b20_config_t ds_cfg = {};
if (ds18b20_new_device(&next_onewire_device, &ds_cfg, &ds18b20s[ds18b20_device_num]) == ESP_OK) {
ESP_LOGI(TAG, "Found a DS18B20[%d], address: %016llX", ds18b20_device_num, next_onewire_device.address);
ds18b20_device_num++;
if (ds18b20_device_num >= EXAMPLE_ONEWIRE_MAX_DS18B20) {
ESP_LOGI(TAG, "Max DS18B20 number reached, stop searching...");
break;
}
} else {
ESP_LOGI(TAG, "Found an unknown device, address: %016llX", next_onewire_device.address);
}
}
} while (search_result != ESP_ERR_NOT_FOUND);
ESP_ERROR_CHECK(onewire_del_device_iter(iter));
ESP_LOGI(TAG, "Searching done, %d DS18B20 device(s) found", ds18b20_device_num);

// set resolution for all DS18B20s
for (int i = 0; i < ds18b20_device_num; i++) {
// set resolution
ESP_ERROR_CHECK(ds18b20_set_resolution(ds18b20s[i], DS18B20_RESOLUTION_12B));
}

// get temperature from sensors one by one
float temperature;
while (1) {
vTaskDelay(pdMS_TO_TICKS(200));

for (int i = 0; i < ds18b20_device_num; i ++) {
ESP_ERROR_CHECK(ds18b20_trigger_temperature_conversion(ds18b20s[i]));
ESP_ERROR_CHECK(ds18b20_get_temperature(ds18b20s[i], &temperature));
ESP_LOGI(TAG, "temperature read from DS18B20[%d]: %.2fC", i, temperature);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
def test_onewire_ds18b20_example(dut: Dut) -> None:
dut.expect_exact('onewire_rmt: RMT Tx channel created for 1-wire bus')
dut.expect_exact('onewire_rmt: RMT Rx channel created for 1-wire bus')
dut.expect_exact('example: 1-wire bus installed')
dut.expect_exact('example: 1-wire bus deleted')
def test_onewire_example(dut: Dut) -> None:
dut.expect_exact('example: 1-Wire bus installed on GPIO')
dut.expect_exact('example: Device iterator created, start searching')
dut.expect_exact('example: Searching done')
90 changes: 0 additions & 90 deletions examples/peripherals/rmt/onewire_ds18b20/README.md

This file was deleted.

This file was deleted.

Loading

0 comments on commit 14dac35

Please sign in to comment.